1 #include <petscvec.h>
2 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/
3 #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/
4 #include <petsc/private/petscdsimpl.h> /*I "petscds.h" I*/
5 #include <petscdmplex.h>
6 #include <petscdmfield.h>
7 #include <petscsf.h>
8 #include <petscds.h>
9
10 #if defined(PETSC_HAVE_VALGRIND)
11 # include <valgrind/memcheck.h>
12 #endif
13
14 PetscClassId DM_CLASSID;
15 PetscClassId DMLABEL_CLASSID;
16 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_Refine, DM_CreateInterpolation, DM_CreateRestriction, DM_CreateInjection, DM_CreateMatrix, DM_Load, DM_AdaptInterpolator;
17
18 const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DMBoundaryType","DM_BOUNDARY_", NULL};
19 const char *const DMBoundaryConditionTypes[] = {"INVALID","ESSENTIAL","NATURAL","INVALID","INVALID","ESSENTIAL_FIELD","NATURAL_FIELD","INVALID","INVALID","INVALID","NATURAL_RIEMANN","DMBoundaryConditionType","DM_BC_", NULL};
20 const char *const DMPolytopeTypes[] = {"vertex", "segment", "tensor_segment", "triangle", "quadrilateral", "tensor_quad", "tetrahedron", "hexahedron", "triangular_prism", "tensor_triangular_prism", "tensor_quadrilateral_prism", "FV_ghost_cell", "interior_ghost_cell", "unknown", "invalid", "DMPolytopeType", "DM_POLYTOPE_", NULL};
21 /*@
22 DMCreate - Creates an empty DM object. The type can then be set with DMSetType().
23
24 If you never call DMSetType() it will generate an
25 error when you try to use the vector.
26
27 Collective
28
29 Input Parameter:
30 . comm - The communicator for the DM object
31
32 Output Parameter:
33 . dm - The DM object
34
35 Level: beginner
36
37 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK
38 @*/
DMCreate(MPI_Comm comm,DM * dm)39 PetscErrorCode DMCreate(MPI_Comm comm,DM *dm)
40 {
41 DM v;
42 PetscDS ds;
43 PetscErrorCode ierr;
44
45 PetscFunctionBegin;
46 PetscValidPointer(dm,2);
47 *dm = NULL;
48 ierr = DMInitializePackage();CHKERRQ(ierr);
49
50 ierr = PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr);
51
52 v->setupcalled = PETSC_FALSE;
53 v->setfromoptionscalled = PETSC_FALSE;
54 v->ltogmap = NULL;
55 v->bs = 1;
56 v->coloringtype = IS_COLORING_GLOBAL;
57 ierr = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr);
58 ierr = PetscSFCreate(comm, &v->sectionSF);CHKERRQ(ierr);
59 v->labels = NULL;
60 v->adjacency[0] = PETSC_FALSE;
61 v->adjacency[1] = PETSC_TRUE;
62 v->depthLabel = NULL;
63 v->celltypeLabel = NULL;
64 v->localSection = NULL;
65 v->globalSection = NULL;
66 v->defaultConstraintSection = NULL;
67 v->defaultConstraintMat = NULL;
68 v->L = NULL;
69 v->maxCell = NULL;
70 v->bdtype = NULL;
71 v->dimEmbed = PETSC_DEFAULT;
72 v->dim = PETSC_DETERMINE;
73 {
74 PetscInt i;
75 for (i = 0; i < 10; ++i) {
76 v->nullspaceConstructors[i] = NULL;
77 v->nearnullspaceConstructors[i] = NULL;
78 }
79 }
80 ierr = PetscDSCreate(PetscObjectComm((PetscObject) v), &ds);CHKERRQ(ierr);
81 ierr = DMSetRegionDS(v, NULL, NULL, ds);CHKERRQ(ierr);
82 ierr = PetscDSDestroy(&ds);CHKERRQ(ierr);
83 v->dmBC = NULL;
84 v->coarseMesh = NULL;
85 v->outputSequenceNum = -1;
86 v->outputSequenceVal = 0.0;
87 ierr = DMSetVecType(v,VECSTANDARD);CHKERRQ(ierr);
88 ierr = DMSetMatType(v,MATAIJ);CHKERRQ(ierr);
89
90 *dm = v;
91 PetscFunctionReturn(0);
92 }
93
94 /*@
95 DMClone - Creates a DM object with the same topology as the original.
96
97 Collective
98
99 Input Parameter:
100 . dm - The original DM object
101
102 Output Parameter:
103 . newdm - The new DM object
104
105 Level: beginner
106
107 Notes:
108 For some DM implementations this is a shallow clone, the result of which may share (referent counted) information with its parent. For example,
109 DMClone() applied to a DMPLEX object will result in a new DMPLEX that shares the topology with the original DMPLEX. It does not
110 share the PetscSection of the original DM.
111
112 The clone is considered set up iff the original is.
113
114 .seealso: DMDestroy(), DMCreate(), DMSetType(), DMSetLocalSection(), DMSetGlobalSection()
115
116 @*/
DMClone(DM dm,DM * newdm)117 PetscErrorCode DMClone(DM dm, DM *newdm)
118 {
119 PetscSF sf;
120 Vec coords;
121 void *ctx;
122 PetscInt dim, cdim;
123 PetscErrorCode ierr;
124
125 PetscFunctionBegin;
126 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
127 PetscValidPointer(newdm,2);
128 ierr = DMCreate(PetscObjectComm((PetscObject) dm), newdm);CHKERRQ(ierr);
129 ierr = DMCopyLabels(dm, *newdm, PETSC_COPY_VALUES, PETSC_TRUE);CHKERRQ(ierr);
130 (*newdm)->leveldown = dm->leveldown;
131 (*newdm)->levelup = dm->levelup;
132 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
133 ierr = DMSetDimension(*newdm, dim);CHKERRQ(ierr);
134 if (dm->ops->clone) {
135 ierr = (*dm->ops->clone)(dm, newdm);CHKERRQ(ierr);
136 }
137 (*newdm)->setupcalled = dm->setupcalled;
138 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
139 ierr = DMSetPointSF(*newdm, sf);CHKERRQ(ierr);
140 ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr);
141 ierr = DMSetApplicationContext(*newdm, ctx);CHKERRQ(ierr);
142 if (dm->coordinateDM) {
143 DM ncdm;
144 PetscSection cs;
145 PetscInt pEnd = -1, pEndMax = -1;
146
147 ierr = DMGetLocalSection(dm->coordinateDM, &cs);CHKERRQ(ierr);
148 if (cs) {ierr = PetscSectionGetChart(cs, NULL, &pEnd);CHKERRQ(ierr);}
149 ierr = MPI_Allreduce(&pEnd,&pEndMax,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
150 if (pEndMax >= 0) {
151 ierr = DMClone(dm->coordinateDM, &ncdm);CHKERRQ(ierr);
152 ierr = DMCopyDisc(dm->coordinateDM, ncdm);CHKERRQ(ierr);
153 ierr = DMSetLocalSection(ncdm, cs);CHKERRQ(ierr);
154 ierr = DMSetCoordinateDM(*newdm, ncdm);CHKERRQ(ierr);
155 ierr = DMDestroy(&ncdm);CHKERRQ(ierr);
156 }
157 }
158 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
159 ierr = DMSetCoordinateDim(*newdm, cdim);CHKERRQ(ierr);
160 ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr);
161 if (coords) {
162 ierr = DMSetCoordinatesLocal(*newdm, coords);CHKERRQ(ierr);
163 } else {
164 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr);
165 if (coords) {ierr = DMSetCoordinates(*newdm, coords);CHKERRQ(ierr);}
166 }
167 {
168 PetscBool isper;
169 const PetscReal *maxCell, *L;
170 const DMBoundaryType *bd;
171 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr);
172 ierr = DMSetPeriodicity(*newdm, isper, maxCell, L, bd);CHKERRQ(ierr);
173 }
174 {
175 PetscBool useCone, useClosure;
176
177 ierr = DMGetAdjacency(dm, PETSC_DEFAULT, &useCone, &useClosure);CHKERRQ(ierr);
178 ierr = DMSetAdjacency(*newdm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr);
179 }
180 PetscFunctionReturn(0);
181 }
182
183 /*@C
184 DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
185
186 Logically Collective on da
187
188 Input Parameter:
189 + da - initial distributed array
190 . ctype - the vector type, currently either VECSTANDARD, VECCUDA, or VECVIENNACL
191
192 Options Database:
193 . -dm_vec_type ctype
194
195 Level: intermediate
196
197 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType(), DMSetMatType(), DMGetMatType()
198 @*/
DMSetVecType(DM da,VecType ctype)199 PetscErrorCode DMSetVecType(DM da,VecType ctype)
200 {
201 PetscErrorCode ierr;
202
203 PetscFunctionBegin;
204 PetscValidHeaderSpecific(da,DM_CLASSID,1);
205 ierr = PetscFree(da->vectype);CHKERRQ(ierr);
206 ierr = PetscStrallocpy(ctype,(char**)&da->vectype);CHKERRQ(ierr);
207 PetscFunctionReturn(0);
208 }
209
210 /*@C
211 DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
212
213 Logically Collective on da
214
215 Input Parameter:
216 . da - initial distributed array
217
218 Output Parameter:
219 . ctype - the vector type
220
221 Level: intermediate
222
223 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMSetMatType(), DMGetMatType(), DMSetVecType()
224 @*/
DMGetVecType(DM da,VecType * ctype)225 PetscErrorCode DMGetVecType(DM da,VecType *ctype)
226 {
227 PetscFunctionBegin;
228 PetscValidHeaderSpecific(da,DM_CLASSID,1);
229 *ctype = da->vectype;
230 PetscFunctionReturn(0);
231 }
232
233 /*@
234 VecGetDM - Gets the DM defining the data layout of the vector
235
236 Not collective
237
238 Input Parameter:
239 . v - The Vec
240
241 Output Parameter:
242 . dm - The DM
243
244 Level: intermediate
245
246 .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
247 @*/
VecGetDM(Vec v,DM * dm)248 PetscErrorCode VecGetDM(Vec v, DM *dm)
249 {
250 PetscErrorCode ierr;
251
252 PetscFunctionBegin;
253 PetscValidHeaderSpecific(v,VEC_CLASSID,1);
254 PetscValidPointer(dm,2);
255 ierr = PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr);
256 PetscFunctionReturn(0);
257 }
258
259 /*@
260 VecSetDM - Sets the DM defining the data layout of the vector.
261
262 Not collective
263
264 Input Parameters:
265 + v - The Vec
266 - dm - The DM
267
268 Note: This is NOT the same as DMCreateGlobalVector() since it does not change the view methods or perform other customization, but merely sets the DM member.
269
270 Level: intermediate
271
272 .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
273 @*/
VecSetDM(Vec v,DM dm)274 PetscErrorCode VecSetDM(Vec v, DM dm)
275 {
276 PetscErrorCode ierr;
277
278 PetscFunctionBegin;
279 PetscValidHeaderSpecific(v,VEC_CLASSID,1);
280 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2);
281 ierr = PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr);
282 PetscFunctionReturn(0);
283 }
284
285 /*@C
286 DMSetISColoringType - Sets the type of coloring, global or local, that is created by the DM
287
288 Logically Collective on dm
289
290 Input Parameters:
291 + dm - the DM context
292 - ctype - the matrix type
293
294 Options Database:
295 . -dm_is_coloring_type - global or local
296
297 Level: intermediate
298
299 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(),
300 DMGetISColoringType()
301 @*/
DMSetISColoringType(DM dm,ISColoringType ctype)302 PetscErrorCode DMSetISColoringType(DM dm,ISColoringType ctype)
303 {
304 PetscFunctionBegin;
305 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
306 dm->coloringtype = ctype;
307 PetscFunctionReturn(0);
308 }
309
310 /*@C
311 DMGetISColoringType - Gets the type of coloring, global or local, that is created by the DM
312
313 Logically Collective on dm
314
315 Input Parameter:
316 . dm - the DM context
317
318 Output Parameter:
319 . ctype - the matrix type
320
321 Options Database:
322 . -dm_is_coloring_type - global or local
323
324 Level: intermediate
325
326 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(),
327 DMGetISColoringType()
328 @*/
DMGetISColoringType(DM dm,ISColoringType * ctype)329 PetscErrorCode DMGetISColoringType(DM dm,ISColoringType *ctype)
330 {
331 PetscFunctionBegin;
332 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
333 *ctype = dm->coloringtype;
334 PetscFunctionReturn(0);
335 }
336
337 /*@C
338 DMSetMatType - Sets the type of matrix created with DMCreateMatrix()
339
340 Logically Collective on dm
341
342 Input Parameters:
343 + dm - the DM context
344 - ctype - the matrix type
345
346 Options Database:
347 . -dm_mat_type ctype
348
349 Level: intermediate
350
351 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(), DMSetMatType(), DMGetMatType()
352 @*/
DMSetMatType(DM dm,MatType ctype)353 PetscErrorCode DMSetMatType(DM dm,MatType ctype)
354 {
355 PetscErrorCode ierr;
356
357 PetscFunctionBegin;
358 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
359 ierr = PetscFree(dm->mattype);CHKERRQ(ierr);
360 ierr = PetscStrallocpy(ctype,(char**)&dm->mattype);CHKERRQ(ierr);
361 PetscFunctionReturn(0);
362 }
363
364 /*@C
365 DMGetMatType - Gets the type of matrix created with DMCreateMatrix()
366
367 Logically Collective on dm
368
369 Input Parameter:
370 . dm - the DM context
371
372 Output Parameter:
373 . ctype - the matrix type
374
375 Options Database:
376 . -dm_mat_type ctype
377
378 Level: intermediate
379
380 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType(), DMSetMatType(), DMGetMatType()
381 @*/
DMGetMatType(DM dm,MatType * ctype)382 PetscErrorCode DMGetMatType(DM dm,MatType *ctype)
383 {
384 PetscFunctionBegin;
385 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
386 *ctype = dm->mattype;
387 PetscFunctionReturn(0);
388 }
389
390 /*@
391 MatGetDM - Gets the DM defining the data layout of the matrix
392
393 Not collective
394
395 Input Parameter:
396 . A - The Mat
397
398 Output Parameter:
399 . dm - The DM
400
401 Level: intermediate
402
403 Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with
404 the Mat through a PetscObjectCompose() operation
405
406 .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType()
407 @*/
MatGetDM(Mat A,DM * dm)408 PetscErrorCode MatGetDM(Mat A, DM *dm)
409 {
410 PetscErrorCode ierr;
411
412 PetscFunctionBegin;
413 PetscValidHeaderSpecific(A,MAT_CLASSID,1);
414 PetscValidPointer(dm,2);
415 ierr = PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr);
416 PetscFunctionReturn(0);
417 }
418
419 /*@
420 MatSetDM - Sets the DM defining the data layout of the matrix
421
422 Not collective
423
424 Input Parameters:
425 + A - The Mat
426 - dm - The DM
427
428 Level: intermediate
429
430 Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with
431 the Mat through a PetscObjectCompose() operation
432
433
434 .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType()
435 @*/
MatSetDM(Mat A,DM dm)436 PetscErrorCode MatSetDM(Mat A, DM dm)
437 {
438 PetscErrorCode ierr;
439
440 PetscFunctionBegin;
441 PetscValidHeaderSpecific(A,MAT_CLASSID,1);
442 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2);
443 ierr = PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr);
444 PetscFunctionReturn(0);
445 }
446
447 /*@C
448 DMSetOptionsPrefix - Sets the prefix used for searching for all
449 DM options in the database.
450
451 Logically Collective on dm
452
453 Input Parameter:
454 + da - the DM context
455 - prefix - the prefix to prepend to all option names
456
457 Notes:
458 A hyphen (-) must NOT be given at the beginning of the prefix name.
459 The first character of all runtime options is AUTOMATICALLY the hyphen.
460
461 Level: advanced
462
463 .seealso: DMSetFromOptions()
464 @*/
DMSetOptionsPrefix(DM dm,const char prefix[])465 PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[])
466 {
467 PetscErrorCode ierr;
468
469 PetscFunctionBegin;
470 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
471 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr);
472 if (dm->sf) {
473 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);CHKERRQ(ierr);
474 }
475 if (dm->sectionSF) {
476 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->sectionSF,prefix);CHKERRQ(ierr);
477 }
478 PetscFunctionReturn(0);
479 }
480
481 /*@C
482 DMAppendOptionsPrefix - Appends to the prefix used for searching for all
483 DM options in the database.
484
485 Logically Collective on dm
486
487 Input Parameters:
488 + dm - the DM context
489 - prefix - the prefix string to prepend to all DM option requests
490
491 Notes:
492 A hyphen (-) must NOT be given at the beginning of the prefix name.
493 The first character of all runtime options is AUTOMATICALLY the hyphen.
494
495 Level: advanced
496
497 .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix()
498 @*/
DMAppendOptionsPrefix(DM dm,const char prefix[])499 PetscErrorCode DMAppendOptionsPrefix(DM dm,const char prefix[])
500 {
501 PetscErrorCode ierr;
502
503 PetscFunctionBegin;
504 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
505 ierr = PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr);
506 PetscFunctionReturn(0);
507 }
508
509 /*@C
510 DMGetOptionsPrefix - Gets the prefix used for searching for all
511 DM options in the database.
512
513 Not Collective
514
515 Input Parameters:
516 . dm - the DM context
517
518 Output Parameters:
519 . prefix - pointer to the prefix string used is returned
520
521 Notes:
522 On the fortran side, the user should pass in a string 'prefix' of
523 sufficient length to hold the prefix.
524
525 Level: advanced
526
527 .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix()
528 @*/
DMGetOptionsPrefix(DM dm,const char * prefix[])529 PetscErrorCode DMGetOptionsPrefix(DM dm,const char *prefix[])
530 {
531 PetscErrorCode ierr;
532
533 PetscFunctionBegin;
534 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
535 ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr);
536 PetscFunctionReturn(0);
537 }
538
DMCountNonCyclicReferences(DM dm,PetscBool recurseCoarse,PetscBool recurseFine,PetscInt * ncrefct)539 static PetscErrorCode DMCountNonCyclicReferences(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct)
540 {
541 PetscInt refct = ((PetscObject) dm)->refct;
542 PetscErrorCode ierr;
543
544 PetscFunctionBegin;
545 *ncrefct = 0;
546 if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) {
547 refct--;
548 if (recurseCoarse) {
549 PetscInt coarseCount;
550
551 ierr = DMCountNonCyclicReferences(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE,&coarseCount);CHKERRQ(ierr);
552 refct += coarseCount;
553 }
554 }
555 if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) {
556 refct--;
557 if (recurseFine) {
558 PetscInt fineCount;
559
560 ierr = DMCountNonCyclicReferences(dm->fineMesh, PETSC_FALSE, PETSC_TRUE,&fineCount);CHKERRQ(ierr);
561 refct += fineCount;
562 }
563 }
564 *ncrefct = refct;
565 PetscFunctionReturn(0);
566 }
567
DMDestroyLabelLinkList_Internal(DM dm)568 PetscErrorCode DMDestroyLabelLinkList_Internal(DM dm)
569 {
570 DMLabelLink next = dm->labels;
571 PetscErrorCode ierr;
572
573 PetscFunctionBegin;
574 /* destroy the labels */
575 while (next) {
576 DMLabelLink tmp = next->next;
577
578 if (next->label == dm->depthLabel) dm->depthLabel = NULL;
579 if (next->label == dm->celltypeLabel) dm->celltypeLabel = NULL;
580 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr);
581 ierr = PetscFree(next);CHKERRQ(ierr);
582 next = tmp;
583 }
584 dm->labels = NULL;
585 PetscFunctionReturn(0);
586 }
587
588 /*@
589 DMDestroy - Destroys a vector packer or DM.
590
591 Collective on dm
592
593 Input Parameter:
594 . dm - the DM object to destroy
595
596 Level: developer
597
598 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
599
600 @*/
DMDestroy(DM * dm)601 PetscErrorCode DMDestroy(DM *dm)
602 {
603 PetscInt cnt;
604 DMNamedVecLink nlink,nnext;
605 PetscErrorCode ierr;
606
607 PetscFunctionBegin;
608 if (!*dm) PetscFunctionReturn(0);
609 PetscValidHeaderSpecific((*dm),DM_CLASSID,1);
610
611 /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */
612 ierr = DMCountNonCyclicReferences(*dm,PETSC_TRUE,PETSC_TRUE,&cnt);CHKERRQ(ierr);
613 --((PetscObject)(*dm))->refct;
614 if (--cnt > 0) {*dm = NULL; PetscFunctionReturn(0);}
615 if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0);
616 ((PetscObject)(*dm))->refct = 0;
617
618 ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr);
619 ierr = DMClearLocalVectors(*dm);CHKERRQ(ierr);
620
621 nnext=(*dm)->namedglobal;
622 (*dm)->namedglobal = NULL;
623 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */
624 nnext = nlink->next;
625 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
626 ierr = PetscFree(nlink->name);CHKERRQ(ierr);
627 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr);
628 ierr = PetscFree(nlink);CHKERRQ(ierr);
629 }
630 nnext=(*dm)->namedlocal;
631 (*dm)->namedlocal = NULL;
632 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */
633 nnext = nlink->next;
634 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
635 ierr = PetscFree(nlink->name);CHKERRQ(ierr);
636 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr);
637 ierr = PetscFree(nlink);CHKERRQ(ierr);
638 }
639
640 /* Destroy the list of hooks */
641 {
642 DMCoarsenHookLink link,next;
643 for (link=(*dm)->coarsenhook; link; link=next) {
644 next = link->next;
645 ierr = PetscFree(link);CHKERRQ(ierr);
646 }
647 (*dm)->coarsenhook = NULL;
648 }
649 {
650 DMRefineHookLink link,next;
651 for (link=(*dm)->refinehook; link; link=next) {
652 next = link->next;
653 ierr = PetscFree(link);CHKERRQ(ierr);
654 }
655 (*dm)->refinehook = NULL;
656 }
657 {
658 DMSubDomainHookLink link,next;
659 for (link=(*dm)->subdomainhook; link; link=next) {
660 next = link->next;
661 ierr = PetscFree(link);CHKERRQ(ierr);
662 }
663 (*dm)->subdomainhook = NULL;
664 }
665 {
666 DMGlobalToLocalHookLink link,next;
667 for (link=(*dm)->gtolhook; link; link=next) {
668 next = link->next;
669 ierr = PetscFree(link);CHKERRQ(ierr);
670 }
671 (*dm)->gtolhook = NULL;
672 }
673 {
674 DMLocalToGlobalHookLink link,next;
675 for (link=(*dm)->ltoghook; link; link=next) {
676 next = link->next;
677 ierr = PetscFree(link);CHKERRQ(ierr);
678 }
679 (*dm)->ltoghook = NULL;
680 }
681 /* Destroy the work arrays */
682 {
683 DMWorkLink link,next;
684 if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out");
685 for (link=(*dm)->workin; link; link=next) {
686 next = link->next;
687 ierr = PetscFree(link->mem);CHKERRQ(ierr);
688 ierr = PetscFree(link);CHKERRQ(ierr);
689 }
690 (*dm)->workin = NULL;
691 }
692 /* destroy the labels */
693 ierr = DMDestroyLabelLinkList_Internal(*dm);CHKERRQ(ierr);
694 /* destroy the fields */
695 ierr = DMClearFields(*dm);CHKERRQ(ierr);
696 /* destroy the boundaries */
697 {
698 DMBoundary next = (*dm)->boundary;
699 while (next) {
700 DMBoundary b = next;
701
702 next = b->next;
703 ierr = PetscFree(b);CHKERRQ(ierr);
704 }
705 }
706
707 ierr = PetscObjectDestroy(&(*dm)->dmksp);CHKERRQ(ierr);
708 ierr = PetscObjectDestroy(&(*dm)->dmsnes);CHKERRQ(ierr);
709 ierr = PetscObjectDestroy(&(*dm)->dmts);CHKERRQ(ierr);
710
711 if ((*dm)->ctx && (*dm)->ctxdestroy) {
712 ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr);
713 }
714 ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr);
715 ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr);
716 ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr);
717 ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr);
718
719 ierr = PetscSectionDestroy(&(*dm)->localSection);CHKERRQ(ierr);
720 ierr = PetscSectionDestroy(&(*dm)->globalSection);CHKERRQ(ierr);
721 ierr = PetscLayoutDestroy(&(*dm)->map);CHKERRQ(ierr);
722 ierr = PetscSectionDestroy(&(*dm)->defaultConstraintSection);CHKERRQ(ierr);
723 ierr = MatDestroy(&(*dm)->defaultConstraintMat);CHKERRQ(ierr);
724 ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr);
725 ierr = PetscSFDestroy(&(*dm)->sectionSF);CHKERRQ(ierr);
726 if ((*dm)->useNatural) {
727 if ((*dm)->sfNatural) {
728 ierr = PetscSFDestroy(&(*dm)->sfNatural);CHKERRQ(ierr);
729 }
730 ierr = PetscObjectDereference((PetscObject) (*dm)->sfMigration);CHKERRQ(ierr);
731 }
732 if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) {
733 ierr = DMSetFineDM((*dm)->coarseMesh,NULL);CHKERRQ(ierr);
734 }
735
736 ierr = DMDestroy(&(*dm)->coarseMesh);CHKERRQ(ierr);
737 if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) {
738 ierr = DMSetCoarseDM((*dm)->fineMesh,NULL);CHKERRQ(ierr);
739 }
740 ierr = DMDestroy(&(*dm)->fineMesh);CHKERRQ(ierr);
741 ierr = DMFieldDestroy(&(*dm)->coordinateField);CHKERRQ(ierr);
742 ierr = DMDestroy(&(*dm)->coordinateDM);CHKERRQ(ierr);
743 ierr = VecDestroy(&(*dm)->coordinates);CHKERRQ(ierr);
744 ierr = VecDestroy(&(*dm)->coordinatesLocal);CHKERRQ(ierr);
745 ierr = PetscFree((*dm)->L);CHKERRQ(ierr);
746 ierr = PetscFree((*dm)->maxCell);CHKERRQ(ierr);
747 ierr = PetscFree((*dm)->bdtype);CHKERRQ(ierr);
748 if ((*dm)->transformDestroy) {ierr = (*(*dm)->transformDestroy)(*dm, (*dm)->transformCtx);CHKERRQ(ierr);}
749 ierr = DMDestroy(&(*dm)->transformDM);CHKERRQ(ierr);
750 ierr = VecDestroy(&(*dm)->transform);CHKERRQ(ierr);
751
752 ierr = DMClearDS(*dm);CHKERRQ(ierr);
753 ierr = DMDestroy(&(*dm)->dmBC);CHKERRQ(ierr);
754 /* if memory was published with SAWs then destroy it */
755 ierr = PetscObjectSAWsViewOff((PetscObject)*dm);CHKERRQ(ierr);
756
757 if ((*dm)->ops->destroy) {
758 ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr);
759 }
760 ierr = DMMonitorCancel(*dm);CHKERRQ(ierr);
761 /* We do not destroy (*dm)->data here so that we can reference count backend objects */
762 ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr);
763 PetscFunctionReturn(0);
764 }
765
766 /*@
767 DMSetUp - sets up the data structures inside a DM object
768
769 Collective on dm
770
771 Input Parameter:
772 . dm - the DM object to setup
773
774 Level: developer
775
776 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
777
778 @*/
DMSetUp(DM dm)779 PetscErrorCode DMSetUp(DM dm)
780 {
781 PetscErrorCode ierr;
782
783 PetscFunctionBegin;
784 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
785 if (dm->setupcalled) PetscFunctionReturn(0);
786 if (dm->ops->setup) {
787 ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr);
788 }
789 dm->setupcalled = PETSC_TRUE;
790 PetscFunctionReturn(0);
791 }
792
793 /*@
794 DMSetFromOptions - sets parameters in a DM from the options database
795
796 Collective on dm
797
798 Input Parameter:
799 . dm - the DM object to set options for
800
801 Options Database:
802 + -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros
803 . -dm_vec_type <type> - type of vector to create inside DM
804 . -dm_mat_type <type> - type of matrix to create inside DM
805 - -dm_is_coloring_type - <global or local>
806
807 DMPLEX Specific Checks
808 + -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric - DMPlexCheckSymmetry()
809 . -dm_plex_check_skeleton - Check that each cell has the correct number of vertices (only for homogeneous simplex or tensor meshes) - DMPlexCheckSkeleton()
810 . -dm_plex_check_faces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type - DMPlexCheckFaces()
811 . -dm_plex_check_geometry - Check that cells have positive volume - DMPlexCheckGeometry()
812 . -dm_plex_check_pointsf - Check some necessary conditions for PointSF - DMPlexCheckPointSF()
813 . -dm_plex_check_interface_cones - Check points on inter-partition interfaces have conforming order of cone points - DMPlexCheckInterfaceCones()
814 - -dm_plex_check_all - Perform all the checks above
815
816 Level: intermediate
817
818 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(),
819 DMPlexCheckSymmetry(), DMPlexCheckSkeleton(), DMPlexCheckFaces(), DMPlexCheckGeometry(), DMPlexCheckPointSF(), DMPlexCheckInterfaceCones()
820
821 @*/
DMSetFromOptions(DM dm)822 PetscErrorCode DMSetFromOptions(DM dm)
823 {
824 char typeName[256];
825 PetscBool flg;
826 PetscErrorCode ierr;
827
828 PetscFunctionBegin;
829 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
830 dm->setfromoptionscalled = PETSC_TRUE;
831 if (dm->sf) {ierr = PetscSFSetFromOptions(dm->sf);CHKERRQ(ierr);}
832 if (dm->sectionSF) {ierr = PetscSFSetFromOptions(dm->sectionSF);CHKERRQ(ierr);}
833 ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr);
834 ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);CHKERRQ(ierr);
835 ierr = PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr);
836 if (flg) {
837 ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr);
838 }
839 ierr = PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);CHKERRQ(ierr);
840 if (flg) {
841 ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr);
842 }
843 ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","DMSetISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);CHKERRQ(ierr);
844 if (dm->ops->setfromoptions) {
845 ierr = (*dm->ops->setfromoptions)(PetscOptionsObject,dm);CHKERRQ(ierr);
846 }
847 /* process any options handlers added with PetscObjectAddOptionsHandler() */
848 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) dm);CHKERRQ(ierr);
849 ierr = PetscOptionsEnd();CHKERRQ(ierr);
850 PetscFunctionReturn(0);
851 }
852
853 /*@C
854 DMViewFromOptions - View from Options
855
856 Collective on DM
857
858 Input Parameters:
859 + dm - the DM object
860 . obj - Optional object
861 - name - command line option
862
863 Level: intermediate
864 .seealso: DM, DMView, PetscObjectViewFromOptions(), DMCreate()
865 @*/
DMViewFromOptions(DM dm,PetscObject obj,const char name[])866 PetscErrorCode DMViewFromOptions(DM dm,PetscObject obj,const char name[])
867 {
868 PetscErrorCode ierr;
869
870 PetscFunctionBegin;
871 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
872 ierr = PetscObjectViewFromOptions((PetscObject)dm,obj,name);CHKERRQ(ierr);
873 PetscFunctionReturn(0);
874 }
875
876 /*@C
877 DMView - Views a DM
878
879 Collective on dm
880
881 Input Parameter:
882 + dm - the DM object to view
883 - v - the viewer
884
885 Level: beginner
886
887 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
888
889 @*/
DMView(DM dm,PetscViewer v)890 PetscErrorCode DMView(DM dm,PetscViewer v)
891 {
892 PetscErrorCode ierr;
893 PetscBool isbinary;
894 PetscMPIInt size;
895 PetscViewerFormat format;
896
897 PetscFunctionBegin;
898 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
899 if (!v) {
900 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);CHKERRQ(ierr);
901 }
902 PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,2);
903 /* Ideally, we would like to have this test on.
904 However, it currently breaks socket viz via GLVis.
905 During DMView(parallel_mesh,glvis_viewer), each
906 process opens a sequential ASCII socket to visualize
907 the local mesh, and PetscObjectView(dm,local_socket)
908 is internally called inside VecView_GLVis, incurring
909 in an error here */
910 /* PetscCheckSameComm(dm,1,v,2); */
911 ierr = PetscViewerCheckWritable(v);CHKERRQ(ierr);
912
913 ierr = PetscViewerGetFormat(v,&format);CHKERRQ(ierr);
914 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);CHKERRQ(ierr);
915 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
916 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);CHKERRQ(ierr);
917 ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
918 if (isbinary) {
919 PetscInt classid = DM_FILE_CLASSID;
920 char type[256];
921
922 ierr = PetscViewerBinaryWrite(v,&classid,1,PETSC_INT);CHKERRQ(ierr);
923 ierr = PetscStrncpy(type,((PetscObject)dm)->type_name,256);CHKERRQ(ierr);
924 ierr = PetscViewerBinaryWrite(v,type,256,PETSC_CHAR);CHKERRQ(ierr);
925 }
926 if (dm->ops->view) {
927 ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr);
928 }
929 PetscFunctionReturn(0);
930 }
931
932 /*@
933 DMCreateGlobalVector - Creates a global vector from a DM object
934
935 Collective on dm
936
937 Input Parameter:
938 . dm - the DM object
939
940 Output Parameter:
941 . vec - the global vector
942
943 Level: beginner
944
945 .seealso DMCreateLocalVector(), DMGetGlobalVector(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
946
947 @*/
DMCreateGlobalVector(DM dm,Vec * vec)948 PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec)
949 {
950 PetscErrorCode ierr;
951
952 PetscFunctionBegin;
953 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
954 PetscValidPointer(vec,2);
955 if (!dm->ops->createglobalvector) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateGlobalVector",((PetscObject)dm)->type_name);
956 ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr);
957 if (PetscDefined(USE_DEBUG)) {
958 DM vdm;
959
960 ierr = VecGetDM(*vec,&vdm);CHKERRQ(ierr);
961 if (!vdm) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"DM type '%s' did not attach the DM to the vector\n",((PetscObject)dm)->type_name);
962 }
963 PetscFunctionReturn(0);
964 }
965
966 /*@
967 DMCreateLocalVector - Creates a local vector from a DM object
968
969 Not Collective
970
971 Input Parameter:
972 . dm - the DM object
973
974 Output Parameter:
975 . vec - the local vector
976
977 Level: beginner
978
979 .seealso DMCreateGlobalVector(), DMGetLocalVector(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
980
981 @*/
DMCreateLocalVector(DM dm,Vec * vec)982 PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec)
983 {
984 PetscErrorCode ierr;
985
986 PetscFunctionBegin;
987 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
988 PetscValidPointer(vec,2);
989 if (!dm->ops->createlocalvector) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateLocalVector",((PetscObject)dm)->type_name);
990 ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr);
991 if (PetscDefined(USE_DEBUG)) {
992 DM vdm;
993
994 ierr = VecGetDM(*vec,&vdm);CHKERRQ(ierr);
995 if (!vdm) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"DM type '%s' did not attach the DM to the vector\n",((PetscObject)dm)->type_name);
996 }
997 PetscFunctionReturn(0);
998 }
999
1000 /*@
1001 DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM.
1002
1003 Collective on dm
1004
1005 Input Parameter:
1006 . dm - the DM that provides the mapping
1007
1008 Output Parameter:
1009 . ltog - the mapping
1010
1011 Level: intermediate
1012
1013 Notes:
1014 This mapping can then be used by VecSetLocalToGlobalMapping() or
1015 MatSetLocalToGlobalMapping().
1016
1017 .seealso: DMCreateLocalVector()
1018 @*/
DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping * ltog)1019 PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog)
1020 {
1021 PetscInt bs = -1, bsLocal[2], bsMinMax[2];
1022 PetscErrorCode ierr;
1023
1024 PetscFunctionBegin;
1025 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1026 PetscValidPointer(ltog,2);
1027 if (!dm->ltogmap) {
1028 PetscSection section, sectionGlobal;
1029
1030 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);
1031 if (section) {
1032 const PetscInt *cdofs;
1033 PetscInt *ltog;
1034 PetscInt pStart, pEnd, n, p, k, l;
1035
1036 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr);
1037 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
1038 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr);
1039 ierr = PetscMalloc1(n, <og);CHKERRQ(ierr); /* We want the local+overlap size */
1040 for (p = pStart, l = 0; p < pEnd; ++p) {
1041 PetscInt bdof, cdof, dof, off, c, cind = 0;
1042
1043 /* Should probably use constrained dofs */
1044 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
1045 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
1046 ierr = PetscSectionGetConstraintIndices(section, p, &cdofs);CHKERRQ(ierr);
1047 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr);
1048 /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */
1049 bdof = cdof && (dof-cdof) ? 1 : dof;
1050 if (dof) {
1051 if (bs < 0) {bs = bdof;}
1052 else if (bs != bdof) {bs = 1;}
1053 }
1054 for (c = 0; c < dof; ++c, ++l) {
1055 if ((cind < cdof) && (c == cdofs[cind])) ltog[l] = off < 0 ? off-c : off+c;
1056 else ltog[l] = (off < 0 ? -(off+1) : off) + c;
1057 }
1058 }
1059 /* Must have same blocksize on all procs (some might have no points) */
1060 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
1061 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr);
1062 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
1063 else {bs = bsMinMax[0];}
1064 bs = bs < 0 ? 1 : bs;
1065 /* Must reduce indices by blocksize */
1066 if (bs > 1) {
1067 for (l = 0, k = 0; l < n; l += bs, ++k) ltog[k] = ltog[l]/bs;
1068 n /= bs;
1069 }
1070 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr);
1071 ierr = PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);CHKERRQ(ierr);
1072 } else {
1073 if (!dm->ops->getlocaltoglobalmapping) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetLocalToGlobalMapping",((PetscObject)dm)->type_name);
1074 ierr = (*dm->ops->getlocaltoglobalmapping)(dm);CHKERRQ(ierr);
1075 }
1076 }
1077 *ltog = dm->ltogmap;
1078 PetscFunctionReturn(0);
1079 }
1080
1081 /*@
1082 DMGetBlockSize - Gets the inherent block size associated with a DM
1083
1084 Not Collective
1085
1086 Input Parameter:
1087 . dm - the DM with block structure
1088
1089 Output Parameter:
1090 . bs - the block size, 1 implies no exploitable block structure
1091
1092 Level: intermediate
1093
1094 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping()
1095 @*/
DMGetBlockSize(DM dm,PetscInt * bs)1096 PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs)
1097 {
1098 PetscFunctionBegin;
1099 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1100 PetscValidIntPointer(bs,2);
1101 if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet");
1102 *bs = dm->bs;
1103 PetscFunctionReturn(0);
1104 }
1105
1106 /*@
1107 DMCreateInterpolation - Gets interpolation matrix between two DM objects
1108
1109 Collective on dmc
1110
1111 Input Parameter:
1112 + dmc - the DM object
1113 - dmf - the second, finer DM object
1114
1115 Output Parameter:
1116 + mat - the interpolation
1117 - vec - the scaling (optional)
1118
1119 Level: developer
1120
1121 Notes:
1122 For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1123 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.
1124
1125 For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors
1126 EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
1127
1128
1129 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction(), DMCreateInterpolationScale()
1130
1131 @*/
DMCreateInterpolation(DM dmc,DM dmf,Mat * mat,Vec * vec)1132 PetscErrorCode DMCreateInterpolation(DM dmc,DM dmf,Mat *mat,Vec *vec)
1133 {
1134 PetscErrorCode ierr;
1135
1136 PetscFunctionBegin;
1137 PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
1138 PetscValidHeaderSpecific(dmf,DM_CLASSID,2);
1139 PetscValidPointer(mat,3);
1140 if (!dmc->ops->createinterpolation) SETERRQ1(PetscObjectComm((PetscObject)dmc),PETSC_ERR_SUP,"DM type %s does not implement DMCreateInterpolation",((PetscObject)dmc)->type_name);
1141 ierr = PetscLogEventBegin(DM_CreateInterpolation,dmc,dmf,0,0);CHKERRQ(ierr);
1142 ierr = (*dmc->ops->createinterpolation)(dmc,dmf,mat,vec);CHKERRQ(ierr);
1143 ierr = PetscLogEventEnd(DM_CreateInterpolation,dmc,dmf,0,0);CHKERRQ(ierr);
1144 PetscFunctionReturn(0);
1145 }
1146
1147 /*@
1148 DMCreateInterpolationScale - Forms L = 1/(R*1) such that diag(L)*R preserves scale and is thus suitable for state (versus residual) restriction.
1149
1150 Input Parameters:
1151 + dac - DM that defines a coarse mesh
1152 . daf - DM that defines a fine mesh
1153 - mat - the restriction (or interpolation operator) from fine to coarse
1154
1155 Output Parameter:
1156 . scale - the scaled vector
1157
1158 Level: developer
1159
1160 .seealso: DMCreateInterpolation()
1161
1162 @*/
DMCreateInterpolationScale(DM dac,DM daf,Mat mat,Vec * scale)1163 PetscErrorCode DMCreateInterpolationScale(DM dac,DM daf,Mat mat,Vec *scale)
1164 {
1165 PetscErrorCode ierr;
1166 Vec fine;
1167 PetscScalar one = 1.0;
1168
1169 PetscFunctionBegin;
1170 ierr = DMCreateGlobalVector(daf,&fine);CHKERRQ(ierr);
1171 ierr = DMCreateGlobalVector(dac,scale);CHKERRQ(ierr);
1172 ierr = VecSet(fine,one);CHKERRQ(ierr);
1173 ierr = MatRestrict(mat,fine,*scale);CHKERRQ(ierr);
1174 ierr = VecDestroy(&fine);CHKERRQ(ierr);
1175 ierr = VecReciprocal(*scale);CHKERRQ(ierr);
1176 PetscFunctionReturn(0);
1177 }
1178
1179 /*@
1180 DMCreateRestriction - Gets restriction matrix between two DM objects
1181
1182 Collective on dmc
1183
1184 Input Parameter:
1185 + dmc - the DM object
1186 - dmf - the second, finer DM object
1187
1188 Output Parameter:
1189 . mat - the restriction
1190
1191
1192 Level: developer
1193
1194 Notes:
1195 For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1196 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.
1197
1198
1199 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateInterpolation()
1200
1201 @*/
DMCreateRestriction(DM dmc,DM dmf,Mat * mat)1202 PetscErrorCode DMCreateRestriction(DM dmc,DM dmf,Mat *mat)
1203 {
1204 PetscErrorCode ierr;
1205
1206 PetscFunctionBegin;
1207 PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
1208 PetscValidHeaderSpecific(dmf,DM_CLASSID,2);
1209 PetscValidPointer(mat,3);
1210 if (!dmc->ops->createrestriction) SETERRQ1(PetscObjectComm((PetscObject)dmc),PETSC_ERR_SUP,"DM type %s does not implement DMCreateRestriction",((PetscObject)dmc)->type_name);
1211 ierr = PetscLogEventBegin(DM_CreateRestriction,dmc,dmf,0,0);CHKERRQ(ierr);
1212 ierr = (*dmc->ops->createrestriction)(dmc,dmf,mat);CHKERRQ(ierr);
1213 ierr = PetscLogEventEnd(DM_CreateRestriction,dmc,dmf,0,0);CHKERRQ(ierr);
1214 PetscFunctionReturn(0);
1215 }
1216
1217 /*@
1218 DMCreateInjection - Gets injection matrix between two DM objects
1219
1220 Collective on dac
1221
1222 Input Parameter:
1223 + dac - the DM object
1224 - daf - the second, finer DM object
1225
1226 Output Parameter:
1227 . mat - the injection
1228
1229 Level: developer
1230
1231 Notes:
1232 For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1233 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection.
1234
1235 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation()
1236
1237 @*/
DMCreateInjection(DM dac,DM daf,Mat * mat)1238 PetscErrorCode DMCreateInjection(DM dac,DM daf,Mat *mat)
1239 {
1240 PetscErrorCode ierr;
1241
1242 PetscFunctionBegin;
1243 PetscValidHeaderSpecific(dac,DM_CLASSID,1);
1244 PetscValidHeaderSpecific(daf,DM_CLASSID,2);
1245 PetscValidPointer(mat,3);
1246 if (!dac->ops->createinjection) SETERRQ1(PetscObjectComm((PetscObject)dac),PETSC_ERR_SUP,"DM type %s does not implement DMCreateInjection",((PetscObject)dac)->type_name);
1247 ierr = PetscLogEventBegin(DM_CreateInjection,dac,daf,0,0);CHKERRQ(ierr);
1248 ierr = (*dac->ops->createinjection)(dac,daf,mat);CHKERRQ(ierr);
1249 ierr = PetscLogEventEnd(DM_CreateInjection,dac,daf,0,0);CHKERRQ(ierr);
1250 PetscFunctionReturn(0);
1251 }
1252
1253 /*@
1254 DMCreateMassMatrix - Gets mass matrix between two DM objects, M_ij = \int \phi_i \psi_j
1255
1256 Collective on dac
1257
1258 Input Parameter:
1259 + dac - the DM object
1260 - daf - the second, finer DM object
1261
1262 Output Parameter:
1263 . mat - the interpolation
1264
1265 Level: developer
1266
1267 .seealso DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction(), DMCreateInterpolation(), DMCreateInjection()
1268 @*/
DMCreateMassMatrix(DM dac,DM daf,Mat * mat)1269 PetscErrorCode DMCreateMassMatrix(DM dac, DM daf, Mat *mat)
1270 {
1271 PetscErrorCode ierr;
1272
1273 PetscFunctionBegin;
1274 PetscValidHeaderSpecific(dac, DM_CLASSID, 1);
1275 PetscValidHeaderSpecific(daf, DM_CLASSID, 2);
1276 PetscValidPointer(mat,3);
1277 if (!dac->ops->createmassmatrix) SETERRQ1(PetscObjectComm((PetscObject)dac),PETSC_ERR_SUP,"DM type %s does not implement DMCreateMassMatrix",((PetscObject)dac)->type_name);
1278 ierr = (*dac->ops->createmassmatrix)(dac, daf, mat);CHKERRQ(ierr);
1279 PetscFunctionReturn(0);
1280 }
1281
1282 /*@
1283 DMCreateColoring - Gets coloring for a DM
1284
1285 Collective on dm
1286
1287 Input Parameter:
1288 + dm - the DM object
1289 - ctype - IS_COLORING_LOCAL or IS_COLORING_GLOBAL
1290
1291 Output Parameter:
1292 . coloring - the coloring
1293
1294 Notes:
1295 Coloring of matrices can be computed directly from the sparse matrix nonzero structure via the MatColoring object or from the mesh from which the
1296 matrix comes from. In general using the mesh produces a more optimal coloring (fewer colors).
1297
1298 This produces a coloring with the distance of 2, see MatSetColoringDistance() which can be used for efficiently computing Jacobians with MatFDColoringCreate()
1299
1300 Level: developer
1301
1302 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType(), MatColoring, MatFDColoringCreate()
1303
1304 @*/
DMCreateColoring(DM dm,ISColoringType ctype,ISColoring * coloring)1305 PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring)
1306 {
1307 PetscErrorCode ierr;
1308
1309 PetscFunctionBegin;
1310 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1311 PetscValidPointer(coloring,3);
1312 if (!dm->ops->getcoloring) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateColoring",((PetscObject)dm)->type_name);
1313 ierr = (*dm->ops->getcoloring)(dm,ctype,coloring);CHKERRQ(ierr);
1314 PetscFunctionReturn(0);
1315 }
1316
1317 /*@
1318 DMCreateMatrix - Gets empty Jacobian for a DM
1319
1320 Collective on dm
1321
1322 Input Parameter:
1323 . dm - the DM object
1324
1325 Output Parameter:
1326 . mat - the empty Jacobian
1327
1328 Level: beginner
1329
1330 Notes:
1331 This properly preallocates the number of nonzeros in the sparse matrix so you
1332 do not need to do it yourself.
1333
1334 By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
1335 the nonzero pattern call DMSetMatrixPreallocateOnly()
1336
1337 For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used
1338 internally by PETSc.
1339
1340 For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires
1341 the indices for the global numbering for DMDAs which is complicated.
1342
1343 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType()
1344
1345 @*/
DMCreateMatrix(DM dm,Mat * mat)1346 PetscErrorCode DMCreateMatrix(DM dm,Mat *mat)
1347 {
1348 PetscErrorCode ierr;
1349
1350 PetscFunctionBegin;
1351 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1352 PetscValidPointer(mat,3);
1353 if (!dm->ops->creatematrix) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateMatrix",((PetscObject)dm)->type_name);
1354 ierr = MatInitializePackage();CHKERRQ(ierr);
1355 ierr = PetscLogEventBegin(DM_CreateMatrix,0,0,0,0);CHKERRQ(ierr);
1356 ierr = (*dm->ops->creatematrix)(dm,mat);CHKERRQ(ierr);
1357 if (PetscDefined(USE_DEBUG)) {
1358 DM mdm;
1359
1360 ierr = MatGetDM(*mat,&mdm);CHKERRQ(ierr);
1361 if (!mdm) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"DM type '%s' did not attach the DM to the matrix\n",((PetscObject)dm)->type_name);
1362 }
1363 /* Handle nullspace and near nullspace */
1364 if (dm->Nf) {
1365 MatNullSpace nullSpace;
1366 PetscInt Nf;
1367
1368 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
1369 if (Nf == 1) {
1370 if (dm->nullspaceConstructors[0]) {
1371 ierr = (*dm->nullspaceConstructors[0])(dm, 0, 0, &nullSpace);CHKERRQ(ierr);
1372 ierr = MatSetNullSpace(*mat, nullSpace);CHKERRQ(ierr);
1373 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr);
1374 }
1375 if (dm->nearnullspaceConstructors[0]) {
1376 ierr = (*dm->nearnullspaceConstructors[0])(dm, 0, 0, &nullSpace);CHKERRQ(ierr);
1377 ierr = MatSetNearNullSpace(*mat, nullSpace);CHKERRQ(ierr);
1378 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr);
1379 }
1380 }
1381 }
1382 ierr = PetscLogEventEnd(DM_CreateMatrix,0,0,0,0);CHKERRQ(ierr);
1383 PetscFunctionReturn(0);
1384 }
1385
1386 /*@
1387 DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly
1388 preallocated but the nonzero structure and zero values will not be set.
1389
1390 Logically Collective on dm
1391
1392 Input Parameter:
1393 + dm - the DM
1394 - only - PETSC_TRUE if only want preallocation
1395
1396 Level: developer
1397 .seealso DMCreateMatrix(), DMSetMatrixStructureOnly()
1398 @*/
DMSetMatrixPreallocateOnly(DM dm,PetscBool only)1399 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
1400 {
1401 PetscFunctionBegin;
1402 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1403 dm->prealloc_only = only;
1404 PetscFunctionReturn(0);
1405 }
1406
1407 /*@
1408 DMSetMatrixStructureOnly - When DMCreateMatrix() is called, the matrix structure will be created
1409 but the array for values will not be allocated.
1410
1411 Logically Collective on dm
1412
1413 Input Parameter:
1414 + dm - the DM
1415 - only - PETSC_TRUE if only want matrix stucture
1416
1417 Level: developer
1418 .seealso DMCreateMatrix(), DMSetMatrixPreallocateOnly()
1419 @*/
DMSetMatrixStructureOnly(DM dm,PetscBool only)1420 PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only)
1421 {
1422 PetscFunctionBegin;
1423 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1424 dm->structure_only = only;
1425 PetscFunctionReturn(0);
1426 }
1427
1428 /*@C
1429 DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1430
1431 Not Collective
1432
1433 Input Parameters:
1434 + dm - the DM object
1435 . count - The minium size
1436 - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT)
1437
1438 Output Parameter:
1439 . array - the work array
1440
1441 Level: developer
1442
1443 .seealso DMDestroy(), DMCreate()
1444 @*/
DMGetWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void * mem)1445 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem)
1446 {
1447 PetscErrorCode ierr;
1448 DMWorkLink link;
1449 PetscMPIInt dsize;
1450
1451 PetscFunctionBegin;
1452 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1453 PetscValidPointer(mem,4);
1454 if (dm->workin) {
1455 link = dm->workin;
1456 dm->workin = dm->workin->next;
1457 } else {
1458 ierr = PetscNewLog(dm,&link);CHKERRQ(ierr);
1459 }
1460 ierr = MPI_Type_size(dtype,&dsize);CHKERRQ(ierr);
1461 if (((size_t)dsize*count) > link->bytes) {
1462 ierr = PetscFree(link->mem);CHKERRQ(ierr);
1463 ierr = PetscMalloc(dsize*count,&link->mem);CHKERRQ(ierr);
1464 link->bytes = dsize*count;
1465 }
1466 link->next = dm->workout;
1467 dm->workout = link;
1468 #if defined(PETSC_HAVE_VALGRIND)
1469 VALGRIND_MAKE_MEM_NOACCESS((char*)link->mem + (size_t)dsize*count, link->bytes - (size_t)dsize*count);
1470 VALGRIND_MAKE_MEM_UNDEFINED(link->mem, (size_t)dsize*count);
1471 #endif
1472 *(void**)mem = link->mem;
1473 PetscFunctionReturn(0);
1474 }
1475
1476 /*@C
1477 DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1478
1479 Not Collective
1480
1481 Input Parameters:
1482 + dm - the DM object
1483 . count - The minium size
1484 - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT
1485
1486 Output Parameter:
1487 . array - the work array
1488
1489 Level: developer
1490
1491 Developer Notes:
1492 count and dtype are ignored, they are only needed for DMGetWorkArray()
1493 .seealso DMDestroy(), DMCreate()
1494 @*/
DMRestoreWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void * mem)1495 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem)
1496 {
1497 DMWorkLink *p,link;
1498
1499 PetscFunctionBegin;
1500 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1501 PetscValidPointer(mem,4);
1502 for (p=&dm->workout; (link=*p); p=&link->next) {
1503 if (link->mem == *(void**)mem) {
1504 *p = link->next;
1505 link->next = dm->workin;
1506 dm->workin = link;
1507 *(void**)mem = NULL;
1508 PetscFunctionReturn(0);
1509 }
1510 }
1511 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out");
1512 }
1513
1514 /*@C
1515 DMSetNullSpaceConstructor - Provide a callback function which constructs the nullspace for a given field
1516
1517 Logically collective on DM
1518
1519 Input Parameters:
1520 + dm - The DM
1521 . field - The field number for the nullspace
1522 - nullsp - A callback to create the nullspace
1523
1524 Notes:
1525 The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is
1526 $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1527 $ dm - The present DM
1528 $ origField - The field number given above, in the original DM
1529 $ field - The field number in dm
1530 $ nullSpace - The nullspace for the given field
1531
1532 This function is currently not available from Fortran.
1533
1534 .seealso: DMGetNullSpaceConstructor(), DMSetNearNullSpaceConstructor(), DMGetNearNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM()
1535 */
DMSetNullSpaceConstructor(DM dm,PetscInt field,PetscErrorCode (* nullsp)(DM dm,PetscInt origField,PetscInt field,MatNullSpace * nullSpace))1536 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1537 {
1538 PetscFunctionBegin;
1539 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1540 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1541 dm->nullspaceConstructors[field] = nullsp;
1542 PetscFunctionReturn(0);
1543 }
1544
1545 /*@C
1546 DMGetNullSpaceConstructor - Return the callback function which constructs the nullspace for a given field, or NULL
1547
1548 Not collective
1549
1550 Input Parameters:
1551 + dm - The DM
1552 - field - The field number for the nullspace
1553
1554 Output Parameter:
1555 . nullsp - A callback to create the nullspace
1556
1557 Notes:
1558 The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is
1559 $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1560 $ dm - The present DM
1561 $ origField - The field number given above, in the original DM
1562 $ field - The field number in dm
1563 $ nullSpace - The nullspace for the given field
1564
1565 This function is currently not available from Fortran.
1566
1567 .seealso: DMSetNullSpaceConstructor(), DMSetNearNullSpaceConstructor(), DMGetNearNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM()
1568 */
DMGetNullSpaceConstructor(DM dm,PetscInt field,PetscErrorCode (** nullsp)(DM dm,PetscInt origField,PetscInt field,MatNullSpace * nullSpace))1569 PetscErrorCode DMGetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1570 {
1571 PetscFunctionBegin;
1572 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1573 PetscValidPointer(nullsp, 3);
1574 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1575 *nullsp = dm->nullspaceConstructors[field];
1576 PetscFunctionReturn(0);
1577 }
1578
1579 /*@C
1580 DMSetNearNullSpaceConstructor - Provide a callback function which constructs the near-nullspace for a given field
1581
1582 Logically collective on DM
1583
1584 Input Parameters:
1585 + dm - The DM
1586 . field - The field number for the nullspace
1587 - nullsp - A callback to create the near-nullspace
1588
1589 Notes:
1590 The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is
1591 $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1592 $ dm - The present DM
1593 $ origField - The field number given above, in the original DM
1594 $ field - The field number in dm
1595 $ nullSpace - The nullspace for the given field
1596
1597 This function is currently not available from Fortran.
1598
1599 .seealso: DMGetNearNullSpaceConstructor(), DMSetNullSpaceConstructor(), DMGetNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM()
1600 */
DMSetNearNullSpaceConstructor(DM dm,PetscInt field,PetscErrorCode (* nullsp)(DM dm,PetscInt origField,PetscInt field,MatNullSpace * nullSpace))1601 PetscErrorCode DMSetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1602 {
1603 PetscFunctionBegin;
1604 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1605 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1606 dm->nearnullspaceConstructors[field] = nullsp;
1607 PetscFunctionReturn(0);
1608 }
1609
1610 /*@C
1611 DMGetNearNullSpaceConstructor - Return the callback function which constructs the near-nullspace for a given field, or NULL
1612
1613 Not collective
1614
1615 Input Parameters:
1616 + dm - The DM
1617 - field - The field number for the nullspace
1618
1619 Output Parameter:
1620 . nullsp - A callback to create the near-nullspace
1621
1622 Notes:
1623 The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is
1624 $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1625 $ dm - The present DM
1626 $ origField - The field number given above, in the original DM
1627 $ field - The field number in dm
1628 $ nullSpace - The nullspace for the given field
1629
1630 This function is currently not available from Fortran.
1631
1632 .seealso: DMSetNearNullSpaceConstructor(), DMSetNullSpaceConstructor(), DMGetNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM()
1633 */
DMGetNearNullSpaceConstructor(DM dm,PetscInt field,PetscErrorCode (** nullsp)(DM dm,PetscInt origField,PetscInt field,MatNullSpace * nullSpace))1634 PetscErrorCode DMGetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1635 {
1636 PetscFunctionBegin;
1637 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1638 PetscValidPointer(nullsp, 3);
1639 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1640 *nullsp = dm->nearnullspaceConstructors[field];
1641 PetscFunctionReturn(0);
1642 }
1643
1644 /*@C
1645 DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field
1646
1647 Not collective
1648
1649 Input Parameter:
1650 . dm - the DM object
1651
1652 Output Parameters:
1653 + numFields - The number of fields (or NULL if not requested)
1654 . fieldNames - The name for each field (or NULL if not requested)
1655 - fields - The global indices for each field (or NULL if not requested)
1656
1657 Level: intermediate
1658
1659 Notes:
1660 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1661 PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with
1662 PetscFree().
1663
1664 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
1665 @*/
DMCreateFieldIS(DM dm,PetscInt * numFields,char *** fieldNames,IS ** fields)1666 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1667 {
1668 PetscSection section, sectionGlobal;
1669 PetscErrorCode ierr;
1670
1671 PetscFunctionBegin;
1672 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1673 if (numFields) {
1674 PetscValidIntPointer(numFields,2);
1675 *numFields = 0;
1676 }
1677 if (fieldNames) {
1678 PetscValidPointer(fieldNames,3);
1679 *fieldNames = NULL;
1680 }
1681 if (fields) {
1682 PetscValidPointer(fields,4);
1683 *fields = NULL;
1684 }
1685 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);
1686 if (section) {
1687 PetscInt *fieldSizes, *fieldNc, **fieldIndices;
1688 PetscInt nF, f, pStart, pEnd, p;
1689
1690 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr);
1691 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr);
1692 ierr = PetscMalloc3(nF,&fieldSizes,nF,&fieldNc,nF,&fieldIndices);CHKERRQ(ierr);
1693 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr);
1694 for (f = 0; f < nF; ++f) {
1695 fieldSizes[f] = 0;
1696 ierr = PetscSectionGetFieldComponents(section, f, &fieldNc[f]);CHKERRQ(ierr);
1697 }
1698 for (p = pStart; p < pEnd; ++p) {
1699 PetscInt gdof;
1700
1701 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr);
1702 if (gdof > 0) {
1703 for (f = 0; f < nF; ++f) {
1704 PetscInt fdof, fcdof, fpdof;
1705
1706 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
1707 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
1708 fpdof = fdof-fcdof;
1709 if (fpdof && fpdof != fieldNc[f]) {
1710 /* Layout does not admit a pointwise block size */
1711 fieldNc[f] = 1;
1712 }
1713 fieldSizes[f] += fpdof;
1714 }
1715 }
1716 }
1717 for (f = 0; f < nF; ++f) {
1718 ierr = PetscMalloc1(fieldSizes[f], &fieldIndices[f]);CHKERRQ(ierr);
1719 fieldSizes[f] = 0;
1720 }
1721 for (p = pStart; p < pEnd; ++p) {
1722 PetscInt gdof, goff;
1723
1724 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr);
1725 if (gdof > 0) {
1726 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr);
1727 for (f = 0; f < nF; ++f) {
1728 PetscInt fdof, fcdof, fc;
1729
1730 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
1731 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
1732 for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) {
1733 fieldIndices[f][fieldSizes[f]] = goff++;
1734 }
1735 }
1736 }
1737 }
1738 if (numFields) *numFields = nF;
1739 if (fieldNames) {
1740 ierr = PetscMalloc1(nF, fieldNames);CHKERRQ(ierr);
1741 for (f = 0; f < nF; ++f) {
1742 const char *fieldName;
1743
1744 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr);
1745 ierr = PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);CHKERRQ(ierr);
1746 }
1747 }
1748 if (fields) {
1749 ierr = PetscMalloc1(nF, fields);CHKERRQ(ierr);
1750 for (f = 0; f < nF; ++f) {
1751 PetscInt bs, in[2], out[2];
1752
1753 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr);
1754 in[0] = -fieldNc[f];
1755 in[1] = fieldNc[f];
1756 ierr = MPIU_Allreduce(in, out, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
1757 bs = (-out[0] == out[1]) ? out[1] : 1;
1758 ierr = ISSetBlockSize((*fields)[f], bs);CHKERRQ(ierr);
1759 }
1760 }
1761 ierr = PetscFree3(fieldSizes,fieldNc,fieldIndices);CHKERRQ(ierr);
1762 } else if (dm->ops->createfieldis) {
1763 ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr);
1764 }
1765 PetscFunctionReturn(0);
1766 }
1767
1768
1769 /*@C
1770 DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems
1771 corresponding to different fields: each IS contains the global indices of the dofs of the
1772 corresponding field. The optional list of DMs define the DM for each subproblem.
1773 Generalizes DMCreateFieldIS().
1774
1775 Not collective
1776
1777 Input Parameter:
1778 . dm - the DM object
1779
1780 Output Parameters:
1781 + len - The number of subproblems in the field decomposition (or NULL if not requested)
1782 . namelist - The name for each field (or NULL if not requested)
1783 . islist - The global indices for each field (or NULL if not requested)
1784 - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1785
1786 Level: intermediate
1787
1788 Notes:
1789 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1790 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1791 and all of the arrays should be freed with PetscFree().
1792
1793 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1794 @*/
DMCreateFieldDecomposition(DM dm,PetscInt * len,char *** namelist,IS ** islist,DM ** dmlist)1795 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
1796 {
1797 PetscErrorCode ierr;
1798
1799 PetscFunctionBegin;
1800 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1801 if (len) {
1802 PetscValidIntPointer(len,2);
1803 *len = 0;
1804 }
1805 if (namelist) {
1806 PetscValidPointer(namelist,3);
1807 *namelist = NULL;
1808 }
1809 if (islist) {
1810 PetscValidPointer(islist,4);
1811 *islist = NULL;
1812 }
1813 if (dmlist) {
1814 PetscValidPointer(dmlist,5);
1815 *dmlist = NULL;
1816 }
1817 /*
1818 Is it a good idea to apply the following check across all impls?
1819 Perhaps some impls can have a well-defined decomposition before DMSetUp?
1820 This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1821 */
1822 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1823 if (!dm->ops->createfielddecomposition) {
1824 PetscSection section;
1825 PetscInt numFields, f;
1826
1827 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);
1828 if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);}
1829 if (section && numFields && dm->ops->createsubdm) {
1830 if (len) *len = numFields;
1831 if (namelist) {ierr = PetscMalloc1(numFields,namelist);CHKERRQ(ierr);}
1832 if (islist) {ierr = PetscMalloc1(numFields,islist);CHKERRQ(ierr);}
1833 if (dmlist) {ierr = PetscMalloc1(numFields,dmlist);CHKERRQ(ierr);}
1834 for (f = 0; f < numFields; ++f) {
1835 const char *fieldName;
1836
1837 ierr = DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);CHKERRQ(ierr);
1838 if (namelist) {
1839 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr);
1840 ierr = PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);CHKERRQ(ierr);
1841 }
1842 }
1843 } else {
1844 ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr);
1845 /* By default there are no DMs associated with subproblems. */
1846 if (dmlist) *dmlist = NULL;
1847 }
1848 } else {
1849 ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);CHKERRQ(ierr);
1850 }
1851 PetscFunctionReturn(0);
1852 }
1853
1854 /*@
1855 DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in.
1856 The fields are defined by DMCreateFieldIS().
1857
1858 Not collective
1859
1860 Input Parameters:
1861 + dm - The DM object
1862 . numFields - The number of fields in this subproblem
1863 - fields - The field numbers of the selected fields
1864
1865 Output Parameters:
1866 + is - The global indices for the subproblem
1867 - subdm - The DM for the subproblem
1868
1869 Note: You need to call DMPlexSetMigrationSF() on the original DM if you want the Global-To-Natural map to be automatically constructed
1870
1871 Level: intermediate
1872
1873 .seealso DMPlexSetMigrationSF(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1874 @*/
DMCreateSubDM(DM dm,PetscInt numFields,const PetscInt fields[],IS * is,DM * subdm)1875 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
1876 {
1877 PetscErrorCode ierr;
1878
1879 PetscFunctionBegin;
1880 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1881 PetscValidPointer(fields,3);
1882 if (is) PetscValidPointer(is,4);
1883 if (subdm) PetscValidPointer(subdm,5);
1884 if (!dm->ops->createsubdm) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateSubDM",((PetscObject)dm)->type_name);
1885 ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);CHKERRQ(ierr);
1886 PetscFunctionReturn(0);
1887 }
1888
1889 /*@C
1890 DMCreateSuperDM - Returns an arrays of ISes and DM encapsulating a superproblem defined by the DMs passed in.
1891
1892 Not collective
1893
1894 Input Parameter:
1895 + dms - The DM objects
1896 - len - The number of DMs
1897
1898 Output Parameters:
1899 + is - The global indices for the subproblem, or NULL
1900 - superdm - The DM for the superproblem
1901
1902 Note: You need to call DMPlexSetMigrationSF() on the original DM if you want the Global-To-Natural map to be automatically constructed
1903
1904 Level: intermediate
1905
1906 .seealso DMPlexSetMigrationSF(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1907 @*/
DMCreateSuperDM(DM dms[],PetscInt len,IS ** is,DM * superdm)1908 PetscErrorCode DMCreateSuperDM(DM dms[], PetscInt len, IS **is, DM *superdm)
1909 {
1910 PetscInt i;
1911 PetscErrorCode ierr;
1912
1913 PetscFunctionBegin;
1914 PetscValidPointer(dms,1);
1915 for (i = 0; i < len; ++i) {PetscValidHeaderSpecific(dms[i],DM_CLASSID,1);}
1916 if (is) PetscValidPointer(is,3);
1917 PetscValidPointer(superdm,4);
1918 if (len < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of DMs must be nonnegative: %D", len);
1919 if (len) {
1920 DM dm = dms[0];
1921 if (!dm->ops->createsuperdm) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateSuperDM",((PetscObject)dm)->type_name);
1922 ierr = (*dm->ops->createsuperdm)(dms, len, is, superdm);CHKERRQ(ierr);
1923 }
1924 PetscFunctionReturn(0);
1925 }
1926
1927
1928 /*@C
1929 DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems
1930 corresponding to restrictions to pairs nested subdomains: each IS contains the global
1931 indices of the dofs of the corresponding subdomains. The inner subdomains conceptually
1932 define a nonoverlapping covering, while outer subdomains can overlap.
1933 The optional list of DMs define the DM for each subproblem.
1934
1935 Not collective
1936
1937 Input Parameter:
1938 . dm - the DM object
1939
1940 Output Parameters:
1941 + len - The number of subproblems in the domain decomposition (or NULL if not requested)
1942 . namelist - The name for each subdomain (or NULL if not requested)
1943 . innerislist - The global indices for each inner subdomain (or NULL, if not requested)
1944 . outerislist - The global indices for each outer subdomain (or NULL, if not requested)
1945 - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1946
1947 Level: intermediate
1948
1949 Notes:
1950 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1951 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1952 and all of the arrays should be freed with PetscFree().
1953
1954 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldDecomposition()
1955 @*/
DMCreateDomainDecomposition(DM dm,PetscInt * len,char *** namelist,IS ** innerislist,IS ** outerislist,DM ** dmlist)1956 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
1957 {
1958 PetscErrorCode ierr;
1959 DMSubDomainHookLink link;
1960 PetscInt i,l;
1961
1962 PetscFunctionBegin;
1963 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1964 if (len) {PetscValidPointer(len,2); *len = 0;}
1965 if (namelist) {PetscValidPointer(namelist,3); *namelist = NULL;}
1966 if (innerislist) {PetscValidPointer(innerislist,4); *innerislist = NULL;}
1967 if (outerislist) {PetscValidPointer(outerislist,5); *outerislist = NULL;}
1968 if (dmlist) {PetscValidPointer(dmlist,6); *dmlist = NULL;}
1969 /*
1970 Is it a good idea to apply the following check across all impls?
1971 Perhaps some impls can have a well-defined decomposition before DMSetUp?
1972 This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1973 */
1974 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1975 if (dm->ops->createdomaindecomposition) {
1976 ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr);
1977 /* copy subdomain hooks and context over to the subdomain DMs */
1978 if (dmlist && *dmlist) {
1979 for (i = 0; i < l; i++) {
1980 for (link=dm->subdomainhook; link; link=link->next) {
1981 if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);}
1982 }
1983 if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx;
1984 }
1985 }
1986 if (len) *len = l;
1987 }
1988 PetscFunctionReturn(0);
1989 }
1990
1991
1992 /*@C
1993 DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector
1994
1995 Not collective
1996
1997 Input Parameters:
1998 + dm - the DM object
1999 . n - the number of subdomain scatters
2000 - subdms - the local subdomains
2001
2002 Output Parameters:
2003 + n - the number of scatters returned
2004 . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
2005 . oscat - scatter from global vector to overlapping global vector entries on subdomain
2006 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)
2007
2008 Notes:
2009 This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution
2010 of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets
2011 of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
2012 solution and residual data.
2013
2014 Level: developer
2015
2016 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
2017 @*/
DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM * subdms,VecScatter ** iscat,VecScatter ** oscat,VecScatter ** gscat)2018 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat)
2019 {
2020 PetscErrorCode ierr;
2021
2022 PetscFunctionBegin;
2023 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2024 PetscValidPointer(subdms,3);
2025 if (!dm->ops->createddscatters) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateDomainDecompositionScatters",((PetscObject)dm)->type_name);
2026 ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr);
2027 PetscFunctionReturn(0);
2028 }
2029
2030 /*@
2031 DMRefine - Refines a DM object
2032
2033 Collective on dm
2034
2035 Input Parameter:
2036 + dm - the DM object
2037 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
2038
2039 Output Parameter:
2040 . dmf - the refined DM, or NULL
2041
2042 Options Dtabase Keys:
2043 . -dm_plex_cell_refiner <strategy> - chooses the refinement strategy, e.g. regular, tohex
2044
2045 Note: If no refinement was done, the return value is NULL
2046
2047 Level: developer
2048
2049 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2050 @*/
DMRefine(DM dm,MPI_Comm comm,DM * dmf)2051 PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf)
2052 {
2053 PetscErrorCode ierr;
2054 DMRefineHookLink link;
2055
2056 PetscFunctionBegin;
2057 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2058 if (!dm->ops->refine) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMRefine",((PetscObject)dm)->type_name);
2059 ierr = PetscLogEventBegin(DM_Refine,dm,0,0,0);CHKERRQ(ierr);
2060 ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr);
2061 if (*dmf) {
2062 (*dmf)->ops->creatematrix = dm->ops->creatematrix;
2063
2064 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr);
2065
2066 (*dmf)->ctx = dm->ctx;
2067 (*dmf)->leveldown = dm->leveldown;
2068 (*dmf)->levelup = dm->levelup + 1;
2069
2070 ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr);
2071 for (link=dm->refinehook; link; link=link->next) {
2072 if (link->refinehook) {
2073 ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr);
2074 }
2075 }
2076 }
2077 ierr = PetscLogEventEnd(DM_Refine,dm,0,0,0);CHKERRQ(ierr);
2078 PetscFunctionReturn(0);
2079 }
2080
2081 /*@C
2082 DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid
2083
2084 Logically Collective
2085
2086 Input Arguments:
2087 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
2088 . refinehook - function to run when setting up a coarser level
2089 . interphook - function to run to update data on finer levels (once per SNESSolve())
2090 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2091
2092 Calling sequence of refinehook:
2093 $ refinehook(DM coarse,DM fine,void *ctx);
2094
2095 + coarse - coarse level DM
2096 . fine - fine level DM to interpolate problem to
2097 - ctx - optional user-defined function context
2098
2099 Calling sequence for interphook:
2100 $ interphook(DM coarse,Mat interp,DM fine,void *ctx)
2101
2102 + coarse - coarse level DM
2103 . interp - matrix interpolating a coarse-level solution to the finer grid
2104 . fine - fine level DM to update
2105 - ctx - optional user-defined function context
2106
2107 Level: advanced
2108
2109 Notes:
2110 This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing
2111
2112 If this function is called multiple times, the hooks will be run in the order they are added.
2113
2114 This function is currently not available from Fortran.
2115
2116 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2117 @*/
DMRefineHookAdd(DM coarse,PetscErrorCode (* refinehook)(DM,DM,void *),PetscErrorCode (* interphook)(DM,Mat,DM,void *),void * ctx)2118 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
2119 {
2120 PetscErrorCode ierr;
2121 DMRefineHookLink link,*p;
2122
2123 PetscFunctionBegin;
2124 PetscValidHeaderSpecific(coarse,DM_CLASSID,1);
2125 for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
2126 if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) PetscFunctionReturn(0);
2127 }
2128 ierr = PetscNew(&link);CHKERRQ(ierr);
2129 link->refinehook = refinehook;
2130 link->interphook = interphook;
2131 link->ctx = ctx;
2132 link->next = NULL;
2133 *p = link;
2134 PetscFunctionReturn(0);
2135 }
2136
2137 /*@C
2138 DMRefineHookRemove - remove a callback from the list of hooks to be run when interpolating a nonlinear problem to a finer grid
2139
2140 Logically Collective
2141
2142 Input Arguments:
2143 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
2144 . refinehook - function to run when setting up a coarser level
2145 . interphook - function to run to update data on finer levels (once per SNESSolve())
2146 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2147
2148 Level: advanced
2149
2150 Notes:
2151 This function does nothing if the hook is not in the list.
2152
2153 This function is currently not available from Fortran.
2154
2155 .seealso: DMCoarsenHookRemove(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2156 @*/
DMRefineHookRemove(DM coarse,PetscErrorCode (* refinehook)(DM,DM,void *),PetscErrorCode (* interphook)(DM,Mat,DM,void *),void * ctx)2157 PetscErrorCode DMRefineHookRemove(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
2158 {
2159 PetscErrorCode ierr;
2160 DMRefineHookLink link,*p;
2161
2162 PetscFunctionBegin;
2163 PetscValidHeaderSpecific(coarse,DM_CLASSID,1);
2164 for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Search the list of current hooks */
2165 if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) {
2166 link = *p;
2167 *p = link->next;
2168 ierr = PetscFree(link);CHKERRQ(ierr);
2169 break;
2170 }
2171 }
2172 PetscFunctionReturn(0);
2173 }
2174
2175 /*@
2176 DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd()
2177
2178 Collective if any hooks are
2179
2180 Input Arguments:
2181 + coarse - coarser DM to use as a base
2182 . interp - interpolation matrix, apply using MatInterpolate()
2183 - fine - finer DM to update
2184
2185 Level: developer
2186
2187 .seealso: DMRefineHookAdd(), MatInterpolate()
2188 @*/
DMInterpolate(DM coarse,Mat interp,DM fine)2189 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine)
2190 {
2191 PetscErrorCode ierr;
2192 DMRefineHookLink link;
2193
2194 PetscFunctionBegin;
2195 for (link=fine->refinehook; link; link=link->next) {
2196 if (link->interphook) {
2197 ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr);
2198 }
2199 }
2200 PetscFunctionReturn(0);
2201 }
2202
2203 /*@
2204 DMGetRefineLevel - Gets the number of refinements that have generated this DM.
2205
2206 Not Collective
2207
2208 Input Parameter:
2209 . dm - the DM object
2210
2211 Output Parameter:
2212 . level - number of refinements
2213
2214 Level: developer
2215
2216 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2217
2218 @*/
DMGetRefineLevel(DM dm,PetscInt * level)2219 PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level)
2220 {
2221 PetscFunctionBegin;
2222 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2223 *level = dm->levelup;
2224 PetscFunctionReturn(0);
2225 }
2226
2227 /*@
2228 DMSetRefineLevel - Sets the number of refinements that have generated this DM.
2229
2230 Not Collective
2231
2232 Input Parameter:
2233 + dm - the DM object
2234 - level - number of refinements
2235
2236 Level: advanced
2237
2238 Notes:
2239 This value is used by PCMG to determine how many multigrid levels to use
2240
2241 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2242
2243 @*/
DMSetRefineLevel(DM dm,PetscInt level)2244 PetscErrorCode DMSetRefineLevel(DM dm,PetscInt level)
2245 {
2246 PetscFunctionBegin;
2247 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2248 dm->levelup = level;
2249 PetscFunctionReturn(0);
2250 }
2251
DMGetBasisTransformDM_Internal(DM dm,DM * tdm)2252 PetscErrorCode DMGetBasisTransformDM_Internal(DM dm, DM *tdm)
2253 {
2254 PetscFunctionBegin;
2255 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2256 PetscValidPointer(tdm, 2);
2257 *tdm = dm->transformDM;
2258 PetscFunctionReturn(0);
2259 }
2260
DMGetBasisTransformVec_Internal(DM dm,Vec * tv)2261 PetscErrorCode DMGetBasisTransformVec_Internal(DM dm, Vec *tv)
2262 {
2263 PetscFunctionBegin;
2264 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2265 PetscValidPointer(tv, 2);
2266 *tv = dm->transform;
2267 PetscFunctionReturn(0);
2268 }
2269
2270 /*@
2271 DMHasBasisTransform - Whether we employ a basis transformation from functions in global vectors to functions in local vectors
2272
2273 Input Parameter:
2274 . dm - The DM
2275
2276 Output Parameter:
2277 . flg - PETSC_TRUE if a basis transformation should be done
2278
2279 Level: developer
2280
2281 .seealso: DMPlexGlobalToLocalBasis(), DMPlexLocalToGlobalBasis(), DMPlexCreateBasisRotation()
2282 @*/
DMHasBasisTransform(DM dm,PetscBool * flg)2283 PetscErrorCode DMHasBasisTransform(DM dm, PetscBool *flg)
2284 {
2285 Vec tv;
2286 PetscErrorCode ierr;
2287
2288 PetscFunctionBegin;
2289 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2290 PetscValidBoolPointer(flg, 2);
2291 ierr = DMGetBasisTransformVec_Internal(dm, &tv);CHKERRQ(ierr);
2292 *flg = tv ? PETSC_TRUE : PETSC_FALSE;
2293 PetscFunctionReturn(0);
2294 }
2295
DMConstructBasisTransform_Internal(DM dm)2296 PetscErrorCode DMConstructBasisTransform_Internal(DM dm)
2297 {
2298 PetscSection s, ts;
2299 PetscScalar *ta;
2300 PetscInt cdim, pStart, pEnd, p, Nf, f, Nc, dof;
2301 PetscErrorCode ierr;
2302
2303 PetscFunctionBegin;
2304 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
2305 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr);
2306 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
2307 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr);
2308 ierr = DMClone(dm, &dm->transformDM);CHKERRQ(ierr);
2309 ierr = DMGetLocalSection(dm->transformDM, &ts);CHKERRQ(ierr);
2310 ierr = PetscSectionSetNumFields(ts, Nf);CHKERRQ(ierr);
2311 ierr = PetscSectionSetChart(ts, pStart, pEnd);CHKERRQ(ierr);
2312 for (f = 0; f < Nf; ++f) {
2313 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr);
2314 /* We could start to label fields by their transformation properties */
2315 if (Nc != cdim) continue;
2316 for (p = pStart; p < pEnd; ++p) {
2317 ierr = PetscSectionGetFieldDof(s, p, f, &dof);CHKERRQ(ierr);
2318 if (!dof) continue;
2319 ierr = PetscSectionSetFieldDof(ts, p, f, PetscSqr(cdim));CHKERRQ(ierr);
2320 ierr = PetscSectionAddDof(ts, p, PetscSqr(cdim));CHKERRQ(ierr);
2321 }
2322 }
2323 ierr = PetscSectionSetUp(ts);CHKERRQ(ierr);
2324 ierr = DMCreateLocalVector(dm->transformDM, &dm->transform);CHKERRQ(ierr);
2325 ierr = VecGetArray(dm->transform, &ta);CHKERRQ(ierr);
2326 for (p = pStart; p < pEnd; ++p) {
2327 for (f = 0; f < Nf; ++f) {
2328 ierr = PetscSectionGetFieldDof(ts, p, f, &dof);CHKERRQ(ierr);
2329 if (dof) {
2330 PetscReal x[3] = {0.0, 0.0, 0.0};
2331 PetscScalar *tva;
2332 const PetscScalar *A;
2333
2334 /* TODO Get quadrature point for this dual basis vector for coordinate */
2335 ierr = (*dm->transformGetMatrix)(dm, x, PETSC_TRUE, &A, dm->transformCtx);CHKERRQ(ierr);
2336 ierr = DMPlexPointLocalFieldRef(dm->transformDM, p, f, ta, (void *) &tva);CHKERRQ(ierr);
2337 ierr = PetscArraycpy(tva, A, PetscSqr(cdim));CHKERRQ(ierr);
2338 }
2339 }
2340 }
2341 ierr = VecRestoreArray(dm->transform, &ta);CHKERRQ(ierr);
2342 PetscFunctionReturn(0);
2343 }
2344
DMCopyTransform(DM dm,DM newdm)2345 PetscErrorCode DMCopyTransform(DM dm, DM newdm)
2346 {
2347 PetscErrorCode ierr;
2348
2349 PetscFunctionBegin;
2350 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2351 PetscValidHeaderSpecific(newdm, DM_CLASSID, 2);
2352 newdm->transformCtx = dm->transformCtx;
2353 newdm->transformSetUp = dm->transformSetUp;
2354 newdm->transformDestroy = NULL;
2355 newdm->transformGetMatrix = dm->transformGetMatrix;
2356 if (newdm->transformSetUp) {ierr = DMConstructBasisTransform_Internal(newdm);CHKERRQ(ierr);}
2357 PetscFunctionReturn(0);
2358 }
2359
2360 /*@C
2361 DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called
2362
2363 Logically Collective
2364
2365 Input Arguments:
2366 + dm - the DM
2367 . beginhook - function to run at the beginning of DMGlobalToLocalBegin()
2368 . endhook - function to run after DMGlobalToLocalEnd() has completed
2369 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2370
2371 Calling sequence for beginhook:
2372 $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
2373
2374 + dm - global DM
2375 . g - global vector
2376 . mode - mode
2377 . l - local vector
2378 - ctx - optional user-defined function context
2379
2380
2381 Calling sequence for endhook:
2382 $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
2383
2384 + global - global DM
2385 - ctx - optional user-defined function context
2386
2387 Level: advanced
2388
2389 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2390 @*/
DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (* beginhook)(DM,Vec,InsertMode,Vec,void *),PetscErrorCode (* endhook)(DM,Vec,InsertMode,Vec,void *),void * ctx)2391 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
2392 {
2393 PetscErrorCode ierr;
2394 DMGlobalToLocalHookLink link,*p;
2395
2396 PetscFunctionBegin;
2397 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2398 for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2399 ierr = PetscNew(&link);CHKERRQ(ierr);
2400 link->beginhook = beginhook;
2401 link->endhook = endhook;
2402 link->ctx = ctx;
2403 link->next = NULL;
2404 *p = link;
2405 PetscFunctionReturn(0);
2406 }
2407
DMGlobalToLocalHook_Constraints(DM dm,Vec g,InsertMode mode,Vec l,void * ctx)2408 static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx)
2409 {
2410 Mat cMat;
2411 Vec cVec;
2412 PetscSection section, cSec;
2413 PetscInt pStart, pEnd, p, dof;
2414 PetscErrorCode ierr;
2415
2416 PetscFunctionBegin;
2417 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2418 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr);
2419 if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) {
2420 PetscInt nRows;
2421
2422 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr);
2423 if (nRows <= 0) PetscFunctionReturn(0);
2424 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr);
2425 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr);
2426 ierr = MatMult(cMat,l,cVec);CHKERRQ(ierr);
2427 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr);
2428 for (p = pStart; p < pEnd; p++) {
2429 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr);
2430 if (dof) {
2431 PetscScalar *vals;
2432 ierr = VecGetValuesSection(cVec,cSec,p,&vals);CHKERRQ(ierr);
2433 ierr = VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);CHKERRQ(ierr);
2434 }
2435 }
2436 ierr = VecDestroy(&cVec);CHKERRQ(ierr);
2437 }
2438 PetscFunctionReturn(0);
2439 }
2440
2441 /*@
2442 DMGlobalToLocal - update local vectors from global vector
2443
2444 Neighbor-wise Collective on dm
2445
2446 Input Parameters:
2447 + dm - the DM object
2448 . g - the global vector
2449 . mode - INSERT_VALUES or ADD_VALUES
2450 - l - the local vector
2451
2452 Notes:
2453 The communication involved in this update can be overlapped with computation by using
2454 DMGlobalToLocalBegin() and DMGlobalToLocalEnd().
2455
2456 Level: beginner
2457
2458 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd()
2459
2460 @*/
DMGlobalToLocal(DM dm,Vec g,InsertMode mode,Vec l)2461 PetscErrorCode DMGlobalToLocal(DM dm,Vec g,InsertMode mode,Vec l)
2462 {
2463 PetscErrorCode ierr;
2464
2465 PetscFunctionBegin;
2466 ierr = DMGlobalToLocalBegin(dm,g,mode,l);CHKERRQ(ierr);
2467 ierr = DMGlobalToLocalEnd(dm,g,mode,l);CHKERRQ(ierr);
2468 PetscFunctionReturn(0);
2469 }
2470
2471 /*@
2472 DMGlobalToLocalBegin - Begins updating local vectors from global vector
2473
2474 Neighbor-wise Collective on dm
2475
2476 Input Parameters:
2477 + dm - the DM object
2478 . g - the global vector
2479 . mode - INSERT_VALUES or ADD_VALUES
2480 - l - the local vector
2481
2482 Level: intermediate
2483
2484 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd()
2485
2486 @*/
DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)2487 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2488 {
2489 PetscSF sf;
2490 PetscErrorCode ierr;
2491 DMGlobalToLocalHookLink link;
2492
2493
2494 PetscFunctionBegin;
2495 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2496 for (link=dm->gtolhook; link; link=link->next) {
2497 if (link->beginhook) {
2498 ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);
2499 }
2500 }
2501 ierr = DMGetSectionSF(dm, &sf);CHKERRQ(ierr);
2502 if (sf) {
2503 const PetscScalar *gArray;
2504 PetscScalar *lArray;
2505 PetscMemType lmtype,gmtype;
2506
2507 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2508 ierr = VecGetArrayInPlace_Internal(l, &lArray, &lmtype);CHKERRQ(ierr);
2509 ierr = VecGetArrayReadInPlace_Internal(g, &gArray, &gmtype);CHKERRQ(ierr);
2510 ierr = PetscSFBcastWithMemTypeBegin(sf, MPIU_SCALAR, gmtype, gArray, lmtype, lArray);CHKERRQ(ierr);
2511 ierr = VecRestoreArrayInPlace(l, &lArray);CHKERRQ(ierr);
2512 ierr = VecRestoreArrayReadInPlace(g, &gArray);CHKERRQ(ierr);
2513 } else {
2514 if (!dm->ops->globaltolocalbegin) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMGlobalToLocalBegin() for type %s",((PetscObject)dm)->type_name);
2515 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
2516 }
2517 PetscFunctionReturn(0);
2518 }
2519
2520 /*@
2521 DMGlobalToLocalEnd - Ends updating local vectors from global vector
2522
2523 Neighbor-wise Collective on dm
2524
2525 Input Parameters:
2526 + dm - the DM object
2527 . g - the global vector
2528 . mode - INSERT_VALUES or ADD_VALUES
2529 - l - the local vector
2530
2531 Level: intermediate
2532
2533 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd()
2534
2535 @*/
DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)2536 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2537 {
2538 PetscSF sf;
2539 PetscErrorCode ierr;
2540 const PetscScalar *gArray;
2541 PetscScalar *lArray;
2542 PetscBool transform;
2543 DMGlobalToLocalHookLink link;
2544 PetscMemType lmtype,gmtype;
2545
2546 PetscFunctionBegin;
2547 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2548 ierr = DMGetSectionSF(dm, &sf);CHKERRQ(ierr);
2549 ierr = DMHasBasisTransform(dm, &transform);CHKERRQ(ierr);
2550 if (sf) {
2551 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2552
2553 ierr = VecGetArrayInPlace_Internal(l, &lArray, &lmtype);CHKERRQ(ierr);
2554 ierr = VecGetArrayReadInPlace_Internal(g, &gArray, &gmtype);CHKERRQ(ierr);
2555 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr);
2556 ierr = VecRestoreArrayInPlace(l, &lArray);CHKERRQ(ierr);
2557 ierr = VecRestoreArrayReadInPlace(g, &gArray);CHKERRQ(ierr);
2558 if (transform) {ierr = DMPlexGlobalToLocalBasis(dm, l);CHKERRQ(ierr);}
2559 } else {
2560 if (!dm->ops->globaltolocalend) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMGlobalToLocalEnd() for type %s",((PetscObject)dm)->type_name);
2561 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
2562 }
2563 ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr);
2564 for (link=dm->gtolhook; link; link=link->next) {
2565 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);}
2566 }
2567 PetscFunctionReturn(0);
2568 }
2569
2570 /*@C
2571 DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called
2572
2573 Logically Collective
2574
2575 Input Arguments:
2576 + dm - the DM
2577 . beginhook - function to run at the beginning of DMLocalToGlobalBegin()
2578 . endhook - function to run after DMLocalToGlobalEnd() has completed
2579 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2580
2581 Calling sequence for beginhook:
2582 $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
2583
2584 + dm - global DM
2585 . l - local vector
2586 . mode - mode
2587 . g - global vector
2588 - ctx - optional user-defined function context
2589
2590
2591 Calling sequence for endhook:
2592 $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
2593
2594 + global - global DM
2595 . l - local vector
2596 . mode - mode
2597 . g - global vector
2598 - ctx - optional user-defined function context
2599
2600 Level: advanced
2601
2602 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2603 @*/
DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (* beginhook)(DM,Vec,InsertMode,Vec,void *),PetscErrorCode (* endhook)(DM,Vec,InsertMode,Vec,void *),void * ctx)2604 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
2605 {
2606 PetscErrorCode ierr;
2607 DMLocalToGlobalHookLink link,*p;
2608
2609 PetscFunctionBegin;
2610 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2611 for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2612 ierr = PetscNew(&link);CHKERRQ(ierr);
2613 link->beginhook = beginhook;
2614 link->endhook = endhook;
2615 link->ctx = ctx;
2616 link->next = NULL;
2617 *p = link;
2618 PetscFunctionReturn(0);
2619 }
2620
DMLocalToGlobalHook_Constraints(DM dm,Vec l,InsertMode mode,Vec g,void * ctx)2621 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
2622 {
2623 Mat cMat;
2624 Vec cVec;
2625 PetscSection section, cSec;
2626 PetscInt pStart, pEnd, p, dof;
2627 PetscErrorCode ierr;
2628
2629 PetscFunctionBegin;
2630 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2631 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr);
2632 if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) {
2633 PetscInt nRows;
2634
2635 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr);
2636 if (nRows <= 0) PetscFunctionReturn(0);
2637 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr);
2638 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr);
2639 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr);
2640 for (p = pStart; p < pEnd; p++) {
2641 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr);
2642 if (dof) {
2643 PetscInt d;
2644 PetscScalar *vals;
2645 ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr);
2646 ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr);
2647 /* for this to be the true transpose, we have to zero the values that
2648 * we just extracted */
2649 for (d = 0; d < dof; d++) {
2650 vals[d] = 0.;
2651 }
2652 }
2653 }
2654 ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr);
2655 ierr = VecDestroy(&cVec);CHKERRQ(ierr);
2656 }
2657 PetscFunctionReturn(0);
2658 }
2659 /*@
2660 DMLocalToGlobal - updates global vectors from local vectors
2661
2662 Neighbor-wise Collective on dm
2663
2664 Input Parameters:
2665 + dm - the DM object
2666 . l - the local vector
2667 . mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that base point.
2668 - g - the global vector
2669
2670 Notes:
2671 The communication involved in this update can be overlapped with computation by using
2672 DMLocalToGlobalBegin() and DMLocalToGlobalEnd().
2673
2674 In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation.
2675 INSERT_VALUES is not supported for DMDA; in that case simply compute the values directly into a global vector instead of a local one.
2676
2677 Level: beginner
2678
2679 .seealso DMLocalToGlobalBegin(), DMLocalToGlobalEnd(), DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
2680
2681 @*/
DMLocalToGlobal(DM dm,Vec l,InsertMode mode,Vec g)2682 PetscErrorCode DMLocalToGlobal(DM dm,Vec l,InsertMode mode,Vec g)
2683 {
2684 PetscErrorCode ierr;
2685
2686 PetscFunctionBegin;
2687 ierr = DMLocalToGlobalBegin(dm,l,mode,g);CHKERRQ(ierr);
2688 ierr = DMLocalToGlobalEnd(dm,l,mode,g);CHKERRQ(ierr);
2689 PetscFunctionReturn(0);
2690 }
2691
2692 /*@
2693 DMLocalToGlobalBegin - begins updating global vectors from local vectors
2694
2695 Neighbor-wise Collective on dm
2696
2697 Input Parameters:
2698 + dm - the DM object
2699 . l - the local vector
2700 . mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that base point.
2701 - g - the global vector
2702
2703 Notes:
2704 In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation.
2705 INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one.
2706
2707 Level: intermediate
2708
2709 .seealso DMLocalToGlobal(), DMLocalToGlobalEnd(), DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
2710
2711 @*/
DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)2712 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
2713 {
2714 PetscSF sf;
2715 PetscSection s, gs;
2716 DMLocalToGlobalHookLink link;
2717 Vec tmpl;
2718 const PetscScalar *lArray;
2719 PetscScalar *gArray;
2720 PetscBool isInsert, transform, l_inplace = PETSC_FALSE, g_inplace = PETSC_FALSE;
2721 PetscErrorCode ierr;
2722 PetscMemType lmtype=PETSC_MEMTYPE_HOST,gmtype=PETSC_MEMTYPE_HOST;
2723
2724 PetscFunctionBegin;
2725 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2726 for (link=dm->ltoghook; link; link=link->next) {
2727 if (link->beginhook) {
2728 ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr);
2729 }
2730 }
2731 ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr);
2732 ierr = DMGetSectionSF(dm, &sf);CHKERRQ(ierr);
2733 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr);
2734 switch (mode) {
2735 case INSERT_VALUES:
2736 case INSERT_ALL_VALUES:
2737 case INSERT_BC_VALUES:
2738 isInsert = PETSC_TRUE; break;
2739 case ADD_VALUES:
2740 case ADD_ALL_VALUES:
2741 case ADD_BC_VALUES:
2742 isInsert = PETSC_FALSE; break;
2743 default:
2744 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2745 }
2746 if ((sf && !isInsert) || (s && isInsert)) {
2747 ierr = DMHasBasisTransform(dm, &transform);CHKERRQ(ierr);
2748 if (transform) {
2749 ierr = DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr);
2750 ierr = VecCopy(l, tmpl);CHKERRQ(ierr);
2751 ierr = DMPlexLocalToGlobalBasis(dm, tmpl);CHKERRQ(ierr);
2752 ierr = VecGetArrayRead(tmpl, &lArray);CHKERRQ(ierr);
2753 } else if (isInsert) {
2754 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr);
2755 } else {
2756 ierr = VecGetArrayReadInPlace_Internal(l, &lArray, &lmtype);CHKERRQ(ierr);
2757 l_inplace = PETSC_TRUE;
2758 }
2759 if (s && isInsert) {
2760 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
2761 } else {
2762 ierr = VecGetArrayInPlace_Internal(g, &gArray, &gmtype);CHKERRQ(ierr);
2763 g_inplace = PETSC_TRUE;
2764 }
2765 if (sf && !isInsert) {
2766 ierr = PetscSFReduceWithMemTypeBegin(sf, MPIU_SCALAR, lmtype, lArray, gmtype, gArray, MPIU_SUM);CHKERRQ(ierr);
2767 } else if (s && isInsert) {
2768 PetscInt gStart, pStart, pEnd, p;
2769
2770 ierr = DMGetGlobalSection(dm, &gs);CHKERRQ(ierr);
2771 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
2772 ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr);
2773 for (p = pStart; p < pEnd; ++p) {
2774 PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
2775
2776 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
2777 ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr);
2778 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
2779 ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr);
2780 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr);
2781 ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr);
2782 /* Ignore off-process data and points with no global data */
2783 if (!gdof || goff < 0) continue;
2784 if (dof != gdof) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof);
2785 /* If no constraints are enforced in the global vector */
2786 if (!gcdof) {
2787 for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d];
2788 /* If constraints are enforced in the global vector */
2789 } else if (cdof == gcdof) {
2790 const PetscInt *cdofs;
2791 PetscInt cind = 0;
2792
2793 ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr);
2794 for (d = 0, e = 0; d < dof; ++d) {
2795 if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;}
2796 gArray[goff-gStart+e++] = lArray[off+d];
2797 }
2798 } else SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof);
2799 }
2800 }
2801 if (g_inplace) {
2802 ierr = VecRestoreArrayInPlace(g, &gArray);CHKERRQ(ierr);
2803 } else {
2804 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
2805 }
2806 if (transform) {
2807 ierr = VecRestoreArrayRead(tmpl, &lArray);CHKERRQ(ierr);
2808 ierr = DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr);
2809 } else if (l_inplace) {
2810 ierr = VecRestoreArrayReadInPlace(l, &lArray);CHKERRQ(ierr);
2811 } else {
2812 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr);
2813 }
2814 } else {
2815 if (!dm->ops->localtoglobalbegin) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMLocalToGlobalBegin() for type %s",((PetscObject)dm)->type_name);
2816 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
2817 }
2818 PetscFunctionReturn(0);
2819 }
2820
2821 /*@
2822 DMLocalToGlobalEnd - updates global vectors from local vectors
2823
2824 Neighbor-wise Collective on dm
2825
2826 Input Parameters:
2827 + dm - the DM object
2828 . l - the local vector
2829 . mode - INSERT_VALUES or ADD_VALUES
2830 - g - the global vector
2831
2832 Level: intermediate
2833
2834 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()
2835
2836 @*/
DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)2837 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
2838 {
2839 PetscSF sf;
2840 PetscSection s;
2841 DMLocalToGlobalHookLink link;
2842 PetscBool isInsert, transform;
2843 PetscErrorCode ierr;
2844
2845 PetscFunctionBegin;
2846 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2847 ierr = DMGetSectionSF(dm, &sf);CHKERRQ(ierr);
2848 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr);
2849 switch (mode) {
2850 case INSERT_VALUES:
2851 case INSERT_ALL_VALUES:
2852 isInsert = PETSC_TRUE; break;
2853 case ADD_VALUES:
2854 case ADD_ALL_VALUES:
2855 isInsert = PETSC_FALSE; break;
2856 default:
2857 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2858 }
2859 if (sf && !isInsert) {
2860 const PetscScalar *lArray;
2861 PetscScalar *gArray;
2862 Vec tmpl;
2863
2864 ierr = DMHasBasisTransform(dm, &transform);CHKERRQ(ierr);
2865 if (transform) {
2866 ierr = DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr);
2867 ierr = VecGetArrayRead(tmpl, &lArray);CHKERRQ(ierr);
2868 } else {
2869 ierr = VecGetArrayReadInPlace_Internal(l, &lArray, NULL);CHKERRQ(ierr);
2870 }
2871 ierr = VecGetArrayInPlace_Internal(g, &gArray, NULL);CHKERRQ(ierr);
2872 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr);
2873 if (transform) {
2874 ierr = VecRestoreArrayRead(tmpl, &lArray);CHKERRQ(ierr);
2875 ierr = DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr);
2876 } else {
2877 ierr = VecRestoreArrayReadInPlace(l, &lArray);CHKERRQ(ierr);
2878 }
2879 ierr = VecRestoreArrayInPlace(g, &gArray);CHKERRQ(ierr);
2880 } else if (s && isInsert) {
2881 } else {
2882 if (!dm->ops->localtoglobalend) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMLocalToGlobalEnd() for type %s",((PetscObject)dm)->type_name);
2883 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
2884 }
2885 for (link=dm->ltoghook; link; link=link->next) {
2886 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);}
2887 }
2888 PetscFunctionReturn(0);
2889 }
2890
2891 /*@
2892 DMLocalToLocalBegin - Maps from a local vector (including ghost points
2893 that contain irrelevant values) to another local vector where the ghost
2894 points in the second are set correctly. Must be followed by DMLocalToLocalEnd().
2895
2896 Neighbor-wise Collective on dm
2897
2898 Input Parameters:
2899 + dm - the DM object
2900 . g - the original local vector
2901 - mode - one of INSERT_VALUES or ADD_VALUES
2902
2903 Output Parameter:
2904 . l - the local vector with correct ghost values
2905
2906 Level: intermediate
2907
2908 Notes:
2909 The local vectors used here need not be the same as those
2910 obtained from DMCreateLocalVector(), BUT they
2911 must have the same parallel data layout; they could, for example, be
2912 obtained with VecDuplicate() from the DM originating vectors.
2913
2914 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2915
2916 @*/
DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)2917 PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2918 {
2919 PetscErrorCode ierr;
2920
2921 PetscFunctionBegin;
2922 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2923 if (!dm->ops->localtolocalbegin) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps");
2924 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
2925 PetscFunctionReturn(0);
2926 }
2927
2928 /*@
2929 DMLocalToLocalEnd - Maps from a local vector (including ghost points
2930 that contain irrelevant values) to another local vector where the ghost
2931 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin().
2932
2933 Neighbor-wise Collective on dm
2934
2935 Input Parameters:
2936 + da - the DM object
2937 . g - the original local vector
2938 - mode - one of INSERT_VALUES or ADD_VALUES
2939
2940 Output Parameter:
2941 . l - the local vector with correct ghost values
2942
2943 Level: intermediate
2944
2945 Notes:
2946 The local vectors used here need not be the same as those
2947 obtained from DMCreateLocalVector(), BUT they
2948 must have the same parallel data layout; they could, for example, be
2949 obtained with VecDuplicate() from the DM originating vectors.
2950
2951 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2952
2953 @*/
DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)2954 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2955 {
2956 PetscErrorCode ierr;
2957
2958 PetscFunctionBegin;
2959 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2960 if (!dm->ops->localtolocalend) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps");
2961 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
2962 PetscFunctionReturn(0);
2963 }
2964
2965
2966 /*@
2967 DMCoarsen - Coarsens a DM object
2968
2969 Collective on dm
2970
2971 Input Parameter:
2972 + dm - the DM object
2973 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
2974
2975 Output Parameter:
2976 . dmc - the coarsened DM
2977
2978 Level: developer
2979
2980 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2981
2982 @*/
DMCoarsen(DM dm,MPI_Comm comm,DM * dmc)2983 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
2984 {
2985 PetscErrorCode ierr;
2986 DMCoarsenHookLink link;
2987
2988 PetscFunctionBegin;
2989 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2990 if (!dm->ops->coarsen) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCoarsen",((PetscObject)dm)->type_name);
2991 ierr = PetscLogEventBegin(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr);
2992 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr);
2993 if (*dmc) {
2994 ierr = DMSetCoarseDM(dm,*dmc);CHKERRQ(ierr);
2995 (*dmc)->ops->creatematrix = dm->ops->creatematrix;
2996 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr);
2997 (*dmc)->ctx = dm->ctx;
2998 (*dmc)->levelup = dm->levelup;
2999 (*dmc)->leveldown = dm->leveldown + 1;
3000 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr);
3001 for (link=dm->coarsenhook; link; link=link->next) {
3002 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);}
3003 }
3004 }
3005 ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr);
3006 if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
3007 PetscFunctionReturn(0);
3008 }
3009
3010 /*@C
3011 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
3012
3013 Logically Collective
3014
3015 Input Arguments:
3016 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level
3017 . coarsenhook - function to run when setting up a coarser level
3018 . restricthook - function to run to update data on coarser levels (once per SNESSolve())
3019 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3020
3021 Calling sequence of coarsenhook:
3022 $ coarsenhook(DM fine,DM coarse,void *ctx);
3023
3024 + fine - fine level DM
3025 . coarse - coarse level DM to restrict problem to
3026 - ctx - optional user-defined function context
3027
3028 Calling sequence for restricthook:
3029 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)
3030
3031 + fine - fine level DM
3032 . mrestrict - matrix restricting a fine-level solution to the coarse grid
3033 . rscale - scaling vector for restriction
3034 . inject - matrix restricting by injection
3035 . coarse - coarse level DM to update
3036 - ctx - optional user-defined function context
3037
3038 Level: advanced
3039
3040 Notes:
3041 This function is only needed if auxiliary data needs to be set up on coarse grids.
3042
3043 If this function is called multiple times, the hooks will be run in the order they are added.
3044
3045 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3046 extract the finest level information from its context (instead of from the SNES).
3047
3048 This function is currently not available from Fortran.
3049
3050 .seealso: DMCoarsenHookRemove(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
3051 @*/
DMCoarsenHookAdd(DM fine,PetscErrorCode (* coarsenhook)(DM,DM,void *),PetscErrorCode (* restricthook)(DM,Mat,Vec,Mat,DM,void *),void * ctx)3052 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
3053 {
3054 PetscErrorCode ierr;
3055 DMCoarsenHookLink link,*p;
3056
3057 PetscFunctionBegin;
3058 PetscValidHeaderSpecific(fine,DM_CLASSID,1);
3059 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
3060 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0);
3061 }
3062 ierr = PetscNew(&link);CHKERRQ(ierr);
3063 link->coarsenhook = coarsenhook;
3064 link->restricthook = restricthook;
3065 link->ctx = ctx;
3066 link->next = NULL;
3067 *p = link;
3068 PetscFunctionReturn(0);
3069 }
3070
3071 /*@C
3072 DMCoarsenHookRemove - remove a callback from the list of hooks to be run when restricting a nonlinear problem to the coarse grid
3073
3074 Logically Collective
3075
3076 Input Arguments:
3077 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level
3078 . coarsenhook - function to run when setting up a coarser level
3079 . restricthook - function to run to update data on coarser levels (once per SNESSolve())
3080 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3081
3082 Level: advanced
3083
3084 Notes:
3085 This function does nothing if the hook is not in the list.
3086
3087 This function is currently not available from Fortran.
3088
3089 .seealso: DMCoarsenHookAdd(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
3090 @*/
DMCoarsenHookRemove(DM fine,PetscErrorCode (* coarsenhook)(DM,DM,void *),PetscErrorCode (* restricthook)(DM,Mat,Vec,Mat,DM,void *),void * ctx)3091 PetscErrorCode DMCoarsenHookRemove(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
3092 {
3093 PetscErrorCode ierr;
3094 DMCoarsenHookLink link,*p;
3095
3096 PetscFunctionBegin;
3097 PetscValidHeaderSpecific(fine,DM_CLASSID,1);
3098 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Search the list of current hooks */
3099 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3100 link = *p;
3101 *p = link->next;
3102 ierr = PetscFree(link);CHKERRQ(ierr);
3103 break;
3104 }
3105 }
3106 PetscFunctionReturn(0);
3107 }
3108
3109
3110 /*@
3111 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd()
3112
3113 Collective if any hooks are
3114
3115 Input Arguments:
3116 + fine - finer DM to use as a base
3117 . restrct - restriction matrix, apply using MatRestrict()
3118 . rscale - scaling vector for restriction
3119 . inject - injection matrix, also use MatRestrict()
3120 - coarse - coarser DM to update
3121
3122 Level: developer
3123
3124 .seealso: DMCoarsenHookAdd(), MatRestrict()
3125 @*/
DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse)3126 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse)
3127 {
3128 PetscErrorCode ierr;
3129 DMCoarsenHookLink link;
3130
3131 PetscFunctionBegin;
3132 for (link=fine->coarsenhook; link; link=link->next) {
3133 if (link->restricthook) {
3134 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr);
3135 }
3136 }
3137 PetscFunctionReturn(0);
3138 }
3139
3140 /*@C
3141 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
3142
3143 Logically Collective on global
3144
3145 Input Arguments:
3146 + global - global DM
3147 . ddhook - function to run to pass data to the decomposition DM upon its creation
3148 . restricthook - function to run to update data on block solve (at the beginning of the block solve)
3149 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3150
3151
3152 Calling sequence for ddhook:
3153 $ ddhook(DM global,DM block,void *ctx)
3154
3155 + global - global DM
3156 . block - block DM
3157 - ctx - optional user-defined function context
3158
3159 Calling sequence for restricthook:
3160 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)
3161
3162 + global - global DM
3163 . out - scatter to the outer (with ghost and overlap points) block vector
3164 . in - scatter to block vector values only owned locally
3165 . block - block DM
3166 - ctx - optional user-defined function context
3167
3168 Level: advanced
3169
3170 Notes:
3171 This function is only needed if auxiliary data needs to be set up on subdomain DMs.
3172
3173 If this function is called multiple times, the hooks will be run in the order they are added.
3174
3175 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3176 extract the global information from its context (instead of from the SNES).
3177
3178 This function is currently not available from Fortran.
3179
3180 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
3181 @*/
DMSubDomainHookAdd(DM global,PetscErrorCode (* ddhook)(DM,DM,void *),PetscErrorCode (* restricthook)(DM,VecScatter,VecScatter,DM,void *),void * ctx)3182 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
3183 {
3184 PetscErrorCode ierr;
3185 DMSubDomainHookLink link,*p;
3186
3187 PetscFunctionBegin;
3188 PetscValidHeaderSpecific(global,DM_CLASSID,1);
3189 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
3190 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0);
3191 }
3192 ierr = PetscNew(&link);CHKERRQ(ierr);
3193 link->restricthook = restricthook;
3194 link->ddhook = ddhook;
3195 link->ctx = ctx;
3196 link->next = NULL;
3197 *p = link;
3198 PetscFunctionReturn(0);
3199 }
3200
3201 /*@C
3202 DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid
3203
3204 Logically Collective
3205
3206 Input Arguments:
3207 + global - global DM
3208 . ddhook - function to run to pass data to the decomposition DM upon its creation
3209 . restricthook - function to run to update data on block solve (at the beginning of the block solve)
3210 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3211
3212 Level: advanced
3213
3214 Notes:
3215
3216 This function is currently not available from Fortran.
3217
3218 .seealso: DMSubDomainHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
3219 @*/
DMSubDomainHookRemove(DM global,PetscErrorCode (* ddhook)(DM,DM,void *),PetscErrorCode (* restricthook)(DM,VecScatter,VecScatter,DM,void *),void * ctx)3220 PetscErrorCode DMSubDomainHookRemove(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
3221 {
3222 PetscErrorCode ierr;
3223 DMSubDomainHookLink link,*p;
3224
3225 PetscFunctionBegin;
3226 PetscValidHeaderSpecific(global,DM_CLASSID,1);
3227 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Search the list of current hooks */
3228 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3229 link = *p;
3230 *p = link->next;
3231 ierr = PetscFree(link);CHKERRQ(ierr);
3232 break;
3233 }
3234 }
3235 PetscFunctionReturn(0);
3236 }
3237
3238 /*@
3239 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd()
3240
3241 Collective if any hooks are
3242
3243 Input Arguments:
3244 + fine - finer DM to use as a base
3245 . oscatter - scatter from domain global vector filling subdomain global vector with overlap
3246 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts
3247 - coarse - coarer DM to update
3248
3249 Level: developer
3250
3251 .seealso: DMCoarsenHookAdd(), MatRestrict()
3252 @*/
DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm)3253 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm)
3254 {
3255 PetscErrorCode ierr;
3256 DMSubDomainHookLink link;
3257
3258 PetscFunctionBegin;
3259 for (link=global->subdomainhook; link; link=link->next) {
3260 if (link->restricthook) {
3261 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr);
3262 }
3263 }
3264 PetscFunctionReturn(0);
3265 }
3266
3267 /*@
3268 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM.
3269
3270 Not Collective
3271
3272 Input Parameter:
3273 . dm - the DM object
3274
3275 Output Parameter:
3276 . level - number of coarsenings
3277
3278 Level: developer
3279
3280 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
3281
3282 @*/
DMGetCoarsenLevel(DM dm,PetscInt * level)3283 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level)
3284 {
3285 PetscFunctionBegin;
3286 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3287 PetscValidIntPointer(level,2);
3288 *level = dm->leveldown;
3289 PetscFunctionReturn(0);
3290 }
3291
3292 /*@
3293 DMSetCoarsenLevel - Sets the number of coarsenings that have generated this DM.
3294
3295 Not Collective
3296
3297 Input Parameters:
3298 + dm - the DM object
3299 - level - number of coarsenings
3300
3301 Level: developer
3302
3303 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
3304 @*/
DMSetCoarsenLevel(DM dm,PetscInt level)3305 PetscErrorCode DMSetCoarsenLevel(DM dm,PetscInt level)
3306 {
3307 PetscFunctionBegin;
3308 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3309 dm->leveldown = level;
3310 PetscFunctionReturn(0);
3311 }
3312
3313
3314
3315 /*@C
3316 DMRefineHierarchy - Refines a DM object, all levels at once
3317
3318 Collective on dm
3319
3320 Input Parameter:
3321 + dm - the DM object
3322 - nlevels - the number of levels of refinement
3323
3324 Output Parameter:
3325 . dmf - the refined DM hierarchy
3326
3327 Level: developer
3328
3329 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
3330
3331 @*/
DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])3332 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
3333 {
3334 PetscErrorCode ierr;
3335
3336 PetscFunctionBegin;
3337 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3338 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
3339 if (nlevels == 0) PetscFunctionReturn(0);
3340 PetscValidPointer(dmf,3);
3341 if (dm->ops->refinehierarchy) {
3342 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr);
3343 } else if (dm->ops->refine) {
3344 PetscInt i;
3345
3346 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr);
3347 for (i=1; i<nlevels; i++) {
3348 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr);
3349 }
3350 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
3351 PetscFunctionReturn(0);
3352 }
3353
3354 /*@C
3355 DMCoarsenHierarchy - Coarsens a DM object, all levels at once
3356
3357 Collective on dm
3358
3359 Input Parameter:
3360 + dm - the DM object
3361 - nlevels - the number of levels of coarsening
3362
3363 Output Parameter:
3364 . dmc - the coarsened DM hierarchy
3365
3366 Level: developer
3367
3368 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
3369
3370 @*/
DMCoarsenHierarchy(DM dm,PetscInt nlevels,DM dmc[])3371 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
3372 {
3373 PetscErrorCode ierr;
3374
3375 PetscFunctionBegin;
3376 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3377 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
3378 if (nlevels == 0) PetscFunctionReturn(0);
3379 PetscValidPointer(dmc,3);
3380 if (dm->ops->coarsenhierarchy) {
3381 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr);
3382 } else if (dm->ops->coarsen) {
3383 PetscInt i;
3384
3385 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr);
3386 for (i=1; i<nlevels; i++) {
3387 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr);
3388 }
3389 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
3390 PetscFunctionReturn(0);
3391 }
3392
3393 /*@C
3394 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed
3395
3396 Not Collective
3397
3398 Input Parameters:
3399 + dm - the DM object
3400 - destroy - the destroy function
3401
3402 Level: intermediate
3403
3404 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3405
3406 @*/
DMSetApplicationContextDestroy(DM dm,PetscErrorCode (* destroy)(void **))3407 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**))
3408 {
3409 PetscFunctionBegin;
3410 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3411 dm->ctxdestroy = destroy;
3412 PetscFunctionReturn(0);
3413 }
3414
3415 /*@
3416 DMSetApplicationContext - Set a user context into a DM object
3417
3418 Not Collective
3419
3420 Input Parameters:
3421 + dm - the DM object
3422 - ctx - the user context
3423
3424 Level: intermediate
3425
3426 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3427
3428 @*/
DMSetApplicationContext(DM dm,void * ctx)3429 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx)
3430 {
3431 PetscFunctionBegin;
3432 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3433 dm->ctx = ctx;
3434 PetscFunctionReturn(0);
3435 }
3436
3437 /*@
3438 DMGetApplicationContext - Gets a user context from a DM object
3439
3440 Not Collective
3441
3442 Input Parameter:
3443 . dm - the DM object
3444
3445 Output Parameter:
3446 . ctx - the user context
3447
3448 Level: intermediate
3449
3450 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3451
3452 @*/
DMGetApplicationContext(DM dm,void * ctx)3453 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx)
3454 {
3455 PetscFunctionBegin;
3456 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3457 *(void**)ctx = dm->ctx;
3458 PetscFunctionReturn(0);
3459 }
3460
3461 /*@C
3462 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI.
3463
3464 Logically Collective on dm
3465
3466 Input Parameter:
3467 + dm - the DM object
3468 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)
3469
3470 Level: intermediate
3471
3472 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(),
3473 DMSetJacobian()
3474
3475 @*/
DMSetVariableBounds(DM dm,PetscErrorCode (* f)(DM,Vec,Vec))3476 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
3477 {
3478 PetscFunctionBegin;
3479 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3480 dm->ops->computevariablebounds = f;
3481 PetscFunctionReturn(0);
3482 }
3483
3484 /*@
3485 DMHasVariableBounds - does the DM object have a variable bounds function?
3486
3487 Not Collective
3488
3489 Input Parameter:
3490 . dm - the DM object to destroy
3491
3492 Output Parameter:
3493 . flg - PETSC_TRUE if the variable bounds function exists
3494
3495 Level: developer
3496
3497 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3498
3499 @*/
DMHasVariableBounds(DM dm,PetscBool * flg)3500 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg)
3501 {
3502 PetscFunctionBegin;
3503 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3504 PetscValidBoolPointer(flg,2);
3505 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
3506 PetscFunctionReturn(0);
3507 }
3508
3509 /*@C
3510 DMComputeVariableBounds - compute variable bounds used by SNESVI.
3511
3512 Logically Collective on dm
3513
3514 Input Parameters:
3515 . dm - the DM object
3516
3517 Output parameters:
3518 + xl - lower bound
3519 - xu - upper bound
3520
3521 Level: advanced
3522
3523 Notes:
3524 This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
3525
3526 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
3527
3528 @*/
DMComputeVariableBounds(DM dm,Vec xl,Vec xu)3529 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
3530 {
3531 PetscErrorCode ierr;
3532
3533 PetscFunctionBegin;
3534 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3535 PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
3536 PetscValidHeaderSpecific(xu,VEC_CLASSID,3);
3537 if (!dm->ops->computevariablebounds) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeVariableBounds",((PetscObject)dm)->type_name);
3538 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr);
3539 PetscFunctionReturn(0);
3540 }
3541
3542 /*@
3543 DMHasColoring - does the DM object have a method of providing a coloring?
3544
3545 Not Collective
3546
3547 Input Parameter:
3548 . dm - the DM object
3549
3550 Output Parameter:
3551 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring().
3552
3553 Level: developer
3554
3555 .seealso DMCreateColoring()
3556
3557 @*/
DMHasColoring(DM dm,PetscBool * flg)3558 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg)
3559 {
3560 PetscFunctionBegin;
3561 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3562 PetscValidBoolPointer(flg,2);
3563 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
3564 PetscFunctionReturn(0);
3565 }
3566
3567 /*@
3568 DMHasCreateRestriction - does the DM object have a method of providing a restriction?
3569
3570 Not Collective
3571
3572 Input Parameter:
3573 . dm - the DM object
3574
3575 Output Parameter:
3576 . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction().
3577
3578 Level: developer
3579
3580 .seealso DMCreateRestriction()
3581
3582 @*/
DMHasCreateRestriction(DM dm,PetscBool * flg)3583 PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg)
3584 {
3585 PetscFunctionBegin;
3586 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3587 PetscValidBoolPointer(flg,2);
3588 *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE;
3589 PetscFunctionReturn(0);
3590 }
3591
3592
3593 /*@
3594 DMHasCreateInjection - does the DM object have a method of providing an injection?
3595
3596 Not Collective
3597
3598 Input Parameter:
3599 . dm - the DM object
3600
3601 Output Parameter:
3602 . flg - PETSC_TRUE if the DM has facilities for DMCreateInjection().
3603
3604 Level: developer
3605
3606 .seealso DMCreateInjection()
3607
3608 @*/
DMHasCreateInjection(DM dm,PetscBool * flg)3609 PetscErrorCode DMHasCreateInjection(DM dm,PetscBool *flg)
3610 {
3611 PetscErrorCode ierr;
3612
3613 PetscFunctionBegin;
3614 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3615 PetscValidBoolPointer(flg,2);
3616 if (dm->ops->hascreateinjection) {
3617 ierr = (*dm->ops->hascreateinjection)(dm,flg);CHKERRQ(ierr);
3618 } else {
3619 *flg = (dm->ops->createinjection) ? PETSC_TRUE : PETSC_FALSE;
3620 }
3621 PetscFunctionReturn(0);
3622 }
3623
3624 PetscFunctionList DMList = NULL;
3625 PetscBool DMRegisterAllCalled = PETSC_FALSE;
3626
3627 /*@C
3628 DMSetType - Builds a DM, for a particular DM implementation.
3629
3630 Collective on dm
3631
3632 Input Parameters:
3633 + dm - The DM object
3634 - method - The name of the DM type
3635
3636 Options Database Key:
3637 . -dm_type <type> - Sets the DM type; use -help for a list of available types
3638
3639 Notes:
3640 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).
3641
3642 Level: intermediate
3643
3644 .seealso: DMGetType(), DMCreate()
3645 @*/
DMSetType(DM dm,DMType method)3646 PetscErrorCode DMSetType(DM dm, DMType method)
3647 {
3648 PetscErrorCode (*r)(DM);
3649 PetscBool match;
3650 PetscErrorCode ierr;
3651
3652 PetscFunctionBegin;
3653 PetscValidHeaderSpecific(dm, DM_CLASSID,1);
3654 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr);
3655 if (match) PetscFunctionReturn(0);
3656
3657 ierr = DMRegisterAll();CHKERRQ(ierr);
3658 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr);
3659 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
3660
3661 if (dm->ops->destroy) {
3662 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr);
3663 }
3664 ierr = PetscMemzero(dm->ops,sizeof(*dm->ops));CHKERRQ(ierr);
3665 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr);
3666 ierr = (*r)(dm);CHKERRQ(ierr);
3667 PetscFunctionReturn(0);
3668 }
3669
3670 /*@C
3671 DMGetType - Gets the DM type name (as a string) from the DM.
3672
3673 Not Collective
3674
3675 Input Parameter:
3676 . dm - The DM
3677
3678 Output Parameter:
3679 . type - The DM type name
3680
3681 Level: intermediate
3682
3683 .seealso: DMSetType(), DMCreate()
3684 @*/
DMGetType(DM dm,DMType * type)3685 PetscErrorCode DMGetType(DM dm, DMType *type)
3686 {
3687 PetscErrorCode ierr;
3688
3689 PetscFunctionBegin;
3690 PetscValidHeaderSpecific(dm, DM_CLASSID,1);
3691 PetscValidPointer(type,2);
3692 ierr = DMRegisterAll();CHKERRQ(ierr);
3693 *type = ((PetscObject)dm)->type_name;
3694 PetscFunctionReturn(0);
3695 }
3696
3697 /*@C
3698 DMConvert - Converts a DM to another DM, either of the same or different type.
3699
3700 Collective on dm
3701
3702 Input Parameters:
3703 + dm - the DM
3704 - newtype - new DM type (use "same" for the same type)
3705
3706 Output Parameter:
3707 . M - pointer to new DM
3708
3709 Notes:
3710 Cannot be used to convert a sequential DM to parallel or parallel to sequential,
3711 the MPI communicator of the generated DM is always the same as the communicator
3712 of the input DM.
3713
3714 Level: intermediate
3715
3716 .seealso: DMCreate()
3717 @*/
DMConvert(DM dm,DMType newtype,DM * M)3718 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
3719 {
3720 DM B;
3721 char convname[256];
3722 PetscBool sametype/*, issame */;
3723 PetscErrorCode ierr;
3724
3725 PetscFunctionBegin;
3726 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3727 PetscValidType(dm,1);
3728 PetscValidPointer(M,3);
3729 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr);
3730 /* ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); */
3731 if (sametype) {
3732 *M = dm;
3733 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
3734 PetscFunctionReturn(0);
3735 } else {
3736 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL;
3737
3738 /*
3739 Order of precedence:
3740 1) See if a specialized converter is known to the current DM.
3741 2) See if a specialized converter is known to the desired DM class.
3742 3) See if a good general converter is registered for the desired class
3743 4) See if a good general converter is known for the current matrix.
3744 5) Use a really basic converter.
3745 */
3746
3747 /* 1) See if a specialized converter is known to the current DM and the desired class */
3748 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr);
3749 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr);
3750 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr);
3751 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr);
3752 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr);
3753 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr);
3754 if (conv) goto foundconv;
3755
3756 /* 2) See if a specialized converter is known to the desired DM class. */
3757 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr);
3758 ierr = DMSetType(B, newtype);CHKERRQ(ierr);
3759 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr);
3760 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr);
3761 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr);
3762 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr);
3763 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr);
3764 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr);
3765 if (conv) {
3766 ierr = DMDestroy(&B);CHKERRQ(ierr);
3767 goto foundconv;
3768 }
3769
3770 #if 0
3771 /* 3) See if a good general converter is registered for the desired class */
3772 conv = B->ops->convertfrom;
3773 ierr = DMDestroy(&B);CHKERRQ(ierr);
3774 if (conv) goto foundconv;
3775
3776 /* 4) See if a good general converter is known for the current matrix */
3777 if (dm->ops->convert) {
3778 conv = dm->ops->convert;
3779 }
3780 if (conv) goto foundconv;
3781 #endif
3782
3783 /* 5) Use a really basic converter. */
3784 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);
3785
3786 foundconv:
3787 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
3788 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr);
3789 /* Things that are independent of DM type: We should consult DMClone() here */
3790 {
3791 PetscBool isper;
3792 const PetscReal *maxCell, *L;
3793 const DMBoundaryType *bd;
3794 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr);
3795 ierr = DMSetPeriodicity(*M, isper, maxCell, L, bd);CHKERRQ(ierr);
3796 }
3797 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
3798 }
3799 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr);
3800 PetscFunctionReturn(0);
3801 }
3802
3803 /*--------------------------------------------------------------------------------------------------------------------*/
3804
3805 /*@C
3806 DMRegister - Adds a new DM component implementation
3807
3808 Not Collective
3809
3810 Input Parameters:
3811 + name - The name of a new user-defined creation routine
3812 - create_func - The creation routine itself
3813
3814 Notes:
3815 DMRegister() may be called multiple times to add several user-defined DMs
3816
3817
3818 Sample usage:
3819 .vb
3820 DMRegister("my_da", MyDMCreate);
3821 .ve
3822
3823 Then, your DM type can be chosen with the procedural interface via
3824 .vb
3825 DMCreate(MPI_Comm, DM *);
3826 DMSetType(DM,"my_da");
3827 .ve
3828 or at runtime via the option
3829 .vb
3830 -da_type my_da
3831 .ve
3832
3833 Level: advanced
3834
3835 .seealso: DMRegisterAll(), DMRegisterDestroy()
3836
3837 @*/
DMRegister(const char sname[],PetscErrorCode (* function)(DM))3838 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM))
3839 {
3840 PetscErrorCode ierr;
3841
3842 PetscFunctionBegin;
3843 ierr = DMInitializePackage();CHKERRQ(ierr);
3844 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr);
3845 PetscFunctionReturn(0);
3846 }
3847
3848 /*@C
3849 DMLoad - Loads a DM that has been stored in binary with DMView().
3850
3851 Collective on viewer
3852
3853 Input Parameters:
3854 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
3855 some related function before a call to DMLoad().
3856 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
3857 HDF5 file viewer, obtained from PetscViewerHDF5Open()
3858
3859 Level: intermediate
3860
3861 Notes:
3862 The type is determined by the data in the file, any type set into the DM before this call is ignored.
3863
3864 Notes for advanced users:
3865 Most users should not need to know the details of the binary storage
3866 format, since DMLoad() and DMView() completely hide these details.
3867 But for anyone who's interested, the standard binary matrix storage
3868 format is
3869 .vb
3870 has not yet been determined
3871 .ve
3872
3873 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad()
3874 @*/
DMLoad(DM newdm,PetscViewer viewer)3875 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer)
3876 {
3877 PetscBool isbinary, ishdf5;
3878 PetscErrorCode ierr;
3879
3880 PetscFunctionBegin;
3881 PetscValidHeaderSpecific(newdm,DM_CLASSID,1);
3882 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
3883 ierr = PetscViewerCheckReadable(viewer);CHKERRQ(ierr);
3884 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
3885 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
3886 ierr = PetscLogEventBegin(DM_Load,viewer,0,0,0);CHKERRQ(ierr);
3887 if (isbinary) {
3888 PetscInt classid;
3889 char type[256];
3890
3891 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr);
3892 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid);
3893 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr);
3894 ierr = DMSetType(newdm, type);CHKERRQ(ierr);
3895 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
3896 } else if (ishdf5) {
3897 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
3898 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
3899 ierr = PetscLogEventEnd(DM_Load,viewer,0,0,0);CHKERRQ(ierr);
3900 PetscFunctionReturn(0);
3901 }
3902
3903 /*@
3904 DMGetLocalBoundingBox - Returns the bounding box for the piece of the DM on this process.
3905
3906 Not collective
3907
3908 Input Parameter:
3909 . dm - the DM
3910
3911 Output Parameters:
3912 + lmin - local minimum coordinates (length coord dim, optional)
3913 - lmax - local maximim coordinates (length coord dim, optional)
3914
3915 Level: beginner
3916
3917 Note: If the DM is a DMDA and has no coordinates, the index bounds are returned instead.
3918
3919
3920 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetBoundingBox()
3921 @*/
DMGetLocalBoundingBox(DM dm,PetscReal lmin[],PetscReal lmax[])3922 PetscErrorCode DMGetLocalBoundingBox(DM dm, PetscReal lmin[], PetscReal lmax[])
3923 {
3924 Vec coords = NULL;
3925 PetscReal min[3] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL};
3926 PetscReal max[3] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
3927 const PetscScalar *local_coords;
3928 PetscInt N, Ni;
3929 PetscInt cdim, i, j;
3930 PetscErrorCode ierr;
3931
3932 PetscFunctionBegin;
3933 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3934 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
3935 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr);
3936 if (coords) {
3937 ierr = VecGetArrayRead(coords, &local_coords);CHKERRQ(ierr);
3938 ierr = VecGetLocalSize(coords, &N);CHKERRQ(ierr);
3939 Ni = N/cdim;
3940 for (i = 0; i < Ni; ++i) {
3941 for (j = 0; j < 3; ++j) {
3942 min[j] = j < cdim ? PetscMin(min[j], PetscRealPart(local_coords[i*cdim+j])) : 0;
3943 max[j] = j < cdim ? PetscMax(max[j], PetscRealPart(local_coords[i*cdim+j])) : 0;
3944 }
3945 }
3946 ierr = VecRestoreArrayRead(coords, &local_coords);CHKERRQ(ierr);
3947 } else {
3948 PetscBool isda;
3949
3950 ierr = PetscObjectTypeCompare((PetscObject) dm, DMDA, &isda);CHKERRQ(ierr);
3951 if (isda) {ierr = DMGetLocalBoundingIndices_DMDA(dm, min, max);CHKERRQ(ierr);}
3952 }
3953 if (lmin) {ierr = PetscArraycpy(lmin, min, cdim);CHKERRQ(ierr);}
3954 if (lmax) {ierr = PetscArraycpy(lmax, max, cdim);CHKERRQ(ierr);}
3955 PetscFunctionReturn(0);
3956 }
3957
3958 /*@
3959 DMGetBoundingBox - Returns the global bounding box for the DM.
3960
3961 Collective
3962
3963 Input Parameter:
3964 . dm - the DM
3965
3966 Output Parameters:
3967 + gmin - global minimum coordinates (length coord dim, optional)
3968 - gmax - global maximim coordinates (length coord dim, optional)
3969
3970 Level: beginner
3971
3972 .seealso: DMGetLocalBoundingBox(), DMGetCoordinates(), DMGetCoordinatesLocal()
3973 @*/
DMGetBoundingBox(DM dm,PetscReal gmin[],PetscReal gmax[])3974 PetscErrorCode DMGetBoundingBox(DM dm, PetscReal gmin[], PetscReal gmax[])
3975 {
3976 PetscReal lmin[3], lmax[3];
3977 PetscInt cdim;
3978 PetscMPIInt count;
3979 PetscErrorCode ierr;
3980
3981 PetscFunctionBegin;
3982 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3983 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
3984 ierr = PetscMPIIntCast(cdim, &count);CHKERRQ(ierr);
3985 ierr = DMGetLocalBoundingBox(dm, lmin, lmax);CHKERRQ(ierr);
3986 if (gmin) {ierr = MPIU_Allreduce(lmin, gmin, count, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr);}
3987 if (gmax) {ierr = MPIU_Allreduce(lmax, gmax, count, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr);}
3988 PetscFunctionReturn(0);
3989 }
3990
3991 /******************************** FEM Support **********************************/
3992
DMPrintCellVector(PetscInt c,const char name[],PetscInt len,const PetscScalar x[])3993 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
3994 {
3995 PetscInt f;
3996 PetscErrorCode ierr;
3997
3998 PetscFunctionBegin;
3999 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
4000 for (f = 0; f < len; ++f) {
4001 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr);
4002 }
4003 PetscFunctionReturn(0);
4004 }
4005
DMPrintCellMatrix(PetscInt c,const char name[],PetscInt rows,PetscInt cols,const PetscScalar A[])4006 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
4007 {
4008 PetscInt f, g;
4009 PetscErrorCode ierr;
4010
4011 PetscFunctionBegin;
4012 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
4013 for (f = 0; f < rows; ++f) {
4014 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr);
4015 for (g = 0; g < cols; ++g) {
4016 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr);
4017 }
4018 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr);
4019 }
4020 PetscFunctionReturn(0);
4021 }
4022
DMPrintLocalVec(DM dm,const char name[],PetscReal tol,Vec X)4023 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
4024 {
4025 PetscInt localSize, bs;
4026 PetscMPIInt size;
4027 Vec x, xglob;
4028 const PetscScalar *xarray;
4029 PetscErrorCode ierr;
4030
4031 PetscFunctionBegin;
4032 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);CHKERRQ(ierr);
4033 ierr = VecDuplicate(X, &x);CHKERRQ(ierr);
4034 ierr = VecCopy(X, x);CHKERRQ(ierr);
4035 ierr = VecChop(x, tol);CHKERRQ(ierr);
4036 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);CHKERRQ(ierr);
4037 if (size > 1) {
4038 ierr = VecGetLocalSize(x,&localSize);CHKERRQ(ierr);
4039 ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr);
4040 ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
4041 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);CHKERRQ(ierr);
4042 } else {
4043 xglob = x;
4044 }
4045 ierr = VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));CHKERRQ(ierr);
4046 if (size > 1) {
4047 ierr = VecDestroy(&xglob);CHKERRQ(ierr);
4048 ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr);
4049 }
4050 ierr = VecDestroy(&x);CHKERRQ(ierr);
4051 PetscFunctionReturn(0);
4052 }
4053
4054 /*@
4055 DMGetSection - Get the PetscSection encoding the local data layout for the DM. This is equivalent to DMGetLocalSection(). Deprecated in v3.12
4056
4057 Input Parameter:
4058 . dm - The DM
4059
4060 Output Parameter:
4061 . section - The PetscSection
4062
4063 Options Database Keys:
4064 . -dm_petscsection_view - View the Section created by the DM
4065
4066 Level: advanced
4067
4068 Notes:
4069 Use DMGetLocalSection() in new code.
4070
4071 This gets a borrowed reference, so the user should not destroy this PetscSection.
4072
4073 .seealso: DMGetLocalSection(), DMSetLocalSection(), DMGetGlobalSection()
4074 @*/
DMGetSection(DM dm,PetscSection * section)4075 PetscErrorCode DMGetSection(DM dm, PetscSection *section)
4076 {
4077 PetscErrorCode ierr;
4078
4079 PetscFunctionBegin;
4080 ierr = DMGetLocalSection(dm,section);CHKERRQ(ierr);
4081 PetscFunctionReturn(0);
4082 }
4083
4084 /*@
4085 DMGetLocalSection - Get the PetscSection encoding the local data layout for the DM.
4086
4087 Input Parameter:
4088 . dm - The DM
4089
4090 Output Parameter:
4091 . section - The PetscSection
4092
4093 Options Database Keys:
4094 . -dm_petscsection_view - View the Section created by the DM
4095
4096 Level: intermediate
4097
4098 Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
4099
4100 .seealso: DMSetLocalSection(), DMGetGlobalSection()
4101 @*/
DMGetLocalSection(DM dm,PetscSection * section)4102 PetscErrorCode DMGetLocalSection(DM dm, PetscSection *section)
4103 {
4104 PetscErrorCode ierr;
4105
4106 PetscFunctionBegin;
4107 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4108 PetscValidPointer(section, 2);
4109 if (!dm->localSection && dm->ops->createlocalsection) {
4110 PetscInt d;
4111
4112 if (dm->setfromoptionscalled) for (d = 0; d < dm->Nds; ++d) {ierr = PetscDSSetFromOptions(dm->probs[d].ds);CHKERRQ(ierr);}
4113 ierr = (*dm->ops->createlocalsection)(dm);CHKERRQ(ierr);
4114 if (dm->localSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->localSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);}
4115 }
4116 *section = dm->localSection;
4117 PetscFunctionReturn(0);
4118 }
4119
4120 /*@
4121 DMSetSection - Set the PetscSection encoding the local data layout for the DM. This is equivalent to DMSetLocalSection(). Deprecated in v3.12
4122
4123 Input Parameters:
4124 + dm - The DM
4125 - section - The PetscSection
4126
4127 Level: advanced
4128
4129 Notes:
4130 Use DMSetLocalSection() in new code.
4131
4132 Any existing Section will be destroyed
4133
4134 .seealso: DMSetLocalSection(), DMGetLocalSection(), DMSetGlobalSection()
4135 @*/
DMSetSection(DM dm,PetscSection section)4136 PetscErrorCode DMSetSection(DM dm, PetscSection section)
4137 {
4138 PetscErrorCode ierr;
4139
4140 PetscFunctionBegin;
4141 ierr = DMSetLocalSection(dm,section);CHKERRQ(ierr);
4142 PetscFunctionReturn(0);
4143 }
4144
4145 /*@
4146 DMSetLocalSection - Set the PetscSection encoding the local data layout for the DM.
4147
4148 Input Parameters:
4149 + dm - The DM
4150 - section - The PetscSection
4151
4152 Level: intermediate
4153
4154 Note: Any existing Section will be destroyed
4155
4156 .seealso: DMGetLocalSection(), DMSetGlobalSection()
4157 @*/
DMSetLocalSection(DM dm,PetscSection section)4158 PetscErrorCode DMSetLocalSection(DM dm, PetscSection section)
4159 {
4160 PetscInt numFields = 0;
4161 PetscInt f;
4162 PetscErrorCode ierr;
4163
4164 PetscFunctionBegin;
4165 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4166 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
4167 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
4168 ierr = PetscSectionDestroy(&dm->localSection);CHKERRQ(ierr);
4169 dm->localSection = section;
4170 if (section) {ierr = PetscSectionGetNumFields(dm->localSection, &numFields);CHKERRQ(ierr);}
4171 if (numFields) {
4172 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr);
4173 for (f = 0; f < numFields; ++f) {
4174 PetscObject disc;
4175 const char *name;
4176
4177 ierr = PetscSectionGetFieldName(dm->localSection, f, &name);CHKERRQ(ierr);
4178 ierr = DMGetField(dm, f, NULL, &disc);CHKERRQ(ierr);
4179 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr);
4180 }
4181 }
4182 /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */
4183 ierr = PetscSectionDestroy(&dm->globalSection);CHKERRQ(ierr);
4184 PetscFunctionReturn(0);
4185 }
4186
4187 /*@
4188 DMGetDefaultConstraints - Get the PetscSection and Mat that specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation.
4189
4190 not collective
4191
4192 Input Parameter:
4193 . dm - The DM
4194
4195 Output Parameter:
4196 + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section. Returns NULL if there are no local constraints.
4197 - mat - The Mat that interpolates local constraints: its width should be the layout size of the default section. Returns NULL if there are no local constraints.
4198
4199 Level: advanced
4200
4201 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat.
4202
4203 .seealso: DMSetDefaultConstraints()
4204 @*/
DMGetDefaultConstraints(DM dm,PetscSection * section,Mat * mat)4205 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat)
4206 {
4207 PetscErrorCode ierr;
4208
4209 PetscFunctionBegin;
4210 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4211 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);}
4212 if (section) {*section = dm->defaultConstraintSection;}
4213 if (mat) {*mat = dm->defaultConstraintMat;}
4214 PetscFunctionReturn(0);
4215 }
4216
4217 /*@
4218 DMSetDefaultConstraints - Set the PetscSection and Mat that specify the local constraint interpolation.
4219
4220 If a constraint matrix is specified, then it is applied during DMGlobalToLocalEnd() when mode is INSERT_VALUES, INSERT_BC_VALUES, or INSERT_ALL_VALUES. Without a constraint matrix, the local vector l returned by DMGlobalToLocalEnd() contains values that have been scattered from a global vector without modification; with a constraint matrix A, l is modified by computing c = A * l, l[s[i]] = c[i], where the scatter s is defined by the PetscSection returned by DMGetDefaultConstraintMatrix().
4221
4222 If a constraint matrix is specified, then its adjoint is applied during DMLocalToGlobalBegin() when mode is ADD_VALUES, ADD_BC_VALUES, or ADD_ALL_VALUES. Without a constraint matrix, the local vector l is accumulated into a global vector without modification; with a constraint matrix A, l is first modified by computing c[i] = l[s[i]], l[s[i]] = 0, l = l + A'*c, which is the adjoint of the operation described above.
4223
4224 collective on dm
4225
4226 Input Parameters:
4227 + dm - The DM
4228 + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section. Must have a local communicator (PETSC_COMM_SELF or derivative).
4229 - mat - The Mat that interpolates local constraints: its width should be the layout size of the default section: NULL indicates no constraints. Must have a local communicator (PETSC_COMM_SELF or derivative).
4230
4231 Level: advanced
4232
4233 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them
4234
4235 .seealso: DMGetDefaultConstraints()
4236 @*/
DMSetDefaultConstraints(DM dm,PetscSection section,Mat mat)4237 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat)
4238 {
4239 PetscMPIInt result;
4240 PetscErrorCode ierr;
4241
4242 PetscFunctionBegin;
4243 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4244 if (section) {
4245 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
4246 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr);
4247 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator");
4248 }
4249 if (mat) {
4250 PetscValidHeaderSpecific(mat,MAT_CLASSID,3);
4251 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr);
4252 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator");
4253 }
4254 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
4255 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr);
4256 dm->defaultConstraintSection = section;
4257 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
4258 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr);
4259 dm->defaultConstraintMat = mat;
4260 PetscFunctionReturn(0);
4261 }
4262
4263 #if defined(PETSC_USE_DEBUG)
4264 /*
4265 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections.
4266
4267 Input Parameters:
4268 + dm - The DM
4269 . localSection - PetscSection describing the local data layout
4270 - globalSection - PetscSection describing the global data layout
4271
4272 Level: intermediate
4273
4274 .seealso: DMGetSectionSF(), DMSetSectionSF()
4275 */
DMDefaultSectionCheckConsistency_Internal(DM dm,PetscSection localSection,PetscSection globalSection)4276 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
4277 {
4278 MPI_Comm comm;
4279 PetscLayout layout;
4280 const PetscInt *ranges;
4281 PetscInt pStart, pEnd, p, nroots;
4282 PetscMPIInt size, rank;
4283 PetscBool valid = PETSC_TRUE, gvalid;
4284 PetscErrorCode ierr;
4285
4286 PetscFunctionBegin;
4287 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
4288 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4289 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
4290 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
4291 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr);
4292 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr);
4293 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
4294 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
4295 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr);
4296 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
4297 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
4298 for (p = pStart; p < pEnd; ++p) {
4299 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d;
4300
4301 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr);
4302 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr);
4303 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr);
4304 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
4305 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
4306 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr);
4307 if (!gdof) continue; /* Censored point */
4308 if ((gdof < 0 ? -(gdof+1) : gdof) != dof) {ierr = PetscSynchronizedPrintf(comm, "[%d]Global dof %d for point %d not equal to local dof %d\n", rank, gdof, p, dof);CHKERRQ(ierr); valid = PETSC_FALSE;}
4309 if (gcdof && (gcdof != cdof)) {ierr = PetscSynchronizedPrintf(comm, "[%d]Global constraints %d for point %d not equal to local constraints %d\n", rank, gcdof, p, cdof);CHKERRQ(ierr); valid = PETSC_FALSE;}
4310 if (gdof < 0) {
4311 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
4312 for (d = 0; d < gsize; ++d) {
4313 PetscInt offset = -(goff+1) + d, r;
4314
4315 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr);
4316 if (r < 0) r = -(r+2);
4317 if ((r < 0) || (r >= size)) {ierr = PetscSynchronizedPrintf(comm, "[%d]Point %d mapped to invalid process %d (%d, %d)\n", rank, p, r, gdof, goff);CHKERRQ(ierr); valid = PETSC_FALSE;break;}
4318 }
4319 }
4320 }
4321 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
4322 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
4323 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr);
4324 if (!gvalid) {
4325 ierr = DMView(dm, NULL);CHKERRQ(ierr);
4326 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
4327 }
4328 PetscFunctionReturn(0);
4329 }
4330 #endif
4331
4332 /*@
4333 DMGetGlobalSection - Get the PetscSection encoding the global data layout for the DM.
4334
4335 Collective on dm
4336
4337 Input Parameter:
4338 . dm - The DM
4339
4340 Output Parameter:
4341 . section - The PetscSection
4342
4343 Level: intermediate
4344
4345 Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
4346
4347 .seealso: DMSetLocalSection(), DMGetLocalSection()
4348 @*/
DMGetGlobalSection(DM dm,PetscSection * section)4349 PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section)
4350 {
4351 PetscErrorCode ierr;
4352
4353 PetscFunctionBegin;
4354 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4355 PetscValidPointer(section, 2);
4356 if (!dm->globalSection) {
4357 PetscSection s;
4358
4359 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr);
4360 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
4361 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection");
4362 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->globalSection);CHKERRQ(ierr);
4363 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr);
4364 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->globalSection, &dm->map);CHKERRQ(ierr);
4365 ierr = PetscSectionViewFromOptions(dm->globalSection, NULL, "-global_section_view");CHKERRQ(ierr);
4366 }
4367 *section = dm->globalSection;
4368 PetscFunctionReturn(0);
4369 }
4370
4371 /*@
4372 DMSetGlobalSection - Set the PetscSection encoding the global data layout for the DM.
4373
4374 Input Parameters:
4375 + dm - The DM
4376 - section - The PetscSection, or NULL
4377
4378 Level: intermediate
4379
4380 Note: Any existing Section will be destroyed
4381
4382 .seealso: DMGetGlobalSection(), DMSetLocalSection()
4383 @*/
DMSetGlobalSection(DM dm,PetscSection section)4384 PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section)
4385 {
4386 PetscErrorCode ierr;
4387
4388 PetscFunctionBegin;
4389 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4390 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
4391 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
4392 ierr = PetscSectionDestroy(&dm->globalSection);CHKERRQ(ierr);
4393 dm->globalSection = section;
4394 #if defined(PETSC_USE_DEBUG)
4395 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->localSection, section);CHKERRQ(ierr);}
4396 #endif
4397 PetscFunctionReturn(0);
4398 }
4399
4400 /*@
4401 DMGetSectionSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set,
4402 it is created from the default PetscSection layouts in the DM.
4403
4404 Input Parameter:
4405 . dm - The DM
4406
4407 Output Parameter:
4408 . sf - The PetscSF
4409
4410 Level: intermediate
4411
4412 Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
4413
4414 .seealso: DMSetSectionSF(), DMCreateSectionSF()
4415 @*/
DMGetSectionSF(DM dm,PetscSF * sf)4416 PetscErrorCode DMGetSectionSF(DM dm, PetscSF *sf)
4417 {
4418 PetscInt nroots;
4419 PetscErrorCode ierr;
4420
4421 PetscFunctionBegin;
4422 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4423 PetscValidPointer(sf, 2);
4424 if (!dm->sectionSF) {
4425 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm),&dm->sectionSF);CHKERRQ(ierr);
4426 }
4427 ierr = PetscSFGetGraph(dm->sectionSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
4428 if (nroots < 0) {
4429 PetscSection section, gSection;
4430
4431 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);
4432 if (section) {
4433 ierr = DMGetGlobalSection(dm, &gSection);CHKERRQ(ierr);
4434 ierr = DMCreateSectionSF(dm, section, gSection);CHKERRQ(ierr);
4435 } else {
4436 *sf = NULL;
4437 PetscFunctionReturn(0);
4438 }
4439 }
4440 *sf = dm->sectionSF;
4441 PetscFunctionReturn(0);
4442 }
4443
4444 /*@
4445 DMSetSectionSF - Set the PetscSF encoding the parallel dof overlap for the DM
4446
4447 Input Parameters:
4448 + dm - The DM
4449 - sf - The PetscSF
4450
4451 Level: intermediate
4452
4453 Note: Any previous SF is destroyed
4454
4455 .seealso: DMGetSectionSF(), DMCreateSectionSF()
4456 @*/
DMSetSectionSF(DM dm,PetscSF sf)4457 PetscErrorCode DMSetSectionSF(DM dm, PetscSF sf)
4458 {
4459 PetscErrorCode ierr;
4460
4461 PetscFunctionBegin;
4462 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4463 if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
4464 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr);
4465 ierr = PetscSFDestroy(&dm->sectionSF);CHKERRQ(ierr);
4466 dm->sectionSF = sf;
4467 PetscFunctionReturn(0);
4468 }
4469
4470 /*@C
4471 DMCreateSectionSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections
4472 describing the data layout.
4473
4474 Input Parameters:
4475 + dm - The DM
4476 . localSection - PetscSection describing the local data layout
4477 - globalSection - PetscSection describing the global data layout
4478
4479 Notes: One usually uses DMGetSectionSF() to obtain the PetscSF
4480
4481 Level: developer
4482
4483 Developer Note: Since this routine has for arguments the two sections from the DM and puts the resulting PetscSF
4484 directly into the DM, perhaps this function should not take the local and global sections as
4485 input and should just obtain them from the DM?
4486
4487 .seealso: DMGetSectionSF(), DMSetSectionSF(), DMGetLocalSection(), DMGetGlobalSection()
4488 @*/
DMCreateSectionSF(DM dm,PetscSection localSection,PetscSection globalSection)4489 PetscErrorCode DMCreateSectionSF(DM dm, PetscSection localSection, PetscSection globalSection)
4490 {
4491 MPI_Comm comm;
4492 PetscLayout layout;
4493 const PetscInt *ranges;
4494 PetscInt *local;
4495 PetscSFNode *remote;
4496 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l;
4497 PetscMPIInt size, rank;
4498 PetscErrorCode ierr;
4499
4500 PetscFunctionBegin;
4501 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4502 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
4503 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
4504 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
4505 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr);
4506 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr);
4507 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
4508 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
4509 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr);
4510 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
4511 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
4512 for (p = pStart; p < pEnd; ++p) {
4513 PetscInt gdof, gcdof;
4514
4515 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
4516 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
4517 if (gcdof > (gdof < 0 ? -(gdof+1) : gdof)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d has %d constraints > %d dof", p, gcdof, (gdof < 0 ? -(gdof+1) : gdof));
4518 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
4519 }
4520 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr);
4521 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr);
4522 for (p = pStart, l = 0; p < pEnd; ++p) {
4523 const PetscInt *cind;
4524 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c;
4525
4526 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr);
4527 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr);
4528 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr);
4529 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr);
4530 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
4531 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
4532 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr);
4533 if (!gdof) continue; /* Censored point */
4534 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
4535 if (gsize != dof-cdof) {
4536 if (gsize != dof) SETERRQ4(comm, PETSC_ERR_ARG_WRONG, "Global dof %d for point %d is neither the constrained size %d, nor the unconstrained %d", gsize, p, dof-cdof, dof);
4537 cdof = 0; /* Ignore constraints */
4538 }
4539 for (d = 0, c = 0; d < dof; ++d) {
4540 if ((c < cdof) && (cind[c] == d)) {++c; continue;}
4541 local[l+d-c] = off+d;
4542 }
4543 if (gdof < 0) {
4544 for (d = 0; d < gsize; ++d, ++l) {
4545 PetscInt offset = -(goff+1) + d, r;
4546
4547 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr);
4548 if (r < 0) r = -(r+2);
4549 if ((r < 0) || (r >= size)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d mapped to invalid process %d (%d, %d)", p, r, gdof, goff);
4550 remote[l].rank = r;
4551 remote[l].index = offset - ranges[r];
4552 }
4553 } else {
4554 for (d = 0; d < gsize; ++d, ++l) {
4555 remote[l].rank = rank;
4556 remote[l].index = goff+d - ranges[rank];
4557 }
4558 }
4559 }
4560 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves);
4561 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
4562 ierr = PetscSFSetGraph(dm->sectionSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr);
4563 PetscFunctionReturn(0);
4564 }
4565
4566 /*@
4567 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM.
4568
4569 Input Parameter:
4570 . dm - The DM
4571
4572 Output Parameter:
4573 . sf - The PetscSF
4574
4575 Level: intermediate
4576
4577 Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
4578
4579 .seealso: DMSetPointSF(), DMGetSectionSF(), DMSetSectionSF(), DMCreateSectionSF()
4580 @*/
DMGetPointSF(DM dm,PetscSF * sf)4581 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
4582 {
4583 PetscFunctionBegin;
4584 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4585 PetscValidPointer(sf, 2);
4586 *sf = dm->sf;
4587 PetscFunctionReturn(0);
4588 }
4589
4590 /*@
4591 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM.
4592
4593 Input Parameters:
4594 + dm - The DM
4595 - sf - The PetscSF
4596
4597 Level: intermediate
4598
4599 .seealso: DMGetPointSF(), DMGetSectionSF(), DMSetSectionSF(), DMCreateSectionSF()
4600 @*/
DMSetPointSF(DM dm,PetscSF sf)4601 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
4602 {
4603 PetscErrorCode ierr;
4604
4605 PetscFunctionBegin;
4606 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4607 if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
4608 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr);
4609 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr);
4610 dm->sf = sf;
4611 PetscFunctionReturn(0);
4612 }
4613
DMSetDefaultAdjacency_Private(DM dm,PetscInt f,PetscObject disc)4614 static PetscErrorCode DMSetDefaultAdjacency_Private(DM dm, PetscInt f, PetscObject disc)
4615 {
4616 PetscClassId id;
4617 PetscErrorCode ierr;
4618
4619 PetscFunctionBegin;
4620 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr);
4621 if (id == PETSCFE_CLASSID) {
4622 ierr = DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);CHKERRQ(ierr);
4623 } else if (id == PETSCFV_CLASSID) {
4624 ierr = DMSetAdjacency(dm, f, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr);
4625 } else {
4626 ierr = DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);CHKERRQ(ierr);
4627 }
4628 PetscFunctionReturn(0);
4629 }
4630
DMFieldEnlarge_Static(DM dm,PetscInt NfNew)4631 static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew)
4632 {
4633 RegionField *tmpr;
4634 PetscInt Nf = dm->Nf, f;
4635 PetscErrorCode ierr;
4636
4637 PetscFunctionBegin;
4638 if (Nf >= NfNew) PetscFunctionReturn(0);
4639 ierr = PetscMalloc1(NfNew, &tmpr);CHKERRQ(ierr);
4640 for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f];
4641 for (f = Nf; f < NfNew; ++f) {tmpr[f].disc = NULL; tmpr[f].label = NULL;}
4642 ierr = PetscFree(dm->fields);CHKERRQ(ierr);
4643 dm->Nf = NfNew;
4644 dm->fields = tmpr;
4645 PetscFunctionReturn(0);
4646 }
4647
4648 /*@
4649 DMClearFields - Remove all fields from the DM
4650
4651 Logically collective on dm
4652
4653 Input Parameter:
4654 . dm - The DM
4655
4656 Level: intermediate
4657
4658 .seealso: DMGetNumFields(), DMSetNumFields(), DMSetField()
4659 @*/
DMClearFields(DM dm)4660 PetscErrorCode DMClearFields(DM dm)
4661 {
4662 PetscInt f;
4663 PetscErrorCode ierr;
4664
4665 PetscFunctionBegin;
4666 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4667 for (f = 0; f < dm->Nf; ++f) {
4668 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr);
4669 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr);
4670 }
4671 ierr = PetscFree(dm->fields);CHKERRQ(ierr);
4672 dm->fields = NULL;
4673 dm->Nf = 0;
4674 PetscFunctionReturn(0);
4675 }
4676
4677 /*@
4678 DMGetNumFields - Get the number of fields in the DM
4679
4680 Not collective
4681
4682 Input Parameter:
4683 . dm - The DM
4684
4685 Output Parameter:
4686 . Nf - The number of fields
4687
4688 Level: intermediate
4689
4690 .seealso: DMSetNumFields(), DMSetField()
4691 @*/
DMGetNumFields(DM dm,PetscInt * numFields)4692 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
4693 {
4694 PetscFunctionBegin;
4695 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4696 PetscValidIntPointer(numFields, 2);
4697 *numFields = dm->Nf;
4698 PetscFunctionReturn(0);
4699 }
4700
4701 /*@
4702 DMSetNumFields - Set the number of fields in the DM
4703
4704 Logically collective on dm
4705
4706 Input Parameters:
4707 + dm - The DM
4708 - Nf - The number of fields
4709
4710 Level: intermediate
4711
4712 .seealso: DMGetNumFields(), DMSetField()
4713 @*/
DMSetNumFields(DM dm,PetscInt numFields)4714 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
4715 {
4716 PetscInt Nf, f;
4717 PetscErrorCode ierr;
4718
4719 PetscFunctionBegin;
4720 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4721 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
4722 for (f = Nf; f < numFields; ++f) {
4723 PetscContainer obj;
4724
4725 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr);
4726 ierr = DMAddField(dm, NULL, (PetscObject) obj);CHKERRQ(ierr);
4727 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr);
4728 }
4729 PetscFunctionReturn(0);
4730 }
4731
4732 /*@
4733 DMGetField - Return the discretization object for a given DM field
4734
4735 Not collective
4736
4737 Input Parameters:
4738 + dm - The DM
4739 - f - The field number
4740
4741 Output Parameters:
4742 + label - The label indicating the support of the field, or NULL for the entire mesh
4743 - field - The discretization object
4744
4745 Level: intermediate
4746
4747 .seealso: DMAddField(), DMSetField()
4748 @*/
DMGetField(DM dm,PetscInt f,DMLabel * label,PetscObject * field)4749 PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *field)
4750 {
4751 PetscFunctionBegin;
4752 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4753 PetscValidPointer(field, 3);
4754 if ((f < 0) || (f >= dm->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, dm->Nf);
4755 if (label) *label = dm->fields[f].label;
4756 if (field) *field = dm->fields[f].disc;
4757 PetscFunctionReturn(0);
4758 }
4759
4760 /* Does not clear the DS */
DMSetField_Internal(DM dm,PetscInt f,DMLabel label,PetscObject field)4761 PetscErrorCode DMSetField_Internal(DM dm, PetscInt f, DMLabel label, PetscObject field)
4762 {
4763 PetscErrorCode ierr;
4764
4765 PetscFunctionBegin;
4766 ierr = DMFieldEnlarge_Static(dm, f+1);CHKERRQ(ierr);
4767 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr);
4768 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr);
4769 dm->fields[f].label = label;
4770 dm->fields[f].disc = field;
4771 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr);
4772 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr);
4773 PetscFunctionReturn(0);
4774 }
4775
4776 /*@
4777 DMSetField - Set the discretization object for a given DM field
4778
4779 Logically collective on dm
4780
4781 Input Parameters:
4782 + dm - The DM
4783 . f - The field number
4784 . label - The label indicating the support of the field, or NULL for the entire mesh
4785 - field - The discretization object
4786
4787 Level: intermediate
4788
4789 .seealso: DMAddField(), DMGetField()
4790 @*/
DMSetField(DM dm,PetscInt f,DMLabel label,PetscObject field)4791 PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject field)
4792 {
4793 PetscErrorCode ierr;
4794
4795 PetscFunctionBegin;
4796 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4797 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
4798 PetscValidHeader(field, 4);
4799 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
4800 ierr = DMSetField_Internal(dm, f, label, field);CHKERRQ(ierr);
4801 ierr = DMSetDefaultAdjacency_Private(dm, f, field);CHKERRQ(ierr);
4802 ierr = DMClearDS(dm);CHKERRQ(ierr);
4803 PetscFunctionReturn(0);
4804 }
4805
4806 /*@
4807 DMAddField - Add the discretization object for the given DM field
4808
4809 Logically collective on dm
4810
4811 Input Parameters:
4812 + dm - The DM
4813 . label - The label indicating the support of the field, or NULL for the entire mesh
4814 - field - The discretization object
4815
4816 Level: intermediate
4817
4818 .seealso: DMSetField(), DMGetField()
4819 @*/
DMAddField(DM dm,DMLabel label,PetscObject field)4820 PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject field)
4821 {
4822 PetscInt Nf = dm->Nf;
4823 PetscErrorCode ierr;
4824
4825 PetscFunctionBegin;
4826 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4827 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
4828 PetscValidHeader(field, 3);
4829 ierr = DMFieldEnlarge_Static(dm, Nf+1);CHKERRQ(ierr);
4830 dm->fields[Nf].label = label;
4831 dm->fields[Nf].disc = field;
4832 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr);
4833 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr);
4834 ierr = DMSetDefaultAdjacency_Private(dm, Nf, field);CHKERRQ(ierr);
4835 ierr = DMClearDS(dm);CHKERRQ(ierr);
4836 PetscFunctionReturn(0);
4837 }
4838
4839 /*@
4840 DMCopyFields - Copy the discretizations for the DM into another DM
4841
4842 Collective on dm
4843
4844 Input Parameter:
4845 . dm - The DM
4846
4847 Output Parameter:
4848 . newdm - The DM
4849
4850 Level: advanced
4851
4852 .seealso: DMGetField(), DMSetField(), DMAddField(), DMCopyDS(), DMGetDS(), DMGetCellDS()
4853 @*/
DMCopyFields(DM dm,DM newdm)4854 PetscErrorCode DMCopyFields(DM dm, DM newdm)
4855 {
4856 PetscInt Nf, f;
4857 PetscErrorCode ierr;
4858
4859 PetscFunctionBegin;
4860 if (dm == newdm) PetscFunctionReturn(0);
4861 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
4862 ierr = DMClearFields(newdm);CHKERRQ(ierr);
4863 for (f = 0; f < Nf; ++f) {
4864 DMLabel label;
4865 PetscObject field;
4866 PetscBool useCone, useClosure;
4867
4868 ierr = DMGetField(dm, f, &label, &field);CHKERRQ(ierr);
4869 ierr = DMSetField(newdm, f, label, field);CHKERRQ(ierr);
4870 ierr = DMGetAdjacency(dm, f, &useCone, &useClosure);CHKERRQ(ierr);
4871 ierr = DMSetAdjacency(newdm, f, useCone, useClosure);CHKERRQ(ierr);
4872 }
4873 PetscFunctionReturn(0);
4874 }
4875
4876 /*@
4877 DMGetAdjacency - Returns the flags for determining variable influence
4878
4879 Not collective
4880
4881 Input Parameters:
4882 + dm - The DM object
4883 - f - The field number, or PETSC_DEFAULT for the default adjacency
4884
4885 Output Parameter:
4886 + useCone - Flag for variable influence starting with the cone operation
4887 - useClosure - Flag for variable influence using transitive closure
4888
4889 Notes:
4890 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE
4891 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE
4892 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE
4893 Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
4894
4895 Level: developer
4896
4897 .seealso: DMSetAdjacency(), DMGetField(), DMSetField()
4898 @*/
DMGetAdjacency(DM dm,PetscInt f,PetscBool * useCone,PetscBool * useClosure)4899 PetscErrorCode DMGetAdjacency(DM dm, PetscInt f, PetscBool *useCone, PetscBool *useClosure)
4900 {
4901 PetscFunctionBegin;
4902 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4903 if (useCone) PetscValidBoolPointer(useCone, 3);
4904 if (useClosure) PetscValidBoolPointer(useClosure, 4);
4905 if (f < 0) {
4906 if (useCone) *useCone = dm->adjacency[0];
4907 if (useClosure) *useClosure = dm->adjacency[1];
4908 } else {
4909 PetscInt Nf;
4910 PetscErrorCode ierr;
4911
4912 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
4913 if (f >= Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf);
4914 if (useCone) *useCone = dm->fields[f].adjacency[0];
4915 if (useClosure) *useClosure = dm->fields[f].adjacency[1];
4916 }
4917 PetscFunctionReturn(0);
4918 }
4919
4920 /*@
4921 DMSetAdjacency - Set the flags for determining variable influence
4922
4923 Not collective
4924
4925 Input Parameters:
4926 + dm - The DM object
4927 . f - The field number
4928 . useCone - Flag for variable influence starting with the cone operation
4929 - useClosure - Flag for variable influence using transitive closure
4930
4931 Notes:
4932 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE
4933 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE
4934 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE
4935 Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
4936
4937 Level: developer
4938
4939 .seealso: DMGetAdjacency(), DMGetField(), DMSetField()
4940 @*/
DMSetAdjacency(DM dm,PetscInt f,PetscBool useCone,PetscBool useClosure)4941 PetscErrorCode DMSetAdjacency(DM dm, PetscInt f, PetscBool useCone, PetscBool useClosure)
4942 {
4943 PetscFunctionBegin;
4944 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4945 if (f < 0) {
4946 dm->adjacency[0] = useCone;
4947 dm->adjacency[1] = useClosure;
4948 } else {
4949 PetscInt Nf;
4950 PetscErrorCode ierr;
4951
4952 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
4953 if (f >= Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf);
4954 dm->fields[f].adjacency[0] = useCone;
4955 dm->fields[f].adjacency[1] = useClosure;
4956 }
4957 PetscFunctionReturn(0);
4958 }
4959
4960 /*@
4961 DMGetBasicAdjacency - Returns the flags for determining variable influence, using either the default or field 0 if it is defined
4962
4963 Not collective
4964
4965 Input Parameters:
4966 . dm - The DM object
4967
4968 Output Parameter:
4969 + useCone - Flag for variable influence starting with the cone operation
4970 - useClosure - Flag for variable influence using transitive closure
4971
4972 Notes:
4973 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE
4974 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE
4975 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE
4976
4977 Level: developer
4978
4979 .seealso: DMSetBasicAdjacency(), DMGetField(), DMSetField()
4980 @*/
DMGetBasicAdjacency(DM dm,PetscBool * useCone,PetscBool * useClosure)4981 PetscErrorCode DMGetBasicAdjacency(DM dm, PetscBool *useCone, PetscBool *useClosure)
4982 {
4983 PetscInt Nf;
4984 PetscErrorCode ierr;
4985
4986 PetscFunctionBegin;
4987 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4988 if (useCone) PetscValidBoolPointer(useCone, 3);
4989 if (useClosure) PetscValidBoolPointer(useClosure, 4);
4990 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
4991 if (!Nf) {
4992 ierr = DMGetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr);
4993 } else {
4994 ierr = DMGetAdjacency(dm, 0, useCone, useClosure);CHKERRQ(ierr);
4995 }
4996 PetscFunctionReturn(0);
4997 }
4998
4999 /*@
5000 DMSetBasicAdjacency - Set the flags for determining variable influence, using either the default or field 0 if it is defined
5001
5002 Not collective
5003
5004 Input Parameters:
5005 + dm - The DM object
5006 . useCone - Flag for variable influence starting with the cone operation
5007 - useClosure - Flag for variable influence using transitive closure
5008
5009 Notes:
5010 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE
5011 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE
5012 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE
5013
5014 Level: developer
5015
5016 .seealso: DMGetBasicAdjacency(), DMGetField(), DMSetField()
5017 @*/
DMSetBasicAdjacency(DM dm,PetscBool useCone,PetscBool useClosure)5018 PetscErrorCode DMSetBasicAdjacency(DM dm, PetscBool useCone, PetscBool useClosure)
5019 {
5020 PetscInt Nf;
5021 PetscErrorCode ierr;
5022
5023 PetscFunctionBegin;
5024 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5025 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
5026 if (!Nf) {
5027 ierr = DMSetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr);
5028 } else {
5029 ierr = DMSetAdjacency(dm, 0, useCone, useClosure);CHKERRQ(ierr);
5030 }
5031 PetscFunctionReturn(0);
5032 }
5033
5034 /* Complete labels that are being used for FEM BC */
DMCompleteBoundaryLabel_Internal(DM dm,PetscDS ds,PetscInt field,PetscInt bdNum,const char labelname[])5035 static PetscErrorCode DMCompleteBoundaryLabel_Internal(DM dm, PetscDS ds, PetscInt field, PetscInt bdNum, const char labelname[])
5036 {
5037 DMLabel label;
5038 PetscObject obj;
5039 PetscClassId id;
5040 PetscInt Nbd, bd;
5041 PetscBool isFE = PETSC_FALSE;
5042 PetscBool duplicate = PETSC_FALSE;
5043 PetscErrorCode ierr;
5044
5045 PetscFunctionBegin;
5046 ierr = DMGetField(dm, field, NULL, &obj);CHKERRQ(ierr);
5047 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
5048 if (id == PETSCFE_CLASSID) isFE = PETSC_TRUE;
5049 ierr = DMGetLabel(dm, labelname, &label);CHKERRQ(ierr);
5050 if (isFE && label) {
5051 /* Only want to modify label once */
5052 ierr = PetscDSGetNumBoundary(ds, &Nbd);CHKERRQ(ierr);
5053 for (bd = 0; bd < PetscMin(Nbd, bdNum); ++bd) {
5054 const char *lname;
5055
5056 ierr = PetscDSGetBoundary(ds, bd, NULL, NULL, &lname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
5057 ierr = PetscStrcmp(lname, labelname, &duplicate);CHKERRQ(ierr);
5058 if (duplicate) break;
5059 }
5060 if (!duplicate) {
5061 DM plex;
5062
5063 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr);
5064 if (plex) {ierr = DMPlexLabelComplete(plex, label);CHKERRQ(ierr);}
5065 ierr = DMDestroy(&plex);CHKERRQ(ierr);
5066 }
5067 }
5068 PetscFunctionReturn(0);
5069 }
5070
DMDSEnlarge_Static(DM dm,PetscInt NdsNew)5071 static PetscErrorCode DMDSEnlarge_Static(DM dm, PetscInt NdsNew)
5072 {
5073 DMSpace *tmpd;
5074 PetscInt Nds = dm->Nds, s;
5075 PetscErrorCode ierr;
5076
5077 PetscFunctionBegin;
5078 if (Nds >= NdsNew) PetscFunctionReturn(0);
5079 ierr = PetscMalloc1(NdsNew, &tmpd);CHKERRQ(ierr);
5080 for (s = 0; s < Nds; ++s) tmpd[s] = dm->probs[s];
5081 for (s = Nds; s < NdsNew; ++s) {tmpd[s].ds = NULL; tmpd[s].label = NULL; tmpd[s].fields = NULL;}
5082 ierr = PetscFree(dm->probs);CHKERRQ(ierr);
5083 dm->Nds = NdsNew;
5084 dm->probs = tmpd;
5085 PetscFunctionReturn(0);
5086 }
5087
5088 /*@
5089 DMGetNumDS - Get the number of discrete systems in the DM
5090
5091 Not collective
5092
5093 Input Parameter:
5094 . dm - The DM
5095
5096 Output Parameter:
5097 . Nds - The number of PetscDS objects
5098
5099 Level: intermediate
5100
5101 .seealso: DMGetDS(), DMGetCellDS()
5102 @*/
DMGetNumDS(DM dm,PetscInt * Nds)5103 PetscErrorCode DMGetNumDS(DM dm, PetscInt *Nds)
5104 {
5105 PetscFunctionBegin;
5106 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5107 PetscValidIntPointer(Nds, 2);
5108 *Nds = dm->Nds;
5109 PetscFunctionReturn(0);
5110 }
5111
5112 /*@
5113 DMClearDS - Remove all discrete systems from the DM
5114
5115 Logically collective on dm
5116
5117 Input Parameter:
5118 . dm - The DM
5119
5120 Level: intermediate
5121
5122 .seealso: DMGetNumDS(), DMGetDS(), DMSetField()
5123 @*/
DMClearDS(DM dm)5124 PetscErrorCode DMClearDS(DM dm)
5125 {
5126 PetscInt s;
5127 PetscErrorCode ierr;
5128
5129 PetscFunctionBegin;
5130 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5131 for (s = 0; s < dm->Nds; ++s) {
5132 ierr = PetscDSDestroy(&dm->probs[s].ds);CHKERRQ(ierr);
5133 ierr = DMLabelDestroy(&dm->probs[s].label);CHKERRQ(ierr);
5134 ierr = ISDestroy(&dm->probs[s].fields);CHKERRQ(ierr);
5135 }
5136 ierr = PetscFree(dm->probs);CHKERRQ(ierr);
5137 dm->probs = NULL;
5138 dm->Nds = 0;
5139 PetscFunctionReturn(0);
5140 }
5141
5142 /*@
5143 DMGetDS - Get the default PetscDS
5144
5145 Not collective
5146
5147 Input Parameter:
5148 . dm - The DM
5149
5150 Output Parameter:
5151 . prob - The default PetscDS
5152
5153 Level: intermediate
5154
5155 .seealso: DMGetCellDS(), DMGetRegionDS()
5156 @*/
DMGetDS(DM dm,PetscDS * prob)5157 PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
5158 {
5159 PetscErrorCode ierr;
5160
5161 PetscFunctionBeginHot;
5162 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5163 PetscValidPointer(prob, 2);
5164 if (dm->Nds <= 0) {
5165 PetscDS ds;
5166
5167 ierr = PetscDSCreate(PetscObjectComm((PetscObject) dm), &ds);CHKERRQ(ierr);
5168 ierr = DMSetRegionDS(dm, NULL, NULL, ds);CHKERRQ(ierr);
5169 ierr = PetscDSDestroy(&ds);CHKERRQ(ierr);
5170 }
5171 *prob = dm->probs[0].ds;
5172 PetscFunctionReturn(0);
5173 }
5174
5175 /*@
5176 DMGetCellDS - Get the PetscDS defined on a given cell
5177
5178 Not collective
5179
5180 Input Parameters:
5181 + dm - The DM
5182 - point - Cell for the DS
5183
5184 Output Parameter:
5185 . prob - The PetscDS defined on the given cell
5186
5187 Level: developer
5188
5189 .seealso: DMGetDS(), DMSetRegionDS()
5190 @*/
DMGetCellDS(DM dm,PetscInt point,PetscDS * prob)5191 PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *prob)
5192 {
5193 PetscDS probDef = NULL;
5194 PetscInt s;
5195 PetscErrorCode ierr;
5196
5197 PetscFunctionBeginHot;
5198 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5199 PetscValidPointer(prob, 3);
5200 if (point < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point cannot be negative: %D", point);
5201 *prob = NULL;
5202 for (s = 0; s < dm->Nds; ++s) {
5203 PetscInt val;
5204
5205 if (!dm->probs[s].label) {probDef = dm->probs[s].ds;}
5206 else {
5207 ierr = DMLabelGetValue(dm->probs[s].label, point, &val);CHKERRQ(ierr);
5208 if (val >= 0) {*prob = dm->probs[s].ds; break;}
5209 }
5210 }
5211 if (!*prob) *prob = probDef;
5212 PetscFunctionReturn(0);
5213 }
5214
5215 /*@
5216 DMGetRegionDS - Get the PetscDS for a given mesh region, defined by a DMLabel
5217
5218 Not collective
5219
5220 Input Parameters:
5221 + dm - The DM
5222 - label - The DMLabel defining the mesh region, or NULL for the entire mesh
5223
5224 Output Parameters:
5225 + fields - The IS containing the DM field numbers for the fields in this DS, or NULL
5226 - prob - The PetscDS defined on the given region, or NULL
5227
5228 Note: If the label is missing, this function returns an error
5229
5230 Level: advanced
5231
5232 .seealso: DMGetRegionNumDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS()
5233 @*/
DMGetRegionDS(DM dm,DMLabel label,IS * fields,PetscDS * ds)5234 PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds)
5235 {
5236 PetscInt Nds = dm->Nds, s;
5237
5238 PetscFunctionBegin;
5239 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5240 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
5241 if (fields) {PetscValidPointer(fields, 3); *fields = NULL;}
5242 if (ds) {PetscValidPointer(ds, 4); *ds = NULL;}
5243 for (s = 0; s < Nds; ++s) {
5244 if (dm->probs[s].label == label) {
5245 if (fields) *fields = dm->probs[s].fields;
5246 if (ds) *ds = dm->probs[s].ds;
5247 PetscFunctionReturn(0);
5248 }
5249 }
5250 PetscFunctionReturn(0);
5251 }
5252
5253 /*@
5254 DMSetRegionDS - Set the PetscDS for a given mesh region, defined by a DMLabel
5255
5256 Collective on dm
5257
5258 Input Parameters:
5259 + dm - The DM
5260 . label - The DMLabel defining the mesh region, or NULL for the entire mesh
5261 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL for all fields
5262 - prob - The PetscDS defined on the given cell
5263
5264 Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM. If DS is replaced,
5265 the fields argument is ignored.
5266
5267 Level: advanced
5268
5269 .seealso: DMGetRegionDS(), DMSetRegionNumDS(), DMGetDS(), DMGetCellDS()
5270 @*/
DMSetRegionDS(DM dm,DMLabel label,IS fields,PetscDS ds)5271 PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds)
5272 {
5273 PetscInt Nds = dm->Nds, s;
5274 PetscErrorCode ierr;
5275
5276 PetscFunctionBegin;
5277 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5278 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
5279 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 3);
5280 for (s = 0; s < Nds; ++s) {
5281 if (dm->probs[s].label == label) {
5282 ierr = PetscDSDestroy(&dm->probs[s].ds);CHKERRQ(ierr);
5283 dm->probs[s].ds = ds;
5284 PetscFunctionReturn(0);
5285 }
5286 }
5287 ierr = DMDSEnlarge_Static(dm, Nds+1);CHKERRQ(ierr);
5288 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr);
5289 ierr = PetscObjectReference((PetscObject) fields);CHKERRQ(ierr);
5290 ierr = PetscObjectReference((PetscObject) ds);CHKERRQ(ierr);
5291 if (!label) {
5292 /* Put the NULL label at the front, so it is returned as the default */
5293 for (s = Nds-1; s >=0; --s) dm->probs[s+1] = dm->probs[s];
5294 Nds = 0;
5295 }
5296 dm->probs[Nds].label = label;
5297 dm->probs[Nds].fields = fields;
5298 dm->probs[Nds].ds = ds;
5299 PetscFunctionReturn(0);
5300 }
5301
5302 /*@
5303 DMGetRegionNumDS - Get the PetscDS for a given mesh region, defined by the region number
5304
5305 Not collective
5306
5307 Input Parameters:
5308 + dm - The DM
5309 - num - The region number, in [0, Nds)
5310
5311 Output Parameters:
5312 + label - The region label, or NULL
5313 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL
5314 - ds - The PetscDS defined on the given region, or NULL
5315
5316 Level: advanced
5317
5318 .seealso: DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS()
5319 @*/
DMGetRegionNumDS(DM dm,PetscInt num,DMLabel * label,IS * fields,PetscDS * ds)5320 PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds)
5321 {
5322 PetscInt Nds;
5323 PetscErrorCode ierr;
5324
5325 PetscFunctionBegin;
5326 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5327 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
5328 if ((num < 0) || (num >= Nds)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Region number %D is not in [0, %D)", num, Nds);
5329 if (label) {
5330 PetscValidPointer(label, 3);
5331 *label = dm->probs[num].label;
5332 }
5333 if (fields) {
5334 PetscValidPointer(fields, 4);
5335 *fields = dm->probs[num].fields;
5336 }
5337 if (ds) {
5338 PetscValidPointer(ds, 5);
5339 *ds = dm->probs[num].ds;
5340 }
5341 PetscFunctionReturn(0);
5342 }
5343
5344 /*@
5345 DMSetRegionNumDS - Set the PetscDS for a given mesh region, defined by the region number
5346
5347 Not collective
5348
5349 Input Parameters:
5350 + dm - The DM
5351 . num - The region number, in [0, Nds)
5352 . label - The region label, or NULL
5353 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL to prevent setting
5354 - ds - The PetscDS defined on the given region, or NULL to prevent setting
5355
5356 Level: advanced
5357
5358 .seealso: DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS()
5359 @*/
DMSetRegionNumDS(DM dm,PetscInt num,DMLabel label,IS fields,PetscDS ds)5360 PetscErrorCode DMSetRegionNumDS(DM dm, PetscInt num, DMLabel label, IS fields, PetscDS ds)
5361 {
5362 PetscInt Nds;
5363 PetscErrorCode ierr;
5364
5365 PetscFunctionBegin;
5366 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5367 if (label) {PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);}
5368 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
5369 if ((num < 0) || (num >= Nds)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Region number %D is not in [0, %D)", num, Nds);
5370 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr);
5371 ierr = DMLabelDestroy(&dm->probs[num].label);CHKERRQ(ierr);
5372 dm->probs[num].label = label;
5373 if (fields) {
5374 PetscValidHeaderSpecific(fields, IS_CLASSID, 4);
5375 ierr = PetscObjectReference((PetscObject) fields);CHKERRQ(ierr);
5376 ierr = ISDestroy(&dm->probs[num].fields);CHKERRQ(ierr);
5377 dm->probs[num].fields = fields;
5378 }
5379 if (ds) {
5380 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 5);
5381 ierr = PetscObjectReference((PetscObject) ds);CHKERRQ(ierr);
5382 ierr = PetscDSDestroy(&dm->probs[num].ds);CHKERRQ(ierr);
5383 dm->probs[num].ds = ds;
5384 }
5385 PetscFunctionReturn(0);
5386 }
5387
5388 /*@
5389 DMFindRegionNum - Find the region number for a given PetscDS, or -1 if it is not found.
5390
5391 Not collective
5392
5393 Input Parameters:
5394 + dm - The DM
5395 - ds - The PetscDS defined on the given region
5396
5397 Output Parameter:
5398 . num - The region number, in [0, Nds), or -1 if not found
5399
5400 Level: advanced
5401
5402 .seealso: DMGetRegionNumDS(), DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS()
5403 @*/
DMFindRegionNum(DM dm,PetscDS ds,PetscInt * num)5404 PetscErrorCode DMFindRegionNum(DM dm, PetscDS ds, PetscInt *num)
5405 {
5406 PetscInt Nds, n;
5407 PetscErrorCode ierr;
5408
5409 PetscFunctionBegin;
5410 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5411 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 2);
5412 PetscValidPointer(num, 3);
5413 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
5414 for (n = 0; n < Nds; ++n) if (ds == dm->probs[n].ds) break;
5415 if (n >= Nds) *num = -1;
5416 else *num = n;
5417 PetscFunctionReturn(0);
5418 }
5419
5420 /*@
5421 DMCreateDS - Create the discrete systems for the DM based upon the fields added to the DM
5422
5423 Collective on dm
5424
5425 Input Parameter:
5426 . dm - The DM
5427
5428 Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM.
5429
5430 Level: intermediate
5431
5432 .seealso: DMSetField, DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS()
5433 @*/
DMCreateDS(DM dm)5434 PetscErrorCode DMCreateDS(DM dm)
5435 {
5436 MPI_Comm comm;
5437 PetscDS dsDef;
5438 DMLabel *labelSet;
5439 PetscInt dE, Nf = dm->Nf, f, s, Nl, l, Ndef;
5440 PetscBool doSetup = PETSC_TRUE;
5441 PetscErrorCode ierr;
5442
5443 PetscFunctionBegin;
5444 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5445 if (!dm->fields) PetscFunctionReturn(0);
5446 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
5447 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr);
5448 /* Determine how many regions we have */
5449 ierr = PetscMalloc1(Nf, &labelSet);CHKERRQ(ierr);
5450 Nl = 0;
5451 Ndef = 0;
5452 for (f = 0; f < Nf; ++f) {
5453 DMLabel label = dm->fields[f].label;
5454 PetscInt l;
5455
5456 if (!label) {++Ndef; continue;}
5457 for (l = 0; l < Nl; ++l) if (label == labelSet[l]) break;
5458 if (l < Nl) continue;
5459 labelSet[Nl++] = label;
5460 }
5461 /* Create default DS if there are no labels to intersect with */
5462 ierr = DMGetRegionDS(dm, NULL, NULL, &dsDef);CHKERRQ(ierr);
5463 if (!dsDef && Ndef && !Nl) {
5464 IS fields;
5465 PetscInt *fld, nf;
5466
5467 for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) ++nf;
5468 if (nf) {
5469 ierr = PetscMalloc1(nf, &fld);CHKERRQ(ierr);
5470 for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) fld[nf++] = f;
5471 ierr = ISCreate(PETSC_COMM_SELF, &fields);CHKERRQ(ierr);
5472 ierr = PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");CHKERRQ(ierr);
5473 ierr = ISSetType(fields, ISGENERAL);CHKERRQ(ierr);
5474 ierr = ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER);CHKERRQ(ierr);
5475
5476 ierr = PetscDSCreate(comm, &dsDef);CHKERRQ(ierr);
5477 ierr = DMSetRegionDS(dm, NULL, fields, dsDef);CHKERRQ(ierr);
5478 ierr = PetscDSDestroy(&dsDef);CHKERRQ(ierr);
5479 ierr = ISDestroy(&fields);CHKERRQ(ierr);
5480 }
5481 }
5482 ierr = DMGetRegionDS(dm, NULL, NULL, &dsDef);CHKERRQ(ierr);
5483 if (dsDef) {ierr = PetscDSSetCoordinateDimension(dsDef, dE);CHKERRQ(ierr);}
5484 /* Intersect labels with default fields */
5485 if (Ndef && Nl) {
5486 DM plex;
5487 DMLabel cellLabel;
5488 IS fieldIS, allcellIS, defcellIS = NULL;
5489 PetscInt *fields;
5490 const PetscInt *cells;
5491 PetscInt depth, nf = 0, n, c;
5492
5493 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr);
5494 ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr);
5495 ierr = DMGetStratumIS(plex, "dim", depth, &allcellIS);CHKERRQ(ierr);
5496 if (!allcellIS) {ierr = DMGetStratumIS(plex, "depth", depth, &allcellIS);CHKERRQ(ierr);}
5497 for (l = 0; l < Nl; ++l) {
5498 DMLabel label = labelSet[l];
5499 IS pointIS;
5500
5501 ierr = ISDestroy(&defcellIS);CHKERRQ(ierr);
5502 ierr = DMLabelGetStratumIS(label, 1, &pointIS);CHKERRQ(ierr);
5503 ierr = ISDifference(allcellIS, pointIS, &defcellIS);CHKERRQ(ierr);
5504 ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
5505 }
5506 ierr = ISDestroy(&allcellIS);CHKERRQ(ierr);
5507
5508 ierr = DMLabelCreate(PETSC_COMM_SELF, "defaultCells", &cellLabel);CHKERRQ(ierr);
5509 ierr = ISGetLocalSize(defcellIS, &n);CHKERRQ(ierr);
5510 ierr = ISGetIndices(defcellIS, &cells);CHKERRQ(ierr);
5511 for (c = 0; c < n; ++c) {ierr = DMLabelSetValue(cellLabel, cells[c], 1);CHKERRQ(ierr);}
5512 ierr = ISRestoreIndices(defcellIS, &cells);CHKERRQ(ierr);
5513 ierr = ISDestroy(&defcellIS);CHKERRQ(ierr);
5514 ierr = DMPlexLabelComplete(plex, cellLabel);CHKERRQ(ierr);
5515
5516 ierr = PetscMalloc1(Ndef, &fields);CHKERRQ(ierr);
5517 for (f = 0; f < Nf; ++f) if (!dm->fields[f].label) fields[nf++] = f;
5518 ierr = ISCreate(PETSC_COMM_SELF, &fieldIS);CHKERRQ(ierr);
5519 ierr = PetscObjectSetOptionsPrefix((PetscObject) fieldIS, "dm_fields_");CHKERRQ(ierr);
5520 ierr = ISSetType(fieldIS, ISGENERAL);CHKERRQ(ierr);
5521 ierr = ISGeneralSetIndices(fieldIS, nf, fields, PETSC_OWN_POINTER);CHKERRQ(ierr);
5522
5523 ierr = PetscDSCreate(comm, &dsDef);CHKERRQ(ierr);
5524 ierr = DMSetRegionDS(dm, cellLabel, fieldIS, dsDef);CHKERRQ(ierr);
5525 ierr = DMLabelDestroy(&cellLabel);CHKERRQ(ierr);
5526 ierr = PetscDSSetCoordinateDimension(dsDef, dE);CHKERRQ(ierr);
5527 ierr = PetscDSDestroy(&dsDef);CHKERRQ(ierr);
5528 ierr = ISDestroy(&fieldIS);CHKERRQ(ierr);
5529 ierr = DMDestroy(&plex);CHKERRQ(ierr);
5530 }
5531 /* Create label DSes
5532 - WE ONLY SUPPORT IDENTICAL OR DISJOINT LABELS
5533 */
5534 /* TODO Should check that labels are disjoint */
5535 for (l = 0; l < Nl; ++l) {
5536 DMLabel label = labelSet[l];
5537 PetscDS ds;
5538 IS fields;
5539 PetscInt *fld, nf;
5540
5541 ierr = PetscDSCreate(comm, &ds);CHKERRQ(ierr);
5542 for (f = 0, nf = 0; f < Nf; ++f) if (label == dm->fields[f].label || !dm->fields[f].label) ++nf;
5543 ierr = PetscMalloc1(nf, &fld);CHKERRQ(ierr);
5544 for (f = 0, nf = 0; f < Nf; ++f) if (label == dm->fields[f].label || !dm->fields[f].label) fld[nf++] = f;
5545 ierr = ISCreate(PETSC_COMM_SELF, &fields);CHKERRQ(ierr);
5546 ierr = PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");CHKERRQ(ierr);
5547 ierr = ISSetType(fields, ISGENERAL);CHKERRQ(ierr);
5548 ierr = ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER);CHKERRQ(ierr);
5549 ierr = DMSetRegionDS(dm, label, fields, ds);CHKERRQ(ierr);
5550 ierr = ISDestroy(&fields);CHKERRQ(ierr);
5551 ierr = PetscDSSetCoordinateDimension(ds, dE);CHKERRQ(ierr);
5552 {
5553 DMPolytopeType ct;
5554 PetscInt lStart, lEnd;
5555 PetscBool isHybridLocal = PETSC_FALSE, isHybrid;
5556
5557 ierr = DMLabelGetBounds(label, &lStart, &lEnd);CHKERRQ(ierr);
5558 if (lStart >= 0) {
5559 ierr = DMPlexGetCellType(dm, lStart, &ct);CHKERRQ(ierr);
5560 switch (ct) {
5561 case DM_POLYTOPE_POINT_PRISM_TENSOR:
5562 case DM_POLYTOPE_SEG_PRISM_TENSOR:
5563 case DM_POLYTOPE_TRI_PRISM_TENSOR:
5564 case DM_POLYTOPE_QUAD_PRISM_TENSOR:
5565 isHybridLocal = PETSC_TRUE;break;
5566 default: break;
5567 }
5568 }
5569 ierr = MPI_Allreduce(&isHybridLocal, &isHybrid, 1, MPIU_BOOL, MPI_LOR, comm);CHKERRQ(ierr);
5570 ierr = PetscDSSetHybrid(ds, isHybrid);CHKERRQ(ierr);
5571 }
5572 ierr = PetscDSDestroy(&ds);CHKERRQ(ierr);
5573 }
5574 ierr = PetscFree(labelSet);CHKERRQ(ierr);
5575 /* Set fields in DSes */
5576 for (s = 0; s < dm->Nds; ++s) {
5577 PetscDS ds = dm->probs[s].ds;
5578 IS fields = dm->probs[s].fields;
5579 const PetscInt *fld;
5580 PetscInt nf;
5581
5582 ierr = ISGetLocalSize(fields, &nf);CHKERRQ(ierr);
5583 ierr = ISGetIndices(fields, &fld);CHKERRQ(ierr);
5584 for (f = 0; f < nf; ++f) {
5585 PetscObject disc = dm->fields[fld[f]].disc;
5586 PetscBool isHybrid;
5587 PetscClassId id;
5588
5589 ierr = PetscDSGetHybrid(ds, &isHybrid);CHKERRQ(ierr);
5590 /* If this is a cohesive cell, then it needs the lower dimensional discretization */
5591 if (isHybrid && f < nf-1) {ierr = PetscFEGetHeightSubspace((PetscFE) disc, 1, (PetscFE *) &disc);CHKERRQ(ierr);}
5592 ierr = PetscDSSetDiscretization(ds, f, disc);CHKERRQ(ierr);
5593 /* We allow people to have placeholder fields and construct the Section by hand */
5594 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr);
5595 if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE;
5596 }
5597 ierr = ISRestoreIndices(fields, &fld);CHKERRQ(ierr);
5598 }
5599 /* Setup DSes */
5600 if (doSetup) {
5601 for (s = 0; s < dm->Nds; ++s) {ierr = PetscDSSetUp(dm->probs[s].ds);CHKERRQ(ierr);}
5602 }
5603 PetscFunctionReturn(0);
5604 }
5605
5606 /*@
5607 DMComputeExactSolution - Compute the exact solution for a given DM, using the PetscDS information.
5608
5609 Collective on DM
5610
5611 Input Parameters:
5612 + dm - The DM
5613 - time - The time
5614
5615 Output Parameters:
5616 + u - The vector will be filled with exact solution values, or NULL
5617 - u_t - The vector will be filled with the time derivative of exact solution values, or NULL
5618
5619 Note: The user must call PetscDSSetExactSolution() beforehand
5620
5621 Level: developer
5622
5623 .seealso: PetscDSSetExactSolution()
5624 @*/
DMComputeExactSolution(DM dm,PetscReal time,Vec u,Vec u_t)5625 PetscErrorCode DMComputeExactSolution(DM dm, PetscReal time, Vec u, Vec u_t)
5626 {
5627 PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx);
5628 void **ectxs;
5629 PetscInt Nf, Nds, s;
5630 PetscErrorCode ierr;
5631
5632 PetscFunctionBegin;
5633 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5634 if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
5635 if (u_t) PetscValidHeaderSpecific(u_t, VEC_CLASSID, 4);
5636 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
5637 ierr = PetscMalloc2(Nf, &exacts, Nf, &ectxs);CHKERRQ(ierr);
5638 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
5639 for (s = 0; s < Nds; ++s) {
5640 PetscDS ds;
5641 DMLabel label;
5642 IS fieldIS;
5643 const PetscInt *fields, id = 1;
5644 PetscInt dsNf, f;
5645
5646 ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr);
5647 ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr);
5648 ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr);
5649 ierr = PetscArrayzero(exacts, Nf);CHKERRQ(ierr);
5650 ierr = PetscArrayzero(ectxs, Nf);CHKERRQ(ierr);
5651 if (u) {
5652 for (f = 0; f < dsNf; ++f) {
5653 const PetscInt field = fields[f];
5654 ierr = PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr);
5655 }
5656 ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr);
5657 if (label) {
5658 ierr = DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u);CHKERRQ(ierr);
5659 } else {
5660 ierr = DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u);CHKERRQ(ierr);
5661 }
5662 }
5663 if (u_t) {
5664 ierr = PetscArrayzero(exacts, Nf);CHKERRQ(ierr);
5665 ierr = PetscArrayzero(ectxs, Nf);CHKERRQ(ierr);
5666 for (f = 0; f < dsNf; ++f) {
5667 const PetscInt field = fields[f];
5668 ierr = PetscDSGetExactSolutionTimeDerivative(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr);
5669 }
5670 ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr);
5671 if (label) {
5672 ierr = DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u_t);CHKERRQ(ierr);
5673 } else {
5674 ierr = DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u_t);CHKERRQ(ierr);
5675 }
5676 }
5677 }
5678 if (u) {
5679 ierr = PetscObjectSetName((PetscObject) u, "Exact Solution");CHKERRQ(ierr);
5680 ierr = PetscObjectSetOptionsPrefix((PetscObject) u, "exact_");CHKERRQ(ierr);
5681 }
5682 if (u_t) {
5683 ierr = PetscObjectSetName((PetscObject) u, "Exact Solution Time Derivative");CHKERRQ(ierr);
5684 ierr = PetscObjectSetOptionsPrefix((PetscObject) u_t, "exact_t_");CHKERRQ(ierr);
5685 }
5686 ierr = PetscFree2(exacts, ectxs);CHKERRQ(ierr);
5687 PetscFunctionReturn(0);
5688 }
5689
5690 /*@
5691 DMCopyDS - Copy the discrete systems for the DM into another DM
5692
5693 Collective on dm
5694
5695 Input Parameter:
5696 . dm - The DM
5697
5698 Output Parameter:
5699 . newdm - The DM
5700
5701 Level: advanced
5702
5703 .seealso: DMCopyFields(), DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS()
5704 @*/
DMCopyDS(DM dm,DM newdm)5705 PetscErrorCode DMCopyDS(DM dm, DM newdm)
5706 {
5707 PetscInt Nds, s;
5708 PetscErrorCode ierr;
5709
5710 PetscFunctionBegin;
5711 if (dm == newdm) PetscFunctionReturn(0);
5712 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
5713 ierr = DMClearDS(newdm);CHKERRQ(ierr);
5714 for (s = 0; s < Nds; ++s) {
5715 DMLabel label;
5716 IS fields;
5717 PetscDS ds;
5718 PetscInt Nbd, bd;
5719
5720 ierr = DMGetRegionNumDS(dm, s, &label, &fields, &ds);CHKERRQ(ierr);
5721 ierr = DMSetRegionDS(newdm, label, fields, ds);CHKERRQ(ierr);
5722 ierr = PetscDSGetNumBoundary(ds, &Nbd);CHKERRQ(ierr);
5723 for (bd = 0; bd < Nbd; ++bd) {
5724 const char *labelname, *name;
5725 PetscInt field;
5726
5727 /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */
5728 ierr = PetscDSGetBoundary(ds, bd, NULL, &name, &labelname, &field, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
5729 ierr = DMCompleteBoundaryLabel_Internal(newdm, ds, field, bd, labelname);CHKERRQ(ierr);
5730 }
5731 }
5732 PetscFunctionReturn(0);
5733 }
5734
5735 /*@
5736 DMCopyDisc - Copy the fields and discrete systems for the DM into another DM
5737
5738 Collective on dm
5739
5740 Input Parameter:
5741 . dm - The DM
5742
5743 Output Parameter:
5744 . newdm - The DM
5745
5746 Level: advanced
5747
5748 .seealso: DMCopyFields(), DMCopyDS()
5749 @*/
DMCopyDisc(DM dm,DM newdm)5750 PetscErrorCode DMCopyDisc(DM dm, DM newdm)
5751 {
5752 PetscErrorCode ierr;
5753
5754 PetscFunctionBegin;
5755 ierr = DMCopyFields(dm, newdm);CHKERRQ(ierr);
5756 ierr = DMCopyDS(dm, newdm);CHKERRQ(ierr);
5757 PetscFunctionReturn(0);
5758 }
5759
DMRestrictHook_Coordinates(DM dm,DM dmc,void * ctx)5760 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx)
5761 {
5762 DM dm_coord,dmc_coord;
5763 PetscErrorCode ierr;
5764 Vec coords,ccoords;
5765 Mat inject;
5766 PetscFunctionBegin;
5767 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
5768 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr);
5769 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
5770 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr);
5771 if (coords && !ccoords) {
5772 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr);
5773 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr);
5774 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr);
5775 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr);
5776 ierr = MatDestroy(&inject);CHKERRQ(ierr);
5777 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr);
5778 ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
5779 }
5780 PetscFunctionReturn(0);
5781 }
5782
DMSubDomainHook_Coordinates(DM dm,DM subdm,void * ctx)5783 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx)
5784 {
5785 DM dm_coord,subdm_coord;
5786 PetscErrorCode ierr;
5787 Vec coords,ccoords,clcoords;
5788 VecScatter *scat_i,*scat_g;
5789 PetscFunctionBegin;
5790 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
5791 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr);
5792 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
5793 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr);
5794 if (coords && !ccoords) {
5795 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr);
5796 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr);
5797 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr);
5798 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr);
5799 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr);
5800 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5801 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5802 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5803 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5804 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr);
5805 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr);
5806 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr);
5807 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr);
5808 ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
5809 ierr = VecDestroy(&clcoords);CHKERRQ(ierr);
5810 ierr = PetscFree(scat_i);CHKERRQ(ierr);
5811 ierr = PetscFree(scat_g);CHKERRQ(ierr);
5812 }
5813 PetscFunctionReturn(0);
5814 }
5815
5816 /*@
5817 DMGetDimension - Return the topological dimension of the DM
5818
5819 Not collective
5820
5821 Input Parameter:
5822 . dm - The DM
5823
5824 Output Parameter:
5825 . dim - The topological dimension
5826
5827 Level: beginner
5828
5829 .seealso: DMSetDimension(), DMCreate()
5830 @*/
DMGetDimension(DM dm,PetscInt * dim)5831 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
5832 {
5833 PetscFunctionBegin;
5834 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5835 PetscValidIntPointer(dim, 2);
5836 *dim = dm->dim;
5837 PetscFunctionReturn(0);
5838 }
5839
5840 /*@
5841 DMSetDimension - Set the topological dimension of the DM
5842
5843 Collective on dm
5844
5845 Input Parameters:
5846 + dm - The DM
5847 - dim - The topological dimension
5848
5849 Level: beginner
5850
5851 .seealso: DMGetDimension(), DMCreate()
5852 @*/
DMSetDimension(DM dm,PetscInt dim)5853 PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
5854 {
5855 PetscDS ds;
5856 PetscErrorCode ierr;
5857
5858 PetscFunctionBegin;
5859 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5860 PetscValidLogicalCollectiveInt(dm, dim, 2);
5861 dm->dim = dim;
5862 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
5863 if (ds->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(ds, dm->dim);CHKERRQ(ierr);}
5864 PetscFunctionReturn(0);
5865 }
5866
5867 /*@
5868 DMGetDimPoints - Get the half-open interval for all points of a given dimension
5869
5870 Collective on dm
5871
5872 Input Parameters:
5873 + dm - the DM
5874 - dim - the dimension
5875
5876 Output Parameters:
5877 + pStart - The first point of the given dimension
5878 - pEnd - The first point following points of the given dimension
5879
5880 Note:
5881 The points are vertices in the Hasse diagram encoding the topology. This is explained in
5882 https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme,
5883 then the interval is empty.
5884
5885 Level: intermediate
5886
5887 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum()
5888 @*/
DMGetDimPoints(DM dm,PetscInt dim,PetscInt * pStart,PetscInt * pEnd)5889 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
5890 {
5891 PetscInt d;
5892 PetscErrorCode ierr;
5893
5894 PetscFunctionBegin;
5895 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
5896 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr);
5897 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d);
5898 if (!dm->ops->getdimpoints) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DM type %s does not implement DMGetDimPoints",((PetscObject)dm)->type_name);
5899 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr);
5900 PetscFunctionReturn(0);
5901 }
5902
5903 /*@
5904 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates
5905
5906 Collective on dm
5907
5908 Input Parameters:
5909 + dm - the DM
5910 - c - coordinate vector
5911
5912 Notes:
5913 The coordinates do include those for ghost points, which are in the local vector.
5914
5915 The vector c should be destroyed by the caller.
5916
5917 Level: intermediate
5918
5919 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
5920 @*/
DMSetCoordinates(DM dm,Vec c)5921 PetscErrorCode DMSetCoordinates(DM dm, Vec c)
5922 {
5923 PetscErrorCode ierr;
5924
5925 PetscFunctionBegin;
5926 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
5927 PetscValidHeaderSpecific(c,VEC_CLASSID,2);
5928 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
5929 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
5930 dm->coordinates = c;
5931 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
5932 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
5933 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
5934 PetscFunctionReturn(0);
5935 }
5936
5937 /*@
5938 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates
5939
5940 Not collective
5941
5942 Input Parameters:
5943 + dm - the DM
5944 - c - coordinate vector
5945
5946 Notes:
5947 The coordinates of ghost points can be set using DMSetCoordinates()
5948 followed by DMGetCoordinatesLocal(). This is intended to enable the
5949 setting of ghost coordinates outside of the domain.
5950
5951 The vector c should be destroyed by the caller.
5952
5953 Level: intermediate
5954
5955 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM()
5956 @*/
DMSetCoordinatesLocal(DM dm,Vec c)5957 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c)
5958 {
5959 PetscErrorCode ierr;
5960
5961 PetscFunctionBegin;
5962 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
5963 PetscValidHeaderSpecific(c,VEC_CLASSID,2);
5964 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
5965 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
5966
5967 dm->coordinatesLocal = c;
5968
5969 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
5970 PetscFunctionReturn(0);
5971 }
5972
5973 /*@
5974 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM.
5975
5976 Collective on dm
5977
5978 Input Parameter:
5979 . dm - the DM
5980
5981 Output Parameter:
5982 . c - global coordinate vector
5983
5984 Note:
5985 This is a borrowed reference, so the user should NOT destroy this vector
5986
5987 Each process has only the local coordinates (does NOT have the ghost coordinates).
5988
5989 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
5990 and (x_0,y_0,z_0,x_1,y_1,z_1...)
5991
5992 Level: intermediate
5993
5994 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
5995 @*/
DMGetCoordinates(DM dm,Vec * c)5996 PetscErrorCode DMGetCoordinates(DM dm, Vec *c)
5997 {
5998 PetscErrorCode ierr;
5999
6000 PetscFunctionBegin;
6001 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6002 PetscValidPointer(c,2);
6003 if (!dm->coordinates && dm->coordinatesLocal) {
6004 DM cdm = NULL;
6005 PetscBool localized;
6006
6007 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
6008 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr);
6009 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
6010 /* Block size is not correctly set by CreateGlobalVector() if coordinates are localized */
6011 if (localized) {
6012 PetscInt cdim;
6013
6014 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
6015 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr);
6016 }
6017 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr);
6018 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
6019 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
6020 }
6021 *c = dm->coordinates;
6022 PetscFunctionReturn(0);
6023 }
6024
6025 /*@
6026 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards.
6027
6028 Collective on dm
6029
6030 Input Parameter:
6031 . dm - the DM
6032
6033 Level: advanced
6034
6035 .seealso: DMGetCoordinatesLocalNoncollective()
6036 @*/
DMGetCoordinatesLocalSetUp(DM dm)6037 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm)
6038 {
6039 PetscErrorCode ierr;
6040
6041 PetscFunctionBegin;
6042 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6043 if (!dm->coordinatesLocal && dm->coordinates) {
6044 DM cdm = NULL;
6045 PetscBool localized;
6046
6047 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
6048 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr);
6049 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
6050 /* Block size is not correctly set by CreateLocalVector() if coordinates are localized */
6051 if (localized) {
6052 PetscInt cdim;
6053
6054 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
6055 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr);
6056 }
6057 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr);
6058 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
6059 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
6060 }
6061 PetscFunctionReturn(0);
6062 }
6063
6064 /*@
6065 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM.
6066
6067 Collective on dm
6068
6069 Input Parameter:
6070 . dm - the DM
6071
6072 Output Parameter:
6073 . c - coordinate vector
6074
6075 Note:
6076 This is a borrowed reference, so the user should NOT destroy this vector
6077
6078 Each process has the local and ghost coordinates
6079
6080 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
6081 and (x_0,y_0,z_0,x_1,y_1,z_1...)
6082
6083 Level: intermediate
6084
6085 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective()
6086 @*/
DMGetCoordinatesLocal(DM dm,Vec * c)6087 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c)
6088 {
6089 PetscErrorCode ierr;
6090
6091 PetscFunctionBegin;
6092 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6093 PetscValidPointer(c,2);
6094 ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr);
6095 *c = dm->coordinatesLocal;
6096 PetscFunctionReturn(0);
6097 }
6098
6099 /*@
6100 DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called.
6101
6102 Not collective
6103
6104 Input Parameter:
6105 . dm - the DM
6106
6107 Output Parameter:
6108 . c - coordinate vector
6109
6110 Level: advanced
6111
6112 .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
6113 @*/
DMGetCoordinatesLocalNoncollective(DM dm,Vec * c)6114 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c)
6115 {
6116 PetscFunctionBegin;
6117 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6118 PetscValidPointer(c,2);
6119 if (!dm->coordinatesLocal && dm->coordinates) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called");
6120 *c = dm->coordinatesLocal;
6121 PetscFunctionReturn(0);
6122 }
6123
6124 /*@
6125 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout.
6126
6127 Not collective
6128
6129 Input Parameter:
6130 + dm - the DM
6131 - p - the IS of points whose coordinates will be returned
6132
6133 Output Parameter:
6134 + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates
6135 - pCoord - the Vec with coordinates of points in p
6136
6137 Note:
6138 DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective.
6139
6140 This creates a new vector, so the user SHOULD destroy this vector
6141
6142 Each process has the local and ghost coordinates
6143
6144 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
6145 and (x_0,y_0,z_0,x_1,y_1,z_1...)
6146
6147 Level: advanced
6148
6149 .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
6150 @*/
DMGetCoordinatesLocalTuple(DM dm,IS p,PetscSection * pCoordSection,Vec * pCoord)6151 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord)
6152 {
6153 PetscSection cs, newcs;
6154 Vec coords;
6155 const PetscScalar *arr;
6156 PetscScalar *newarr=NULL;
6157 PetscInt n;
6158 PetscErrorCode ierr;
6159
6160 PetscFunctionBegin;
6161 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6162 PetscValidHeaderSpecific(p, IS_CLASSID, 2);
6163 if (pCoordSection) PetscValidPointer(pCoordSection, 3);
6164 if (pCoord) PetscValidPointer(pCoord, 4);
6165 if (!dm->coordinatesLocal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set");
6166 if (!dm->coordinateDM || !dm->coordinateDM->localSection) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported");
6167 cs = dm->coordinateDM->localSection;
6168 coords = dm->coordinatesLocal;
6169 ierr = VecGetArrayRead(coords, &arr);CHKERRQ(ierr);
6170 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);CHKERRQ(ierr);
6171 ierr = VecRestoreArrayRead(coords, &arr);CHKERRQ(ierr);
6172 if (pCoord) {
6173 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr);
6174 /* set array in two steps to mimic PETSC_OWN_POINTER */
6175 ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);CHKERRQ(ierr);
6176 ierr = VecReplaceArray(*pCoord, newarr);CHKERRQ(ierr);
6177 } else {
6178 ierr = PetscFree(newarr);CHKERRQ(ierr);
6179 }
6180 if (pCoordSection) {*pCoordSection = newcs;}
6181 else {ierr = PetscSectionDestroy(&newcs);CHKERRQ(ierr);}
6182 PetscFunctionReturn(0);
6183 }
6184
DMGetCoordinateField(DM dm,DMField * field)6185 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field)
6186 {
6187 PetscErrorCode ierr;
6188
6189 PetscFunctionBegin;
6190 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6191 PetscValidPointer(field,2);
6192 if (!dm->coordinateField) {
6193 if (dm->ops->createcoordinatefield) {
6194 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr);
6195 }
6196 }
6197 *field = dm->coordinateField;
6198 PetscFunctionReturn(0);
6199 }
6200
DMSetCoordinateField(DM dm,DMField field)6201 PetscErrorCode DMSetCoordinateField(DM dm, DMField field)
6202 {
6203 PetscErrorCode ierr;
6204
6205 PetscFunctionBegin;
6206 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6207 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2);
6208 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr);
6209 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr);
6210 dm->coordinateField = field;
6211 PetscFunctionReturn(0);
6212 }
6213
6214 /*@
6215 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates
6216
6217 Collective on dm
6218
6219 Input Parameter:
6220 . dm - the DM
6221
6222 Output Parameter:
6223 . cdm - coordinate DM
6224
6225 Level: intermediate
6226
6227 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
6228 @*/
DMGetCoordinateDM(DM dm,DM * cdm)6229 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm)
6230 {
6231 PetscErrorCode ierr;
6232
6233 PetscFunctionBegin;
6234 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6235 PetscValidPointer(cdm,2);
6236 if (!dm->coordinateDM) {
6237 DM cdm;
6238
6239 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM");
6240 ierr = (*dm->ops->createcoordinatedm)(dm, &cdm);CHKERRQ(ierr);
6241 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup
6242 * until the call to CreateCoordinateDM) */
6243 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr);
6244 dm->coordinateDM = cdm;
6245 }
6246 *cdm = dm->coordinateDM;
6247 PetscFunctionReturn(0);
6248 }
6249
6250 /*@
6251 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates
6252
6253 Logically Collective on dm
6254
6255 Input Parameters:
6256 + dm - the DM
6257 - cdm - coordinate DM
6258
6259 Level: intermediate
6260
6261 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
6262 @*/
DMSetCoordinateDM(DM dm,DM cdm)6263 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm)
6264 {
6265 PetscErrorCode ierr;
6266
6267 PetscFunctionBegin;
6268 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6269 PetscValidHeaderSpecific(cdm,DM_CLASSID,2);
6270 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr);
6271 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr);
6272 dm->coordinateDM = cdm;
6273 PetscFunctionReturn(0);
6274 }
6275
6276 /*@
6277 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values.
6278
6279 Not Collective
6280
6281 Input Parameter:
6282 . dm - The DM object
6283
6284 Output Parameter:
6285 . dim - The embedding dimension
6286
6287 Level: intermediate
6288
6289 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection()
6290 @*/
DMGetCoordinateDim(DM dm,PetscInt * dim)6291 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim)
6292 {
6293 PetscFunctionBegin;
6294 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6295 PetscValidIntPointer(dim, 2);
6296 if (dm->dimEmbed == PETSC_DEFAULT) {
6297 dm->dimEmbed = dm->dim;
6298 }
6299 *dim = dm->dimEmbed;
6300 PetscFunctionReturn(0);
6301 }
6302
6303 /*@
6304 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values.
6305
6306 Not Collective
6307
6308 Input Parameters:
6309 + dm - The DM object
6310 - dim - The embedding dimension
6311
6312 Level: intermediate
6313
6314 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection()
6315 @*/
DMSetCoordinateDim(DM dm,PetscInt dim)6316 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim)
6317 {
6318 PetscDS ds;
6319 PetscErrorCode ierr;
6320
6321 PetscFunctionBegin;
6322 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6323 dm->dimEmbed = dim;
6324 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
6325 ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr);
6326 PetscFunctionReturn(0);
6327 }
6328
6329 /*@
6330 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.
6331
6332 Collective on dm
6333
6334 Input Parameter:
6335 . dm - The DM object
6336
6337 Output Parameter:
6338 . section - The PetscSection object
6339
6340 Level: intermediate
6341
6342 .seealso: DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection()
6343 @*/
DMGetCoordinateSection(DM dm,PetscSection * section)6344 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section)
6345 {
6346 DM cdm;
6347 PetscErrorCode ierr;
6348
6349 PetscFunctionBegin;
6350 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6351 PetscValidPointer(section, 2);
6352 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
6353 ierr = DMGetLocalSection(cdm, section);CHKERRQ(ierr);
6354 PetscFunctionReturn(0);
6355 }
6356
6357 /*@
6358 DMSetCoordinateSection - Set the layout of coordinate values over the mesh.
6359
6360 Not Collective
6361
6362 Input Parameters:
6363 + dm - The DM object
6364 . dim - The embedding dimension, or PETSC_DETERMINE
6365 - section - The PetscSection object
6366
6367 Level: intermediate
6368
6369 .seealso: DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection()
6370 @*/
DMSetCoordinateSection(DM dm,PetscInt dim,PetscSection section)6371 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section)
6372 {
6373 DM cdm;
6374 PetscErrorCode ierr;
6375
6376 PetscFunctionBegin;
6377 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6378 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3);
6379 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
6380 ierr = DMSetLocalSection(cdm, section);CHKERRQ(ierr);
6381 if (dim == PETSC_DETERMINE) {
6382 PetscInt d = PETSC_DEFAULT;
6383 PetscInt pStart, pEnd, vStart, vEnd, v, dd;
6384
6385 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
6386 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
6387 pStart = PetscMax(vStart, pStart);
6388 pEnd = PetscMin(vEnd, pEnd);
6389 for (v = pStart; v < pEnd; ++v) {
6390 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr);
6391 if (dd) {d = dd; break;}
6392 }
6393 if (d >= 0) {ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);}
6394 }
6395 PetscFunctionReturn(0);
6396 }
6397
6398 /*@
6399 DMProjectCoordinates - Project coordinates to a different space
6400
6401 Input Parameters:
6402 + dm - The DM object
6403 - disc - The new coordinate discretization
6404
6405 Level: intermediate
6406
6407 .seealso: DMGetCoordinateField()
6408 @*/
DMProjectCoordinates(DM dm,PetscFE disc)6409 PetscErrorCode DMProjectCoordinates(DM dm, PetscFE disc)
6410 {
6411 PetscObject discOld;
6412 PetscClassId classid;
6413 DM cdmOld,cdmNew;
6414 Vec coordsOld,coordsNew;
6415 Mat matInterp;
6416 PetscErrorCode ierr;
6417
6418 PetscFunctionBegin;
6419 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6420 PetscValidHeaderSpecific(disc,PETSCFE_CLASSID,2);
6421
6422 ierr = DMGetCoordinateDM(dm, &cdmOld);CHKERRQ(ierr);
6423 /* Check current discretization is compatible */
6424 ierr = DMGetField(cdmOld, 0, NULL, &discOld);CHKERRQ(ierr);
6425 ierr = PetscObjectGetClassId(discOld, &classid);CHKERRQ(ierr);
6426 if (classid != PETSCFE_CLASSID) SETERRQ(PetscObjectComm(discOld), PETSC_ERR_SUP, "Discretization type not supported");
6427 /* Make a fresh clone of the coordinate DM */
6428 ierr = DMClone(cdmOld, &cdmNew);CHKERRQ(ierr);
6429 ierr = DMSetField(cdmNew, 0, NULL, (PetscObject) disc);CHKERRQ(ierr);
6430 ierr = DMCreateDS(cdmNew);CHKERRQ(ierr);
6431 /* Project the coordinate vector from old to new space */
6432 ierr = DMGetCoordinates(dm, &coordsOld);CHKERRQ(ierr);
6433 ierr = DMCreateGlobalVector(cdmNew, &coordsNew);CHKERRQ(ierr);
6434 ierr = DMCreateInterpolation(cdmOld, cdmNew, &matInterp, NULL);CHKERRQ(ierr);
6435 ierr = MatInterpolate(matInterp, coordsOld, coordsNew);CHKERRQ(ierr);
6436 ierr = MatDestroy(&matInterp);CHKERRQ(ierr);
6437 /* Set new coordinate structures */
6438 ierr = DMSetCoordinateField(dm, NULL);CHKERRQ(ierr);
6439 ierr = DMSetCoordinateDM(dm, cdmNew);CHKERRQ(ierr);
6440 ierr = DMSetCoordinates(dm, coordsNew);CHKERRQ(ierr);
6441 ierr = VecDestroy(&coordsNew);CHKERRQ(ierr);
6442 ierr = DMDestroy(&cdmNew);CHKERRQ(ierr);
6443 PetscFunctionReturn(0);
6444 }
6445
6446 /*@C
6447 DMGetPeriodicity - Get the description of mesh periodicity
6448
6449 Input Parameters:
6450 . dm - The DM object
6451
6452 Output Parameters:
6453 + per - Whether the DM is periodic or not
6454 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
6455 . L - If we assume the mesh is a torus, this is the length of each coordinate
6456 - bd - This describes the type of periodicity in each topological dimension
6457
6458 Level: developer
6459
6460 .seealso: DMGetPeriodicity()
6461 @*/
DMGetPeriodicity(DM dm,PetscBool * per,const PetscReal ** maxCell,const PetscReal ** L,const DMBoundaryType ** bd)6462 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd)
6463 {
6464 PetscFunctionBegin;
6465 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6466 if (per) *per = dm->periodic;
6467 if (L) *L = dm->L;
6468 if (maxCell) *maxCell = dm->maxCell;
6469 if (bd) *bd = dm->bdtype;
6470 PetscFunctionReturn(0);
6471 }
6472
6473 /*@C
6474 DMSetPeriodicity - Set the description of mesh periodicity
6475
6476 Input Parameters:
6477 + dm - The DM object
6478 . per - Whether the DM is periodic or not.
6479 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates. Pass NULL to remove such information.
6480 . L - If we assume the mesh is a torus, this is the length of each coordinate
6481 - bd - This describes the type of periodicity in each topological dimension
6482
6483 Notes: If per is PETSC_TRUE and maxCell is not provided, coordinates need to be already localized, or must be localized by hand by the user.
6484
6485 Level: developer
6486
6487 .seealso: DMGetPeriodicity()
6488 @*/
DMSetPeriodicity(DM dm,PetscBool per,const PetscReal maxCell[],const PetscReal L[],const DMBoundaryType bd[])6489 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[])
6490 {
6491 PetscInt dim, d;
6492 PetscErrorCode ierr;
6493
6494 PetscFunctionBegin;
6495 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6496 PetscValidLogicalCollectiveBool(dm,per,2);
6497 if (maxCell) {PetscValidRealPointer(maxCell,3);}
6498 if (L) {PetscValidRealPointer(L,4);}
6499 if (bd) {PetscValidPointer(bd,5);}
6500 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
6501 if (maxCell) {
6502 if (!dm->maxCell) {ierr = PetscMalloc1(dim, &dm->maxCell);CHKERRQ(ierr);}
6503 for (d = 0; d < dim; ++d) dm->maxCell[d] = maxCell[d];
6504 } else { /* remove maxCell information to disable automatic computation of localized vertices */
6505 ierr = PetscFree(dm->maxCell);CHKERRQ(ierr);
6506 }
6507
6508 if (L) {
6509 if (!dm->L) {ierr = PetscMalloc1(dim, &dm->L);CHKERRQ(ierr);}
6510 for (d = 0; d < dim; ++d) dm->L[d] = L[d];
6511 }
6512 if (bd) {
6513 if (!dm->bdtype) {ierr = PetscMalloc1(dim, &dm->bdtype);CHKERRQ(ierr);}
6514 for (d = 0; d < dim; ++d) dm->bdtype[d] = bd[d];
6515 }
6516 dm->periodic = per;
6517 PetscFunctionReturn(0);
6518 }
6519
6520 /*@
6521 DMLocalizeCoordinate - If a mesh is periodic (a torus with lengths L_i, some of which can be infinite), project the coordinate onto [0, L_i) in each dimension.
6522
6523 Input Parameters:
6524 + dm - The DM
6525 . in - The input coordinate point (dim numbers)
6526 - endpoint - Include the endpoint L_i
6527
6528 Output Parameter:
6529 . out - The localized coordinate point
6530
6531 Level: developer
6532
6533 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
6534 @*/
DMLocalizeCoordinate(DM dm,const PetscScalar in[],PetscBool endpoint,PetscScalar out[])6535 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[])
6536 {
6537 PetscInt dim, d;
6538 PetscErrorCode ierr;
6539
6540 PetscFunctionBegin;
6541 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr);
6542 if (!dm->maxCell) {
6543 for (d = 0; d < dim; ++d) out[d] = in[d];
6544 } else {
6545 if (endpoint) {
6546 for (d = 0; d < dim; ++d) {
6547 if ((PetscAbsReal(PetscRealPart(in[d])/dm->L[d] - PetscFloorReal(PetscRealPart(in[d])/dm->L[d])) < PETSC_SMALL) && (PetscRealPart(in[d])/dm->L[d] > PETSC_SMALL)) {
6548 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1);
6549 } else {
6550 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]);
6551 }
6552 }
6553 } else {
6554 for (d = 0; d < dim; ++d) {
6555 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]);
6556 }
6557 }
6558 }
6559 PetscFunctionReturn(0);
6560 }
6561
6562 /*
6563 DMLocalizeCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer.
6564
6565 Input Parameters:
6566 + dm - The DM
6567 . dim - The spatial dimension
6568 . anchor - The anchor point, the input point can be no more than maxCell away from it
6569 - in - The input coordinate point (dim numbers)
6570
6571 Output Parameter:
6572 . out - The localized coordinate point
6573
6574 Level: developer
6575
6576 Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell
6577
6578 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
6579 */
DMLocalizeCoordinate_Internal(DM dm,PetscInt dim,const PetscScalar anchor[],const PetscScalar in[],PetscScalar out[])6580 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
6581 {
6582 PetscInt d;
6583
6584 PetscFunctionBegin;
6585 if (!dm->maxCell) {
6586 for (d = 0; d < dim; ++d) out[d] = in[d];
6587 } else {
6588 for (d = 0; d < dim; ++d) {
6589 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) {
6590 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
6591 } else {
6592 out[d] = in[d];
6593 }
6594 }
6595 }
6596 PetscFunctionReturn(0);
6597 }
6598
DMLocalizeCoordinateReal_Internal(DM dm,PetscInt dim,const PetscReal anchor[],const PetscReal in[],PetscReal out[])6599 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[])
6600 {
6601 PetscInt d;
6602
6603 PetscFunctionBegin;
6604 if (!dm->maxCell) {
6605 for (d = 0; d < dim; ++d) out[d] = in[d];
6606 } else {
6607 for (d = 0; d < dim; ++d) {
6608 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) {
6609 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d];
6610 } else {
6611 out[d] = in[d];
6612 }
6613 }
6614 }
6615 PetscFunctionReturn(0);
6616 }
6617
6618 /*
6619 DMLocalizeAddCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer.
6620
6621 Input Parameters:
6622 + dm - The DM
6623 . dim - The spatial dimension
6624 . anchor - The anchor point, the input point can be no more than maxCell away from it
6625 . in - The input coordinate delta (dim numbers)
6626 - out - The input coordinate point (dim numbers)
6627
6628 Output Parameter:
6629 . out - The localized coordinate in + out
6630
6631 Level: developer
6632
6633 Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell
6634
6635 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate()
6636 */
DMLocalizeAddCoordinate_Internal(DM dm,PetscInt dim,const PetscScalar anchor[],const PetscScalar in[],PetscScalar out[])6637 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
6638 {
6639 PetscInt d;
6640
6641 PetscFunctionBegin;
6642 if (!dm->maxCell) {
6643 for (d = 0; d < dim; ++d) out[d] += in[d];
6644 } else {
6645 for (d = 0; d < dim; ++d) {
6646 const PetscReal maxC = dm->maxCell[d];
6647
6648 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > maxC)) {
6649 const PetscScalar newCoord = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
6650
6651 if (PetscAbsScalar(newCoord - anchor[d]) > maxC)
6652 SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "%D-Coordinate %g more than %g away from anchor %g", d, (double) PetscRealPart(in[d]), (double) maxC, (double) PetscRealPart(anchor[d]));
6653 out[d] += newCoord;
6654 } else {
6655 out[d] += in[d];
6656 }
6657 }
6658 }
6659 PetscFunctionReturn(0);
6660 }
6661
6662 /*@
6663 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process
6664
6665 Not collective
6666
6667 Input Parameter:
6668 . dm - The DM
6669
6670 Output Parameter:
6671 areLocalized - True if localized
6672
6673 Level: developer
6674
6675 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity()
6676 @*/
DMGetCoordinatesLocalizedLocal(DM dm,PetscBool * areLocalized)6677 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized)
6678 {
6679 DM cdm;
6680 PetscSection coordSection;
6681 PetscInt cStart, cEnd, sStart, sEnd, c, dof;
6682 PetscBool isPlex, alreadyLocalized;
6683 PetscErrorCode ierr;
6684
6685 PetscFunctionBegin;
6686 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6687 PetscValidBoolPointer(areLocalized, 2);
6688 *areLocalized = PETSC_FALSE;
6689
6690 /* We need some generic way of refering to cells/vertices */
6691 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
6692 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr);
6693 if (!isPlex) PetscFunctionReturn(0);
6694
6695 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
6696 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr);
6697 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr);
6698 alreadyLocalized = PETSC_FALSE;
6699 for (c = cStart; c < cEnd; ++c) {
6700 if (c < sStart || c >= sEnd) continue;
6701 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr);
6702 if (dof) { alreadyLocalized = PETSC_TRUE; break; }
6703 }
6704 *areLocalized = alreadyLocalized;
6705 PetscFunctionReturn(0);
6706 }
6707
6708 /*@
6709 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells
6710
6711 Collective on dm
6712
6713 Input Parameter:
6714 . dm - The DM
6715
6716 Output Parameter:
6717 areLocalized - True if localized
6718
6719 Level: developer
6720
6721 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal()
6722 @*/
DMGetCoordinatesLocalized(DM dm,PetscBool * areLocalized)6723 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized)
6724 {
6725 PetscBool localized;
6726 PetscErrorCode ierr;
6727
6728 PetscFunctionBegin;
6729 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6730 PetscValidBoolPointer(areLocalized, 2);
6731 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr);
6732 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
6733 PetscFunctionReturn(0);
6734 }
6735
6736 /*@
6737 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces
6738
6739 Collective on dm
6740
6741 Input Parameter:
6742 . dm - The DM
6743
6744 Level: developer
6745
6746 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate()
6747 @*/
DMLocalizeCoordinates(DM dm)6748 PetscErrorCode DMLocalizeCoordinates(DM dm)
6749 {
6750 DM cdm;
6751 PetscSection coordSection, cSection;
6752 Vec coordinates, cVec;
6753 PetscScalar *coords, *coords2, *anchor, *localized;
6754 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize;
6755 PetscBool alreadyLocalized, alreadyLocalizedGlobal;
6756 PetscInt maxHeight = 0, h;
6757 PetscInt *pStart = NULL, *pEnd = NULL;
6758 PetscErrorCode ierr;
6759
6760 PetscFunctionBegin;
6761 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6762 if (!dm->periodic) PetscFunctionReturn(0);
6763 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr);
6764 if (alreadyLocalized) PetscFunctionReturn(0);
6765
6766 /* We need some generic way of refering to cells/vertices */
6767 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
6768 {
6769 PetscBool isplex;
6770
6771 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr);
6772 if (isplex) {
6773 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr);
6774 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr);
6775 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr);
6776 pEnd = &pStart[maxHeight + 1];
6777 newStart = vStart;
6778 newEnd = vEnd;
6779 for (h = 0; h <= maxHeight; h++) {
6780 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr);
6781 newStart = PetscMin(newStart,pStart[h]);
6782 newEnd = PetscMax(newEnd,pEnd[h]);
6783 }
6784 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM");
6785 }
6786 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
6787 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector");
6788 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
6789 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr);
6790 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr);
6791
6792 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr);
6793 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr);
6794 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr);
6795 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr);
6796 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr);
6797
6798 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr);
6799 localized = &anchor[bs];
6800 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE;
6801 for (h = 0; h <= maxHeight; h++) {
6802 PetscInt cStart = pStart[h], cEnd = pEnd[h], c;
6803
6804 for (c = cStart; c < cEnd; ++c) {
6805 PetscScalar *cellCoords = NULL;
6806 PetscInt b;
6807
6808 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE;
6809 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr);
6810 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b];
6811 for (d = 0; d < dof/bs; ++d) {
6812 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr);
6813 for (b = 0; b < bs; b++) {
6814 if (cellCoords[d*bs + b] != localized[b]) break;
6815 }
6816 if (b < bs) break;
6817 }
6818 if (d < dof/bs) {
6819 if (c >= sStart && c < sEnd) {
6820 PetscInt cdof;
6821
6822 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr);
6823 if (cdof != dof) alreadyLocalized = PETSC_FALSE;
6824 }
6825 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr);
6826 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr);
6827 }
6828 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr);
6829 }
6830 }
6831 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
6832 if (alreadyLocalizedGlobal) {
6833 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr);
6834 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr);
6835 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr);
6836 PetscFunctionReturn(0);
6837 }
6838 for (v = vStart; v < vEnd; ++v) {
6839 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr);
6840 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr);
6841 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr);
6842 }
6843 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr);
6844 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr);
6845 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr);
6846 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr);
6847 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr);
6848 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr);
6849 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr);
6850 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr);
6851 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr);
6852 for (v = vStart; v < vEnd; ++v) {
6853 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr);
6854 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
6855 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr);
6856 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d];
6857 }
6858 for (h = 0; h <= maxHeight; h++) {
6859 PetscInt cStart = pStart[h], cEnd = pEnd[h], c;
6860
6861 for (c = cStart; c < cEnd; ++c) {
6862 PetscScalar *cellCoords = NULL;
6863 PetscInt b, cdof;
6864
6865 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr);
6866 if (!cdof) continue;
6867 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr);
6868 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr);
6869 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b];
6870 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);}
6871 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr);
6872 }
6873 }
6874 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr);
6875 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr);
6876 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr);
6877 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr);
6878 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr);
6879 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr);
6880 ierr = VecDestroy(&cVec);CHKERRQ(ierr);
6881 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr);
6882 PetscFunctionReturn(0);
6883 }
6884
6885 /*@
6886 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells
6887
6888 Collective on v (see explanation below)
6889
6890 Input Parameters:
6891 + dm - The DM
6892 . v - The Vec of points
6893 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST
6894 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point.
6895
6896 Output Parameter:
6897 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used
6898 - cells - The PetscSF containing the ranks and local indices of the containing points.
6899
6900
6901 Level: developer
6902
6903 Notes:
6904 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator.
6905 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm.
6906
6907 If *cellSF is NULL on input, a PetscSF will be created.
6908 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses.
6909
6910 An array that maps each point to its containing cell can be obtained with
6911
6912 $ const PetscSFNode *cells;
6913 $ PetscInt nFound;
6914 $ const PetscInt *found;
6915 $
6916 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells);
6917
6918 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is
6919 the index of the cell in its rank's local numbering.
6920
6921 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType
6922 @*/
DMLocatePoints(DM dm,Vec v,DMPointLocationType ltype,PetscSF * cellSF)6923 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF)
6924 {
6925 PetscErrorCode ierr;
6926
6927 PetscFunctionBegin;
6928 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6929 PetscValidHeaderSpecific(v,VEC_CLASSID,2);
6930 PetscValidPointer(cellSF,4);
6931 if (*cellSF) {
6932 PetscMPIInt result;
6933
6934 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4);
6935 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr);
6936 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's");
6937 } else {
6938 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr);
6939 }
6940 if (!dm->ops->locatepoints) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM");
6941 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr);
6942 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr);
6943 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr);
6944 PetscFunctionReturn(0);
6945 }
6946
6947 /*@
6948 DMGetOutputDM - Retrieve the DM associated with the layout for output
6949
6950 Collective on dm
6951
6952 Input Parameter:
6953 . dm - The original DM
6954
6955 Output Parameter:
6956 . odm - The DM which provides the layout for output
6957
6958 Level: intermediate
6959
6960 .seealso: VecView(), DMGetGlobalSection()
6961 @*/
DMGetOutputDM(DM dm,DM * odm)6962 PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
6963 {
6964 PetscSection section;
6965 PetscBool hasConstraints, ghasConstraints;
6966 PetscErrorCode ierr;
6967
6968 PetscFunctionBegin;
6969 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
6970 PetscValidPointer(odm,2);
6971 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);
6972 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr);
6973 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr);
6974 if (!ghasConstraints) {
6975 *odm = dm;
6976 PetscFunctionReturn(0);
6977 }
6978 if (!dm->dmBC) {
6979 PetscSection newSection, gsection;
6980 PetscSF sf;
6981
6982 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr);
6983 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr);
6984 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr);
6985 ierr = DMSetLocalSection(dm->dmBC, newSection);CHKERRQ(ierr);
6986 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr);
6987 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr);
6988 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr);
6989 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr);
6990 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr);
6991 }
6992 *odm = dm->dmBC;
6993 PetscFunctionReturn(0);
6994 }
6995
6996 /*@
6997 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
6998
6999 Input Parameter:
7000 . dm - The original DM
7001
7002 Output Parameters:
7003 + num - The output sequence number
7004 - val - The output sequence value
7005
7006 Level: intermediate
7007
7008 Note: This is intended for output that should appear in sequence, for instance
7009 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
7010
7011 .seealso: VecView()
7012 @*/
DMGetOutputSequenceNumber(DM dm,PetscInt * num,PetscReal * val)7013 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
7014 {
7015 PetscFunctionBegin;
7016 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
7017 if (num) {PetscValidIntPointer(num,2); *num = dm->outputSequenceNum;}
7018 if (val) {PetscValidRealPointer(val,3);*val = dm->outputSequenceVal;}
7019 PetscFunctionReturn(0);
7020 }
7021
7022 /*@
7023 DMSetOutputSequenceNumber - Set the sequence number/value for output
7024
7025 Input Parameters:
7026 + dm - The original DM
7027 . num - The output sequence number
7028 - val - The output sequence value
7029
7030 Level: intermediate
7031
7032 Note: This is intended for output that should appear in sequence, for instance
7033 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
7034
7035 .seealso: VecView()
7036 @*/
DMSetOutputSequenceNumber(DM dm,PetscInt num,PetscReal val)7037 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
7038 {
7039 PetscFunctionBegin;
7040 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
7041 dm->outputSequenceNum = num;
7042 dm->outputSequenceVal = val;
7043 PetscFunctionReturn(0);
7044 }
7045
7046 /*@C
7047 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer
7048
7049 Input Parameters:
7050 + dm - The original DM
7051 . name - The sequence name
7052 - num - The output sequence number
7053
7054 Output Parameter:
7055 . val - The output sequence value
7056
7057 Level: intermediate
7058
7059 Note: This is intended for output that should appear in sequence, for instance
7060 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
7061
7062 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView()
7063 @*/
DMOutputSequenceLoad(DM dm,PetscViewer viewer,const char * name,PetscInt num,PetscReal * val)7064 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
7065 {
7066 PetscBool ishdf5;
7067 PetscErrorCode ierr;
7068
7069 PetscFunctionBegin;
7070 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
7071 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
7072 PetscValidRealPointer(val,4);
7073 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
7074 if (ishdf5) {
7075 #if defined(PETSC_HAVE_HDF5)
7076 PetscScalar value;
7077
7078 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr);
7079 *val = PetscRealPart(value);
7080 #endif
7081 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
7082 PetscFunctionReturn(0);
7083 }
7084
7085 /*@
7086 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution
7087
7088 Not collective
7089
7090 Input Parameter:
7091 . dm - The DM
7092
7093 Output Parameter:
7094 . useNatural - The flag to build the mapping to a natural order during distribution
7095
7096 Level: beginner
7097
7098 .seealso: DMSetUseNatural(), DMCreate()
7099 @*/
DMGetUseNatural(DM dm,PetscBool * useNatural)7100 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
7101 {
7102 PetscFunctionBegin;
7103 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7104 PetscValidBoolPointer(useNatural, 2);
7105 *useNatural = dm->useNatural;
7106 PetscFunctionReturn(0);
7107 }
7108
7109 /*@
7110 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution
7111
7112 Collective on dm
7113
7114 Input Parameters:
7115 + dm - The DM
7116 - useNatural - The flag to build the mapping to a natural order during distribution
7117
7118 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM()
7119
7120 Level: beginner
7121
7122 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM()
7123 @*/
DMSetUseNatural(DM dm,PetscBool useNatural)7124 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
7125 {
7126 PetscFunctionBegin;
7127 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7128 PetscValidLogicalCollectiveBool(dm, useNatural, 2);
7129 dm->useNatural = useNatural;
7130 PetscFunctionReturn(0);
7131 }
7132
7133
7134 /*@C
7135 DMCreateLabel - Create a label of the given name if it does not already exist
7136
7137 Not Collective
7138
7139 Input Parameters:
7140 + dm - The DM object
7141 - name - The label name
7142
7143 Level: intermediate
7144
7145 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7146 @*/
DMCreateLabel(DM dm,const char name[])7147 PetscErrorCode DMCreateLabel(DM dm, const char name[])
7148 {
7149 PetscBool flg;
7150 DMLabel label;
7151 PetscErrorCode ierr;
7152
7153 PetscFunctionBegin;
7154 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7155 PetscValidCharPointer(name, 2);
7156 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr);
7157 if (!flg) {
7158 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr);
7159 ierr = DMAddLabel(dm, label);CHKERRQ(ierr);
7160 ierr = DMLabelDestroy(&label);CHKERRQ(ierr);
7161 }
7162 PetscFunctionReturn(0);
7163 }
7164
7165 /*@C
7166 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default
7167
7168 Not Collective
7169
7170 Input Parameters:
7171 + dm - The DM object
7172 . name - The label name
7173 - point - The mesh point
7174
7175 Output Parameter:
7176 . value - The label value for this point, or -1 if the point is not in the label
7177
7178 Level: beginner
7179
7180 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS()
7181 @*/
DMGetLabelValue(DM dm,const char name[],PetscInt point,PetscInt * value)7182 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
7183 {
7184 DMLabel label;
7185 PetscErrorCode ierr;
7186
7187 PetscFunctionBegin;
7188 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7189 PetscValidCharPointer(name, 2);
7190 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
7191 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
7192 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr);
7193 PetscFunctionReturn(0);
7194 }
7195
7196 /*@C
7197 DMSetLabelValue - Add a point to a Sieve Label with given value
7198
7199 Not Collective
7200
7201 Input Parameters:
7202 + dm - The DM object
7203 . name - The label name
7204 . point - The mesh point
7205 - value - The label value for this point
7206
7207 Output Parameter:
7208
7209 Level: beginner
7210
7211 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue()
7212 @*/
DMSetLabelValue(DM dm,const char name[],PetscInt point,PetscInt value)7213 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
7214 {
7215 DMLabel label;
7216 PetscErrorCode ierr;
7217
7218 PetscFunctionBegin;
7219 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7220 PetscValidCharPointer(name, 2);
7221 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
7222 if (!label) {
7223 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr);
7224 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
7225 }
7226 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr);
7227 PetscFunctionReturn(0);
7228 }
7229
7230 /*@C
7231 DMClearLabelValue - Remove a point from a Sieve Label with given value
7232
7233 Not Collective
7234
7235 Input Parameters:
7236 + dm - The DM object
7237 . name - The label name
7238 . point - The mesh point
7239 - value - The label value for this point
7240
7241 Output Parameter:
7242
7243 Level: beginner
7244
7245 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS()
7246 @*/
DMClearLabelValue(DM dm,const char name[],PetscInt point,PetscInt value)7247 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
7248 {
7249 DMLabel label;
7250 PetscErrorCode ierr;
7251
7252 PetscFunctionBegin;
7253 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7254 PetscValidCharPointer(name, 2);
7255 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
7256 if (!label) PetscFunctionReturn(0);
7257 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr);
7258 PetscFunctionReturn(0);
7259 }
7260
7261 /*@C
7262 DMGetLabelSize - Get the number of different integer ids in a Label
7263
7264 Not Collective
7265
7266 Input Parameters:
7267 + dm - The DM object
7268 - name - The label name
7269
7270 Output Parameter:
7271 . size - The number of different integer ids, or 0 if the label does not exist
7272
7273 Level: beginner
7274
7275 .seealso: DMLabelGetNumValues(), DMSetLabelValue()
7276 @*/
DMGetLabelSize(DM dm,const char name[],PetscInt * size)7277 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
7278 {
7279 DMLabel label;
7280 PetscErrorCode ierr;
7281
7282 PetscFunctionBegin;
7283 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7284 PetscValidCharPointer(name, 2);
7285 PetscValidIntPointer(size, 3);
7286 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
7287 *size = 0;
7288 if (!label) PetscFunctionReturn(0);
7289 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr);
7290 PetscFunctionReturn(0);
7291 }
7292
7293 /*@C
7294 DMGetLabelIdIS - Get the integer ids in a label
7295
7296 Not Collective
7297
7298 Input Parameters:
7299 + mesh - The DM object
7300 - name - The label name
7301
7302 Output Parameter:
7303 . ids - The integer ids, or NULL if the label does not exist
7304
7305 Level: beginner
7306
7307 .seealso: DMLabelGetValueIS(), DMGetLabelSize()
7308 @*/
DMGetLabelIdIS(DM dm,const char name[],IS * ids)7309 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
7310 {
7311 DMLabel label;
7312 PetscErrorCode ierr;
7313
7314 PetscFunctionBegin;
7315 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7316 PetscValidCharPointer(name, 2);
7317 PetscValidPointer(ids, 3);
7318 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
7319 *ids = NULL;
7320 if (label) {
7321 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr);
7322 } else {
7323 /* returning an empty IS */
7324 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr);
7325 }
7326 PetscFunctionReturn(0);
7327 }
7328
7329 /*@C
7330 DMGetStratumSize - Get the number of points in a label stratum
7331
7332 Not Collective
7333
7334 Input Parameters:
7335 + dm - The DM object
7336 . name - The label name
7337 - value - The stratum value
7338
7339 Output Parameter:
7340 . size - The stratum size
7341
7342 Level: beginner
7343
7344 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds()
7345 @*/
DMGetStratumSize(DM dm,const char name[],PetscInt value,PetscInt * size)7346 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
7347 {
7348 DMLabel label;
7349 PetscErrorCode ierr;
7350
7351 PetscFunctionBegin;
7352 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7353 PetscValidCharPointer(name, 2);
7354 PetscValidIntPointer(size, 4);
7355 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
7356 *size = 0;
7357 if (!label) PetscFunctionReturn(0);
7358 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr);
7359 PetscFunctionReturn(0);
7360 }
7361
7362 /*@C
7363 DMGetStratumIS - Get the points in a label stratum
7364
7365 Not Collective
7366
7367 Input Parameters:
7368 + dm - The DM object
7369 . name - The label name
7370 - value - The stratum value
7371
7372 Output Parameter:
7373 . points - The stratum points, or NULL if the label does not exist or does not have that value
7374
7375 Level: beginner
7376
7377 .seealso: DMLabelGetStratumIS(), DMGetStratumSize()
7378 @*/
DMGetStratumIS(DM dm,const char name[],PetscInt value,IS * points)7379 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
7380 {
7381 DMLabel label;
7382 PetscErrorCode ierr;
7383
7384 PetscFunctionBegin;
7385 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7386 PetscValidCharPointer(name, 2);
7387 PetscValidPointer(points, 4);
7388 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
7389 *points = NULL;
7390 if (!label) PetscFunctionReturn(0);
7391 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr);
7392 PetscFunctionReturn(0);
7393 }
7394
7395 /*@C
7396 DMSetStratumIS - Set the points in a label stratum
7397
7398 Not Collective
7399
7400 Input Parameters:
7401 + dm - The DM object
7402 . name - The label name
7403 . value - The stratum value
7404 - points - The stratum points
7405
7406 Level: beginner
7407
7408 .seealso: DMLabelSetStratumIS(), DMGetStratumSize()
7409 @*/
DMSetStratumIS(DM dm,const char name[],PetscInt value,IS points)7410 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points)
7411 {
7412 DMLabel label;
7413 PetscErrorCode ierr;
7414
7415 PetscFunctionBegin;
7416 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7417 PetscValidCharPointer(name, 2);
7418 PetscValidPointer(points, 4);
7419 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
7420 if (!label) PetscFunctionReturn(0);
7421 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr);
7422 PetscFunctionReturn(0);
7423 }
7424
7425 /*@C
7426 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label
7427
7428 Not Collective
7429
7430 Input Parameters:
7431 + dm - The DM object
7432 . name - The label name
7433 - value - The label value for this point
7434
7435 Output Parameter:
7436
7437 Level: beginner
7438
7439 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue()
7440 @*/
DMClearLabelStratum(DM dm,const char name[],PetscInt value)7441 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
7442 {
7443 DMLabel label;
7444 PetscErrorCode ierr;
7445
7446 PetscFunctionBegin;
7447 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7448 PetscValidCharPointer(name, 2);
7449 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
7450 if (!label) PetscFunctionReturn(0);
7451 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr);
7452 PetscFunctionReturn(0);
7453 }
7454
7455 /*@
7456 DMGetNumLabels - Return the number of labels defined by the mesh
7457
7458 Not Collective
7459
7460 Input Parameter:
7461 . dm - The DM object
7462
7463 Output Parameter:
7464 . numLabels - the number of Labels
7465
7466 Level: intermediate
7467
7468 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7469 @*/
DMGetNumLabels(DM dm,PetscInt * numLabels)7470 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
7471 {
7472 DMLabelLink next = dm->labels;
7473 PetscInt n = 0;
7474
7475 PetscFunctionBegin;
7476 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7477 PetscValidIntPointer(numLabels, 2);
7478 while (next) {++n; next = next->next;}
7479 *numLabels = n;
7480 PetscFunctionReturn(0);
7481 }
7482
7483 /*@C
7484 DMGetLabelName - Return the name of nth label
7485
7486 Not Collective
7487
7488 Input Parameters:
7489 + dm - The DM object
7490 - n - the label number
7491
7492 Output Parameter:
7493 . name - the label name
7494
7495 Level: intermediate
7496
7497 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7498 @*/
DMGetLabelName(DM dm,PetscInt n,const char ** name)7499 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name)
7500 {
7501 DMLabelLink next = dm->labels;
7502 PetscInt l = 0;
7503 PetscErrorCode ierr;
7504
7505 PetscFunctionBegin;
7506 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7507 PetscValidPointer(name, 3);
7508 while (next) {
7509 if (l == n) {
7510 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr);
7511 PetscFunctionReturn(0);
7512 }
7513 ++l;
7514 next = next->next;
7515 }
7516 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
7517 }
7518
7519 /*@C
7520 DMHasLabel - Determine whether the mesh has a label of a given name
7521
7522 Not Collective
7523
7524 Input Parameters:
7525 + dm - The DM object
7526 - name - The label name
7527
7528 Output Parameter:
7529 . hasLabel - PETSC_TRUE if the label is present
7530
7531 Level: intermediate
7532
7533 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7534 @*/
DMHasLabel(DM dm,const char name[],PetscBool * hasLabel)7535 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
7536 {
7537 DMLabelLink next = dm->labels;
7538 const char *lname;
7539 PetscErrorCode ierr;
7540
7541 PetscFunctionBegin;
7542 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7543 PetscValidCharPointer(name, 2);
7544 PetscValidBoolPointer(hasLabel, 3);
7545 *hasLabel = PETSC_FALSE;
7546 while (next) {
7547 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr);
7548 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr);
7549 if (*hasLabel) break;
7550 next = next->next;
7551 }
7552 PetscFunctionReturn(0);
7553 }
7554
7555 /*@C
7556 DMGetLabel - Return the label of a given name, or NULL
7557
7558 Not Collective
7559
7560 Input Parameters:
7561 + dm - The DM object
7562 - name - The label name
7563
7564 Output Parameter:
7565 . label - The DMLabel, or NULL if the label is absent
7566
7567 Level: intermediate
7568
7569 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7570 @*/
DMGetLabel(DM dm,const char name[],DMLabel * label)7571 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
7572 {
7573 DMLabelLink next = dm->labels;
7574 PetscBool hasLabel;
7575 const char *lname;
7576 PetscErrorCode ierr;
7577
7578 PetscFunctionBegin;
7579 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7580 PetscValidCharPointer(name, 2);
7581 PetscValidPointer(label, 3);
7582 *label = NULL;
7583 while (next) {
7584 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr);
7585 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr);
7586 if (hasLabel) {
7587 *label = next->label;
7588 break;
7589 }
7590 next = next->next;
7591 }
7592 PetscFunctionReturn(0);
7593 }
7594
7595 /*@C
7596 DMGetLabelByNum - Return the nth label
7597
7598 Not Collective
7599
7600 Input Parameters:
7601 + dm - The DM object
7602 - n - the label number
7603
7604 Output Parameter:
7605 . label - the label
7606
7607 Level: intermediate
7608
7609 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7610 @*/
DMGetLabelByNum(DM dm,PetscInt n,DMLabel * label)7611 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
7612 {
7613 DMLabelLink next = dm->labels;
7614 PetscInt l = 0;
7615
7616 PetscFunctionBegin;
7617 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7618 PetscValidPointer(label, 3);
7619 while (next) {
7620 if (l == n) {
7621 *label = next->label;
7622 PetscFunctionReturn(0);
7623 }
7624 ++l;
7625 next = next->next;
7626 }
7627 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
7628 }
7629
7630 /*@C
7631 DMAddLabel - Add the label to this mesh
7632
7633 Not Collective
7634
7635 Input Parameters:
7636 + dm - The DM object
7637 - label - The DMLabel
7638
7639 Level: developer
7640
7641 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7642 @*/
DMAddLabel(DM dm,DMLabel label)7643 PetscErrorCode DMAddLabel(DM dm, DMLabel label)
7644 {
7645 DMLabelLink l, *p, tmpLabel;
7646 PetscBool hasLabel;
7647 const char *lname;
7648 PetscBool flg;
7649 PetscErrorCode ierr;
7650
7651 PetscFunctionBegin;
7652 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7653 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
7654 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr);
7655 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname);
7656 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr);
7657 tmpLabel->label = label;
7658 tmpLabel->output = PETSC_TRUE;
7659 for (p=&dm->labels; (l=*p); p=&l->next) {}
7660 *p = tmpLabel;
7661 ierr = PetscObjectReference((PetscObject)label);CHKERRQ(ierr);
7662 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr);
7663 if (flg) dm->depthLabel = label;
7664 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr);
7665 if (flg) dm->celltypeLabel = label;
7666 PetscFunctionReturn(0);
7667 }
7668
7669 /*@C
7670 DMRemoveLabel - Remove the label given by name from this mesh
7671
7672 Not Collective
7673
7674 Input Parameters:
7675 + dm - The DM object
7676 - name - The label name
7677
7678 Output Parameter:
7679 . label - The DMLabel, or NULL if the label is absent
7680
7681 Level: developer
7682
7683 Notes:
7684 DMRemoveLabel(dm,name,NULL) removes the label from dm and calls
7685 DMLabelDestroy() on the label.
7686
7687 DMRemoveLabel(dm,name,&label) removes the label from dm, but it DOES NOT
7688 call DMLabelDestroy(). Instead, the label is returned and the user is
7689 responsible of calling DMLabelDestroy() at some point.
7690
7691 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel(), DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabelBySelf()
7692 @*/
DMRemoveLabel(DM dm,const char name[],DMLabel * label)7693 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
7694 {
7695 DMLabelLink link, *pnext;
7696 PetscBool hasLabel;
7697 const char *lname;
7698 PetscErrorCode ierr;
7699
7700 PetscFunctionBegin;
7701 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7702 PetscValidCharPointer(name, 2);
7703 if (label) {
7704 PetscValidPointer(label, 3);
7705 *label = NULL;
7706 }
7707 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) {
7708 ierr = PetscObjectGetName((PetscObject) link->label, &lname);CHKERRQ(ierr);
7709 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr);
7710 if (hasLabel) {
7711 *pnext = link->next; /* Remove from list */
7712 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr);
7713 if (hasLabel) dm->depthLabel = NULL;
7714 ierr = PetscStrcmp(name, "celltype", &hasLabel);CHKERRQ(ierr);
7715 if (hasLabel) dm->celltypeLabel = NULL;
7716 if (label) *label = link->label;
7717 else {ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr);}
7718 ierr = PetscFree(link);CHKERRQ(ierr);
7719 break;
7720 }
7721 }
7722 PetscFunctionReturn(0);
7723 }
7724
7725 /*@
7726 DMRemoveLabelBySelf - Remove the label from this mesh
7727
7728 Not Collective
7729
7730 Input Parameters:
7731 + dm - The DM object
7732 . label - (Optional) The DMLabel to be removed from the DM
7733 - failNotFound - Should it fail if the label is not found in the DM?
7734
7735 Level: developer
7736
7737 Notes:
7738 Only exactly the same instance is removed if found, name match is ignored.
7739 If the DM has an exclusive reference to the label, it gets destroyed and
7740 *label nullified.
7741
7742 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel() DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabel()
7743 @*/
DMRemoveLabelBySelf(DM dm,DMLabel * label,PetscBool failNotFound)7744 PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound)
7745 {
7746 DMLabelLink link, *pnext;
7747 PetscBool hasLabel = PETSC_FALSE;
7748 PetscErrorCode ierr;
7749
7750 PetscFunctionBegin;
7751 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7752 PetscValidPointer(label, 2);
7753 if (!*label && !failNotFound) PetscFunctionReturn(0);
7754 PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2);
7755 PetscValidLogicalCollectiveBool(dm,failNotFound,3);
7756 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) {
7757 if (*label == link->label) {
7758 hasLabel = PETSC_TRUE;
7759 *pnext = link->next; /* Remove from list */
7760 if (*label == dm->depthLabel) dm->depthLabel = NULL;
7761 if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL;
7762 if (((PetscObject) link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */
7763 ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr);
7764 ierr = PetscFree(link);CHKERRQ(ierr);
7765 break;
7766 }
7767 }
7768 if (!hasLabel && failNotFound) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM");
7769 PetscFunctionReturn(0);
7770 }
7771
7772 /*@C
7773 DMGetLabelOutput - Get the output flag for a given label
7774
7775 Not Collective
7776
7777 Input Parameters:
7778 + dm - The DM object
7779 - name - The label name
7780
7781 Output Parameter:
7782 . output - The flag for output
7783
7784 Level: developer
7785
7786 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7787 @*/
DMGetLabelOutput(DM dm,const char name[],PetscBool * output)7788 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output)
7789 {
7790 DMLabelLink next = dm->labels;
7791 const char *lname;
7792 PetscErrorCode ierr;
7793
7794 PetscFunctionBegin;
7795 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7796 PetscValidPointer(name, 2);
7797 PetscValidPointer(output, 3);
7798 while (next) {
7799 PetscBool flg;
7800
7801 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr);
7802 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr);
7803 if (flg) {*output = next->output; PetscFunctionReturn(0);}
7804 next = next->next;
7805 }
7806 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7807 }
7808
7809 /*@C
7810 DMSetLabelOutput - Set the output flag for a given label
7811
7812 Not Collective
7813
7814 Input Parameters:
7815 + dm - The DM object
7816 . name - The label name
7817 - output - The flag for output
7818
7819 Level: developer
7820
7821 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
7822 @*/
DMSetLabelOutput(DM dm,const char name[],PetscBool output)7823 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
7824 {
7825 DMLabelLink next = dm->labels;
7826 const char *lname;
7827 PetscErrorCode ierr;
7828
7829 PetscFunctionBegin;
7830 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7831 PetscValidCharPointer(name, 2);
7832 while (next) {
7833 PetscBool flg;
7834
7835 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr);
7836 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr);
7837 if (flg) {next->output = output; PetscFunctionReturn(0);}
7838 next = next->next;
7839 }
7840 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7841 }
7842
7843 /*@
7844 DMCopyLabels - Copy labels from one mesh to another with a superset of the points
7845
7846 Collective on dmA
7847
7848 Input Parameter:
7849 + dmA - The DM object with initial labels
7850 . dmB - The DM object with copied labels
7851 . mode - Copy labels by pointers (PETSC_OWN_POINTER) or duplicate them (PETSC_COPY_VALUES)
7852 - all - Copy all labels including "depth", "dim", and "celltype" (PETSC_TRUE) which are otherwise ignored (PETSC_FALSE)
7853
7854 Level: intermediate
7855
7856 Note: This is typically used when interpolating or otherwise adding to a mesh
7857
7858 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection(), DMShareLabels()
7859 @*/
DMCopyLabels(DM dmA,DM dmB,PetscCopyMode mode,PetscBool all)7860 PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all)
7861 {
7862 DMLabel label, labelNew;
7863 const char *name;
7864 PetscBool flg;
7865 DMLabelLink link;
7866 PetscErrorCode ierr;
7867
7868 PetscFunctionBegin;
7869 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
7870 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
7871 PetscValidLogicalCollectiveEnum(dmA, mode,3);
7872 PetscValidLogicalCollectiveBool(dmA, all, 4);
7873 if (mode==PETSC_USE_POINTER) SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects");
7874 if (dmA == dmB) PetscFunctionReturn(0);
7875 for (link=dmA->labels; link; link=link->next) {
7876 label=link->label;
7877 ierr = PetscObjectGetName((PetscObject)label, &name);CHKERRQ(ierr);
7878 if (!all) {
7879 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr);
7880 if (flg) continue;
7881 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr);
7882 if (flg) continue;
7883 ierr = PetscStrcmp(name, "celltype", &flg);CHKERRQ(ierr);
7884 if (flg) continue;
7885 }
7886 if (mode==PETSC_COPY_VALUES) {
7887 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr);
7888 } else {
7889 labelNew = label;
7890 }
7891 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr);
7892 if (mode==PETSC_COPY_VALUES) {ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);}
7893 }
7894 PetscFunctionReturn(0);
7895 }
7896
7897 /*@
7898 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement
7899
7900 Input Parameter:
7901 . dm - The DM object
7902
7903 Output Parameter:
7904 . cdm - The coarse DM
7905
7906 Level: intermediate
7907
7908 .seealso: DMSetCoarseDM()
7909 @*/
DMGetCoarseDM(DM dm,DM * cdm)7910 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
7911 {
7912 PetscFunctionBegin;
7913 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7914 PetscValidPointer(cdm, 2);
7915 *cdm = dm->coarseMesh;
7916 PetscFunctionReturn(0);
7917 }
7918
7919 /*@
7920 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement
7921
7922 Input Parameters:
7923 + dm - The DM object
7924 - cdm - The coarse DM
7925
7926 Level: intermediate
7927
7928 .seealso: DMGetCoarseDM()
7929 @*/
DMSetCoarseDM(DM dm,DM cdm)7930 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
7931 {
7932 PetscErrorCode ierr;
7933
7934 PetscFunctionBegin;
7935 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7936 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2);
7937 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr);
7938 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr);
7939 dm->coarseMesh = cdm;
7940 PetscFunctionReturn(0);
7941 }
7942
7943 /*@
7944 DMGetFineDM - Get the fine mesh from which this was obtained by refinement
7945
7946 Input Parameter:
7947 . dm - The DM object
7948
7949 Output Parameter:
7950 . fdm - The fine DM
7951
7952 Level: intermediate
7953
7954 .seealso: DMSetFineDM()
7955 @*/
DMGetFineDM(DM dm,DM * fdm)7956 PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
7957 {
7958 PetscFunctionBegin;
7959 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7960 PetscValidPointer(fdm, 2);
7961 *fdm = dm->fineMesh;
7962 PetscFunctionReturn(0);
7963 }
7964
7965 /*@
7966 DMSetFineDM - Set the fine mesh from which this was obtained by refinement
7967
7968 Input Parameters:
7969 + dm - The DM object
7970 - fdm - The fine DM
7971
7972 Level: intermediate
7973
7974 .seealso: DMGetFineDM()
7975 @*/
DMSetFineDM(DM dm,DM fdm)7976 PetscErrorCode DMSetFineDM(DM dm, DM fdm)
7977 {
7978 PetscErrorCode ierr;
7979
7980 PetscFunctionBegin;
7981 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7982 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2);
7983 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr);
7984 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr);
7985 dm->fineMesh = fdm;
7986 PetscFunctionReturn(0);
7987 }
7988
7989 /*=== DMBoundary code ===*/
7990
DMCopyBoundary(DM dm,DM dmNew)7991 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew)
7992 {
7993 PetscInt d;
7994 PetscErrorCode ierr;
7995
7996 PetscFunctionBegin;
7997 for (d = 0; d < dm->Nds; ++d) {
7998 ierr = PetscDSCopyBoundary(dm->probs[d].ds, dmNew->probs[d].ds);CHKERRQ(ierr);
7999 }
8000 PetscFunctionReturn(0);
8001 }
8002
8003 /*@C
8004 DMAddBoundary - Add a boundary condition to the model
8005
8006 Collective on dm
8007
8008 Input Parameters:
8009 + dm - The DM, with a PetscDS that matches the problem being constrained
8010 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
8011 . name - The BC name
8012 . labelname - The label defining constrained points
8013 . field - The field to constrain
8014 . numcomps - The number of constrained field components (0 will constrain all fields)
8015 . comps - An array of constrained component numbers
8016 . bcFunc - A pointwise function giving boundary values
8017 . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL
8018 . numids - The number of DMLabel ids for constrained points
8019 . ids - An array of ids for constrained points
8020 - ctx - An optional user context for bcFunc
8021
8022 Options Database Keys:
8023 + -bc_<boundary name> <num> - Overrides the boundary ids
8024 - -bc_<boundary name>_comp <num> - Overrides the boundary components
8025
8026 Note:
8027 Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is:
8028
8029 $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
8030
8031 If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is:
8032
8033 $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8034 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8035 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8036 $ PetscReal time, const PetscReal x[], PetscScalar bcval[])
8037
8038 + dim - the spatial dimension
8039 . Nf - the number of fields
8040 . uOff - the offset into u[] and u_t[] for each field
8041 . uOff_x - the offset into u_x[] for each field
8042 . u - each field evaluated at the current point
8043 . u_t - the time derivative of each field evaluated at the current point
8044 . u_x - the gradient of each field evaluated at the current point
8045 . aOff - the offset into a[] and a_t[] for each auxiliary field
8046 . aOff_x - the offset into a_x[] for each auxiliary field
8047 . a - each auxiliary field evaluated at the current point
8048 . a_t - the time derivative of each auxiliary field evaluated at the current point
8049 . a_x - the gradient of auxiliary each field evaluated at the current point
8050 . t - current time
8051 . x - coordinates of the current point
8052 . numConstants - number of constant parameters
8053 . constants - constant parameters
8054 - bcval - output values at the current point
8055
8056 Level: developer
8057
8058 .seealso: DMGetBoundary(), PetscDSAddBoundary()
8059 @*/
DMAddBoundary(DM dm,DMBoundaryConditionType type,const char name[],const char labelname[],PetscInt field,PetscInt numcomps,const PetscInt * comps,void (* bcFunc)(void),void (* bcFunc_t)(void),PetscInt numids,const PetscInt * ids,void * ctx)8060 PetscErrorCode DMAddBoundary(DM dm, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), void (*bcFunc_t)(void), PetscInt numids, const PetscInt *ids, void *ctx)
8061 {
8062 PetscDS ds;
8063 PetscErrorCode ierr;
8064
8065 PetscFunctionBegin;
8066 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8067 PetscValidLogicalCollectiveEnum(dm, type, 2);
8068 PetscValidLogicalCollectiveInt(dm, field, 5);
8069 PetscValidLogicalCollectiveInt(dm, numcomps, 6);
8070 PetscValidLogicalCollectiveInt(dm, numids, 9);
8071 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
8072 ierr = DMCompleteBoundaryLabel_Internal(dm, ds, field, PETSC_MAX_INT, labelname);CHKERRQ(ierr);
8073 ierr = PetscDSAddBoundary(ds, type,name, labelname, field, numcomps, comps, bcFunc, bcFunc_t, numids, ids, ctx);CHKERRQ(ierr);
8074 PetscFunctionReturn(0);
8075 }
8076
8077 /*@
8078 DMGetNumBoundary - Get the number of registered BC
8079
8080 Input Parameters:
8081 . dm - The mesh object
8082
8083 Output Parameters:
8084 . numBd - The number of BC
8085
8086 Level: intermediate
8087
8088 .seealso: DMAddBoundary(), DMGetBoundary()
8089 @*/
DMGetNumBoundary(DM dm,PetscInt * numBd)8090 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd)
8091 {
8092 PetscDS ds;
8093 PetscErrorCode ierr;
8094
8095 PetscFunctionBegin;
8096 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8097 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
8098 ierr = PetscDSGetNumBoundary(ds, numBd);CHKERRQ(ierr);
8099 PetscFunctionReturn(0);
8100 }
8101
8102 /*@C
8103 DMGetBoundary - Get a model boundary condition
8104
8105 Input Parameters:
8106 + dm - The mesh object
8107 - bd - The BC number
8108
8109 Output Parameters:
8110 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
8111 . name - The BC name
8112 . labelname - The label defining constrained points
8113 . field - The field to constrain
8114 . numcomps - The number of constrained field components
8115 . comps - An array of constrained component numbers
8116 . bcFunc - A pointwise function giving boundary values
8117 . bcFunc_t - A pointwise function giving the time derviative of the boundary values
8118 . numids - The number of DMLabel ids for constrained points
8119 . ids - An array of ids for constrained points
8120 - ctx - An optional user context for bcFunc
8121
8122 Options Database Keys:
8123 + -bc_<boundary name> <num> - Overrides the boundary ids
8124 - -bc_<boundary name>_comp <num> - Overrides the boundary components
8125
8126 Level: developer
8127
8128 .seealso: DMAddBoundary()
8129 @*/
DMGetBoundary(DM dm,PetscInt bd,DMBoundaryConditionType * type,const char ** name,const char ** labelname,PetscInt * field,PetscInt * numcomps,const PetscInt ** comps,void (** func)(void),void (** func_t)(void),PetscInt * numids,const PetscInt ** ids,void ** ctx)8130 PetscErrorCode DMGetBoundary(DM dm, PetscInt bd, DMBoundaryConditionType *type, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(void), void (**func_t)(void), PetscInt *numids, const PetscInt **ids, void **ctx)
8131 {
8132 PetscDS ds;
8133 PetscErrorCode ierr;
8134
8135 PetscFunctionBegin;
8136 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8137 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
8138 ierr = PetscDSGetBoundary(ds, bd, type, name, labelname, field, numcomps, comps, func, func_t, numids, ids, ctx);CHKERRQ(ierr);
8139 PetscFunctionReturn(0);
8140 }
8141
DMPopulateBoundary(DM dm)8142 static PetscErrorCode DMPopulateBoundary(DM dm)
8143 {
8144 PetscDS ds;
8145 DMBoundary *lastnext;
8146 DSBoundary dsbound;
8147 PetscErrorCode ierr;
8148
8149 PetscFunctionBegin;
8150 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
8151 dsbound = ds->boundary;
8152 if (dm->boundary) {
8153 DMBoundary next = dm->boundary;
8154
8155 /* quick check to see if the PetscDS has changed */
8156 if (next->dsboundary == dsbound) PetscFunctionReturn(0);
8157 /* the PetscDS has changed: tear down and rebuild */
8158 while (next) {
8159 DMBoundary b = next;
8160
8161 next = b->next;
8162 ierr = PetscFree(b);CHKERRQ(ierr);
8163 }
8164 dm->boundary = NULL;
8165 }
8166
8167 lastnext = &(dm->boundary);
8168 while (dsbound) {
8169 DMBoundary dmbound;
8170
8171 ierr = PetscNew(&dmbound);CHKERRQ(ierr);
8172 dmbound->dsboundary = dsbound;
8173 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr);
8174 if (!dmbound->label) {ierr = PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr);}
8175 /* push on the back instead of the front so that it is in the same order as in the PetscDS */
8176 *lastnext = dmbound;
8177 lastnext = &(dmbound->next);
8178 dsbound = dsbound->next;
8179 }
8180 PetscFunctionReturn(0);
8181 }
8182
DMIsBoundaryPoint(DM dm,PetscInt point,PetscBool * isBd)8183 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
8184 {
8185 DMBoundary b;
8186 PetscErrorCode ierr;
8187
8188 PetscFunctionBegin;
8189 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8190 PetscValidBoolPointer(isBd, 3);
8191 *isBd = PETSC_FALSE;
8192 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr);
8193 b = dm->boundary;
8194 while (b && !(*isBd)) {
8195 DMLabel label = b->label;
8196 DSBoundary dsb = b->dsboundary;
8197
8198 if (label) {
8199 PetscInt i;
8200
8201 for (i = 0; i < dsb->numids && !(*isBd); ++i) {
8202 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr);
8203 }
8204 }
8205 b = b->next;
8206 }
8207 PetscFunctionReturn(0);
8208 }
8209
8210 /*@C
8211 DMProjectFunction - This projects the given function into the function space provided, putting the coefficients in a global vector.
8212
8213 Collective on DM
8214
8215 Input Parameters:
8216 + dm - The DM
8217 . time - The time
8218 . funcs - The coordinate functions to evaluate, one per field
8219 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null.
8220 - mode - The insertion mode for values
8221
8222 Output Parameter:
8223 . X - vector
8224
8225 Calling sequence of func:
8226 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx);
8227
8228 + dim - The spatial dimension
8229 . time - The time at which to sample
8230 . x - The coordinates
8231 . Nf - The number of fields
8232 . u - The output field values
8233 - ctx - optional user-defined function context
8234
8235 Level: developer
8236
8237 .seealso: DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff()
8238 @*/
DMProjectFunction(DM dm,PetscReal time,PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,InsertMode mode,Vec X)8239 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
8240 {
8241 Vec localX;
8242 PetscErrorCode ierr;
8243
8244 PetscFunctionBegin;
8245 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8246 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
8247 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr);
8248 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr);
8249 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr);
8250 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
8251 PetscFunctionReturn(0);
8252 }
8253
8254 /*@C
8255 DMProjectFunctionLocal - This projects the given function into the function space provided, putting the coefficients in a local vector.
8256
8257 Not collective
8258
8259 Input Parameters:
8260 + dm - The DM
8261 . time - The time
8262 . funcs - The coordinate functions to evaluate, one per field
8263 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null.
8264 - mode - The insertion mode for values
8265
8266 Output Parameter:
8267 . localX - vector
8268
8269 Calling sequence of func:
8270 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx);
8271
8272 + dim - The spatial dimension
8273 . x - The coordinates
8274 . Nf - The number of fields
8275 . u - The output field values
8276 - ctx - optional user-defined function context
8277
8278 Level: developer
8279
8280 .seealso: DMProjectFunction(), DMProjectFunctionLabel(), DMComputeL2Diff()
8281 @*/
DMProjectFunctionLocal(DM dm,PetscReal time,PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,InsertMode mode,Vec localX)8282 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
8283 {
8284 PetscErrorCode ierr;
8285
8286 PetscFunctionBegin;
8287 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
8288 PetscValidHeaderSpecific(localX,VEC_CLASSID,5);
8289 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name);
8290 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr);
8291 PetscFunctionReturn(0);
8292 }
8293
8294 /*@C
8295 DMProjectFunctionLabel - This projects the given function into the function space provided, putting the coefficients in a global vector, setting values only for points in the given label.
8296
8297 Collective on DM
8298
8299 Input Parameters:
8300 + dm - The DM
8301 . time - The time
8302 . label - The DMLabel selecting the portion of the mesh for projection
8303 . funcs - The coordinate functions to evaluate, one per field
8304 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null.
8305 - mode - The insertion mode for values
8306
8307 Output Parameter:
8308 . X - vector
8309
8310 Calling sequence of func:
8311 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx);
8312
8313 + dim - The spatial dimension
8314 . x - The coordinates
8315 . Nf - The number of fields
8316 . u - The output field values
8317 - ctx - optional user-defined function context
8318
8319 Level: developer
8320
8321 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal(), DMComputeL2Diff()
8322 @*/
DMProjectFunctionLabel(DM dm,PetscReal time,DMLabel label,PetscInt numIds,const PetscInt ids[],PetscInt Nc,const PetscInt comps[],PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,InsertMode mode,Vec X)8323 PetscErrorCode DMProjectFunctionLabel(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
8324 {
8325 Vec localX;
8326 PetscErrorCode ierr;
8327
8328 PetscFunctionBegin;
8329 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8330 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
8331 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr);
8332 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr);
8333 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr);
8334 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
8335 PetscFunctionReturn(0);
8336 }
8337
8338 /*@C
8339 DMProjectFunctionLabelLocal - This projects the given function into the function space provided, putting the coefficients in a local vector, setting values only for points in the given label.
8340
8341 Not collective
8342
8343 Input Parameters:
8344 + dm - The DM
8345 . time - The time
8346 . label - The DMLabel selecting the portion of the mesh for projection
8347 . funcs - The coordinate functions to evaluate, one per field
8348 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null.
8349 - mode - The insertion mode for values
8350
8351 Output Parameter:
8352 . localX - vector
8353
8354 Calling sequence of func:
8355 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx);
8356
8357 + dim - The spatial dimension
8358 . x - The coordinates
8359 . Nf - The number of fields
8360 . u - The output field values
8361 - ctx - optional user-defined function context
8362
8363 Level: developer
8364
8365 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff()
8366 @*/
DMProjectFunctionLabelLocal(DM dm,PetscReal time,DMLabel label,PetscInt numIds,const PetscInt ids[],PetscInt Nc,const PetscInt comps[],PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,InsertMode mode,Vec localX)8367 PetscErrorCode DMProjectFunctionLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
8368 {
8369 PetscErrorCode ierr;
8370
8371 PetscFunctionBegin;
8372 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
8373 PetscValidHeaderSpecific(localX,VEC_CLASSID,5);
8374 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name);
8375 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr);
8376 PetscFunctionReturn(0);
8377 }
8378
8379 /*@C
8380 DMProjectFieldLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector.
8381
8382 Not collective
8383
8384 Input Parameters:
8385 + dm - The DM
8386 . time - The time
8387 . localU - The input field vector
8388 . funcs - The functions to evaluate, one per field
8389 - mode - The insertion mode for values
8390
8391 Output Parameter:
8392 . localX - The output vector
8393
8394 Calling sequence of func:
8395 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8396 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8397 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8398 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8399
8400 + dim - The spatial dimension
8401 . Nf - The number of input fields
8402 . NfAux - The number of input auxiliary fields
8403 . uOff - The offset of each field in u[]
8404 . uOff_x - The offset of each field in u_x[]
8405 . u - The field values at this point in space
8406 . u_t - The field time derivative at this point in space (or NULL)
8407 . u_x - The field derivatives at this point in space
8408 . aOff - The offset of each auxiliary field in u[]
8409 . aOff_x - The offset of each auxiliary field in u_x[]
8410 . a - The auxiliary field values at this point in space
8411 . a_t - The auxiliary field time derivative at this point in space (or NULL)
8412 . a_x - The auxiliary field derivatives at this point in space
8413 . t - The current time
8414 . x - The coordinates of this point
8415 . numConstants - The number of constants
8416 . constants - The value of each constant
8417 - f - The value of the function at this point in space
8418
8419 Note: There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs.
8420 The input DM, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or
8421 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the
8422 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations.
8423
8424 Level: intermediate
8425
8426 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff()
8427 @*/
DMProjectFieldLocal(DM dm,PetscReal time,Vec localU,void (** funcs)(PetscInt,PetscInt,PetscInt,const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],PetscReal,const PetscReal[],PetscInt,const PetscScalar[],PetscScalar[]),InsertMode mode,Vec localX)8428 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU,
8429 void (**funcs)(PetscInt, PetscInt, PetscInt,
8430 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
8431 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
8432 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
8433 InsertMode mode, Vec localX)
8434 {
8435 PetscErrorCode ierr;
8436
8437 PetscFunctionBegin;
8438 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
8439 PetscValidHeaderSpecific(localU,VEC_CLASSID,3);
8440 PetscValidHeaderSpecific(localX,VEC_CLASSID,6);
8441 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name);
8442 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr);
8443 PetscFunctionReturn(0);
8444 }
8445
8446 /*@C
8447 DMProjectFieldLabelLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector, calculating only over the portion of the domain specified by the label.
8448
8449 Not collective
8450
8451 Input Parameters:
8452 + dm - The DM
8453 . time - The time
8454 . label - The DMLabel marking the portion of the domain to output
8455 . numIds - The number of label ids to use
8456 . ids - The label ids to use for marking
8457 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components
8458 . comps - The components to set in the output, or NULL for all components
8459 . localU - The input field vector
8460 . funcs - The functions to evaluate, one per field
8461 - mode - The insertion mode for values
8462
8463 Output Parameter:
8464 . localX - The output vector
8465
8466 Calling sequence of func:
8467 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8468 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8469 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8470 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8471
8472 + dim - The spatial dimension
8473 . Nf - The number of input fields
8474 . NfAux - The number of input auxiliary fields
8475 . uOff - The offset of each field in u[]
8476 . uOff_x - The offset of each field in u_x[]
8477 . u - The field values at this point in space
8478 . u_t - The field time derivative at this point in space (or NULL)
8479 . u_x - The field derivatives at this point in space
8480 . aOff - The offset of each auxiliary field in u[]
8481 . aOff_x - The offset of each auxiliary field in u_x[]
8482 . a - The auxiliary field values at this point in space
8483 . a_t - The auxiliary field time derivative at this point in space (or NULL)
8484 . a_x - The auxiliary field derivatives at this point in space
8485 . t - The current time
8486 . x - The coordinates of this point
8487 . numConstants - The number of constants
8488 . constants - The value of each constant
8489 - f - The value of the function at this point in space
8490
8491 Note: There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs.
8492 The input DM, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or
8493 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the
8494 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations.
8495
8496 Level: intermediate
8497
8498 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff()
8499 @*/
DMProjectFieldLabelLocal(DM dm,PetscReal time,DMLabel label,PetscInt numIds,const PetscInt ids[],PetscInt Nc,const PetscInt comps[],Vec localU,void (** funcs)(PetscInt,PetscInt,PetscInt,const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],PetscReal,const PetscReal[],PetscInt,const PetscScalar[],PetscScalar[]),InsertMode mode,Vec localX)8500 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU,
8501 void (**funcs)(PetscInt, PetscInt, PetscInt,
8502 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
8503 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
8504 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
8505 InsertMode mode, Vec localX)
8506 {
8507 PetscErrorCode ierr;
8508
8509 PetscFunctionBegin;
8510 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
8511 PetscValidHeaderSpecific(localU,VEC_CLASSID,6);
8512 PetscValidHeaderSpecific(localX,VEC_CLASSID,9);
8513 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLabelLocal",((PetscObject)dm)->type_name);
8514 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr);
8515 PetscFunctionReturn(0);
8516 }
8517
8518 /*@C
8519 DMProjectBdFieldLabelLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector, calculating only over the portion of the domain boundary specified by the label.
8520
8521 Not collective
8522
8523 Input Parameters:
8524 + dm - The DM
8525 . time - The time
8526 . label - The DMLabel marking the portion of the domain boundary to output
8527 . numIds - The number of label ids to use
8528 . ids - The label ids to use for marking
8529 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components
8530 . comps - The components to set in the output, or NULL for all components
8531 . localU - The input field vector
8532 . funcs - The functions to evaluate, one per field
8533 - mode - The insertion mode for values
8534
8535 Output Parameter:
8536 . localX - The output vector
8537
8538 Calling sequence of func:
8539 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8540 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8541 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8542 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8543
8544 + dim - The spatial dimension
8545 . Nf - The number of input fields
8546 . NfAux - The number of input auxiliary fields
8547 . uOff - The offset of each field in u[]
8548 . uOff_x - The offset of each field in u_x[]
8549 . u - The field values at this point in space
8550 . u_t - The field time derivative at this point in space (or NULL)
8551 . u_x - The field derivatives at this point in space
8552 . aOff - The offset of each auxiliary field in u[]
8553 . aOff_x - The offset of each auxiliary field in u_x[]
8554 . a - The auxiliary field values at this point in space
8555 . a_t - The auxiliary field time derivative at this point in space (or NULL)
8556 . a_x - The auxiliary field derivatives at this point in space
8557 . t - The current time
8558 . x - The coordinates of this point
8559 . n - The face normal
8560 . numConstants - The number of constants
8561 . constants - The value of each constant
8562 - f - The value of the function at this point in space
8563
8564 Note:
8565 There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs.
8566 The input DM, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or
8567 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the
8568 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations.
8569
8570 Level: intermediate
8571
8572 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff()
8573 @*/
DMProjectBdFieldLabelLocal(DM dm,PetscReal time,DMLabel label,PetscInt numIds,const PetscInt ids[],PetscInt Nc,const PetscInt comps[],Vec localU,void (** funcs)(PetscInt,PetscInt,PetscInt,const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],PetscReal,const PetscReal[],const PetscReal[],PetscInt,const PetscScalar[],PetscScalar[]),InsertMode mode,Vec localX)8574 PetscErrorCode DMProjectBdFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU,
8575 void (**funcs)(PetscInt, PetscInt, PetscInt,
8576 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
8577 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
8578 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
8579 InsertMode mode, Vec localX)
8580 {
8581 PetscErrorCode ierr;
8582
8583 PetscFunctionBegin;
8584 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
8585 PetscValidHeaderSpecific(localU,VEC_CLASSID,6);
8586 PetscValidHeaderSpecific(localX,VEC_CLASSID,9);
8587 if (!dm->ops->projectbdfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectBdFieldLabelLocal",((PetscObject)dm)->type_name);
8588 ierr = (dm->ops->projectbdfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr);
8589 PetscFunctionReturn(0);
8590 }
8591
8592 /*@C
8593 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
8594
8595 Input Parameters:
8596 + dm - The DM
8597 . time - The time
8598 . funcs - The functions to evaluate for each field component
8599 . ctxs - Optional array of contexts to pass to each function, or NULL.
8600 - X - The coefficient vector u_h, a global vector
8601
8602 Output Parameter:
8603 . diff - The diff ||u - u_h||_2
8604
8605 Level: developer
8606
8607 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
8608 @*/
DMComputeL2Diff(DM dm,PetscReal time,PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,Vec X,PetscReal * diff)8609 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
8610 {
8611 PetscErrorCode ierr;
8612
8613 PetscFunctionBegin;
8614 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
8615 PetscValidHeaderSpecific(X,VEC_CLASSID,5);
8616 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name);
8617 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr);
8618 PetscFunctionReturn(0);
8619 }
8620
8621 /*@C
8622 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
8623
8624 Collective on dm
8625
8626 Input Parameters:
8627 + dm - The DM
8628 , time - The time
8629 . funcs - The gradient functions to evaluate for each field component
8630 . ctxs - Optional array of contexts to pass to each function, or NULL.
8631 . X - The coefficient vector u_h, a global vector
8632 - n - The vector to project along
8633
8634 Output Parameter:
8635 . diff - The diff ||(grad u - grad u_h) . n||_2
8636
8637 Level: developer
8638
8639 .seealso: DMProjectFunction(), DMComputeL2Diff()
8640 @*/
DMComputeL2GradientDiff(DM dm,PetscReal time,PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,Vec X,const PetscReal n[],PetscReal * diff)8641 PetscErrorCode DMComputeL2GradientDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff)
8642 {
8643 PetscErrorCode ierr;
8644
8645 PetscFunctionBegin;
8646 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
8647 PetscValidHeaderSpecific(X,VEC_CLASSID,5);
8648 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name);
8649 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr);
8650 PetscFunctionReturn(0);
8651 }
8652
8653 /*@C
8654 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.
8655
8656 Collective on dm
8657
8658 Input Parameters:
8659 + dm - The DM
8660 . time - The time
8661 . funcs - The functions to evaluate for each field component
8662 . ctxs - Optional array of contexts to pass to each function, or NULL.
8663 - X - The coefficient vector u_h, a global vector
8664
8665 Output Parameter:
8666 . diff - The array of differences, ||u^f - u^f_h||_2
8667
8668 Level: developer
8669
8670 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
8671 @*/
DMComputeL2FieldDiff(DM dm,PetscReal time,PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,Vec X,PetscReal diff[])8672 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
8673 {
8674 PetscErrorCode ierr;
8675
8676 PetscFunctionBegin;
8677 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
8678 PetscValidHeaderSpecific(X,VEC_CLASSID,5);
8679 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name);
8680 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr);
8681 PetscFunctionReturn(0);
8682 }
8683
8684 /*@C
8685 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have
8686 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN.
8687
8688 Collective on dm
8689
8690 Input parameters:
8691 + dm - the pre-adaptation DM object
8692 - label - label with the flags
8693
8694 Output parameters:
8695 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced.
8696
8697 Level: intermediate
8698
8699 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine()
8700 @*/
DMAdaptLabel(DM dm,DMLabel label,DM * dmAdapt)8701 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt)
8702 {
8703 PetscErrorCode ierr;
8704
8705 PetscFunctionBegin;
8706 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8707 PetscValidPointer(label,2);
8708 PetscValidPointer(dmAdapt,3);
8709 *dmAdapt = NULL;
8710 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name);
8711 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr);
8712 PetscFunctionReturn(0);
8713 }
8714
8715 /*@C
8716 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library.
8717
8718 Input Parameters:
8719 + dm - The DM object
8720 . metric - The metric to which the mesh is adapted, defined vertex-wise.
8721 - bdLabel - Label for boundary tags, which will be preserved in the output mesh. bdLabel should be NULL if there is no such label, and should be different from "_boundary_".
8722
8723 Output Parameter:
8724 . dmAdapt - Pointer to the DM object containing the adapted mesh
8725
8726 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object
8727
8728 Level: advanced
8729
8730 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine()
8731 @*/
DMAdaptMetric(DM dm,Vec metric,DMLabel bdLabel,DM * dmAdapt)8732 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt)
8733 {
8734 PetscErrorCode ierr;
8735
8736 PetscFunctionBegin;
8737 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8738 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2);
8739 if (bdLabel) PetscValidPointer(bdLabel, 3);
8740 PetscValidPointer(dmAdapt, 4);
8741 *dmAdapt = NULL;
8742 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name);
8743 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr);
8744 PetscFunctionReturn(0);
8745 }
8746
8747 /*@C
8748 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors
8749
8750 Not Collective
8751
8752 Input Parameter:
8753 . dm - The DM
8754
8755 Output Parameters:
8756 + nranks - the number of neighbours
8757 - ranks - the neighbors ranks
8758
8759 Notes:
8760 Do not free the array, it is freed when the DM is destroyed.
8761
8762 Level: beginner
8763
8764 .seealso: DMDAGetNeighbors(), PetscSFGetRootRanks()
8765 @*/
DMGetNeighbors(DM dm,PetscInt * nranks,const PetscMPIInt * ranks[])8766 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[])
8767 {
8768 PetscErrorCode ierr;
8769
8770 PetscFunctionBegin;
8771 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
8772 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name);
8773 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr);
8774 PetscFunctionReturn(0);
8775 }
8776
8777 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */
8778
8779 /*
8780 Converts the input vector to a ghosted vector and then calls the standard coloring code.
8781 This has be a different function because it requires DM which is not defined in the Mat library
8782 */
MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void * sctx)8783 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx)
8784 {
8785 PetscErrorCode ierr;
8786
8787 PetscFunctionBegin;
8788 if (coloring->ctype == IS_COLORING_LOCAL) {
8789 Vec x1local;
8790 DM dm;
8791 ierr = MatGetDM(J,&dm);CHKERRQ(ierr);
8792 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM");
8793 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr);
8794 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr);
8795 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr);
8796 x1 = x1local;
8797 }
8798 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr);
8799 if (coloring->ctype == IS_COLORING_LOCAL) {
8800 DM dm;
8801 ierr = MatGetDM(J,&dm);CHKERRQ(ierr);
8802 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr);
8803 }
8804 PetscFunctionReturn(0);
8805 }
8806
8807 /*@
8808 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring
8809
8810 Input Parameter:
8811 . coloring - the MatFDColoring object
8812
8813 Developer Notes:
8814 this routine exists because the PETSc Mat library does not know about the DM objects
8815
8816 Level: advanced
8817
8818 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType
8819 @*/
MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring)8820 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring)
8821 {
8822 PetscFunctionBegin;
8823 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM;
8824 PetscFunctionReturn(0);
8825 }
8826
8827 /*@
8828 DMGetCompatibility - determine if two DMs are compatible
8829
8830 Collective
8831
8832 Input Parameters:
8833 + dm1 - the first DM
8834 - dm2 - the second DM
8835
8836 Output Parameters:
8837 + compatible - whether or not the two DMs are compatible
8838 - set - whether or not the compatible value was set
8839
8840 Notes:
8841 Two DMs are deemed compatible if they represent the same parallel decomposition
8842 of the same topology. This implies that the section (field data) on one
8843 "makes sense" with respect to the topology and parallel decomposition of the other.
8844 Loosely speaking, compatible DMs represent the same domain and parallel
8845 decomposition, but hold different data.
8846
8847 Typically, one would confirm compatibility if intending to simultaneously iterate
8848 over a pair of vectors obtained from different DMs.
8849
8850 For example, two DMDA objects are compatible if they have the same local
8851 and global sizes and the same stencil width. They can have different numbers
8852 of degrees of freedom per node. Thus, one could use the node numbering from
8853 either DM in bounds for a loop over vectors derived from either DM.
8854
8855 Consider the operation of summing data living on a 2-dof DMDA to data living
8856 on a 1-dof DMDA, which should be compatible, as in the following snippet.
8857 .vb
8858 ...
8859 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr);
8860 if (set && compatible) {
8861 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr);
8862 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr);
8863 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr);
8864 for (j=y; j<y+n; ++j) {
8865 for (i=x; i<x+m, ++i) {
8866 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1];
8867 }
8868 }
8869 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr);
8870 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr);
8871 } else {
8872 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible");
8873 }
8874 ...
8875 .ve
8876
8877 Checking compatibility might be expensive for a given implementation of DM,
8878 or might be impossible to unambiguously confirm or deny. For this reason,
8879 this function may decline to determine compatibility, and hence users should
8880 always check the "set" output parameter.
8881
8882 A DM is always compatible with itself.
8883
8884 In the current implementation, DMs which live on "unequal" communicators
8885 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed
8886 incompatible.
8887
8888 This function is labeled "Collective," as information about all subdomains
8889 is required on each rank. However, in DM implementations which store all this
8890 information locally, this function may be merely "Logically Collective".
8891
8892 Developer Notes:
8893 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B
8894 iff B is compatible with A. Thus, this function checks the implementations
8895 of both dm and dmc (if they are of different types), attempting to determine
8896 compatibility. It is left to DM implementers to ensure that symmetry is
8897 preserved. The simplest way to do this is, when implementing type-specific
8898 logic for this function, is to check for existing logic in the implementation
8899 of other DM types and let *set = PETSC_FALSE if found.
8900
8901 Level: advanced
8902
8903 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag()
8904 @*/
8905
DMGetCompatibility(DM dm1,DM dm2,PetscBool * compatible,PetscBool * set)8906 PetscErrorCode DMGetCompatibility(DM dm1,DM dm2,PetscBool *compatible,PetscBool *set)
8907 {
8908 PetscErrorCode ierr;
8909 PetscMPIInt compareResult;
8910 DMType type,type2;
8911 PetscBool sameType;
8912
8913 PetscFunctionBegin;
8914 PetscValidHeaderSpecific(dm1,DM_CLASSID,1);
8915 PetscValidHeaderSpecific(dm2,DM_CLASSID,2);
8916
8917 /* Declare a DM compatible with itself */
8918 if (dm1 == dm2) {
8919 *set = PETSC_TRUE;
8920 *compatible = PETSC_TRUE;
8921 PetscFunctionReturn(0);
8922 }
8923
8924 /* Declare a DM incompatible with a DM that lives on an "unequal"
8925 communicator. Note that this does not preclude compatibility with
8926 DMs living on "congruent" or "similar" communicators, but this must be
8927 determined by the implementation-specific logic */
8928 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm1),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRQ(ierr);
8929 if (compareResult == MPI_UNEQUAL) {
8930 *set = PETSC_TRUE;
8931 *compatible = PETSC_FALSE;
8932 PetscFunctionReturn(0);
8933 }
8934
8935 /* Pass to the implementation-specific routine, if one exists. */
8936 if (dm1->ops->getcompatibility) {
8937 ierr = (*dm1->ops->getcompatibility)(dm1,dm2,compatible,set);CHKERRQ(ierr);
8938 if (*set) PetscFunctionReturn(0);
8939 }
8940
8941 /* If dm1 and dm2 are of different types, then attempt to check compatibility
8942 with an implementation of this function from dm2 */
8943 ierr = DMGetType(dm1,&type);CHKERRQ(ierr);
8944 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr);
8945 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr);
8946 if (!sameType && dm2->ops->getcompatibility) {
8947 ierr = (*dm2->ops->getcompatibility)(dm2,dm1,compatible,set);CHKERRQ(ierr); /* Note argument order */
8948 } else {
8949 *set = PETSC_FALSE;
8950 }
8951 PetscFunctionReturn(0);
8952 }
8953
8954 /*@C
8955 DMMonitorSet - Sets an ADDITIONAL function that is to be used after a solve to monitor discretization performance.
8956
8957 Logically Collective on DM
8958
8959 Input Parameters:
8960 + DM - the DM
8961 . f - the monitor function
8962 . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired)
8963 - monitordestroy - [optional] routine that frees monitor context (may be NULL)
8964
8965 Options Database Keys:
8966 - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to DMMonitorSet(), but
8967 does not cancel those set via the options database.
8968
8969 Notes:
8970 Several different monitoring routines may be set by calling
8971 DMMonitorSet() multiple times; all will be called in the
8972 order in which they were set.
8973
8974 Fortran Notes:
8975 Only a single monitor function can be set for each DM object
8976
8977 Level: intermediate
8978
8979 .seealso: DMMonitorCancel()
8980 @*/
DMMonitorSet(DM dm,PetscErrorCode (* f)(DM,void *),void * mctx,PetscErrorCode (* monitordestroy)(void **))8981 PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void**))
8982 {
8983 PetscInt m;
8984 PetscErrorCode ierr;
8985
8986 PetscFunctionBegin;
8987 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8988 for (m = 0; m < dm->numbermonitors; ++m) {
8989 PetscBool identical;
8990
8991 ierr = PetscMonitorCompare((PetscErrorCode (*)(void)) f, mctx, monitordestroy, (PetscErrorCode (*)(void)) dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical);CHKERRQ(ierr);
8992 if (identical) PetscFunctionReturn(0);
8993 }
8994 if (dm->numbermonitors >= MAXDMMONITORS) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
8995 dm->monitor[dm->numbermonitors] = f;
8996 dm->monitordestroy[dm->numbermonitors] = monitordestroy;
8997 dm->monitorcontext[dm->numbermonitors++] = (void *) mctx;
8998 PetscFunctionReturn(0);
8999 }
9000
9001 /*@
9002 DMMonitorCancel - Clears all the monitor functions for a DM object.
9003
9004 Logically Collective on DM
9005
9006 Input Parameter:
9007 . dm - the DM
9008
9009 Options Database Key:
9010 . -dm_monitor_cancel - cancels all monitors that have been hardwired
9011 into a code by calls to DMonitorSet(), but does not cancel those
9012 set via the options database
9013
9014 Notes:
9015 There is no way to clear one specific monitor from a DM object.
9016
9017 Level: intermediate
9018
9019 .seealso: DMMonitorSet()
9020 @*/
DMMonitorCancel(DM dm)9021 PetscErrorCode DMMonitorCancel(DM dm)
9022 {
9023 PetscErrorCode ierr;
9024 PetscInt m;
9025
9026 PetscFunctionBegin;
9027 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9028 for (m = 0; m < dm->numbermonitors; ++m) {
9029 if (dm->monitordestroy[m]) {ierr = (*dm->monitordestroy[m])(&dm->monitorcontext[m]);CHKERRQ(ierr);}
9030 }
9031 dm->numbermonitors = 0;
9032 PetscFunctionReturn(0);
9033 }
9034
9035 /*@C
9036 DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
9037
9038 Collective on DM
9039
9040 Input Parameters:
9041 + dm - DM object you wish to monitor
9042 . name - the monitor type one is seeking
9043 . help - message indicating what monitoring is done
9044 . manual - manual page for the monitor
9045 . monitor - the monitor function
9046 - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the DM or PetscViewer objects
9047
9048 Output Parameter:
9049 . flg - Flag set if the monitor was created
9050
9051 Level: developer
9052
9053 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
9054 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
9055 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
9056 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
9057 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
9058 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
9059 PetscOptionsFList(), PetscOptionsEList()
9060 @*/
DMMonitorSetFromOptions(DM dm,const char name[],const char help[],const char manual[],PetscErrorCode (* monitor)(DM,void *),PetscErrorCode (* monitorsetup)(DM,PetscViewerAndFormat *),PetscBool * flg)9061 PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg)
9062 {
9063 PetscViewer viewer;
9064 PetscViewerFormat format;
9065 PetscErrorCode ierr;
9066
9067 PetscFunctionBegin;
9068 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9069 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) dm), ((PetscObject) dm)->options, ((PetscObject) dm)->prefix, name, &viewer, &format, flg);CHKERRQ(ierr);
9070 if (*flg) {
9071 PetscViewerAndFormat *vf;
9072
9073 ierr = PetscViewerAndFormatCreate(viewer, format, &vf);CHKERRQ(ierr);
9074 ierr = PetscObjectDereference((PetscObject) viewer);CHKERRQ(ierr);
9075 if (monitorsetup) {ierr = (*monitorsetup)(dm, vf);CHKERRQ(ierr);}
9076 ierr = DMMonitorSet(dm,(PetscErrorCode (*)(DM, void *)) monitor, vf, (PetscErrorCode (*)(void **)) PetscViewerAndFormatDestroy);CHKERRQ(ierr);
9077 }
9078 PetscFunctionReturn(0);
9079 }
9080
9081 /*@
9082 DMMonitor - runs the user provided monitor routines, if they exist
9083
9084 Collective on DM
9085
9086 Input Parameters:
9087 . dm - The DM
9088
9089 Level: developer
9090
9091 .seealso: DMMonitorSet()
9092 @*/
DMMonitor(DM dm)9093 PetscErrorCode DMMonitor(DM dm)
9094 {
9095 PetscInt m;
9096 PetscErrorCode ierr;
9097
9098 PetscFunctionBegin;
9099 if (!dm) PetscFunctionReturn(0);
9100 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9101 for (m = 0; m < dm->numbermonitors; ++m) {
9102 ierr = (*dm->monitor[m])(dm, dm->monitorcontext[m]);CHKERRQ(ierr);
9103 }
9104 PetscFunctionReturn(0);
9105 }
9106