Actual source code: dm.c
petsc-3.8.3 2017-12-09
1: #include <petsc/private/dmimpl.h>
2: #include <petsc/private/dmlabelimpl.h>
3: #include <petsc/private/petscdsimpl.h>
4: #include <petscdmplex.h>
5: #include <petscsf.h>
6: #include <petscds.h>
8: PetscClassId DM_CLASSID;
9: PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_Refine, DM_CreateInterpolation, DM_CreateRestriction;
11: const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DM_BOUNDARY_",0};
13: /*@
14: DMCreate - Creates an empty DM object. The type can then be set with DMSetType().
16: If you never call DMSetType() it will generate an
17: error when you try to use the vector.
19: Collective on MPI_Comm
21: Input Parameter:
22: . comm - The communicator for the DM object
24: Output Parameter:
25: . dm - The DM object
27: Level: beginner
29: .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK
30: @*/
31: PetscErrorCode DMCreate(MPI_Comm comm,DM *dm)
32: {
33: DM v;
38: *dm = NULL;
39: PetscSysInitializePackage();
40: VecInitializePackage();
41: MatInitializePackage();
42: DMInitializePackage();
44: PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);
46: v->ltogmap = NULL;
47: v->bs = 1;
48: v->coloringtype = IS_COLORING_GLOBAL;
49: PetscSFCreate(comm, &v->sf);
50: PetscSFCreate(comm, &v->defaultSF);
51: v->labels = NULL;
52: v->depthLabel = NULL;
53: v->defaultSection = NULL;
54: v->defaultGlobalSection = NULL;
55: v->defaultConstraintSection = NULL;
56: v->defaultConstraintMat = NULL;
57: v->L = NULL;
58: v->maxCell = NULL;
59: v->bdtype = NULL;
60: v->dimEmbed = PETSC_DEFAULT;
61: {
62: PetscInt i;
63: for (i = 0; i < 10; ++i) {
64: v->nullspaceConstructors[i] = NULL;
65: }
66: }
67: PetscDSCreate(comm, &v->prob);
68: v->dmBC = NULL;
69: v->coarseMesh = NULL;
70: v->outputSequenceNum = -1;
71: v->outputSequenceVal = 0.0;
72: DMSetVecType(v,VECSTANDARD);
73: DMSetMatType(v,MATAIJ);
74: PetscNew(&(v->labels));
75: v->labels->refct = 1;
76: *dm = v;
77: return(0);
78: }
80: /*@
81: DMClone - Creates a DM object with the same topology as the original.
83: Collective on MPI_Comm
85: Input Parameter:
86: . dm - The original DM object
88: Output Parameter:
89: . newdm - The new DM object
91: Level: beginner
93: .keywords: DM, topology, create
94: @*/
95: PetscErrorCode DMClone(DM dm, DM *newdm)
96: {
97: PetscSF sf;
98: Vec coords;
99: void *ctx;
100: PetscInt dim, cdim;
106: DMCreate(PetscObjectComm((PetscObject) dm), newdm);
107: PetscFree((*newdm)->labels);
108: dm->labels->refct++;
109: (*newdm)->labels = dm->labels;
110: (*newdm)->depthLabel = dm->depthLabel;
111: DMGetDimension(dm, &dim);
112: DMSetDimension(*newdm, dim);
113: if (dm->ops->clone) {
114: (*dm->ops->clone)(dm, newdm);
115: }
116: (*newdm)->setupcalled = dm->setupcalled;
117: DMGetPointSF(dm, &sf);
118: DMSetPointSF(*newdm, sf);
119: DMGetApplicationContext(dm, &ctx);
120: DMSetApplicationContext(*newdm, ctx);
121: if (dm->coordinateDM) {
122: DM ncdm;
123: PetscSection cs;
124: PetscInt pEnd = -1, pEndMax = -1;
126: DMGetDefaultSection(dm->coordinateDM, &cs);
127: if (cs) {PetscSectionGetChart(cs, NULL, &pEnd);}
128: MPI_Allreduce(&pEnd,&pEndMax,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));
129: if (pEndMax >= 0) {
130: DMClone(dm->coordinateDM, &ncdm);
131: DMSetDefaultSection(ncdm, cs);
132: DMSetCoordinateDM(*newdm, ncdm);
133: DMDestroy(&ncdm);
134: }
135: }
136: DMGetCoordinateDim(dm, &cdim);
137: DMSetCoordinateDim(*newdm, cdim);
138: DMGetCoordinatesLocal(dm, &coords);
139: if (coords) {
140: DMSetCoordinatesLocal(*newdm, coords);
141: } else {
142: DMGetCoordinates(dm, &coords);
143: if (coords) {DMSetCoordinates(*newdm, coords);}
144: }
145: {
146: PetscBool isper;
147: const PetscReal *maxCell, *L;
148: const DMBoundaryType *bd;
149: DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);
150: DMSetPeriodicity(*newdm, isper, maxCell, L, bd);
151: }
152: return(0);
153: }
155: /*@C
156: DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
158: Logically Collective on DM
160: Input Parameter:
161: + da - initial distributed array
162: . ctype - the vector type, currently either VECSTANDARD or VECCUSP
164: Options Database:
165: . -dm_vec_type ctype
167: Level: intermediate
169: .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType()
170: @*/
171: PetscErrorCode DMSetVecType(DM da,VecType ctype)
172: {
177: PetscFree(da->vectype);
178: PetscStrallocpy(ctype,(char**)&da->vectype);
179: return(0);
180: }
182: /*@C
183: DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
185: Logically Collective on DM
187: Input Parameter:
188: . da - initial distributed array
190: Output Parameter:
191: . ctype - the vector type
193: Level: intermediate
195: .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType
196: @*/
197: PetscErrorCode DMGetVecType(DM da,VecType *ctype)
198: {
201: *ctype = da->vectype;
202: return(0);
203: }
205: /*@
206: VecGetDM - Gets the DM defining the data layout of the vector
208: Not collective
210: Input Parameter:
211: . v - The Vec
213: Output Parameter:
214: . dm - The DM
216: Level: intermediate
218: .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
219: @*/
220: PetscErrorCode VecGetDM(Vec v, DM *dm)
221: {
227: PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);
228: return(0);
229: }
231: /*@
232: VecSetDM - Sets the DM defining the data layout of the vector.
234: Not collective
236: Input Parameters:
237: + v - The Vec
238: - dm - The DM
240: 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.
242: Level: intermediate
244: .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
245: @*/
246: PetscErrorCode VecSetDM(Vec v, DM dm)
247: {
253: PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);
254: return(0);
255: }
257: /*@C
258: DMSetMatType - Sets the type of matrix created with DMCreateMatrix()
260: Logically Collective on DM
262: Input Parameter:
263: + dm - the DM context
264: - ctype - the matrix type
266: Options Database:
267: . -dm_mat_type ctype
269: Level: intermediate
271: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType()
272: @*/
273: PetscErrorCode DMSetMatType(DM dm,MatType ctype)
274: {
279: PetscFree(dm->mattype);
280: PetscStrallocpy(ctype,(char**)&dm->mattype);
281: return(0);
282: }
284: /*@C
285: DMGetMatType - Gets the type of matrix created with DMCreateMatrix()
287: Logically Collective on DM
289: Input Parameter:
290: . dm - the DM context
292: Output Parameter:
293: . ctype - the matrix type
295: Options Database:
296: . -dm_mat_type ctype
298: Level: intermediate
300: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType()
301: @*/
302: PetscErrorCode DMGetMatType(DM dm,MatType *ctype)
303: {
306: *ctype = dm->mattype;
307: return(0);
308: }
310: /*@
311: MatGetDM - Gets the DM defining the data layout of the matrix
313: Not collective
315: Input Parameter:
316: . A - The Mat
318: Output Parameter:
319: . dm - The DM
321: Level: intermediate
323: .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType()
324: @*/
325: PetscErrorCode MatGetDM(Mat A, DM *dm)
326: {
332: PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);
333: return(0);
334: }
336: /*@
337: MatSetDM - Sets the DM defining the data layout of the matrix
339: Not collective
341: Input Parameters:
342: + A - The Mat
343: - dm - The DM
345: Level: intermediate
347: .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType()
348: @*/
349: PetscErrorCode MatSetDM(Mat A, DM dm)
350: {
356: PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);
357: return(0);
358: }
360: /*@C
361: DMSetOptionsPrefix - Sets the prefix used for searching for all
362: DM options in the database.
364: Logically Collective on DM
366: Input Parameter:
367: + da - the DM context
368: - prefix - the prefix to prepend to all option names
370: Notes:
371: A hyphen (-) must NOT be given at the beginning of the prefix name.
372: The first character of all runtime options is AUTOMATICALLY the hyphen.
374: Level: advanced
376: .keywords: DM, set, options, prefix, database
378: .seealso: DMSetFromOptions()
379: @*/
380: PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[])
381: {
386: PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);
387: if (dm->sf) {
388: PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);
389: }
390: if (dm->defaultSF) {
391: PetscObjectSetOptionsPrefix((PetscObject)dm->defaultSF,prefix);
392: }
393: return(0);
394: }
396: /*@C
397: DMAppendOptionsPrefix - Appends to the prefix used for searching for all
398: DM options in the database.
400: Logically Collective on DM
402: Input Parameters:
403: + dm - the DM context
404: - prefix - the prefix string to prepend to all DM option requests
406: Notes:
407: A hyphen (-) must NOT be given at the beginning of the prefix name.
408: The first character of all runtime options is AUTOMATICALLY the hyphen.
410: Level: advanced
412: .keywords: DM, append, options, prefix, database
414: .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix()
415: @*/
416: PetscErrorCode DMAppendOptionsPrefix(DM dm,const char prefix[])
417: {
422: PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);
423: return(0);
424: }
426: /*@C
427: DMGetOptionsPrefix - Gets the prefix used for searching for all
428: DM options in the database.
430: Not Collective
432: Input Parameters:
433: . dm - the DM context
435: Output Parameters:
436: . prefix - pointer to the prefix string used is returned
438: Notes: On the fortran side, the user should pass in a string 'prefix' of
439: sufficient length to hold the prefix.
441: Level: advanced
443: .keywords: DM, set, options, prefix, database
445: .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix()
446: @*/
447: PetscErrorCode DMGetOptionsPrefix(DM dm,const char *prefix[])
448: {
453: PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);
454: return(0);
455: }
457: static PetscErrorCode DMCountNonCyclicReferences(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct)
458: {
459: PetscInt i, refct = ((PetscObject) dm)->refct;
460: DMNamedVecLink nlink;
464: *ncrefct = 0;
465: /* count all the circular references of DM and its contained Vecs */
466: for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
467: if (dm->localin[i]) refct--;
468: if (dm->globalin[i]) refct--;
469: }
470: for (nlink=dm->namedglobal; nlink; nlink=nlink->next) refct--;
471: for (nlink=dm->namedlocal; nlink; nlink=nlink->next) refct--;
472: if (dm->x) {
473: DM obj;
474: VecGetDM(dm->x, &obj);
475: if (obj == dm) refct--;
476: }
477: if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) {
478: refct--;
479: if (recurseCoarse) {
480: PetscInt coarseCount;
482: DMCountNonCyclicReferences(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE,&coarseCount);
483: refct += coarseCount;
484: }
485: }
486: if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) {
487: refct--;
488: if (recurseFine) {
489: PetscInt fineCount;
491: DMCountNonCyclicReferences(dm->fineMesh, PETSC_FALSE, PETSC_TRUE,&fineCount);
492: refct += fineCount;
493: }
494: }
495: *ncrefct = refct;
496: return(0);
497: }
499: PetscErrorCode DMDestroyLabelLinkList(DM dm)
500: {
504: if (!--(dm->labels->refct)) {
505: DMLabelLink next = dm->labels->next;
507: /* destroy the labels */
508: while (next) {
509: DMLabelLink tmp = next->next;
511: DMLabelDestroy(&next->label);
512: PetscFree(next);
513: next = tmp;
514: }
515: PetscFree(dm->labels);
516: }
517: return(0);
518: }
520: /*@
521: DMDestroy - Destroys a vector packer or DM.
523: Collective on DM
525: Input Parameter:
526: . dm - the DM object to destroy
528: Level: developer
530: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
532: @*/
533: PetscErrorCode DMDestroy(DM *dm)
534: {
535: PetscInt i, cnt;
536: DMNamedVecLink nlink,nnext;
540: if (!*dm) return(0);
543: /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */
544: DMCountNonCyclicReferences(*dm,PETSC_TRUE,PETSC_TRUE,&cnt);
545: --((PetscObject)(*dm))->refct;
546: if (--cnt > 0) {*dm = 0; return(0);}
547: /*
548: Need this test because the dm references the vectors that
549: reference the dm, so destroying the dm calls destroy on the
550: vectors that cause another destroy on the dm
551: */
552: if (((PetscObject)(*dm))->refct < 0) return(0);
553: ((PetscObject) (*dm))->refct = 0;
554: for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
555: if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()");
556: VecDestroy(&(*dm)->localin[i]);
557: }
558: nnext=(*dm)->namedglobal;
559: (*dm)->namedglobal = NULL;
560: for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */
561: nnext = nlink->next;
562: if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
563: PetscFree(nlink->name);
564: VecDestroy(&nlink->X);
565: PetscFree(nlink);
566: }
567: nnext=(*dm)->namedlocal;
568: (*dm)->namedlocal = NULL;
569: for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */
570: nnext = nlink->next;
571: if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
572: PetscFree(nlink->name);
573: VecDestroy(&nlink->X);
574: PetscFree(nlink);
575: }
577: /* Destroy the list of hooks */
578: {
579: DMCoarsenHookLink link,next;
580: for (link=(*dm)->coarsenhook; link; link=next) {
581: next = link->next;
582: PetscFree(link);
583: }
584: (*dm)->coarsenhook = NULL;
585: }
586: {
587: DMRefineHookLink link,next;
588: for (link=(*dm)->refinehook; link; link=next) {
589: next = link->next;
590: PetscFree(link);
591: }
592: (*dm)->refinehook = NULL;
593: }
594: {
595: DMSubDomainHookLink link,next;
596: for (link=(*dm)->subdomainhook; link; link=next) {
597: next = link->next;
598: PetscFree(link);
599: }
600: (*dm)->subdomainhook = NULL;
601: }
602: {
603: DMGlobalToLocalHookLink link,next;
604: for (link=(*dm)->gtolhook; link; link=next) {
605: next = link->next;
606: PetscFree(link);
607: }
608: (*dm)->gtolhook = NULL;
609: }
610: {
611: DMLocalToGlobalHookLink link,next;
612: for (link=(*dm)->ltoghook; link; link=next) {
613: next = link->next;
614: PetscFree(link);
615: }
616: (*dm)->ltoghook = NULL;
617: }
618: /* Destroy the work arrays */
619: {
620: DMWorkLink link,next;
621: if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out");
622: for (link=(*dm)->workin; link; link=next) {
623: next = link->next;
624: PetscFree(link->mem);
625: PetscFree(link);
626: }
627: (*dm)->workin = NULL;
628: }
629: if (!--((*dm)->labels->refct)) {
630: DMLabelLink next = (*dm)->labels->next;
632: /* destroy the labels */
633: while (next) {
634: DMLabelLink tmp = next->next;
636: DMLabelDestroy(&next->label);
637: PetscFree(next);
638: next = tmp;
639: }
640: PetscFree((*dm)->labels);
641: }
642: {
643: DMBoundary next = (*dm)->boundary;
644: while (next) {
645: DMBoundary b = next;
647: next = b->next;
648: PetscFree(b);
649: }
650: }
652: PetscObjectDestroy(&(*dm)->dmksp);
653: PetscObjectDestroy(&(*dm)->dmsnes);
654: PetscObjectDestroy(&(*dm)->dmts);
656: if ((*dm)->ctx && (*dm)->ctxdestroy) {
657: (*(*dm)->ctxdestroy)(&(*dm)->ctx);
658: }
659: VecDestroy(&(*dm)->x);
660: MatFDColoringDestroy(&(*dm)->fd);
661: DMClearGlobalVectors(*dm);
662: ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);
663: PetscFree((*dm)->vectype);
664: PetscFree((*dm)->mattype);
666: PetscSectionDestroy(&(*dm)->defaultSection);
667: PetscSectionDestroy(&(*dm)->defaultGlobalSection);
668: PetscLayoutDestroy(&(*dm)->map);
669: PetscSectionDestroy(&(*dm)->defaultConstraintSection);
670: MatDestroy(&(*dm)->defaultConstraintMat);
671: PetscSFDestroy(&(*dm)->sf);
672: PetscSFDestroy(&(*dm)->defaultSF);
673: PetscSFDestroy(&(*dm)->sfNatural);
675: if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) {
676: DMSetFineDM((*dm)->coarseMesh,NULL);
677: }
678: DMDestroy(&(*dm)->coarseMesh);
679: if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) {
680: DMSetCoarseDM((*dm)->fineMesh,NULL);
681: }
682: DMDestroy(&(*dm)->fineMesh);
683: DMDestroy(&(*dm)->coordinateDM);
684: VecDestroy(&(*dm)->coordinates);
685: VecDestroy(&(*dm)->coordinatesLocal);
686: PetscFree3((*dm)->L,(*dm)->maxCell,(*dm)->bdtype);
688: PetscDSDestroy(&(*dm)->prob);
689: DMDestroy(&(*dm)->dmBC);
690: /* if memory was published with SAWs then destroy it */
691: PetscObjectSAWsViewOff((PetscObject)*dm);
693: (*(*dm)->ops->destroy)(*dm);
694: /* We do not destroy (*dm)->data here so that we can reference count backend objects */
695: PetscHeaderDestroy(dm);
696: return(0);
697: }
699: /*@
700: DMSetUp - sets up the data structures inside a DM object
702: Collective on DM
704: Input Parameter:
705: . dm - the DM object to setup
707: Level: developer
709: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
711: @*/
712: PetscErrorCode DMSetUp(DM dm)
713: {
718: if (dm->setupcalled) return(0);
719: if (dm->ops->setup) {
720: (*dm->ops->setup)(dm);
721: }
722: dm->setupcalled = PETSC_TRUE;
723: return(0);
724: }
726: /*@
727: DMSetFromOptions - sets parameters in a DM from the options database
729: Collective on DM
731: Input Parameter:
732: . dm - the DM object to set options for
734: Options Database:
735: + -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros
736: . -dm_vec_type <type> - type of vector to create inside DM
737: . -dm_mat_type <type> - type of matrix to create inside DM
738: - -dm_coloring_type - <global or ghosted>
740: Level: developer
742: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
744: @*/
745: PetscErrorCode DMSetFromOptions(DM dm)
746: {
747: char typeName[256];
748: PetscBool flg;
753: if (dm->prob) {
754: PetscDSSetFromOptions(dm->prob);
755: }
756: if (dm->sf) {
757: PetscSFSetFromOptions(dm->sf);
758: }
759: if (dm->defaultSF) {
760: PetscSFSetFromOptions(dm->defaultSF);
761: }
762: PetscObjectOptionsBegin((PetscObject)dm);
763: PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);
764: PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);
765: if (flg) {
766: DMSetVecType(dm,typeName);
767: }
768: PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);
769: if (flg) {
770: DMSetMatType(dm,typeName);
771: }
772: PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","ISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);
773: if (dm->ops->setfromoptions) {
774: (*dm->ops->setfromoptions)(PetscOptionsObject,dm);
775: }
776: /* process any options handlers added with PetscObjectAddOptionsHandler() */
777: PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) dm);
778: PetscOptionsEnd();
779: return(0);
780: }
782: /*@C
783: DMView - Views a DM
785: Collective on DM
787: Input Parameter:
788: + dm - the DM object to view
789: - v - the viewer
791: Level: beginner
793: .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
795: @*/
796: PetscErrorCode DMView(DM dm,PetscViewer v)
797: {
799: PetscBool isbinary;
803: if (!v) {
804: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);
805: }
806: PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);
807: PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);
808: if (isbinary) {
809: PetscInt classid = DM_FILE_CLASSID;
810: char type[256];
812: PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);
813: PetscStrncpy(type,((PetscObject)dm)->type_name,256);
814: PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);
815: }
816: if (dm->ops->view) {
817: (*dm->ops->view)(dm,v);
818: }
819: return(0);
820: }
822: /*@
823: DMCreateGlobalVector - Creates a global vector from a DM object
825: Collective on DM
827: Input Parameter:
828: . dm - the DM object
830: Output Parameter:
831: . vec - the global vector
833: Level: beginner
835: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
837: @*/
838: PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec)
839: {
844: (*dm->ops->createglobalvector)(dm,vec);
845: return(0);
846: }
848: /*@
849: DMCreateLocalVector - Creates a local vector from a DM object
851: Not Collective
853: Input Parameter:
854: . dm - the DM object
856: Output Parameter:
857: . vec - the local vector
859: Level: beginner
861: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
863: @*/
864: PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec)
865: {
870: (*dm->ops->createlocalvector)(dm,vec);
871: return(0);
872: }
874: /*@
875: DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM.
877: Collective on DM
879: Input Parameter:
880: . dm - the DM that provides the mapping
882: Output Parameter:
883: . ltog - the mapping
885: Level: intermediate
887: Notes:
888: This mapping can then be used by VecSetLocalToGlobalMapping() or
889: MatSetLocalToGlobalMapping().
891: .seealso: DMCreateLocalVector()
892: @*/
893: PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog)
894: {
895: PetscInt bs = -1, bsLocal, bsMin, bsMax;
901: if (!dm->ltogmap) {
902: PetscSection section, sectionGlobal;
904: DMGetDefaultSection(dm, §ion);
905: if (section) {
906: const PetscInt *cdofs;
907: PetscInt *ltog;
908: PetscInt pStart, pEnd, n, p, k, l;
910: DMGetDefaultGlobalSection(dm, §ionGlobal);
911: PetscSectionGetChart(section, &pStart, &pEnd);
912: PetscSectionGetStorageSize(section, &n);
913: PetscMalloc1(n, <og); /* We want the local+overlap size */
914: for (p = pStart, l = 0; p < pEnd; ++p) {
915: PetscInt bdof, cdof, dof, off, c, cind = 0;
917: /* Should probably use constrained dofs */
918: PetscSectionGetDof(section, p, &dof);
919: PetscSectionGetConstraintDof(section, p, &cdof);
920: PetscSectionGetConstraintIndices(section, p, &cdofs);
921: PetscSectionGetOffset(sectionGlobal, p, &off);
922: /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */
923: bdof = cdof && (dof-cdof) ? 1 : dof;
924: if (dof) {
925: if (bs < 0) {bs = bdof;}
926: else if (bs != bdof) {bs = 1;}
927: }
928: for (c = 0; c < dof; ++c, ++l) {
929: if ((cind < cdof) && (c == cdofs[cind])) ltog[l] = off < 0 ? off-c : off+c;
930: else ltog[l] = (off < 0 ? -(off+1) : off) + c;
931: }
932: }
933: /* Must have same blocksize on all procs (some might have no points) */
934: bsLocal = bs;
935: MPIU_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));
936: bsLocal = bs < 0 ? bsMax : bs;
937: MPIU_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm));
938: if (bsMin != bsMax) {bs = 1;}
939: else {bs = bsMax;}
940: bs = bs < 0 ? 1 : bs;
941: /* Must reduce indices by blocksize */
942: if (bs > 1) {
943: for (l = 0, k = 0; l < n; l += bs, ++k) ltog[k] = ltog[l]/bs;
944: n /= bs;
945: }
946: ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap);
947: PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);
948: } else {
949: if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping");
950: (*dm->ops->getlocaltoglobalmapping)(dm);
951: }
952: }
953: *ltog = dm->ltogmap;
954: return(0);
955: }
957: /*@
958: DMGetBlockSize - Gets the inherent block size associated with a DM
960: Not Collective
962: Input Parameter:
963: . dm - the DM with block structure
965: Output Parameter:
966: . bs - the block size, 1 implies no exploitable block structure
968: Level: intermediate
970: .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping()
971: @*/
972: PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs)
973: {
977: if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet");
978: *bs = dm->bs;
979: return(0);
980: }
982: /*@
983: DMCreateInterpolation - Gets interpolation matrix between two DM objects
985: Collective on DM
987: Input Parameter:
988: + dm1 - the DM object
989: - dm2 - the second, finer DM object
991: Output Parameter:
992: + mat - the interpolation
993: - vec - the scaling (optional)
995: Level: developer
997: Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
998: DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.
1000: For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors
1001: EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
1004: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction()
1006: @*/
1007: PetscErrorCode DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec)
1008: {
1014: PetscLogEventBegin(DM_CreateInterpolation,dm1,dm2,0,0);
1015: (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);
1016: PetscLogEventEnd(DM_CreateInterpolation,dm1,dm2,0,0);
1017: return(0);
1018: }
1020: /*@
1021: DMCreateRestriction - Gets restriction matrix between two DM objects
1023: Collective on DM
1025: Input Parameter:
1026: + dm1 - the DM object
1027: - dm2 - the second, finer DM object
1029: Output Parameter:
1030: . mat - the restriction
1033: Level: developer
1035: Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1036: DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.
1039: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateInterpolation()
1041: @*/
1042: PetscErrorCode DMCreateRestriction(DM dm1,DM dm2,Mat *mat)
1043: {
1049: PetscLogEventBegin(DM_CreateRestriction,dm1,dm2,0,0);
1050: if (!dm1->ops->createrestriction) SETERRQ(PetscObjectComm((PetscObject)dm1),PETSC_ERR_SUP,"DMCreateRestriction not implemented for this type");
1051: (*dm1->ops->createrestriction)(dm1,dm2,mat);
1052: PetscLogEventEnd(DM_CreateRestriction,dm1,dm2,0,0);
1053: return(0);
1054: }
1056: /*@
1057: DMCreateInjection - Gets injection matrix between two DM objects
1059: Collective on DM
1061: Input Parameter:
1062: + dm1 - the DM object
1063: - dm2 - the second, finer DM object
1065: Output Parameter:
1066: . mat - the injection
1068: Level: developer
1070: Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
1071: DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection.
1073: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation()
1075: @*/
1076: PetscErrorCode DMCreateInjection(DM dm1,DM dm2,Mat *mat)
1077: {
1083: if (!dm1->ops->getinjection) SETERRQ(PetscObjectComm((PetscObject)dm1),PETSC_ERR_SUP,"DMCreateInjection not implemented for this type");
1084: (*dm1->ops->getinjection)(dm1,dm2,mat);
1085: return(0);
1086: }
1088: /*@
1089: DMCreateColoring - Gets coloring for a DM
1091: Collective on DM
1093: Input Parameter:
1094: + dm - the DM object
1095: - ctype - IS_COLORING_LOCAL or IS_COLORING_GLOBAL
1097: Output Parameter:
1098: . coloring - the coloring
1100: Level: developer
1102: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType()
1104: @*/
1105: PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring)
1106: {
1111: if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet");
1112: (*dm->ops->getcoloring)(dm,ctype,coloring);
1113: return(0);
1114: }
1116: /*@
1117: DMCreateMatrix - Gets empty Jacobian for a DM
1119: Collective on DM
1121: Input Parameter:
1122: . dm - the DM object
1124: Output Parameter:
1125: . mat - the empty Jacobian
1127: Level: beginner
1129: Notes: This properly preallocates the number of nonzeros in the sparse matrix so you
1130: do not need to do it yourself.
1132: By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
1133: the nonzero pattern call DMSetMatrixPreallocateOnly()
1135: For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used
1136: internally by PETSc.
1138: For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires
1139: the indices for the global numbering for DMDAs which is complicated.
1141: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType()
1143: @*/
1144: PetscErrorCode DMCreateMatrix(DM dm,Mat *mat)
1145: {
1150: MatInitializePackage();
1153: (*dm->ops->creatematrix)(dm,mat);
1154: return(0);
1155: }
1157: /*@
1158: DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly
1159: preallocated but the nonzero structure and zero values will not be set.
1161: Logically Collective on DM
1163: Input Parameter:
1164: + dm - the DM
1165: - only - PETSC_TRUE if only want preallocation
1167: Level: developer
1168: .seealso DMCreateMatrix(), DMSetMatrixStructureOnly()
1169: @*/
1170: PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
1171: {
1174: dm->prealloc_only = only;
1175: return(0);
1176: }
1178: /*@
1179: DMSetMatrixStructureOnly - When DMCreateMatrix() is called, the matrix structure will be created
1180: but the array for values will not be allocated.
1182: Logically Collective on DM
1184: Input Parameter:
1185: + dm - the DM
1186: - only - PETSC_TRUE if only want matrix stucture
1188: Level: developer
1189: .seealso DMCreateMatrix(), DMSetMatrixPreallocateOnly()
1190: @*/
1191: PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only)
1192: {
1195: dm->structure_only = only;
1196: return(0);
1197: }
1199: /*@C
1200: DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1202: Not Collective
1204: Input Parameters:
1205: + dm - the DM object
1206: . count - The minium size
1207: - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT)
1209: Output Parameter:
1210: . array - the work array
1212: Level: developer
1214: .seealso DMDestroy(), DMCreate()
1215: @*/
1216: PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem)
1217: {
1219: DMWorkLink link;
1220: size_t dsize;
1225: if (dm->workin) {
1226: link = dm->workin;
1227: dm->workin = dm->workin->next;
1228: } else {
1229: PetscNewLog(dm,&link);
1230: }
1231: PetscDataTypeGetSize(dtype,&dsize);
1232: if (dsize*count > link->bytes) {
1233: PetscFree(link->mem);
1234: PetscMalloc(dsize*count,&link->mem);
1235: link->bytes = dsize*count;
1236: }
1237: link->next = dm->workout;
1238: dm->workout = link;
1239: *(void**)mem = link->mem;
1240: return(0);
1241: }
1243: /*@C
1244: DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1246: Not Collective
1248: Input Parameters:
1249: + dm - the DM object
1250: . count - The minium size
1251: - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT)
1253: Output Parameter:
1254: . array - the work array
1256: Level: developer
1258: .seealso DMDestroy(), DMCreate()
1259: @*/
1260: PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem)
1261: {
1262: DMWorkLink *p,link;
1267: for (p=&dm->workout; (link=*p); p=&link->next) {
1268: if (link->mem == *(void**)mem) {
1269: *p = link->next;
1270: link->next = dm->workin;
1271: dm->workin = link;
1272: *(void**)mem = NULL;
1273: return(0);
1274: }
1275: }
1276: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out");
1277: }
1279: PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace))
1280: {
1283: if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1284: dm->nullspaceConstructors[field] = nullsp;
1285: return(0);
1286: }
1288: /*@C
1289: DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field
1291: Not collective
1293: Input Parameter:
1294: . dm - the DM object
1296: Output Parameters:
1297: + numFields - The number of fields (or NULL if not requested)
1298: . fieldNames - The name for each field (or NULL if not requested)
1299: - fields - The global indices for each field (or NULL if not requested)
1301: Level: intermediate
1303: Notes:
1304: The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1305: PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with
1306: PetscFree().
1308: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
1309: @*/
1310: PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1311: {
1312: PetscSection section, sectionGlobal;
1317: if (numFields) {
1319: *numFields = 0;
1320: }
1321: if (fieldNames) {
1323: *fieldNames = NULL;
1324: }
1325: if (fields) {
1327: *fields = NULL;
1328: }
1329: DMGetDefaultSection(dm, §ion);
1330: if (section) {
1331: PetscInt *fieldSizes, **fieldIndices;
1332: PetscInt nF, f, pStart, pEnd, p;
1334: DMGetDefaultGlobalSection(dm, §ionGlobal);
1335: PetscSectionGetNumFields(section, &nF);
1336: PetscMalloc2(nF,&fieldSizes,nF,&fieldIndices);
1337: PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);
1338: for (f = 0; f < nF; ++f) {
1339: fieldSizes[f] = 0;
1340: }
1341: for (p = pStart; p < pEnd; ++p) {
1342: PetscInt gdof;
1344: PetscSectionGetDof(sectionGlobal, p, &gdof);
1345: if (gdof > 0) {
1346: for (f = 0; f < nF; ++f) {
1347: PetscInt fdof, fcdof;
1349: PetscSectionGetFieldDof(section, p, f, &fdof);
1350: PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
1351: fieldSizes[f] += fdof-fcdof;
1352: }
1353: }
1354: }
1355: for (f = 0; f < nF; ++f) {
1356: PetscMalloc1(fieldSizes[f], &fieldIndices[f]);
1357: fieldSizes[f] = 0;
1358: }
1359: for (p = pStart; p < pEnd; ++p) {
1360: PetscInt gdof, goff;
1362: PetscSectionGetDof(sectionGlobal, p, &gdof);
1363: if (gdof > 0) {
1364: PetscSectionGetOffset(sectionGlobal, p, &goff);
1365: for (f = 0; f < nF; ++f) {
1366: PetscInt fdof, fcdof, fc;
1368: PetscSectionGetFieldDof(section, p, f, &fdof);
1369: PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
1370: for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) {
1371: fieldIndices[f][fieldSizes[f]] = goff++;
1372: }
1373: }
1374: }
1375: }
1376: if (numFields) *numFields = nF;
1377: if (fieldNames) {
1378: PetscMalloc1(nF, fieldNames);
1379: for (f = 0; f < nF; ++f) {
1380: const char *fieldName;
1382: PetscSectionGetFieldName(section, f, &fieldName);
1383: PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);
1384: }
1385: }
1386: if (fields) {
1387: PetscMalloc1(nF, fields);
1388: for (f = 0; f < nF; ++f) {
1389: ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);
1390: }
1391: }
1392: PetscFree2(fieldSizes,fieldIndices);
1393: } else if (dm->ops->createfieldis) {
1394: (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);
1395: }
1396: return(0);
1397: }
1400: /*@C
1401: DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems
1402: corresponding to different fields: each IS contains the global indices of the dofs of the
1403: corresponding field. The optional list of DMs define the DM for each subproblem.
1404: Generalizes DMCreateFieldIS().
1406: Not collective
1408: Input Parameter:
1409: . dm - the DM object
1411: Output Parameters:
1412: + len - The number of subproblems in the field decomposition (or NULL if not requested)
1413: . namelist - The name for each field (or NULL if not requested)
1414: . islist - The global indices for each field (or NULL if not requested)
1415: - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1417: Level: intermediate
1419: Notes:
1420: The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1421: PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1422: and all of the arrays should be freed with PetscFree().
1424: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1425: @*/
1426: PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
1427: {
1432: if (len) {
1434: *len = 0;
1435: }
1436: if (namelist) {
1438: *namelist = 0;
1439: }
1440: if (islist) {
1442: *islist = 0;
1443: }
1444: if (dmlist) {
1446: *dmlist = 0;
1447: }
1448: /*
1449: Is it a good idea to apply the following check across all impls?
1450: Perhaps some impls can have a well-defined decomposition before DMSetUp?
1451: This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1452: */
1453: if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1454: if (!dm->ops->createfielddecomposition) {
1455: PetscSection section;
1456: PetscInt numFields, f;
1458: DMGetDefaultSection(dm, §ion);
1459: if (section) {PetscSectionGetNumFields(section, &numFields);}
1460: if (section && numFields && dm->ops->createsubdm) {
1461: if (len) *len = numFields;
1462: if (namelist) {PetscMalloc1(numFields,namelist);}
1463: if (islist) {PetscMalloc1(numFields,islist);}
1464: if (dmlist) {PetscMalloc1(numFields,dmlist);}
1465: for (f = 0; f < numFields; ++f) {
1466: const char *fieldName;
1468: DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);
1469: if (namelist) {
1470: PetscSectionGetFieldName(section, f, &fieldName);
1471: PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);
1472: }
1473: }
1474: } else {
1475: DMCreateFieldIS(dm, len, namelist, islist);
1476: /* By default there are no DMs associated with subproblems. */
1477: if (dmlist) *dmlist = NULL;
1478: }
1479: } else {
1480: (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);
1481: }
1482: return(0);
1483: }
1485: /*@
1486: DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in.
1487: The fields are defined by DMCreateFieldIS().
1489: Not collective
1491: Input Parameters:
1492: + dm - the DM object
1493: . numFields - the number of fields in this subproblem
1494: - fields - the fields in the subproblem
1496: Output Parameters:
1497: + is - the global indices for the subproblem
1498: - dm - the DM for the subproblem
1500: Level: intermediate
1502: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1503: @*/
1504: PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
1505: {
1513: if (dm->ops->createsubdm) {
1514: (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);
1515: } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined");
1516: return(0);
1517: }
1520: /*@C
1521: DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems
1522: corresponding to restrictions to pairs nested subdomains: each IS contains the global
1523: indices of the dofs of the corresponding subdomains. The inner subdomains conceptually
1524: define a nonoverlapping covering, while outer subdomains can overlap.
1525: The optional list of DMs define the DM for each subproblem.
1527: Not collective
1529: Input Parameter:
1530: . dm - the DM object
1532: Output Parameters:
1533: + len - The number of subproblems in the domain decomposition (or NULL if not requested)
1534: . namelist - The name for each subdomain (or NULL if not requested)
1535: . innerislist - The global indices for each inner subdomain (or NULL, if not requested)
1536: . outerislist - The global indices for each outer subdomain (or NULL, if not requested)
1537: - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1539: Level: intermediate
1541: Notes:
1542: The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1543: PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1544: and all of the arrays should be freed with PetscFree().
1546: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition()
1547: @*/
1548: PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
1549: {
1550: PetscErrorCode ierr;
1551: DMSubDomainHookLink link;
1552: PetscInt i,l;
1561: /*
1562: Is it a good idea to apply the following check across all impls?
1563: Perhaps some impls can have a well-defined decomposition before DMSetUp?
1564: This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1565: */
1566: if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1567: if (dm->ops->createdomaindecomposition) {
1568: (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);
1569: /* copy subdomain hooks and context over to the subdomain DMs */
1570: if (dmlist && *dmlist) {
1571: for (i = 0; i < l; i++) {
1572: for (link=dm->subdomainhook; link; link=link->next) {
1573: if (link->ddhook) {(*link->ddhook)(dm,(*dmlist)[i],link->ctx);}
1574: }
1575: if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx;
1576: }
1577: }
1578: if (len) *len = l;
1579: }
1580: return(0);
1581: }
1584: /*@C
1585: DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector
1587: Not collective
1589: Input Parameters:
1590: + dm - the DM object
1591: . n - the number of subdomain scatters
1592: - subdms - the local subdomains
1594: Output Parameters:
1595: + n - the number of scatters returned
1596: . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
1597: . oscat - scatter from global vector to overlapping global vector entries on subdomain
1598: - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)
1600: Notes: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution
1601: of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets
1602: of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
1603: solution and residual data.
1605: Level: developer
1607: .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1608: @*/
1609: PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat)
1610: {
1616: if (dm->ops->createddscatters) {
1617: (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);
1618: } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionScatter implementation defined");
1619: return(0);
1620: }
1622: /*@
1623: DMRefine - Refines a DM object
1625: Collective on DM
1627: Input Parameter:
1628: + dm - the DM object
1629: - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
1631: Output Parameter:
1632: . dmf - the refined DM, or NULL
1634: Note: If no refinement was done, the return value is NULL
1636: Level: developer
1638: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1639: @*/
1640: PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf)
1641: {
1642: PetscErrorCode ierr;
1643: DMRefineHookLink link;
1647: PetscLogEventBegin(DM_Refine,dm,0,0,0);
1648: if (!dm->ops->refine) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot refine");
1649: (*dm->ops->refine)(dm,comm,dmf);
1650: if (*dmf) {
1651: (*dmf)->ops->creatematrix = dm->ops->creatematrix;
1653: PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);
1655: (*dmf)->ctx = dm->ctx;
1656: (*dmf)->leveldown = dm->leveldown;
1657: (*dmf)->levelup = dm->levelup + 1;
1659: DMSetMatType(*dmf,dm->mattype);
1660: for (link=dm->refinehook; link; link=link->next) {
1661: if (link->refinehook) {
1662: (*link->refinehook)(dm,*dmf,link->ctx);
1663: }
1664: }
1665: }
1666: PetscLogEventEnd(DM_Refine,dm,0,0,0);
1667: return(0);
1668: }
1670: /*@C
1671: DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid
1673: Logically Collective
1675: Input Arguments:
1676: + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
1677: . refinehook - function to run when setting up a coarser level
1678: . interphook - function to run to update data on finer levels (once per SNESSolve())
1679: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1681: Calling sequence of refinehook:
1682: $ refinehook(DM coarse,DM fine,void *ctx);
1684: + coarse - coarse level DM
1685: . fine - fine level DM to interpolate problem to
1686: - ctx - optional user-defined function context
1688: Calling sequence for interphook:
1689: $ interphook(DM coarse,Mat interp,DM fine,void *ctx)
1691: + coarse - coarse level DM
1692: . interp - matrix interpolating a coarse-level solution to the finer grid
1693: . fine - fine level DM to update
1694: - ctx - optional user-defined function context
1696: Level: advanced
1698: Notes:
1699: This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing
1701: If this function is called multiple times, the hooks will be run in the order they are added.
1703: This function is currently not available from Fortran.
1705: .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1706: @*/
1707: PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
1708: {
1709: PetscErrorCode ierr;
1710: DMRefineHookLink link,*p;
1714: for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
1715: if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) return(0);
1716: }
1717: PetscNew(&link);
1718: link->refinehook = refinehook;
1719: link->interphook = interphook;
1720: link->ctx = ctx;
1721: link->next = NULL;
1722: *p = link;
1723: return(0);
1724: }
1726: /*@C
1727: DMRefineHookRemove - remove a callback from the list of hooks to be run when interpolating a nonlinear problem to a finer grid
1729: Logically Collective
1731: Input Arguments:
1732: + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
1733: . refinehook - function to run when setting up a coarser level
1734: . interphook - function to run to update data on finer levels (once per SNESSolve())
1735: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1737: Level: advanced
1739: Notes:
1740: This function does nothing if the hook is not in the list.
1742: This function is currently not available from Fortran.
1744: .seealso: DMCoarsenHookRemove(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1745: @*/
1746: PetscErrorCode DMRefineHookRemove(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
1747: {
1748: PetscErrorCode ierr;
1749: DMRefineHookLink link,*p;
1753: for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Search the list of current hooks */
1754: if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) {
1755: link = *p;
1756: *p = link->next;
1757: PetscFree(link);
1758: break;
1759: }
1760: }
1761: return(0);
1762: }
1764: /*@
1765: DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd()
1767: Collective if any hooks are
1769: Input Arguments:
1770: + coarse - coarser DM to use as a base
1771: . interp - interpolation matrix, apply using MatInterpolate()
1772: - fine - finer DM to update
1774: Level: developer
1776: .seealso: DMRefineHookAdd(), MatInterpolate()
1777: @*/
1778: PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine)
1779: {
1780: PetscErrorCode ierr;
1781: DMRefineHookLink link;
1784: for (link=fine->refinehook; link; link=link->next) {
1785: if (link->interphook) {
1786: (*link->interphook)(coarse,interp,fine,link->ctx);
1787: }
1788: }
1789: return(0);
1790: }
1792: /*@
1793: DMGetRefineLevel - Get's the number of refinements that have generated this DM.
1795: Not Collective
1797: Input Parameter:
1798: . dm - the DM object
1800: Output Parameter:
1801: . level - number of refinements
1803: Level: developer
1805: .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1807: @*/
1808: PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level)
1809: {
1812: *level = dm->levelup;
1813: return(0);
1814: }
1816: /*@
1817: DMSetRefineLevel - Set's the number of refinements that have generated this DM.
1819: Not Collective
1821: Input Parameter:
1822: + dm - the DM object
1823: - level - number of refinements
1825: Level: advanced
1827: Notes: This value is used by PCMG to determine how many multigrid levels to use
1829: .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1831: @*/
1832: PetscErrorCode DMSetRefineLevel(DM dm,PetscInt level)
1833: {
1836: dm->levelup = level;
1837: return(0);
1838: }
1840: /*@C
1841: DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called
1843: Logically Collective
1845: Input Arguments:
1846: + dm - the DM
1847: . beginhook - function to run at the beginning of DMGlobalToLocalBegin()
1848: . endhook - function to run after DMGlobalToLocalEnd() has completed
1849: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1851: Calling sequence for beginhook:
1852: $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
1854: + dm - global DM
1855: . g - global vector
1856: . mode - mode
1857: . l - local vector
1858: - ctx - optional user-defined function context
1861: Calling sequence for endhook:
1862: $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
1864: + global - global DM
1865: - ctx - optional user-defined function context
1867: Level: advanced
1869: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1870: @*/
1871: PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
1872: {
1873: PetscErrorCode ierr;
1874: DMGlobalToLocalHookLink link,*p;
1878: for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
1879: PetscNew(&link);
1880: link->beginhook = beginhook;
1881: link->endhook = endhook;
1882: link->ctx = ctx;
1883: link->next = NULL;
1884: *p = link;
1885: return(0);
1886: }
1888: static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx)
1889: {
1890: Mat cMat;
1891: Vec cVec;
1892: PetscSection section, cSec;
1893: PetscInt pStart, pEnd, p, dof;
1898: DMGetDefaultConstraints(dm,&cSec,&cMat);
1899: if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) {
1900: PetscInt nRows;
1902: MatGetSize(cMat,&nRows,NULL);
1903: if (nRows <= 0) return(0);
1904: DMGetDefaultSection(dm,§ion);
1905: MatCreateVecs(cMat,NULL,&cVec);
1906: MatMult(cMat,l,cVec);
1907: PetscSectionGetChart(cSec,&pStart,&pEnd);
1908: for (p = pStart; p < pEnd; p++) {
1909: PetscSectionGetDof(cSec,p,&dof);
1910: if (dof) {
1911: PetscScalar *vals;
1912: VecGetValuesSection(cVec,cSec,p,&vals);
1913: VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);
1914: }
1915: }
1916: VecDestroy(&cVec);
1917: }
1918: return(0);
1919: }
1921: /*@
1922: DMGlobalToLocalBegin - Begins updating local vectors from global vector
1924: Neighbor-wise Collective on DM
1926: Input Parameters:
1927: + dm - the DM object
1928: . g - the global vector
1929: . mode - INSERT_VALUES or ADD_VALUES
1930: - l - the local vector
1933: Level: beginner
1935: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
1937: @*/
1938: PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
1939: {
1940: PetscSF sf;
1941: PetscErrorCode ierr;
1942: DMGlobalToLocalHookLink link;
1946: for (link=dm->gtolhook; link; link=link->next) {
1947: if (link->beginhook) {
1948: (*link->beginhook)(dm,g,mode,l,link->ctx);
1949: }
1950: }
1951: DMGetDefaultSF(dm, &sf);
1952: if (sf) {
1953: const PetscScalar *gArray;
1954: PetscScalar *lArray;
1956: if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1957: VecGetArray(l, &lArray);
1958: VecGetArrayRead(g, &gArray);
1959: PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);
1960: VecRestoreArray(l, &lArray);
1961: VecRestoreArrayRead(g, &gArray);
1962: } else {
1963: (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
1964: }
1965: return(0);
1966: }
1968: /*@
1969: DMGlobalToLocalEnd - Ends updating local vectors from global vector
1971: Neighbor-wise Collective on DM
1973: Input Parameters:
1974: + dm - the DM object
1975: . g - the global vector
1976: . mode - INSERT_VALUES or ADD_VALUES
1977: - l - the local vector
1980: Level: beginner
1982: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
1984: @*/
1985: PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
1986: {
1987: PetscSF sf;
1988: PetscErrorCode ierr;
1989: const PetscScalar *gArray;
1990: PetscScalar *lArray;
1991: DMGlobalToLocalHookLink link;
1995: DMGetDefaultSF(dm, &sf);
1996: if (sf) {
1997: if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1999: VecGetArray(l, &lArray);
2000: VecGetArrayRead(g, &gArray);
2001: PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);
2002: VecRestoreArray(l, &lArray);
2003: VecRestoreArrayRead(g, &gArray);
2004: } else {
2005: (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2006: }
2007: DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);
2008: for (link=dm->gtolhook; link; link=link->next) {
2009: if (link->endhook) {(*link->endhook)(dm,g,mode,l,link->ctx);}
2010: }
2011: return(0);
2012: }
2014: /*@C
2015: DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called
2017: Logically Collective
2019: Input Arguments:
2020: + dm - the DM
2021: . beginhook - function to run at the beginning of DMLocalToGlobalBegin()
2022: . endhook - function to run after DMLocalToGlobalEnd() has completed
2023: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2025: Calling sequence for beginhook:
2026: $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
2028: + dm - global DM
2029: . l - local vector
2030: . mode - mode
2031: . g - global vector
2032: - ctx - optional user-defined function context
2035: Calling sequence for endhook:
2036: $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
2038: + global - global DM
2039: . l - local vector
2040: . mode - mode
2041: . g - global vector
2042: - ctx - optional user-defined function context
2044: Level: advanced
2046: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2047: @*/
2048: PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
2049: {
2050: PetscErrorCode ierr;
2051: DMLocalToGlobalHookLink link,*p;
2055: for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2056: PetscNew(&link);
2057: link->beginhook = beginhook;
2058: link->endhook = endhook;
2059: link->ctx = ctx;
2060: link->next = NULL;
2061: *p = link;
2062: return(0);
2063: }
2065: static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
2066: {
2067: Mat cMat;
2068: Vec cVec;
2069: PetscSection section, cSec;
2070: PetscInt pStart, pEnd, p, dof;
2075: DMGetDefaultConstraints(dm,&cSec,&cMat);
2076: if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) {
2077: PetscInt nRows;
2079: MatGetSize(cMat,&nRows,NULL);
2080: if (nRows <= 0) return(0);
2081: DMGetDefaultSection(dm,§ion);
2082: MatCreateVecs(cMat,NULL,&cVec);
2083: PetscSectionGetChart(cSec,&pStart,&pEnd);
2084: for (p = pStart; p < pEnd; p++) {
2085: PetscSectionGetDof(cSec,p,&dof);
2086: if (dof) {
2087: PetscInt d;
2088: PetscScalar *vals;
2089: VecGetValuesSection(l,section,p,&vals);
2090: VecSetValuesSection(cVec,cSec,p,vals,mode);
2091: /* for this to be the true transpose, we have to zero the values that
2092: * we just extracted */
2093: for (d = 0; d < dof; d++) {
2094: vals[d] = 0.;
2095: }
2096: }
2097: }
2098: MatMultTransposeAdd(cMat,cVec,l,l);
2099: VecDestroy(&cVec);
2100: }
2101: return(0);
2102: }
2104: /*@
2105: DMLocalToGlobalBegin - updates global vectors from local vectors
2107: Neighbor-wise Collective on DM
2109: Input Parameters:
2110: + dm - the DM object
2111: . l - the local vector
2112: . 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.
2113: - g - the global vector
2115: Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation.
2116: INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one.
2118: Level: beginner
2120: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
2122: @*/
2123: PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
2124: {
2125: PetscSF sf;
2126: PetscSection s, gs;
2127: DMLocalToGlobalHookLink link;
2128: const PetscScalar *lArray;
2129: PetscScalar *gArray;
2130: PetscBool isInsert;
2131: PetscErrorCode ierr;
2135: for (link=dm->ltoghook; link; link=link->next) {
2136: if (link->beginhook) {
2137: (*link->beginhook)(dm,l,mode,g,link->ctx);
2138: }
2139: }
2140: DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);
2141: DMGetDefaultSF(dm, &sf);
2142: DMGetDefaultSection(dm, &s);
2143: switch (mode) {
2144: case INSERT_VALUES:
2145: case INSERT_ALL_VALUES:
2146: case INSERT_BC_VALUES:
2147: isInsert = PETSC_TRUE; break;
2148: case ADD_VALUES:
2149: case ADD_ALL_VALUES:
2150: case ADD_BC_VALUES:
2151: isInsert = PETSC_FALSE; break;
2152: default:
2153: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2154: }
2155: if (sf && !isInsert) {
2156: VecGetArrayRead(l, &lArray);
2157: VecGetArray(g, &gArray);
2158: PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);
2159: VecRestoreArrayRead(l, &lArray);
2160: VecRestoreArray(g, &gArray);
2161: } else if (s && isInsert) {
2162: PetscInt gStart, pStart, pEnd, p;
2164: DMGetDefaultGlobalSection(dm, &gs);
2165: PetscSectionGetChart(s, &pStart, &pEnd);
2166: VecGetOwnershipRange(g, &gStart, NULL);
2167: VecGetArrayRead(l, &lArray);
2168: VecGetArray(g, &gArray);
2169: for (p = pStart; p < pEnd; ++p) {
2170: PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
2172: PetscSectionGetDof(s, p, &dof);
2173: PetscSectionGetDof(gs, p, &gdof);
2174: PetscSectionGetConstraintDof(s, p, &cdof);
2175: PetscSectionGetConstraintDof(gs, p, &gcdof);
2176: PetscSectionGetOffset(s, p, &off);
2177: PetscSectionGetOffset(gs, p, &goff);
2178: /* Ignore off-process data and points with no global data */
2179: if (!gdof || goff < 0) continue;
2180: 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);
2181: /* If no constraints are enforced in the global vector */
2182: if (!gcdof) {
2183: for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d];
2184: /* If constraints are enforced in the global vector */
2185: } else if (cdof == gcdof) {
2186: const PetscInt *cdofs;
2187: PetscInt cind = 0;
2189: PetscSectionGetConstraintIndices(s, p, &cdofs);
2190: for (d = 0, e = 0; d < dof; ++d) {
2191: if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;}
2192: gArray[goff-gStart+e++] = lArray[off+d];
2193: }
2194: } 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);
2195: }
2196: VecRestoreArrayRead(l, &lArray);
2197: VecRestoreArray(g, &gArray);
2198: } else {
2199: (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);
2200: }
2201: return(0);
2202: }
2204: /*@
2205: DMLocalToGlobalEnd - updates global vectors from local vectors
2207: Neighbor-wise Collective on DM
2209: Input Parameters:
2210: + dm - the DM object
2211: . l - the local vector
2212: . mode - INSERT_VALUES or ADD_VALUES
2213: - g - the global vector
2216: Level: beginner
2218: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()
2220: @*/
2221: PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
2222: {
2223: PetscSF sf;
2224: PetscSection s;
2225: DMLocalToGlobalHookLink link;
2226: PetscBool isInsert;
2227: PetscErrorCode ierr;
2231: DMGetDefaultSF(dm, &sf);
2232: DMGetDefaultSection(dm, &s);
2233: switch (mode) {
2234: case INSERT_VALUES:
2235: case INSERT_ALL_VALUES:
2236: isInsert = PETSC_TRUE; break;
2237: case ADD_VALUES:
2238: case ADD_ALL_VALUES:
2239: isInsert = PETSC_FALSE; break;
2240: default:
2241: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2242: }
2243: if (sf && !isInsert) {
2244: const PetscScalar *lArray;
2245: PetscScalar *gArray;
2247: VecGetArrayRead(l, &lArray);
2248: VecGetArray(g, &gArray);
2249: PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);
2250: VecRestoreArrayRead(l, &lArray);
2251: VecRestoreArray(g, &gArray);
2252: } else if (s && isInsert) {
2253: } else {
2254: (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);
2255: }
2256: for (link=dm->ltoghook; link; link=link->next) {
2257: if (link->endhook) {(*link->endhook)(dm,g,mode,l,link->ctx);}
2258: }
2259: return(0);
2260: }
2262: /*@
2263: DMLocalToLocalBegin - Maps from a local vector (including ghost points
2264: that contain irrelevant values) to another local vector where the ghost
2265: points in the second are set correctly. Must be followed by DMLocalToLocalEnd().
2267: Neighbor-wise Collective on DM and Vec
2269: Input Parameters:
2270: + dm - the DM object
2271: . g - the original local vector
2272: - mode - one of INSERT_VALUES or ADD_VALUES
2274: Output Parameter:
2275: . l - the local vector with correct ghost values
2277: Level: intermediate
2279: Notes:
2280: The local vectors used here need not be the same as those
2281: obtained from DMCreateLocalVector(), BUT they
2282: must have the same parallel data layout; they could, for example, be
2283: obtained with VecDuplicate() from the DM originating vectors.
2285: .keywords: DM, local-to-local, begin
2286: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2288: @*/
2289: PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2290: {
2291: PetscErrorCode ierr;
2295: if (!dm->ops->localtolocalbegin) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps");
2296: (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2297: return(0);
2298: }
2300: /*@
2301: DMLocalToLocalEnd - Maps from a local vector (including ghost points
2302: that contain irrelevant values) to another local vector where the ghost
2303: points in the second are set correctly. Must be preceded by DMLocalToLocalBegin().
2305: Neighbor-wise Collective on DM and Vec
2307: Input Parameters:
2308: + da - the DM object
2309: . g - the original local vector
2310: - mode - one of INSERT_VALUES or ADD_VALUES
2312: Output Parameter:
2313: . l - the local vector with correct ghost values
2315: Level: intermediate
2317: Notes:
2318: The local vectors used here need not be the same as those
2319: obtained from DMCreateLocalVector(), BUT they
2320: must have the same parallel data layout; they could, for example, be
2321: obtained with VecDuplicate() from the DM originating vectors.
2323: .keywords: DM, local-to-local, end
2324: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2326: @*/
2327: PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2328: {
2329: PetscErrorCode ierr;
2333: if (!dm->ops->localtolocalend) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps");
2334: (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);
2335: return(0);
2336: }
2339: /*@
2340: DMCoarsen - Coarsens a DM object
2342: Collective on DM
2344: Input Parameter:
2345: + dm - the DM object
2346: - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
2348: Output Parameter:
2349: . dmc - the coarsened DM
2351: Level: developer
2353: .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2355: @*/
2356: PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
2357: {
2358: PetscErrorCode ierr;
2359: DMCoarsenHookLink link;
2363: if (!dm->ops->coarsen) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot coarsen");
2364: PetscLogEventBegin(DM_Coarsen,dm,0,0,0);
2365: (*dm->ops->coarsen)(dm, comm, dmc);
2366: if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
2367: DMSetCoarseDM(dm,*dmc);
2368: (*dmc)->ops->creatematrix = dm->ops->creatematrix;
2369: PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);
2370: (*dmc)->ctx = dm->ctx;
2371: (*dmc)->levelup = dm->levelup;
2372: (*dmc)->leveldown = dm->leveldown + 1;
2373: DMSetMatType(*dmc,dm->mattype);
2374: for (link=dm->coarsenhook; link; link=link->next) {
2375: if (link->coarsenhook) {(*link->coarsenhook)(dm,*dmc,link->ctx);}
2376: }
2377: PetscLogEventEnd(DM_Coarsen,dm,0,0,0);
2378: return(0);
2379: }
2381: /*@C
2382: DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
2384: Logically Collective
2386: Input Arguments:
2387: + fine - nonlinear solver context on which to run a hook when restricting to a coarser level
2388: . coarsenhook - function to run when setting up a coarser level
2389: . restricthook - function to run to update data on coarser levels (once per SNESSolve())
2390: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2392: Calling sequence of coarsenhook:
2393: $ coarsenhook(DM fine,DM coarse,void *ctx);
2395: + fine - fine level DM
2396: . coarse - coarse level DM to restrict problem to
2397: - ctx - optional user-defined function context
2399: Calling sequence for restricthook:
2400: $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)
2402: + fine - fine level DM
2403: . mrestrict - matrix restricting a fine-level solution to the coarse grid
2404: . rscale - scaling vector for restriction
2405: . inject - matrix restricting by injection
2406: . coarse - coarse level DM to update
2407: - ctx - optional user-defined function context
2409: Level: advanced
2411: Notes:
2412: This function is only needed if auxiliary data needs to be set up on coarse grids.
2414: If this function is called multiple times, the hooks will be run in the order they are added.
2416: In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2417: extract the finest level information from its context (instead of from the SNES).
2419: This function is currently not available from Fortran.
2421: .seealso: DMCoarsenHookRemove(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2422: @*/
2423: PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
2424: {
2425: PetscErrorCode ierr;
2426: DMCoarsenHookLink link,*p;
2430: for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
2431: if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) return(0);
2432: }
2433: PetscNew(&link);
2434: link->coarsenhook = coarsenhook;
2435: link->restricthook = restricthook;
2436: link->ctx = ctx;
2437: link->next = NULL;
2438: *p = link;
2439: return(0);
2440: }
2442: /*@C
2443: DMCoarsenHookRemove - remove a callback from the list of hooks to be run when restricting a nonlinear problem to the coarse grid
2445: Logically Collective
2447: Input Arguments:
2448: + fine - nonlinear solver context on which to run a hook when restricting to a coarser level
2449: . coarsenhook - function to run when setting up a coarser level
2450: . restricthook - function to run to update data on coarser levels (once per SNESSolve())
2451: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2453: Level: advanced
2455: Notes:
2456: This function does nothing if the hook is not in the list.
2458: This function is currently not available from Fortran.
2460: .seealso: DMCoarsenHookAdd(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2461: @*/
2462: PetscErrorCode DMCoarsenHookRemove(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
2463: {
2464: PetscErrorCode ierr;
2465: DMCoarsenHookLink link,*p;
2469: for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Search the list of current hooks */
2470: if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
2471: link = *p;
2472: *p = link->next;
2473: PetscFree(link);
2474: break;
2475: }
2476: }
2477: return(0);
2478: }
2481: /*@
2482: DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd()
2484: Collective if any hooks are
2486: Input Arguments:
2487: + fine - finer DM to use as a base
2488: . restrct - restriction matrix, apply using MatRestrict()
2489: . rscale - scaling vector for restriction
2490: . inject - injection matrix, also use MatRestrict()
2491: - coarse - coarser DM to update
2493: Level: developer
2495: .seealso: DMCoarsenHookAdd(), MatRestrict()
2496: @*/
2497: PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse)
2498: {
2499: PetscErrorCode ierr;
2500: DMCoarsenHookLink link;
2503: for (link=fine->coarsenhook; link; link=link->next) {
2504: if (link->restricthook) {
2505: (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);
2506: }
2507: }
2508: return(0);
2509: }
2511: /*@C
2512: DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
2514: Logically Collective
2516: Input Arguments:
2517: + global - global DM
2518: . ddhook - function to run to pass data to the decomposition DM upon its creation
2519: . restricthook - function to run to update data on block solve (at the beginning of the block solve)
2520: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2523: Calling sequence for ddhook:
2524: $ ddhook(DM global,DM block,void *ctx)
2526: + global - global DM
2527: . block - block DM
2528: - ctx - optional user-defined function context
2530: Calling sequence for restricthook:
2531: $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)
2533: + global - global DM
2534: . out - scatter to the outer (with ghost and overlap points) block vector
2535: . in - scatter to block vector values only owned locally
2536: . block - block DM
2537: - ctx - optional user-defined function context
2539: Level: advanced
2541: Notes:
2542: This function is only needed if auxiliary data needs to be set up on subdomain DMs.
2544: If this function is called multiple times, the hooks will be run in the order they are added.
2546: In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2547: extract the global information from its context (instead of from the SNES).
2549: This function is currently not available from Fortran.
2551: .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2552: @*/
2553: PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2554: {
2555: PetscErrorCode ierr;
2556: DMSubDomainHookLink link,*p;
2560: for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */
2561: if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) return(0);
2562: }
2563: PetscNew(&link);
2564: link->restricthook = restricthook;
2565: link->ddhook = ddhook;
2566: link->ctx = ctx;
2567: link->next = NULL;
2568: *p = link;
2569: return(0);
2570: }
2572: /*@C
2573: DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid
2575: Logically Collective
2577: Input Arguments:
2578: + global - global DM
2579: . ddhook - function to run to pass data to the decomposition DM upon its creation
2580: . restricthook - function to run to update data on block solve (at the beginning of the block solve)
2581: - ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2583: Level: advanced
2585: Notes:
2587: This function is currently not available from Fortran.
2589: .seealso: DMSubDomainHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2590: @*/
2591: PetscErrorCode DMSubDomainHookRemove(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2592: {
2593: PetscErrorCode ierr;
2594: DMSubDomainHookLink link,*p;
2598: for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Search the list of current hooks */
2599: if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
2600: link = *p;
2601: *p = link->next;
2602: PetscFree(link);
2603: break;
2604: }
2605: }
2606: return(0);
2607: }
2609: /*@
2610: DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd()
2612: Collective if any hooks are
2614: Input Arguments:
2615: + fine - finer DM to use as a base
2616: . oscatter - scatter from domain global vector filling subdomain global vector with overlap
2617: . gscatter - scatter from domain global vector filling subdomain local vector with ghosts
2618: - coarse - coarer DM to update
2620: Level: developer
2622: .seealso: DMCoarsenHookAdd(), MatRestrict()
2623: @*/
2624: PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm)
2625: {
2626: PetscErrorCode ierr;
2627: DMSubDomainHookLink link;
2630: for (link=global->subdomainhook; link; link=link->next) {
2631: if (link->restricthook) {
2632: (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);
2633: }
2634: }
2635: return(0);
2636: }
2638: /*@
2639: DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM.
2641: Not Collective
2643: Input Parameter:
2644: . dm - the DM object
2646: Output Parameter:
2647: . level - number of coarsenings
2649: Level: developer
2651: .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2653: @*/
2654: PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level)
2655: {
2658: *level = dm->leveldown;
2659: return(0);
2660: }
2664: /*@C
2665: DMRefineHierarchy - Refines a DM object, all levels at once
2667: Collective on DM
2669: Input Parameter:
2670: + dm - the DM object
2671: - nlevels - the number of levels of refinement
2673: Output Parameter:
2674: . dmf - the refined DM hierarchy
2676: Level: developer
2678: .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2680: @*/
2681: PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
2682: {
2687: if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2688: if (nlevels == 0) return(0);
2689: if (dm->ops->refinehierarchy) {
2690: (*dm->ops->refinehierarchy)(dm,nlevels,dmf);
2691: } else if (dm->ops->refine) {
2692: PetscInt i;
2694: DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);
2695: for (i=1; i<nlevels; i++) {
2696: DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);
2697: }
2698: } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
2699: return(0);
2700: }
2702: /*@C
2703: DMCoarsenHierarchy - Coarsens a DM object, all levels at once
2705: Collective on DM
2707: Input Parameter:
2708: + dm - the DM object
2709: - nlevels - the number of levels of coarsening
2711: Output Parameter:
2712: . dmc - the coarsened DM hierarchy
2714: Level: developer
2716: .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2718: @*/
2719: PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
2720: {
2725: if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2726: if (nlevels == 0) return(0);
2728: if (dm->ops->coarsenhierarchy) {
2729: (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);
2730: } else if (dm->ops->coarsen) {
2731: PetscInt i;
2733: DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);
2734: for (i=1; i<nlevels; i++) {
2735: DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);
2736: }
2737: } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
2738: return(0);
2739: }
2741: /*@
2742: DMCreateAggregates - Gets the aggregates that map between
2743: grids associated with two DMs.
2745: Collective on DM
2747: Input Parameters:
2748: + dmc - the coarse grid DM
2749: - dmf - the fine grid DM
2751: Output Parameters:
2752: . rest - the restriction matrix (transpose of the projection matrix)
2754: Level: intermediate
2756: .keywords: interpolation, restriction, multigrid
2758: .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation()
2759: @*/
2760: PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest)
2761: {
2767: (*dmc->ops->getaggregates)(dmc, dmf, rest);
2768: return(0);
2769: }
2771: /*@C
2772: DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed
2774: Not Collective
2776: Input Parameters:
2777: + dm - the DM object
2778: - destroy - the destroy function
2780: Level: intermediate
2782: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2784: @*/
2785: PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**))
2786: {
2789: dm->ctxdestroy = destroy;
2790: return(0);
2791: }
2793: /*@
2794: DMSetApplicationContext - Set a user context into a DM object
2796: Not Collective
2798: Input Parameters:
2799: + dm - the DM object
2800: - ctx - the user context
2802: Level: intermediate
2804: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2806: @*/
2807: PetscErrorCode DMSetApplicationContext(DM dm,void *ctx)
2808: {
2811: dm->ctx = ctx;
2812: return(0);
2813: }
2815: /*@
2816: DMGetApplicationContext - Gets a user context from a DM object
2818: Not Collective
2820: Input Parameter:
2821: . dm - the DM object
2823: Output Parameter:
2824: . ctx - the user context
2826: Level: intermediate
2828: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2830: @*/
2831: PetscErrorCode DMGetApplicationContext(DM dm,void *ctx)
2832: {
2835: *(void**)ctx = dm->ctx;
2836: return(0);
2837: }
2839: /*@C
2840: DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI.
2842: Logically Collective on DM
2844: Input Parameter:
2845: + dm - the DM object
2846: - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)
2848: Level: intermediate
2850: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(),
2851: DMSetJacobian()
2853: @*/
2854: PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
2855: {
2857: dm->ops->computevariablebounds = f;
2858: return(0);
2859: }
2861: /*@
2862: DMHasVariableBounds - does the DM object have a variable bounds function?
2864: Not Collective
2866: Input Parameter:
2867: . dm - the DM object to destroy
2869: Output Parameter:
2870: . flg - PETSC_TRUE if the variable bounds function exists
2872: Level: developer
2874: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2876: @*/
2877: PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg)
2878: {
2880: *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
2881: return(0);
2882: }
2884: /*@C
2885: DMComputeVariableBounds - compute variable bounds used by SNESVI.
2887: Logically Collective on DM
2889: Input Parameters:
2890: . dm - the DM object
2892: Output parameters:
2893: + xl - lower bound
2894: - xu - upper bound
2896: Level: advanced
2898: Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
2900: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2902: @*/
2903: PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
2904: {
2910: if (dm->ops->computevariablebounds) {
2911: (*dm->ops->computevariablebounds)(dm, xl,xu);
2912: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds.");
2913: return(0);
2914: }
2916: /*@
2917: DMHasColoring - does the DM object have a method of providing a coloring?
2919: Not Collective
2921: Input Parameter:
2922: . dm - the DM object
2924: Output Parameter:
2925: . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring().
2927: Level: developer
2929: .seealso DMHasFunction(), DMCreateColoring()
2931: @*/
2932: PetscErrorCode DMHasColoring(DM dm,PetscBool *flg)
2933: {
2935: *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
2936: return(0);
2937: }
2939: /*@
2940: DMHasCreateRestriction - does the DM object have a method of providing a restriction?
2942: Not Collective
2944: Input Parameter:
2945: . dm - the DM object
2947: Output Parameter:
2948: . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction().
2950: Level: developer
2952: .seealso DMHasFunction(), DMCreateRestriction()
2954: @*/
2955: PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg)
2956: {
2958: *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE;
2959: return(0);
2960: }
2962: /*@C
2963: DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear.
2965: Collective on DM
2967: Input Parameter:
2968: + dm - the DM object
2969: - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems.
2971: Level: developer
2973: .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2975: @*/
2976: PetscErrorCode DMSetVec(DM dm,Vec x)
2977: {
2981: if (x) {
2982: if (!dm->x) {
2983: DMCreateGlobalVector(dm,&dm->x);
2984: }
2985: VecCopy(x,dm->x);
2986: } else if (dm->x) {
2987: VecDestroy(&dm->x);
2988: }
2989: return(0);
2990: }
2992: PetscFunctionList DMList = NULL;
2993: PetscBool DMRegisterAllCalled = PETSC_FALSE;
2995: /*@C
2996: DMSetType - Builds a DM, for a particular DM implementation.
2998: Collective on DM
3000: Input Parameters:
3001: + dm - The DM object
3002: - method - The name of the DM type
3004: Options Database Key:
3005: . -dm_type <type> - Sets the DM type; use -help for a list of available types
3007: Notes:
3008: See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).
3010: Level: intermediate
3012: .keywords: DM, set, type
3013: .seealso: DMGetType(), DMCreate()
3014: @*/
3015: PetscErrorCode DMSetType(DM dm, DMType method)
3016: {
3017: PetscErrorCode (*r)(DM);
3018: PetscBool match;
3023: PetscObjectTypeCompare((PetscObject) dm, method, &match);
3024: if (match) return(0);
3026: DMRegisterAll();
3027: PetscFunctionListFind(DMList,method,&r);
3028: if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
3030: if (dm->ops->destroy) {
3031: (*dm->ops->destroy)(dm);
3032: dm->ops->destroy = NULL;
3033: }
3034: (*r)(dm);
3035: PetscObjectChangeTypeName((PetscObject)dm,method);
3036: return(0);
3037: }
3039: /*@C
3040: DMGetType - Gets the DM type name (as a string) from the DM.
3042: Not Collective
3044: Input Parameter:
3045: . dm - The DM
3047: Output Parameter:
3048: . type - The DM type name
3050: Level: intermediate
3052: .keywords: DM, get, type, name
3053: .seealso: DMSetType(), DMCreate()
3054: @*/
3055: PetscErrorCode DMGetType(DM dm, DMType *type)
3056: {
3062: DMRegisterAll();
3063: *type = ((PetscObject)dm)->type_name;
3064: return(0);
3065: }
3067: /*@C
3068: DMConvert - Converts a DM to another DM, either of the same or different type.
3070: Collective on DM
3072: Input Parameters:
3073: + dm - the DM
3074: - newtype - new DM type (use "same" for the same type)
3076: Output Parameter:
3077: . M - pointer to new DM
3079: Notes:
3080: Cannot be used to convert a sequential DM to parallel or parallel to sequential,
3081: the MPI communicator of the generated DM is always the same as the communicator
3082: of the input DM.
3084: Level: intermediate
3086: .seealso: DMCreate()
3087: @*/
3088: PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
3089: {
3090: DM B;
3091: char convname[256];
3092: PetscBool sametype/*, issame */;
3099: PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);
3100: /* PetscStrcmp(newtype, "same", &issame); */
3101: if (sametype) {
3102: *M = dm;
3103: PetscObjectReference((PetscObject) dm);
3104: return(0);
3105: } else {
3106: PetscErrorCode (*conv)(DM, DMType, DM*) = NULL;
3108: /*
3109: Order of precedence:
3110: 1) See if a specialized converter is known to the current DM.
3111: 2) See if a specialized converter is known to the desired DM class.
3112: 3) See if a good general converter is registered for the desired class
3113: 4) See if a good general converter is known for the current matrix.
3114: 5) Use a really basic converter.
3115: */
3117: /* 1) See if a specialized converter is known to the current DM and the desired class */
3118: PetscStrcpy(convname,"DMConvert_");
3119: PetscStrcat(convname,((PetscObject) dm)->type_name);
3120: PetscStrcat(convname,"_");
3121: PetscStrcat(convname,newtype);
3122: PetscStrcat(convname,"_C");
3123: PetscObjectQueryFunction((PetscObject)dm,convname,&conv);
3124: if (conv) goto foundconv;
3126: /* 2) See if a specialized converter is known to the desired DM class. */
3127: DMCreate(PetscObjectComm((PetscObject)dm), &B);
3128: DMSetType(B, newtype);
3129: PetscStrcpy(convname,"DMConvert_");
3130: PetscStrcat(convname,((PetscObject) dm)->type_name);
3131: PetscStrcat(convname,"_");
3132: PetscStrcat(convname,newtype);
3133: PetscStrcat(convname,"_C");
3134: PetscObjectQueryFunction((PetscObject)B,convname,&conv);
3135: if (conv) {
3136: DMDestroy(&B);
3137: goto foundconv;
3138: }
3140: #if 0
3141: /* 3) See if a good general converter is registered for the desired class */
3142: conv = B->ops->convertfrom;
3143: DMDestroy(&B);
3144: if (conv) goto foundconv;
3146: /* 4) See if a good general converter is known for the current matrix */
3147: if (dm->ops->convert) {
3148: conv = dm->ops->convert;
3149: }
3150: if (conv) goto foundconv;
3151: #endif
3153: /* 5) Use a really basic converter. */
3154: SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);
3156: foundconv:
3157: PetscLogEventBegin(DM_Convert,dm,0,0,0);
3158: (*conv)(dm,newtype,M);
3159: /* Things that are independent of DM type: We should consult DMClone() here */
3160: {
3161: PetscBool isper;
3162: const PetscReal *maxCell, *L;
3163: const DMBoundaryType *bd;
3164: DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);
3165: DMSetPeriodicity(*M, isper, maxCell, L, bd);
3166: }
3167: PetscLogEventEnd(DM_Convert,dm,0,0,0);
3168: }
3169: PetscObjectStateIncrease((PetscObject) *M);
3170: return(0);
3171: }
3173: /*--------------------------------------------------------------------------------------------------------------------*/
3175: /*@C
3176: DMRegister - Adds a new DM component implementation
3178: Not Collective
3180: Input Parameters:
3181: + name - The name of a new user-defined creation routine
3182: - create_func - The creation routine itself
3184: Notes:
3185: DMRegister() may be called multiple times to add several user-defined DMs
3188: Sample usage:
3189: .vb
3190: DMRegister("my_da", MyDMCreate);
3191: .ve
3193: Then, your DM type can be chosen with the procedural interface via
3194: .vb
3195: DMCreate(MPI_Comm, DM *);
3196: DMSetType(DM,"my_da");
3197: .ve
3198: or at runtime via the option
3199: .vb
3200: -da_type my_da
3201: .ve
3203: Level: advanced
3205: .keywords: DM, register
3206: .seealso: DMRegisterAll(), DMRegisterDestroy()
3208: @*/
3209: PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM))
3210: {
3214: PetscFunctionListAdd(&DMList,sname,function);
3215: return(0);
3216: }
3218: /*@C
3219: DMLoad - Loads a DM that has been stored in binary with DMView().
3221: Collective on PetscViewer
3223: Input Parameters:
3224: + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
3225: some related function before a call to DMLoad().
3226: - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
3227: HDF5 file viewer, obtained from PetscViewerHDF5Open()
3229: Level: intermediate
3231: Notes:
3232: The type is determined by the data in the file, any type set into the DM before this call is ignored.
3234: Notes for advanced users:
3235: Most users should not need to know the details of the binary storage
3236: format, since DMLoad() and DMView() completely hide these details.
3237: But for anyone who's interested, the standard binary matrix storage
3238: format is
3239: .vb
3240: has not yet been determined
3241: .ve
3243: .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad()
3244: @*/
3245: PetscErrorCode DMLoad(DM newdm, PetscViewer viewer)
3246: {
3247: PetscBool isbinary, ishdf5;
3253: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
3254: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
3255: if (isbinary) {
3256: PetscInt classid;
3257: char type[256];
3259: PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);
3260: if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid);
3261: PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);
3262: DMSetType(newdm, type);
3263: if (newdm->ops->load) {(*newdm->ops->load)(newdm,viewer);}
3264: } else if (ishdf5) {
3265: if (newdm->ops->load) {(*newdm->ops->load)(newdm,viewer);}
3266: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
3267: return(0);
3268: }
3270: /******************************** FEM Support **********************************/
3272: PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
3273: {
3274: PetscInt f;
3278: PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);
3279: for (f = 0; f < len; ++f) {
3280: PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));
3281: }
3282: return(0);
3283: }
3285: PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
3286: {
3287: PetscInt f, g;
3291: PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);
3292: for (f = 0; f < rows; ++f) {
3293: PetscPrintf(PETSC_COMM_SELF, " |");
3294: for (g = 0; g < cols; ++g) {
3295: PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));
3296: }
3297: PetscPrintf(PETSC_COMM_SELF, " |\n");
3298: }
3299: return(0);
3300: }
3302: PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
3303: {
3304: PetscInt localSize, bs;
3305: PetscMPIInt size;
3306: Vec x, xglob;
3307: const PetscScalar *xarray;
3308: PetscErrorCode ierr;
3311: MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);
3312: VecDuplicate(X, &x);
3313: VecCopy(X, x);
3314: VecChop(x, tol);
3315: PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);
3316: if (size > 1) {
3317: VecGetLocalSize(x,&localSize);
3318: VecGetArrayRead(x,&xarray);
3319: VecGetBlockSize(x,&bs);
3320: VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);
3321: } else {
3322: xglob = x;
3323: }
3324: VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));
3325: if (size > 1) {
3326: VecDestroy(&xglob);
3327: VecRestoreArrayRead(x,&xarray);
3328: }
3329: VecDestroy(&x);
3330: return(0);
3331: }
3333: /*@
3334: DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM.
3336: Input Parameter:
3337: . dm - The DM
3339: Output Parameter:
3340: . section - The PetscSection
3342: Level: intermediate
3344: Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3346: .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3347: @*/
3348: PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section)
3349: {
3355: if (!dm->defaultSection && dm->ops->createdefaultsection) {
3356: (*dm->ops->createdefaultsection)(dm);
3357: if (dm->defaultSection) {PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");}
3358: }
3359: *section = dm->defaultSection;
3360: return(0);
3361: }
3363: /*@
3364: DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM.
3366: Input Parameters:
3367: + dm - The DM
3368: - section - The PetscSection
3370: Level: intermediate
3372: Note: Any existing Section will be destroyed
3374: .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3375: @*/
3376: PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section)
3377: {
3378: PetscInt numFields = 0;
3379: PetscInt f;
3384: if (section) {
3386: PetscObjectReference((PetscObject)section);
3387: }
3388: PetscSectionDestroy(&dm->defaultSection);
3389: dm->defaultSection = section;
3390: if (section) {PetscSectionGetNumFields(dm->defaultSection, &numFields);}
3391: if (numFields) {
3392: DMSetNumFields(dm, numFields);
3393: for (f = 0; f < numFields; ++f) {
3394: PetscObject disc;
3395: const char *name;
3397: PetscSectionGetFieldName(dm->defaultSection, f, &name);
3398: DMGetField(dm, f, &disc);
3399: PetscObjectSetName(disc, name);
3400: }
3401: }
3402: /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */
3403: PetscSectionDestroy(&dm->defaultGlobalSection);
3404: return(0);
3405: }
3407: /*@
3408: DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation.
3410: not collective
3412: Input Parameter:
3413: . dm - The DM
3415: Output Parameter:
3416: + 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.
3417: - 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.
3419: Level: advanced
3421: Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat.
3423: .seealso: DMSetDefaultConstraints()
3424: @*/
3425: PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat)
3426: {
3431: if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {(*dm->ops->createdefaultconstraints)(dm);}
3432: if (section) {*section = dm->defaultConstraintSection;}
3433: if (mat) {*mat = dm->defaultConstraintMat;}
3434: return(0);
3435: }
3437: /*@
3438: DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation.
3440: 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().
3442: 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.
3444: collective on dm
3446: Input Parameters:
3447: + dm - The DM
3448: + 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).
3449: - 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).
3451: Level: advanced
3453: Note: This increments the references of the PetscSection and the Mat, so they user can destroy them
3455: .seealso: DMGetDefaultConstraints()
3456: @*/
3457: PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat)
3458: {
3459: PetscMPIInt result;
3464: if (section) {
3466: MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);
3467: if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator");
3468: }
3469: if (mat) {
3471: MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);
3472: if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator");
3473: }
3474: PetscObjectReference((PetscObject)section);
3475: PetscSectionDestroy(&dm->defaultConstraintSection);
3476: dm->defaultConstraintSection = section;
3477: PetscObjectReference((PetscObject)mat);
3478: MatDestroy(&dm->defaultConstraintMat);
3479: dm->defaultConstraintMat = mat;
3480: return(0);
3481: }
3483: #ifdef PETSC_USE_DEBUG
3484: /*
3485: DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections.
3487: Input Parameters:
3488: + dm - The DM
3489: . localSection - PetscSection describing the local data layout
3490: - globalSection - PetscSection describing the global data layout
3492: Level: intermediate
3494: .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3495: */
3496: static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
3497: {
3498: MPI_Comm comm;
3499: PetscLayout layout;
3500: const PetscInt *ranges;
3501: PetscInt pStart, pEnd, p, nroots;
3502: PetscMPIInt size, rank;
3503: PetscBool valid = PETSC_TRUE, gvalid;
3504: PetscErrorCode ierr;
3507: PetscObjectGetComm((PetscObject)dm,&comm);
3509: MPI_Comm_size(comm, &size);
3510: MPI_Comm_rank(comm, &rank);
3511: PetscSectionGetChart(globalSection, &pStart, &pEnd);
3512: PetscSectionGetConstrainedStorageSize(globalSection, &nroots);
3513: PetscLayoutCreate(comm, &layout);
3514: PetscLayoutSetBlockSize(layout, 1);
3515: PetscLayoutSetLocalSize(layout, nroots);
3516: PetscLayoutSetUp(layout);
3517: PetscLayoutGetRanges(layout, &ranges);
3518: for (p = pStart; p < pEnd; ++p) {
3519: PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d;
3521: PetscSectionGetDof(localSection, p, &dof);
3522: PetscSectionGetOffset(localSection, p, &off);
3523: PetscSectionGetConstraintDof(localSection, p, &cdof);
3524: PetscSectionGetDof(globalSection, p, &gdof);
3525: PetscSectionGetConstraintDof(globalSection, p, &gcdof);
3526: PetscSectionGetOffset(globalSection, p, &goff);
3527: if (!gdof) continue; /* Censored point */
3528: if ((gdof < 0 ? -(gdof+1) : gdof) != dof) {PetscSynchronizedPrintf(comm, "[%d]Global dof %d for point %d not equal to local dof %d\n", rank, gdof, p, dof); valid = PETSC_FALSE;}
3529: if (gcdof && (gcdof != cdof)) {PetscSynchronizedPrintf(comm, "[%d]Global constraints %d for point %d not equal to local constraints %d\n", rank, gcdof, p, cdof); valid = PETSC_FALSE;}
3530: if (gdof < 0) {
3531: gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3532: for (d = 0; d < gsize; ++d) {
3533: PetscInt offset = -(goff+1) + d, r;
3535: PetscFindInt(offset,size+1,ranges,&r);
3536: if (r < 0) r = -(r+2);
3537: if ((r < 0) || (r >= size)) {PetscSynchronizedPrintf(comm, "[%d]Point %d mapped to invalid process %d (%d, %d)\n", rank, p, r, gdof, goff); valid = PETSC_FALSE;break;}
3538: }
3539: }
3540: }
3541: PetscLayoutDestroy(&layout);
3542: PetscSynchronizedFlush(comm, NULL);
3543: MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);
3544: if (!gvalid) {
3545: DMView(dm, NULL);
3546: SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
3547: }
3548: return(0);
3549: }
3550: #endif
3552: /*@
3553: DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM.
3555: Collective on DM
3557: Input Parameter:
3558: . dm - The DM
3560: Output Parameter:
3561: . section - The PetscSection
3563: Level: intermediate
3565: Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3567: .seealso: DMSetDefaultSection(), DMGetDefaultSection()
3568: @*/
3569: PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section)
3570: {
3576: if (!dm->defaultGlobalSection) {
3577: PetscSection s;
3579: DMGetDefaultSection(dm, &s);
3580: if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
3581: if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection");
3582: PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);
3583: PetscLayoutDestroy(&dm->map);
3584: PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);
3585: PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");
3586: }
3587: *section = dm->defaultGlobalSection;
3588: return(0);
3589: }
3591: /*@
3592: DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM.
3594: Input Parameters:
3595: + dm - The DM
3596: - section - The PetscSection, or NULL
3598: Level: intermediate
3600: Note: Any existing Section will be destroyed
3602: .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection()
3603: @*/
3604: PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section)
3605: {
3611: PetscObjectReference((PetscObject)section);
3612: PetscSectionDestroy(&dm->defaultGlobalSection);
3613: dm->defaultGlobalSection = section;
3614: #ifdef PETSC_USE_DEBUG
3615: if (section) {DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);}
3616: #endif
3617: return(0);
3618: }
3620: /*@
3621: DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set,
3622: it is created from the default PetscSection layouts in the DM.
3624: Input Parameter:
3625: . dm - The DM
3627: Output Parameter:
3628: . sf - The PetscSF
3630: Level: intermediate
3632: Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3634: .seealso: DMSetDefaultSF(), DMCreateDefaultSF()
3635: @*/
3636: PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf)
3637: {
3638: PetscInt nroots;
3644: PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);
3645: if (nroots < 0) {
3646: PetscSection section, gSection;
3648: DMGetDefaultSection(dm, §ion);
3649: if (section) {
3650: DMGetDefaultGlobalSection(dm, &gSection);
3651: DMCreateDefaultSF(dm, section, gSection);
3652: } else {
3653: *sf = NULL;
3654: return(0);
3655: }
3656: }
3657: *sf = dm->defaultSF;
3658: return(0);
3659: }
3661: /*@
3662: DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM
3664: Input Parameters:
3665: + dm - The DM
3666: - sf - The PetscSF
3668: Level: intermediate
3670: Note: Any previous SF is destroyed
3672: .seealso: DMGetDefaultSF(), DMCreateDefaultSF()
3673: @*/
3674: PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf)
3675: {
3681: PetscSFDestroy(&dm->defaultSF);
3682: dm->defaultSF = sf;
3683: return(0);
3684: }
3686: /*@C
3687: DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections
3688: describing the data layout.
3690: Input Parameters:
3691: + dm - The DM
3692: . localSection - PetscSection describing the local data layout
3693: - globalSection - PetscSection describing the global data layout
3695: Level: intermediate
3697: .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3698: @*/
3699: PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection)
3700: {
3701: MPI_Comm comm;
3702: PetscLayout layout;
3703: const PetscInt *ranges;
3704: PetscInt *local;
3705: PetscSFNode *remote;
3706: PetscInt pStart, pEnd, p, nroots, nleaves = 0, l;
3707: PetscMPIInt size, rank;
3711: PetscObjectGetComm((PetscObject)dm,&comm);
3713: MPI_Comm_size(comm, &size);
3714: MPI_Comm_rank(comm, &rank);
3715: PetscSectionGetChart(globalSection, &pStart, &pEnd);
3716: PetscSectionGetConstrainedStorageSize(globalSection, &nroots);
3717: PetscLayoutCreate(comm, &layout);
3718: PetscLayoutSetBlockSize(layout, 1);
3719: PetscLayoutSetLocalSize(layout, nroots);
3720: PetscLayoutSetUp(layout);
3721: PetscLayoutGetRanges(layout, &ranges);
3722: for (p = pStart; p < pEnd; ++p) {
3723: PetscInt gdof, gcdof;
3725: PetscSectionGetDof(globalSection, p, &gdof);
3726: PetscSectionGetConstraintDof(globalSection, p, &gcdof);
3727: 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));
3728: nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3729: }
3730: PetscMalloc1(nleaves, &local);
3731: PetscMalloc1(nleaves, &remote);
3732: for (p = pStart, l = 0; p < pEnd; ++p) {
3733: const PetscInt *cind;
3734: PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c;
3736: PetscSectionGetDof(localSection, p, &dof);
3737: PetscSectionGetOffset(localSection, p, &off);
3738: PetscSectionGetConstraintDof(localSection, p, &cdof);
3739: PetscSectionGetConstraintIndices(localSection, p, &cind);
3740: PetscSectionGetDof(globalSection, p, &gdof);
3741: PetscSectionGetConstraintDof(globalSection, p, &gcdof);
3742: PetscSectionGetOffset(globalSection, p, &goff);
3743: if (!gdof) continue; /* Censored point */
3744: gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3745: if (gsize != dof-cdof) {
3746: 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);
3747: cdof = 0; /* Ignore constraints */
3748: }
3749: for (d = 0, c = 0; d < dof; ++d) {
3750: if ((c < cdof) && (cind[c] == d)) {++c; continue;}
3751: local[l+d-c] = off+d;
3752: }
3753: if (gdof < 0) {
3754: for (d = 0; d < gsize; ++d, ++l) {
3755: PetscInt offset = -(goff+1) + d, r;
3757: PetscFindInt(offset,size+1,ranges,&r);
3758: if (r < 0) r = -(r+2);
3759: 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);
3760: remote[l].rank = r;
3761: remote[l].index = offset - ranges[r];
3762: }
3763: } else {
3764: for (d = 0; d < gsize; ++d, ++l) {
3765: remote[l].rank = rank;
3766: remote[l].index = goff+d - ranges[rank];
3767: }
3768: }
3769: }
3770: if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves);
3771: PetscLayoutDestroy(&layout);
3772: PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);
3773: return(0);
3774: }
3776: /*@
3777: DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM.
3779: Input Parameter:
3780: . dm - The DM
3782: Output Parameter:
3783: . sf - The PetscSF
3785: Level: intermediate
3787: Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3789: .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3790: @*/
3791: PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
3792: {
3796: *sf = dm->sf;
3797: return(0);
3798: }
3800: /*@
3801: DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM.
3803: Input Parameters:
3804: + dm - The DM
3805: - sf - The PetscSF
3807: Level: intermediate
3809: .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3810: @*/
3811: PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
3812: {
3818: PetscSFDestroy(&dm->sf);
3819: PetscObjectReference((PetscObject) sf);
3820: dm->sf = sf;
3821: return(0);
3822: }
3824: /*@
3825: DMGetDS - Get the PetscDS
3827: Input Parameter:
3828: . dm - The DM
3830: Output Parameter:
3831: . prob - The PetscDS
3833: Level: developer
3835: .seealso: DMSetDS()
3836: @*/
3837: PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
3838: {
3842: *prob = dm->prob;
3843: return(0);
3844: }
3846: /*@
3847: DMSetDS - Set the PetscDS
3849: Input Parameters:
3850: + dm - The DM
3851: - prob - The PetscDS
3853: Level: developer
3855: .seealso: DMGetDS()
3856: @*/
3857: PetscErrorCode DMSetDS(DM dm, PetscDS prob)
3858: {
3864: PetscObjectReference((PetscObject) prob);
3865: PetscDSDestroy(&dm->prob);
3866: dm->prob = prob;
3867: return(0);
3868: }
3870: PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
3871: {
3876: PetscDSGetNumFields(dm->prob, numFields);
3877: return(0);
3878: }
3880: PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
3881: {
3882: PetscInt Nf, f;
3887: PetscDSGetNumFields(dm->prob, &Nf);
3888: for (f = Nf; f < numFields; ++f) {
3889: PetscContainer obj;
3891: PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);
3892: PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);
3893: PetscContainerDestroy(&obj);
3894: }
3895: return(0);
3896: }
3898: /*@
3899: DMGetField - Return the discretization object for a given DM field
3901: Not collective
3903: Input Parameters:
3904: + dm - The DM
3905: - f - The field number
3907: Output Parameter:
3908: . field - The discretization object
3910: Level: developer
3912: .seealso: DMSetField()
3913: @*/
3914: PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field)
3915: {
3920: PetscDSGetDiscretization(dm->prob, f, field);
3921: return(0);
3922: }
3924: /*@
3925: DMSetField - Set the discretization object for a given DM field
3927: Logically collective on DM
3929: Input Parameters:
3930: + dm - The DM
3931: . f - The field number
3932: - field - The discretization object
3934: Level: developer
3936: .seealso: DMGetField()
3937: @*/
3938: PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field)
3939: {
3944: PetscDSSetDiscretization(dm->prob, f, field);
3945: return(0);
3946: }
3948: PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx)
3949: {
3950: DM dm_coord,dmc_coord;
3952: Vec coords,ccoords;
3953: Mat inject;
3955: DMGetCoordinateDM(dm,&dm_coord);
3956: DMGetCoordinateDM(dmc,&dmc_coord);
3957: DMGetCoordinates(dm,&coords);
3958: DMGetCoordinates(dmc,&ccoords);
3959: if (coords && !ccoords) {
3960: DMCreateGlobalVector(dmc_coord,&ccoords);
3961: PetscObjectSetName((PetscObject)ccoords,"coordinates");
3962: DMCreateInjection(dmc_coord,dm_coord,&inject);
3963: MatRestrict(inject,coords,ccoords);
3964: MatDestroy(&inject);
3965: DMSetCoordinates(dmc,ccoords);
3966: VecDestroy(&ccoords);
3967: }
3968: return(0);
3969: }
3971: static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx)
3972: {
3973: DM dm_coord,subdm_coord;
3975: Vec coords,ccoords,clcoords;
3976: VecScatter *scat_i,*scat_g;
3978: DMGetCoordinateDM(dm,&dm_coord);
3979: DMGetCoordinateDM(subdm,&subdm_coord);
3980: DMGetCoordinates(dm,&coords);
3981: DMGetCoordinates(subdm,&ccoords);
3982: if (coords && !ccoords) {
3983: DMCreateGlobalVector(subdm_coord,&ccoords);
3984: PetscObjectSetName((PetscObject)ccoords,"coordinates");
3985: DMCreateLocalVector(subdm_coord,&clcoords);
3986: PetscObjectSetName((PetscObject)clcoords,"coordinates");
3987: DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);
3988: VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);
3989: VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);
3990: VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);
3991: VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);
3992: DMSetCoordinates(subdm,ccoords);
3993: DMSetCoordinatesLocal(subdm,clcoords);
3994: VecScatterDestroy(&scat_i[0]);
3995: VecScatterDestroy(&scat_g[0]);
3996: VecDestroy(&ccoords);
3997: VecDestroy(&clcoords);
3998: PetscFree(scat_i);
3999: PetscFree(scat_g);
4000: }
4001: return(0);
4002: }
4004: /*@
4005: DMGetDimension - Return the topological dimension of the DM
4007: Not collective
4009: Input Parameter:
4010: . dm - The DM
4012: Output Parameter:
4013: . dim - The topological dimension
4015: Level: beginner
4017: .seealso: DMSetDimension(), DMCreate()
4018: @*/
4019: PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
4020: {
4024: *dim = dm->dim;
4025: return(0);
4026: }
4028: /*@
4029: DMSetDimension - Set the topological dimension of the DM
4031: Collective on dm
4033: Input Parameters:
4034: + dm - The DM
4035: - dim - The topological dimension
4037: Level: beginner
4039: .seealso: DMGetDimension(), DMCreate()
4040: @*/
4041: PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
4042: {
4046: dm->dim = dim;
4047: return(0);
4048: }
4050: /*@
4051: DMGetDimPoints - Get the half-open interval for all points of a given dimension
4053: Collective on DM
4055: Input Parameters:
4056: + dm - the DM
4057: - dim - the dimension
4059: Output Parameters:
4060: + pStart - The first point of the given dimension
4061: . pEnd - The first point following points of the given dimension
4063: Note:
4064: The points are vertices in the Hasse diagram encoding the topology. This is explained in
4065: http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme,
4066: then the interval is empty.
4068: Level: intermediate
4070: .keywords: point, Hasse Diagram, dimension
4071: .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum()
4072: @*/
4073: PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
4074: {
4075: PetscInt d;
4080: DMGetDimension(dm, &d);
4081: if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d);
4082: (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);
4083: return(0);
4084: }
4086: /*@
4087: DMSetCoordinates - Sets into the DM a global vector that holds the coordinates
4089: Collective on DM
4091: Input Parameters:
4092: + dm - the DM
4093: - c - coordinate vector
4095: Note:
4096: The coordinates do include those for ghost points, which are in the local vector
4098: Level: intermediate
4100: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4101: .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM()
4102: @*/
4103: PetscErrorCode DMSetCoordinates(DM dm, Vec c)
4104: {
4110: PetscObjectReference((PetscObject) c);
4111: VecDestroy(&dm->coordinates);
4112: dm->coordinates = c;
4113: VecDestroy(&dm->coordinatesLocal);
4114: DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);
4115: DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);
4116: return(0);
4117: }
4119: /*@
4120: DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates
4122: Collective on DM
4124: Input Parameters:
4125: + dm - the DM
4126: - c - coordinate vector
4128: Note:
4129: The coordinates of ghost points can be set using DMSetCoordinates()
4130: followed by DMGetCoordinatesLocal(). This is intended to enable the
4131: setting of ghost coordinates outside of the domain.
4133: Level: intermediate
4135: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4136: .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM()
4137: @*/
4138: PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c)
4139: {
4145: PetscObjectReference((PetscObject) c);
4146: VecDestroy(&dm->coordinatesLocal);
4148: dm->coordinatesLocal = c;
4150: VecDestroy(&dm->coordinates);
4151: return(0);
4152: }
4154: /*@
4155: DMGetCoordinates - Gets a global vector with the coordinates associated with the DM.
4157: Not Collective
4159: Input Parameter:
4160: . dm - the DM
4162: Output Parameter:
4163: . c - global coordinate vector
4165: Note:
4166: This is a borrowed reference, so the user should NOT destroy this vector
4168: Each process has only the local coordinates (does NOT have the ghost coordinates).
4170: For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
4171: and (x_0,y_0,z_0,x_1,y_1,z_1...)
4173: Level: intermediate
4175: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4176: .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
4177: @*/
4178: PetscErrorCode DMGetCoordinates(DM dm, Vec *c)
4179: {
4185: if (!dm->coordinates && dm->coordinatesLocal) {
4186: DM cdm = NULL;
4188: DMGetCoordinateDM(dm, &cdm);
4189: DMCreateGlobalVector(cdm, &dm->coordinates);
4190: PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");
4191: DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);
4192: DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);
4193: }
4194: *c = dm->coordinates;
4195: return(0);
4196: }
4198: /*@
4199: DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM.
4201: Collective on DM
4203: Input Parameter:
4204: . dm - the DM
4206: Output Parameter:
4207: . c - coordinate vector
4209: Note:
4210: This is a borrowed reference, so the user should NOT destroy this vector
4212: Each process has the local and ghost coordinates
4214: For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
4215: and (x_0,y_0,z_0,x_1,y_1,z_1...)
4217: Level: intermediate
4219: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4220: .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
4221: @*/
4222: PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c)
4223: {
4229: if (!dm->coordinatesLocal && dm->coordinates) {
4230: DM cdm = NULL;
4232: DMGetCoordinateDM(dm, &cdm);
4233: DMCreateLocalVector(cdm, &dm->coordinatesLocal);
4234: PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");
4235: DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);
4236: DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);
4237: }
4238: *c = dm->coordinatesLocal;
4239: return(0);
4240: }
4242: /*@
4243: DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates
4245: Collective on DM
4247: Input Parameter:
4248: . dm - the DM
4250: Output Parameter:
4251: . cdm - coordinate DM
4253: Level: intermediate
4255: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4256: .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4257: @*/
4258: PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm)
4259: {
4265: if (!dm->coordinateDM) {
4266: if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM");
4267: (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);
4268: }
4269: *cdm = dm->coordinateDM;
4270: return(0);
4271: }
4273: /*@
4274: DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates
4276: Logically Collective on DM
4278: Input Parameters:
4279: + dm - the DM
4280: - cdm - coordinate DM
4282: Level: intermediate
4284: .keywords: distributed array, get, corners, nodes, local indices, coordinates
4285: .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4286: @*/
4287: PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm)
4288: {
4294: PetscObjectReference((PetscObject)cdm);
4295: DMDestroy(&dm->coordinateDM);
4296: dm->coordinateDM = cdm;
4297: return(0);
4298: }
4300: /*@
4301: DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values.
4303: Not Collective
4305: Input Parameter:
4306: . dm - The DM object
4308: Output Parameter:
4309: . dim - The embedding dimension
4311: Level: intermediate
4313: .keywords: mesh, coordinates
4314: .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
4315: @*/
4316: PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim)
4317: {
4321: if (dm->dimEmbed == PETSC_DEFAULT) {
4322: dm->dimEmbed = dm->dim;
4323: }
4324: *dim = dm->dimEmbed;
4325: return(0);
4326: }
4328: /*@
4329: DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values.
4331: Not Collective
4333: Input Parameters:
4334: + dm - The DM object
4335: - dim - The embedding dimension
4337: Level: intermediate
4339: .keywords: mesh, coordinates
4340: .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
4341: @*/
4342: PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim)
4343: {
4346: dm->dimEmbed = dim;
4347: return(0);
4348: }
4350: /*@
4351: DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.
4353: Not Collective
4355: Input Parameter:
4356: . dm - The DM object
4358: Output Parameter:
4359: . section - The PetscSection object
4361: Level: intermediate
4363: .keywords: mesh, coordinates
4364: .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
4365: @*/
4366: PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section)
4367: {
4368: DM cdm;
4374: DMGetCoordinateDM(dm, &cdm);
4375: DMGetDefaultSection(cdm, section);
4376: return(0);
4377: }
4379: /*@
4380: DMSetCoordinateSection - Set the layout of coordinate values over the mesh.
4382: Not Collective
4384: Input Parameters:
4385: + dm - The DM object
4386: . dim - The embedding dimension, or PETSC_DETERMINE
4387: - section - The PetscSection object
4389: Level: intermediate
4391: .keywords: mesh, coordinates
4392: .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
4393: @*/
4394: PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section)
4395: {
4396: DM cdm;
4402: DMGetCoordinateDM(dm, &cdm);
4403: DMSetDefaultSection(cdm, section);
4404: if (dim == PETSC_DETERMINE) {
4405: PetscInt d = PETSC_DEFAULT;
4406: PetscInt pStart, pEnd, vStart, vEnd, v, dd;
4408: PetscSectionGetChart(section, &pStart, &pEnd);
4409: DMGetDimPoints(dm, 0, &vStart, &vEnd);
4410: pStart = PetscMax(vStart, pStart);
4411: pEnd = PetscMin(vEnd, pEnd);
4412: for (v = pStart; v < pEnd; ++v) {
4413: PetscSectionGetDof(section, v, &dd);
4414: if (dd) {d = dd; break;}
4415: }
4416: if (d < 0) d = PETSC_DEFAULT;
4417: DMSetCoordinateDim(dm, d);
4418: }
4419: return(0);
4420: }
4422: /*@C
4423: DMGetPeriodicity - Get the description of mesh periodicity
4425: Input Parameters:
4426: . dm - The DM object
4428: Output Parameters:
4429: + per - Whether the DM is periodic or not
4430: . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
4431: . L - If we assume the mesh is a torus, this is the length of each coordinate
4432: - bd - This describes the type of periodicity in each topological dimension
4434: Level: developer
4436: .seealso: DMGetPeriodicity()
4437: @*/
4438: PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd)
4439: {
4442: if (per) *per = dm->periodic;
4443: if (L) *L = dm->L;
4444: if (maxCell) *maxCell = dm->maxCell;
4445: if (bd) *bd = dm->bdtype;
4446: return(0);
4447: }
4449: /*@C
4450: DMSetPeriodicity - Set the description of mesh periodicity
4452: Input Parameters:
4453: + dm - The DM object
4454: . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized
4455: . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
4456: . L - If we assume the mesh is a torus, this is the length of each coordinate
4457: - bd - This describes the type of periodicity in each topological dimension
4459: Level: developer
4461: .seealso: DMGetPeriodicity()
4462: @*/
4463: PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[])
4464: {
4465: PetscInt dim, d;
4471: if (maxCell) {
4475: }
4476: PetscFree3(dm->L,dm->maxCell,dm->bdtype);
4477: DMGetDimension(dm, &dim);
4478: if (maxCell) {
4479: PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);
4480: for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];}
4481: dm->periodic = PETSC_TRUE;
4482: } else {
4483: dm->periodic = per;
4484: }
4485: return(0);
4486: }
4488: /*@
4489: 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.
4491: Input Parameters:
4492: + dm - The DM
4493: . in - The input coordinate point (dim numbers)
4494: - endpoint - Include the endpoint L_i
4496: Output Parameter:
4497: . out - The localized coordinate point
4499: Level: developer
4501: .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
4502: @*/
4503: PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[])
4504: {
4505: PetscInt dim, d;
4509: DMGetCoordinateDim(dm, &dim);
4510: if (!dm->maxCell) {
4511: for (d = 0; d < dim; ++d) out[d] = in[d];
4512: } else {
4513: if (endpoint) {
4514: for (d = 0; d < dim; ++d) {
4515: 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)) {
4516: out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1);
4517: } else {
4518: out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]);
4519: }
4520: }
4521: } else {
4522: for (d = 0; d < dim; ++d) {
4523: out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]);
4524: }
4525: }
4526: }
4527: return(0);
4528: }
4530: /*
4531: 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.
4533: Input Parameters:
4534: + dm - The DM
4535: . dim - The spatial dimension
4536: . anchor - The anchor point, the input point can be no more than maxCell away from it
4537: - in - The input coordinate point (dim numbers)
4539: Output Parameter:
4540: . out - The localized coordinate point
4542: Level: developer
4544: 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
4546: .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate()
4547: */
4548: PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
4549: {
4550: PetscInt d;
4553: if (!dm->maxCell) {
4554: for (d = 0; d < dim; ++d) out[d] = in[d];
4555: } else {
4556: for (d = 0; d < dim; ++d) {
4557: if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) {
4558: out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
4559: } else {
4560: out[d] = in[d];
4561: }
4562: }
4563: }
4564: return(0);
4565: }
4566: PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[])
4567: {
4568: PetscInt d;
4571: if (!dm->maxCell) {
4572: for (d = 0; d < dim; ++d) out[d] = in[d];
4573: } else {
4574: for (d = 0; d < dim; ++d) {
4575: if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) {
4576: out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d];
4577: } else {
4578: out[d] = in[d];
4579: }
4580: }
4581: }
4582: return(0);
4583: }
4585: /*
4586: 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.
4588: Input Parameters:
4589: + dm - The DM
4590: . dim - The spatial dimension
4591: . anchor - The anchor point, the input point can be no more than maxCell away from it
4592: . in - The input coordinate delta (dim numbers)
4593: - out - The input coordinate point (dim numbers)
4595: Output Parameter:
4596: . out - The localized coordinate in + out
4598: Level: developer
4600: 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
4602: .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate()
4603: */
4604: PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
4605: {
4606: PetscInt d;
4609: if (!dm->maxCell) {
4610: for (d = 0; d < dim; ++d) out[d] += in[d];
4611: } else {
4612: for (d = 0; d < dim; ++d) {
4613: if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) {
4614: out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
4615: } else {
4616: out[d] += in[d];
4617: }
4618: }
4619: }
4620: return(0);
4621: }
4623: /*@
4624: DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells
4626: Input Parameter:
4627: . dm - The DM
4629: Output Parameter:
4630: areLocalized - True if localized
4632: Level: developer
4634: .seealso: DMLocalizeCoordinates()
4635: @*/
4636: PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized)
4637: {
4638: DM cdm;
4639: PetscSection coordSection;
4640: PetscInt cStart, cEnd, c, sStart, sEnd, dof;
4641: PetscBool alreadyLocalized, alreadyLocalizedGlobal;
4646: if (!dm->periodic) {
4647: *areLocalized = PETSC_FALSE;
4648: return(0);
4649: }
4650: /* We need some generic way of refering to cells/vertices */
4651: DMGetCoordinateDM(dm, &cdm);
4652: {
4653: PetscBool isplex;
4655: PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);
4656: if (isplex) {
4657: DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);
4658: } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM");
4659: }
4660: DMGetCoordinateSection(dm, &coordSection);
4661: PetscSectionGetChart(coordSection,&sStart,&sEnd);
4662: alreadyLocalized = alreadyLocalizedGlobal = PETSC_FALSE;
4663: for (c = cStart; c < cEnd; ++c) {
4664: if (c < sStart || c >= sEnd) {
4665: alreadyLocalized = PETSC_FALSE;
4666: break;
4667: }
4668: PetscSectionGetDof(coordSection, c, &dof);
4669: if (dof) {
4670: alreadyLocalized = PETSC_TRUE;
4671: break;
4672: }
4673: }
4674: MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));
4675: *areLocalized = alreadyLocalizedGlobal;
4676: return(0);
4677: }
4680: /*@
4681: DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces
4683: Input Parameter:
4684: . dm - The DM
4686: Level: developer
4688: .seealso: DMLocalizeCoordinate(), DMLocalizeAddCoordinate()
4689: @*/
4690: PetscErrorCode DMLocalizeCoordinates(DM dm)
4691: {
4692: DM cdm;
4693: PetscSection coordSection, cSection;
4694: Vec coordinates, cVec;
4695: PetscScalar *coords, *coords2, *anchor, *localized;
4696: PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize;
4697: PetscBool alreadyLocalized, alreadyLocalizedGlobal;
4698: PetscInt maxHeight = 0, h;
4699: PetscInt *pStart = NULL, *pEnd = NULL;
4704: if (!dm->periodic) return(0);
4705: /* We need some generic way of refering to cells/vertices */
4706: DMGetCoordinateDM(dm, &cdm);
4707: {
4708: PetscBool isplex;
4710: PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);
4711: if (isplex) {
4712: DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);
4713: DMPlexGetMaxProjectionHeight(cdm,&maxHeight);
4714: DMGetWorkArray(dm,2*(maxHeight + 1),PETSC_INT,&pStart);
4715: pEnd = &pStart[maxHeight + 1];
4716: newStart = vStart;
4717: newEnd = vEnd;
4718: for (h = 0; h <= maxHeight; h++) {
4719: DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);
4720: newStart = PetscMin(newStart,pStart[h]);
4721: newEnd = PetscMax(newEnd,pEnd[h]);
4722: }
4723: } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM");
4724: }
4725: DMGetCoordinatesLocal(dm, &coordinates);
4726: DMGetCoordinateSection(dm, &coordSection);
4727: VecGetBlockSize(coordinates, &bs);
4728: PetscSectionGetChart(coordSection,&sStart,&sEnd);
4730: PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);
4731: PetscSectionSetNumFields(cSection, 1);
4732: PetscSectionGetFieldComponents(coordSection, 0, &Nc);
4733: PetscSectionSetFieldComponents(cSection, 0, Nc);
4734: PetscSectionSetChart(cSection, newStart, newEnd);
4736: DMGetWorkArray(dm, 2 * bs, PETSC_SCALAR, &anchor);
4737: localized = &anchor[bs];
4738: alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE;
4739: for (h = 0; h <= maxHeight; h++) {
4740: PetscInt cStart = pStart[h], cEnd = pEnd[h], c;
4742: for (c = cStart; c < cEnd; ++c) {
4743: PetscScalar *cellCoords = NULL;
4744: PetscInt b;
4746: if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE;
4747: DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4748: for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b];
4749: for (d = 0; d < dof/bs; ++d) {
4750: DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);
4751: for (b = 0; b < bs; b++) {
4752: if (cellCoords[d*bs + b] != localized[b]) break;
4753: }
4754: if (b < bs) break;
4755: }
4756: if (d < dof/bs) {
4757: if (c >= sStart && c < sEnd) {
4758: PetscInt cdof;
4760: PetscSectionGetDof(coordSection, c, &cdof);
4761: if (cdof != dof) alreadyLocalized = PETSC_FALSE;
4762: }
4763: PetscSectionSetDof(cSection, c, dof);
4764: PetscSectionSetFieldDof(cSection, c, 0, dof);
4765: }
4766: DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4767: }
4768: }
4769: MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));
4770: if (alreadyLocalizedGlobal) {
4771: DMRestoreWorkArray(dm, 2 * bs, PETSC_SCALAR, &anchor);
4772: PetscSectionDestroy(&cSection);
4773: DMRestoreWorkArray(dm,2*(maxHeight + 1),PETSC_INT,&pStart);
4774: return(0);
4775: }
4776: for (v = vStart; v < vEnd; ++v) {
4777: PetscSectionGetDof(coordSection, v, &dof);
4778: PetscSectionSetDof(cSection, v, dof);
4779: PetscSectionSetFieldDof(cSection, v, 0, dof);
4780: }
4781: PetscSectionSetUp(cSection);
4782: PetscSectionGetStorageSize(cSection, &coordSize);
4783: VecCreate(PETSC_COMM_SELF, &cVec);
4784: PetscObjectSetName((PetscObject)cVec,"coordinates");
4785: VecSetBlockSize(cVec, bs);
4786: VecSetSizes(cVec, coordSize, PETSC_DETERMINE);
4787: VecSetType(cVec, VECSTANDARD);
4788: VecGetArrayRead(coordinates, (const PetscScalar**)&coords);
4789: VecGetArray(cVec, &coords2);
4790: for (v = vStart; v < vEnd; ++v) {
4791: PetscSectionGetDof(coordSection, v, &dof);
4792: PetscSectionGetOffset(coordSection, v, &off);
4793: PetscSectionGetOffset(cSection, v, &off2);
4794: for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d];
4795: }
4796: for (h = 0; h <= maxHeight; h++) {
4797: PetscInt cStart = pStart[h], cEnd = pEnd[h], c;
4799: for (c = cStart; c < cEnd; ++c) {
4800: PetscScalar *cellCoords = NULL;
4801: PetscInt b, cdof;
4803: PetscSectionGetDof(cSection,c,&cdof);
4804: if (!cdof) continue;
4805: DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4806: PetscSectionGetOffset(cSection, c, &off2);
4807: for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b];
4808: for (d = 0; d < dof/bs; ++d) {DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);}
4809: DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);
4810: }
4811: }
4812: DMRestoreWorkArray(dm, 2 * bs, PETSC_SCALAR, &anchor);
4813: DMRestoreWorkArray(dm,2*(maxHeight + 1),PETSC_INT,&pStart);
4814: VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);
4815: VecRestoreArray(cVec, &coords2);
4816: DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);
4817: DMSetCoordinatesLocal(dm, cVec);
4818: VecDestroy(&cVec);
4819: PetscSectionDestroy(&cSection);
4820: return(0);
4821: }
4823: /*@
4824: DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells
4826: Collective on Vec v (see explanation below)
4828: Input Parameters:
4829: + dm - The DM
4830: . v - The Vec of points
4831: . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST
4832: - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point.
4834: Output Parameter:
4835: + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used
4836: - cells - The PetscSF containing the ranks and local indices of the containing points.
4839: Level: developer
4841: Notes:
4842: To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator.
4843: To do a search of all the cells in the distributed mesh, v should have the same communicator as dm.
4845: If *cellSF is NULL on input, a PetscSF will be created.
4846: If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses.
4848: An array that maps each point to its containing cell can be obtained with
4850: $ const PetscSFNode *cells;
4851: $ PetscInt nFound;
4852: $ const PetscSFNode *found;
4853: $
4854: $ PetscSFGetGraph(cells,NULL,&nFound,&found,&cells);
4856: Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is
4857: the index of the cell in its rank's local numbering.
4859: .keywords: point location, mesh
4860: .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType
4861: @*/
4862: PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF)
4863: {
4870: if (*cellSF) {
4871: PetscMPIInt result;
4874: MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);
4875: if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's");
4876: } else {
4877: PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);
4878: }
4879: PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);
4880: if (dm->ops->locatepoints) {
4881: (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);
4882: } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM");
4883: PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);
4884: return(0);
4885: }
4887: /*@
4888: DMGetOutputDM - Retrieve the DM associated with the layout for output
4890: Input Parameter:
4891: . dm - The original DM
4893: Output Parameter:
4894: . odm - The DM which provides the layout for output
4896: Level: intermediate
4898: .seealso: VecView(), DMGetDefaultGlobalSection()
4899: @*/
4900: PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
4901: {
4902: PetscSection section;
4903: PetscBool hasConstraints, ghasConstraints;
4909: DMGetDefaultSection(dm, §ion);
4910: PetscSectionHasConstraints(section, &hasConstraints);
4911: MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));
4912: if (!ghasConstraints) {
4913: *odm = dm;
4914: return(0);
4915: }
4916: if (!dm->dmBC) {
4917: PetscDS ds;
4918: PetscSection newSection, gsection;
4919: PetscSF sf;
4921: DMClone(dm, &dm->dmBC);
4922: DMGetDS(dm, &ds);
4923: DMSetDS(dm->dmBC, ds);
4924: PetscSectionClone(section, &newSection);
4925: DMSetDefaultSection(dm->dmBC, newSection);
4926: PetscSectionDestroy(&newSection);
4927: DMGetPointSF(dm->dmBC, &sf);
4928: PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);
4929: DMSetDefaultGlobalSection(dm->dmBC, gsection);
4930: PetscSectionDestroy(&gsection);
4931: }
4932: *odm = dm->dmBC;
4933: return(0);
4934: }
4936: /*@
4937: DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
4939: Input Parameter:
4940: . dm - The original DM
4942: Output Parameters:
4943: + num - The output sequence number
4944: - val - The output sequence value
4946: Level: intermediate
4948: Note: This is intended for output that should appear in sequence, for instance
4949: a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4951: .seealso: VecView()
4952: @*/
4953: PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
4954: {
4959: return(0);
4960: }
4962: /*@
4963: DMSetOutputSequenceNumber - Set the sequence number/value for output
4965: Input Parameters:
4966: + dm - The original DM
4967: . num - The output sequence number
4968: - val - The output sequence value
4970: Level: intermediate
4972: Note: This is intended for output that should appear in sequence, for instance
4973: a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4975: .seealso: VecView()
4976: @*/
4977: PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
4978: {
4981: dm->outputSequenceNum = num;
4982: dm->outputSequenceVal = val;
4983: return(0);
4984: }
4986: /*@C
4987: DMOutputSequenceLoad - Retrieve the sequence value from a Viewer
4989: Input Parameters:
4990: + dm - The original DM
4991: . name - The sequence name
4992: - num - The output sequence number
4994: Output Parameter:
4995: . val - The output sequence value
4997: Level: intermediate
4999: Note: This is intended for output that should appear in sequence, for instance
5000: a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
5002: .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView()
5003: @*/
5004: PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
5005: {
5006: PetscBool ishdf5;
5013: PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);
5014: if (ishdf5) {
5015: #if defined(PETSC_HAVE_HDF5)
5016: PetscScalar value;
5018: DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);
5019: *val = PetscRealPart(value);
5020: #endif
5021: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
5022: return(0);
5023: }
5025: /*@
5026: DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution
5028: Not collective
5030: Input Parameter:
5031: . dm - The DM
5033: Output Parameter:
5034: . useNatural - The flag to build the mapping to a natural order during distribution
5036: Level: beginner
5038: .seealso: DMSetUseNatural(), DMCreate()
5039: @*/
5040: PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
5041: {
5045: *useNatural = dm->useNatural;
5046: return(0);
5047: }
5049: /*@
5050: DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution
5052: Collective on dm
5054: Input Parameters:
5055: + dm - The DM
5056: - useNatural - The flag to build the mapping to a natural order during distribution
5058: Level: beginner
5060: .seealso: DMGetUseNatural(), DMCreate()
5061: @*/
5062: PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
5063: {
5067: dm->useNatural = useNatural;
5068: return(0);
5069: }
5072: /*@C
5073: DMCreateLabel - Create a label of the given name if it does not already exist
5075: Not Collective
5077: Input Parameters:
5078: + dm - The DM object
5079: - name - The label name
5081: Level: intermediate
5083: .keywords: mesh
5084: .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5085: @*/
5086: PetscErrorCode DMCreateLabel(DM dm, const char name[])
5087: {
5088: DMLabelLink next = dm->labels->next;
5089: PetscBool flg = PETSC_FALSE;
5095: while (next) {
5096: PetscStrcmp(name, next->label->name, &flg);
5097: if (flg) break;
5098: next = next->next;
5099: }
5100: if (!flg) {
5101: DMLabelLink tmpLabel;
5103: PetscCalloc1(1, &tmpLabel);
5104: DMLabelCreate(name, &tmpLabel->label);
5105: tmpLabel->output = PETSC_TRUE;
5106: tmpLabel->next = dm->labels->next;
5107: dm->labels->next = tmpLabel;
5108: }
5109: return(0);
5110: }
5112: /*@C
5113: DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default
5115: Not Collective
5117: Input Parameters:
5118: + dm - The DM object
5119: . name - The label name
5120: - point - The mesh point
5122: Output Parameter:
5123: . value - The label value for this point, or -1 if the point is not in the label
5125: Level: beginner
5127: .keywords: mesh
5128: .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS()
5129: @*/
5130: PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
5131: {
5132: DMLabel label;
5138: DMGetLabel(dm, name, &label);
5139: if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
5140: DMLabelGetValue(label, point, value);
5141: return(0);
5142: }
5144: /*@C
5145: DMSetLabelValue - Add a point to a Sieve Label with given value
5147: Not Collective
5149: Input Parameters:
5150: + dm - The DM object
5151: . name - The label name
5152: . point - The mesh point
5153: - value - The label value for this point
5155: Output Parameter:
5157: Level: beginner
5159: .keywords: mesh
5160: .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue()
5161: @*/
5162: PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
5163: {
5164: DMLabel label;
5170: DMGetLabel(dm, name, &label);
5171: if (!label) {
5172: DMCreateLabel(dm, name);
5173: DMGetLabel(dm, name, &label);
5174: }
5175: DMLabelSetValue(label, point, value);
5176: return(0);
5177: }
5179: /*@C
5180: DMClearLabelValue - Remove a point from a Sieve Label with given value
5182: Not Collective
5184: Input Parameters:
5185: + dm - The DM object
5186: . name - The label name
5187: . point - The mesh point
5188: - value - The label value for this point
5190: Output Parameter:
5192: Level: beginner
5194: .keywords: mesh
5195: .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS()
5196: @*/
5197: PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
5198: {
5199: DMLabel label;
5205: DMGetLabel(dm, name, &label);
5206: if (!label) return(0);
5207: DMLabelClearValue(label, point, value);
5208: return(0);
5209: }
5211: /*@C
5212: DMGetLabelSize - Get the number of different integer ids in a Label
5214: Not Collective
5216: Input Parameters:
5217: + dm - The DM object
5218: - name - The label name
5220: Output Parameter:
5221: . size - The number of different integer ids, or 0 if the label does not exist
5223: Level: beginner
5225: .keywords: mesh
5226: .seealso: DMLabeGetNumValues(), DMSetLabelValue()
5227: @*/
5228: PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
5229: {
5230: DMLabel label;
5237: DMGetLabel(dm, name, &label);
5238: *size = 0;
5239: if (!label) return(0);
5240: DMLabelGetNumValues(label, size);
5241: return(0);
5242: }
5244: /*@C
5245: DMGetLabelIdIS - Get the integer ids in a label
5247: Not Collective
5249: Input Parameters:
5250: + mesh - The DM object
5251: - name - The label name
5253: Output Parameter:
5254: . ids - The integer ids, or NULL if the label does not exist
5256: Level: beginner
5258: .keywords: mesh
5259: .seealso: DMLabelGetValueIS(), DMGetLabelSize()
5260: @*/
5261: PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
5262: {
5263: DMLabel label;
5270: DMGetLabel(dm, name, &label);
5271: *ids = NULL;
5272: if (!label) return(0);
5273: DMLabelGetValueIS(label, ids);
5274: return(0);
5275: }
5277: /*@C
5278: DMGetStratumSize - Get the number of points in a label stratum
5280: Not Collective
5282: Input Parameters:
5283: + dm - The DM object
5284: . name - The label name
5285: - value - The stratum value
5287: Output Parameter:
5288: . size - The stratum size
5290: Level: beginner
5292: .keywords: mesh
5293: .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds()
5294: @*/
5295: PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
5296: {
5297: DMLabel label;
5304: DMGetLabel(dm, name, &label);
5305: *size = 0;
5306: if (!label) return(0);
5307: DMLabelGetStratumSize(label, value, size);
5308: return(0);
5309: }
5311: /*@C
5312: DMGetStratumIS - Get the points in a label stratum
5314: Not Collective
5316: Input Parameters:
5317: + dm - The DM object
5318: . name - The label name
5319: - value - The stratum value
5321: Output Parameter:
5322: . points - The stratum points, or NULL if the label does not exist or does not have that value
5324: Level: beginner
5326: .keywords: mesh
5327: .seealso: DMLabelGetStratumIS(), DMGetStratumSize()
5328: @*/
5329: PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
5330: {
5331: DMLabel label;
5338: DMGetLabel(dm, name, &label);
5339: *points = NULL;
5340: if (!label) return(0);
5341: DMLabelGetStratumIS(label, value, points);
5342: return(0);
5343: }
5345: /*@C
5346: DMGetStratumIS - Set the points in a label stratum
5348: Not Collective
5350: Input Parameters:
5351: + dm - The DM object
5352: . name - The label name
5353: . value - The stratum value
5354: - points - The stratum points
5356: Level: beginner
5358: .keywords: mesh
5359: .seealso: DMLabelSetStratumIS(), DMGetStratumSize()
5360: @*/
5361: PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points)
5362: {
5363: DMLabel label;
5370: DMGetLabel(dm, name, &label);
5371: if (!label) return(0);
5372: DMLabelSetStratumIS(label, value, points);
5373: return(0);
5374: }
5376: /*@C
5377: DMClearLabelStratum - Remove all points from a stratum from a Sieve Label
5379: Not Collective
5381: Input Parameters:
5382: + dm - The DM object
5383: . name - The label name
5384: - value - The label value for this point
5386: Output Parameter:
5388: Level: beginner
5390: .keywords: mesh
5391: .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue()
5392: @*/
5393: PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
5394: {
5395: DMLabel label;
5401: DMGetLabel(dm, name, &label);
5402: if (!label) return(0);
5403: DMLabelClearStratum(label, value);
5404: return(0);
5405: }
5407: /*@
5408: DMGetNumLabels - Return the number of labels defined by the mesh
5410: Not Collective
5412: Input Parameter:
5413: . dm - The DM object
5415: Output Parameter:
5416: . numLabels - the number of Labels
5418: Level: intermediate
5420: .keywords: mesh
5421: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5422: @*/
5423: PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
5424: {
5425: DMLabelLink next = dm->labels->next;
5426: PetscInt n = 0;
5431: while (next) {++n; next = next->next;}
5432: *numLabels = n;
5433: return(0);
5434: }
5436: /*@C
5437: DMGetLabelName - Return the name of nth label
5439: Not Collective
5441: Input Parameters:
5442: + dm - The DM object
5443: - n - the label number
5445: Output Parameter:
5446: . name - the label name
5448: Level: intermediate
5450: .keywords: mesh
5451: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5452: @*/
5453: PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name)
5454: {
5455: DMLabelLink next = dm->labels->next;
5456: PetscInt l = 0;
5461: while (next) {
5462: if (l == n) {
5463: *name = next->label->name;
5464: return(0);
5465: }
5466: ++l;
5467: next = next->next;
5468: }
5469: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
5470: }
5472: /*@C
5473: DMHasLabel - Determine whether the mesh has a label of a given name
5475: Not Collective
5477: Input Parameters:
5478: + dm - The DM object
5479: - name - The label name
5481: Output Parameter:
5482: . hasLabel - PETSC_TRUE if the label is present
5484: Level: intermediate
5486: .keywords: mesh
5487: .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5488: @*/
5489: PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
5490: {
5491: DMLabelLink next = dm->labels->next;
5498: *hasLabel = PETSC_FALSE;
5499: while (next) {
5500: PetscStrcmp(name, next->label->name, hasLabel);
5501: if (*hasLabel) break;
5502: next = next->next;
5503: }
5504: return(0);
5505: }
5507: /*@C
5508: DMGetLabel - Return the label of a given name, or NULL
5510: Not Collective
5512: Input Parameters:
5513: + dm - The DM object
5514: - name - The label name
5516: Output Parameter:
5517: . label - The DMLabel, or NULL if the label is absent
5519: Level: intermediate
5521: .keywords: mesh
5522: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5523: @*/
5524: PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
5525: {
5526: DMLabelLink next = dm->labels->next;
5527: PetscBool hasLabel;
5534: *label = NULL;
5535: while (next) {
5536: PetscStrcmp(name, next->label->name, &hasLabel);
5537: if (hasLabel) {
5538: *label = next->label;
5539: break;
5540: }
5541: next = next->next;
5542: }
5543: return(0);
5544: }
5546: /*@C
5547: DMGetLabelByNum - Return the nth label
5549: Not Collective
5551: Input Parameters:
5552: + dm - The DM object
5553: - n - the label number
5555: Output Parameter:
5556: . label - the label
5558: Level: intermediate
5560: .keywords: mesh
5561: .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5562: @*/
5563: PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
5564: {
5565: DMLabelLink next = dm->labels->next;
5566: PetscInt l = 0;
5571: while (next) {
5572: if (l == n) {
5573: *label = next->label;
5574: return(0);
5575: }
5576: ++l;
5577: next = next->next;
5578: }
5579: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n);
5580: }
5582: /*@C
5583: DMAddLabel - Add the label to this mesh
5585: Not Collective
5587: Input Parameters:
5588: + dm - The DM object
5589: - label - The DMLabel
5591: Level: developer
5593: .keywords: mesh
5594: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5595: @*/
5596: PetscErrorCode DMAddLabel(DM dm, DMLabel label)
5597: {
5598: DMLabelLink tmpLabel;
5599: PetscBool hasLabel;
5604: DMHasLabel(dm, label->name, &hasLabel);
5605: if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name);
5606: PetscCalloc1(1, &tmpLabel);
5607: tmpLabel->label = label;
5608: tmpLabel->output = PETSC_TRUE;
5609: tmpLabel->next = dm->labels->next;
5610: dm->labels->next = tmpLabel;
5611: return(0);
5612: }
5614: /*@C
5615: DMRemoveLabel - Remove the label from this mesh
5617: Not Collective
5619: Input Parameters:
5620: + dm - The DM object
5621: - name - The label name
5623: Output Parameter:
5624: . label - The DMLabel, or NULL if the label is absent
5626: Level: developer
5628: .keywords: mesh
5629: .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5630: @*/
5631: PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
5632: {
5633: DMLabelLink next = dm->labels->next;
5634: DMLabelLink last = NULL;
5635: PetscBool hasLabel;
5640: DMHasLabel(dm, name, &hasLabel);
5641: *label = NULL;
5642: if (!hasLabel) return(0);
5643: while (next) {
5644: PetscStrcmp(name, next->label->name, &hasLabel);
5645: if (hasLabel) {
5646: if (last) last->next = next->next;
5647: else dm->labels->next = next->next;
5648: next->next = NULL;
5649: *label = next->label;
5650: PetscStrcmp(name, "depth", &hasLabel);
5651: if (hasLabel) {
5652: dm->depthLabel = NULL;
5653: }
5654: PetscFree(next);
5655: break;
5656: }
5657: last = next;
5658: next = next->next;
5659: }
5660: return(0);
5661: }
5663: /*@C
5664: DMGetLabelOutput - Get the output flag for a given label
5666: Not Collective
5668: Input Parameters:
5669: + dm - The DM object
5670: - name - The label name
5672: Output Parameter:
5673: . output - The flag for output
5675: Level: developer
5677: .keywords: mesh
5678: .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5679: @*/
5680: PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output)
5681: {
5682: DMLabelLink next = dm->labels->next;
5689: while (next) {
5690: PetscBool flg;
5692: PetscStrcmp(name, next->label->name, &flg);
5693: if (flg) {*output = next->output; return(0);}
5694: next = next->next;
5695: }
5696: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
5697: }
5699: /*@C
5700: DMSetLabelOutput - Set the output flag for a given label
5702: Not Collective
5704: Input Parameters:
5705: + dm - The DM object
5706: . name - The label name
5707: - output - The flag for output
5709: Level: developer
5711: .keywords: mesh
5712: .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS()
5713: @*/
5714: PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
5715: {
5716: DMLabelLink next = dm->labels->next;
5722: while (next) {
5723: PetscBool flg;
5725: PetscStrcmp(name, next->label->name, &flg);
5726: if (flg) {next->output = output; return(0);}
5727: next = next->next;
5728: }
5729: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
5730: }
5733: /*@
5734: DMCopyLabels - Copy labels from one mesh to another with a superset of the points
5736: Collective on DM
5738: Input Parameter:
5739: . dmA - The DM object with initial labels
5741: Output Parameter:
5742: . dmB - The DM object with copied labels
5744: Level: intermediate
5746: Note: This is typically used when interpolating or otherwise adding to a mesh
5748: .keywords: mesh
5749: .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection()
5750: @*/
5751: PetscErrorCode DMCopyLabels(DM dmA, DM dmB)
5752: {
5753: PetscInt numLabels, l;
5757: if (dmA == dmB) return(0);
5758: DMGetNumLabels(dmA, &numLabels);
5759: for (l = 0; l < numLabels; ++l) {
5760: DMLabel label, labelNew;
5761: const char *name;
5762: PetscBool flg;
5764: DMGetLabelName(dmA, l, &name);
5765: PetscStrcmp(name, "depth", &flg);
5766: if (flg) continue;
5767: DMGetLabel(dmA, name, &label);
5768: DMLabelDuplicate(label, &labelNew);
5769: DMAddLabel(dmB, labelNew);
5770: }
5771: return(0);
5772: }
5774: /*@
5775: DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement
5777: Input Parameter:
5778: . dm - The DM object
5780: Output Parameter:
5781: . cdm - The coarse DM
5783: Level: intermediate
5785: .seealso: DMSetCoarseDM()
5786: @*/
5787: PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
5788: {
5792: *cdm = dm->coarseMesh;
5793: return(0);
5794: }
5796: /*@
5797: DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement
5799: Input Parameters:
5800: + dm - The DM object
5801: - cdm - The coarse DM
5803: Level: intermediate
5805: .seealso: DMGetCoarseDM()
5806: @*/
5807: PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
5808: {
5814: PetscObjectReference((PetscObject)cdm);
5815: DMDestroy(&dm->coarseMesh);
5816: dm->coarseMesh = cdm;
5817: return(0);
5818: }
5820: /*@
5821: DMGetFineDM - Get the fine mesh from which this was obtained by refinement
5823: Input Parameter:
5824: . dm - The DM object
5826: Output Parameter:
5827: . fdm - The fine DM
5829: Level: intermediate
5831: .seealso: DMSetFineDM()
5832: @*/
5833: PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
5834: {
5838: *fdm = dm->fineMesh;
5839: return(0);
5840: }
5842: /*@
5843: DMSetFineDM - Set the fine mesh from which this was obtained by refinement
5845: Input Parameters:
5846: + dm - The DM object
5847: - fdm - The fine DM
5849: Level: intermediate
5851: .seealso: DMGetFineDM()
5852: @*/
5853: PetscErrorCode DMSetFineDM(DM dm, DM fdm)
5854: {
5860: PetscObjectReference((PetscObject)fdm);
5861: DMDestroy(&dm->fineMesh);
5862: dm->fineMesh = fdm;
5863: return(0);
5864: }
5866: /*=== DMBoundary code ===*/
5868: PetscErrorCode DMCopyBoundary(DM dm, DM dmNew)
5869: {
5873: PetscDSCopyBoundary(dm->prob,dmNew->prob);
5874: return(0);
5875: }
5877: /*@C
5878: DMAddBoundary - Add a boundary condition to the model
5880: Input Parameters:
5881: + dm - The DM, with a PetscDS that matches the problem being constrained
5882: . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
5883: . name - The BC name
5884: . labelname - The label defining constrained points
5885: . field - The field to constrain
5886: . numcomps - The number of constrained field components
5887: . comps - An array of constrained component numbers
5888: . bcFunc - A pointwise function giving boundary values
5889: . numids - The number of DMLabel ids for constrained points
5890: . ids - An array of ids for constrained points
5891: - ctx - An optional user context for bcFunc
5893: Options Database Keys:
5894: + -bc_<boundary name> <num> - Overrides the boundary ids
5895: - -bc_<boundary name>_comp <num> - Overrides the boundary components
5897: Level: developer
5899: .seealso: DMGetBoundary()
5900: @*/
5901: PetscErrorCode DMAddBoundary(DM dm, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), PetscInt numids, const PetscInt *ids, void *ctx)
5902: {
5907: PetscDSAddBoundary(dm->prob,type,name,labelname,field,numcomps,comps,bcFunc,numids,ids,ctx);
5908: return(0);
5909: }
5911: /*@
5912: DMGetNumBoundary - Get the number of registered BC
5914: Input Parameters:
5915: . dm - The mesh object
5917: Output Parameters:
5918: . numBd - The number of BC
5920: Level: intermediate
5922: .seealso: DMAddBoundary(), DMGetBoundary()
5923: @*/
5924: PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd)
5925: {
5930: PetscDSGetNumBoundary(dm->prob,numBd);
5931: return(0);
5932: }
5934: /*@C
5935: DMGetBoundary - Get a model boundary condition
5937: Input Parameters:
5938: + dm - The mesh object
5939: - bd - The BC number
5941: Output Parameters:
5942: + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
5943: . name - The BC name
5944: . labelname - The label defining constrained points
5945: . field - The field to constrain
5946: . numcomps - The number of constrained field components
5947: . comps - An array of constrained component numbers
5948: . bcFunc - A pointwise function giving boundary values
5949: . numids - The number of DMLabel ids for constrained points
5950: . ids - An array of ids for constrained points
5951: - ctx - An optional user context for bcFunc
5953: Options Database Keys:
5954: + -bc_<boundary name> <num> - Overrides the boundary ids
5955: - -bc_<boundary name>_comp <num> - Overrides the boundary components
5957: Level: developer
5959: .seealso: DMAddBoundary()
5960: @*/
5961: PetscErrorCode DMGetBoundary(DM dm, PetscInt bd, DMBoundaryConditionType *type, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(void), PetscInt *numids, const PetscInt **ids, void **ctx)
5962: {
5967: PetscDSGetBoundary(dm->prob,bd,type,name,labelname,field,numcomps,comps,func,numids,ids,ctx);
5968: return(0);
5969: }
5971: static PetscErrorCode DMPopulateBoundary(DM dm)
5972: {
5973: DMBoundary *lastnext;
5974: DSBoundary dsbound;
5978: dsbound = dm->prob->boundary;
5979: if (dm->boundary) {
5980: DMBoundary next = dm->boundary;
5982: /* quick check to see if the PetscDS has changed */
5983: if (next->dsboundary == dsbound) return(0);
5984: /* the PetscDS has changed: tear down and rebuild */
5985: while (next) {
5986: DMBoundary b = next;
5988: next = b->next;
5989: PetscFree(b);
5990: }
5991: dm->boundary = NULL;
5992: }
5994: lastnext = &(dm->boundary);
5995: while (dsbound) {
5996: DMBoundary dmbound;
5998: PetscNew(&dmbound);
5999: dmbound->dsboundary = dsbound;
6000: DMGetLabel(dm, dsbound->labelname, &(dmbound->label));
6001: if (!dmbound->label) PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);
6002: /* push on the back instead of the front so that it is in the same order as in the PetscDS */
6003: *lastnext = dmbound;
6004: lastnext = &(dmbound->next);
6005: dsbound = dsbound->next;
6006: }
6007: return(0);
6008: }
6010: PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
6011: {
6012: DMBoundary b;
6018: *isBd = PETSC_FALSE;
6019: DMPopulateBoundary(dm);
6020: b = dm->boundary;
6021: while (b && !(*isBd)) {
6022: DMLabel label = b->label;
6023: DSBoundary dsb = b->dsboundary;
6025: if (label) {
6026: PetscInt i;
6028: for (i = 0; i < dsb->numids && !(*isBd); ++i) {
6029: DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);
6030: }
6031: }
6032: b = b->next;
6033: }
6034: return(0);
6035: }
6037: /*@C
6038: DMProjectFunction - This projects the given function into the function space provided.
6040: Input Parameters:
6041: + dm - The DM
6042: . time - The time
6043: . funcs - The coordinate functions to evaluate, one per field
6044: . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null.
6045: - mode - The insertion mode for values
6047: Output Parameter:
6048: . X - vector
6050: Calling sequence of func:
6051: $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx);
6053: + dim - The spatial dimension
6054: . x - The coordinates
6055: . Nf - The number of fields
6056: . u - The output field values
6057: - ctx - optional user-defined function context
6059: Level: developer
6061: .seealso: DMComputeL2Diff()
6062: @*/
6063: PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
6064: {
6065: Vec localX;
6070: DMGetLocalVector(dm, &localX);
6071: DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);
6072: DMLocalToGlobalBegin(dm, localX, mode, X);
6073: DMLocalToGlobalEnd(dm, localX, mode, X);
6074: DMRestoreLocalVector(dm, &localX);
6075: return(0);
6076: }
6078: PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
6079: {
6085: if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLocal",((PetscObject)dm)->type_name);
6086: (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);
6087: return(0);
6088: }
6090: 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)
6091: {
6097: if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name);
6098: (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);
6099: return(0);
6100: }
6102: PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU,
6103: void (**funcs)(PetscInt, PetscInt, PetscInt,
6104: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6105: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6106: PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
6107: InsertMode mode, Vec localX)
6108: {
6115: if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFieldLocal",((PetscObject)dm)->type_name);
6116: (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);
6117: return(0);
6118: }
6120: PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU,
6121: void (**funcs)(PetscInt, PetscInt, PetscInt,
6122: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6123: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
6124: PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
6125: InsertMode mode, Vec localX)
6126: {
6133: if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFieldLocal",((PetscObject)dm)->type_name);
6134: (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);
6135: return(0);
6136: }
6138: /*@C
6139: DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
6141: Input Parameters:
6142: + dm - The DM
6143: . time - The time
6144: . funcs - The functions to evaluate for each field component
6145: . ctxs - Optional array of contexts to pass to each function, or NULL.
6146: - X - The coefficient vector u_h
6148: Output Parameter:
6149: . diff - The diff ||u - u_h||_2
6151: Level: developer
6153: .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
6154: @*/
6155: PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
6156: {
6162: if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2Diff",((PetscObject)dm)->type_name);
6163: (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);
6164: return(0);
6165: }
6167: /*@C
6168: DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
6170: Input Parameters:
6171: + dm - The DM
6172: , time - The time
6173: . funcs - The gradient functions to evaluate for each field component
6174: . ctxs - Optional array of contexts to pass to each function, or NULL.
6175: . X - The coefficient vector u_h
6176: - n - The vector to project along
6178: Output Parameter:
6179: . diff - The diff ||(grad u - grad u_h) . n||_2
6181: Level: developer
6183: .seealso: DMProjectFunction(), DMComputeL2Diff()
6184: @*/
6185: 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)
6186: {
6192: if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name);
6193: (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);
6194: return(0);
6195: }
6197: /*@C
6198: DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.
6200: Input Parameters:
6201: + dm - The DM
6202: . time - The time
6203: . funcs - The functions to evaluate for each field component
6204: . ctxs - Optional array of contexts to pass to each function, or NULL.
6205: - X - The coefficient vector u_h
6207: Output Parameter:
6208: . diff - The array of differences, ||u^f - u^f_h||_2
6210: Level: developer
6212: .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff()
6213: @*/
6214: PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
6215: {
6221: if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2FieldDiff",((PetscObject)dm)->type_name);
6222: (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);
6223: return(0);
6224: }
6226: /*@C
6227: DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have
6228: specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN.
6230: Collective on dm
6232: Input parameters:
6233: + dm - the pre-adaptation DM object
6234: - label - label with the flags
6236: Output parameters:
6237: . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced.
6239: Level: intermediate
6241: .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine()
6242: @*/
6243: PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt)
6244: {
6251: *dmAdapt = NULL;
6252: if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name);
6253: (dm->ops->adaptlabel)(dm, label, dmAdapt);
6254: return(0);
6255: }
6257: /*@C
6258: DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library.
6260: Input Parameters:
6261: + dm - The DM object
6262: . metric - The metric to which the mesh is adapted, defined vertex-wise.
6263: - 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_".
6265: Output Parameter:
6266: . dmAdapt - Pointer to the DM object containing the adapted mesh
6268: Note: The label in the adapted mesh will be registered under the name of the input DMLabel object
6270: Level: advanced
6272: .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine()
6273: @*/
6274: PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt)
6275: {
6283: *dmAdapt = NULL;
6284: if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name);
6285: (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);
6286: return(0);
6287: }
6289: /*@C
6290: DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors
6292: Not Collective
6294: Input Parameter:
6295: . dm - The DM
6297: Output Parameter:
6298: . nranks - the number of neighbours
6299: . ranks - the neighbors ranks
6301: Notes:
6302: Do not free the array, it is freed when the DM is destroyed.
6304: Level: beginner
6306: .seealso: DMDAGetNeighbors(), PetscSFGetRanks()
6307: @*/
6308: PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[])
6309: {
6314: if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMGetNeighbors",((PetscObject)dm)->type_name);
6315: (dm->ops->getneighbors)(dm,nranks,ranks);
6316: return(0);
6317: }
6319: #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */
6321: /*
6322: Converts the input vector to a ghosted vector and then calls the standard coloring code.
6323: This has be a different function because it requires DM which is not defined in the Mat library
6324: */
6325: PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx)
6326: {
6330: if (coloring->ctype == IS_COLORING_LOCAL) {
6331: Vec x1local;
6332: DM dm;
6333: MatGetDM(J,&dm);
6334: if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM");
6335: DMGetLocalVector(dm,&x1local);
6336: DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);
6337: DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);
6338: x1 = x1local;
6339: }
6340: MatFDColoringApply_AIJ(J,coloring,x1,sctx);
6341: if (coloring->ctype == IS_COLORING_LOCAL) {
6342: DM dm;
6343: MatGetDM(J,&dm);
6344: DMRestoreLocalVector(dm,&x1);
6345: }
6346: return(0);
6347: }
6349: /*@
6350: MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring
6352: Input Parameter:
6353: . coloring - the MatFDColoring object
6355: Developer Notes: this routine exists because the PETSc Mat library does not know about the DM objects
6357: Level: advanced
6359: .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType
6360: @*/
6361: PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring)
6362: {
6364: coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM;
6365: return(0);
6366: }