xref: /petsc/src/dm/impls/plex/plexgenerate.c (revision 2ca110d9ff3e1e60e87ab3c8f99929f34cd247e6)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2d9deefdfSMatthew G. Knepley 
3d9deefdfSMatthew G. Knepley #undef __FUNCT__
4d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMPlexInvertCell_Internal"
5d9deefdfSMatthew G. Knepley PetscErrorCode DMPlexInvertCell_Internal(PetscInt dim, PetscInt numCorners, PetscInt cone[])
6d9deefdfSMatthew G. Knepley {
7d9deefdfSMatthew G. Knepley   int tmpc;
8d9deefdfSMatthew G. Knepley 
9d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
10d9deefdfSMatthew G. Knepley   if (dim != 3) PetscFunctionReturn(0);
11d9deefdfSMatthew G. Knepley   switch (numCorners) {
12d9deefdfSMatthew G. Knepley   case 4:
13d9deefdfSMatthew G. Knepley     tmpc    = cone[0];
14d9deefdfSMatthew G. Knepley     cone[0] = cone[1];
15d9deefdfSMatthew G. Knepley     cone[1] = tmpc;
16d9deefdfSMatthew G. Knepley     break;
17d9deefdfSMatthew G. Knepley   case 8:
18d9deefdfSMatthew G. Knepley     tmpc    = cone[1];
19d9deefdfSMatthew G. Knepley     cone[1] = cone[3];
20d9deefdfSMatthew G. Knepley     cone[3] = tmpc;
21d9deefdfSMatthew G. Knepley     break;
22d9deefdfSMatthew G. Knepley   default: break;
23d9deefdfSMatthew G. Knepley   }
24d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
25d9deefdfSMatthew G. Knepley }
26d9deefdfSMatthew G. Knepley 
27d9deefdfSMatthew G. Knepley #undef __FUNCT__
28d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMPlexInvertCell"
29d9deefdfSMatthew G. Knepley /*@C
30d9deefdfSMatthew G. Knepley   DMPlexInvertCell - This flips tetrahedron and hexahedron orientation since Plex stores them internally with outward normals. Other cells are left untouched.
31d9deefdfSMatthew G. Knepley 
32d9deefdfSMatthew G. Knepley   Input Parameters:
33d9deefdfSMatthew G. Knepley + numCorners - The number of vertices in a cell
34d9deefdfSMatthew G. Knepley - cone - The incoming cone
35d9deefdfSMatthew G. Knepley 
36d9deefdfSMatthew G. Knepley   Output Parameter:
37d9deefdfSMatthew G. Knepley . cone - The inverted cone (in-place)
38d9deefdfSMatthew G. Knepley 
39d9deefdfSMatthew G. Knepley   Level: developer
40d9deefdfSMatthew G. Knepley 
41d9deefdfSMatthew G. Knepley .seealso: DMPlexGenerate()
42d9deefdfSMatthew G. Knepley @*/
43d9deefdfSMatthew G. Knepley PetscErrorCode DMPlexInvertCell(PetscInt dim, PetscInt numCorners, int cone[])
44d9deefdfSMatthew G. Knepley {
45d9deefdfSMatthew G. Knepley   int tmpc;
46d9deefdfSMatthew G. Knepley 
47d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
48d9deefdfSMatthew G. Knepley   if (dim != 3) PetscFunctionReturn(0);
49d9deefdfSMatthew G. Knepley   switch (numCorners) {
50d9deefdfSMatthew G. Knepley   case 4:
51d9deefdfSMatthew G. Knepley     tmpc    = cone[0];
52d9deefdfSMatthew G. Knepley     cone[0] = cone[1];
53d9deefdfSMatthew G. Knepley     cone[1] = tmpc;
54d9deefdfSMatthew G. Knepley     break;
55d9deefdfSMatthew G. Knepley   case 8:
56d9deefdfSMatthew G. Knepley     tmpc    = cone[1];
57d9deefdfSMatthew G. Knepley     cone[1] = cone[3];
58d9deefdfSMatthew G. Knepley     cone[3] = tmpc;
59d9deefdfSMatthew G. Knepley     break;
60d9deefdfSMatthew G. Knepley   default: break;
61d9deefdfSMatthew G. Knepley   }
62d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
63d9deefdfSMatthew G. Knepley }
64d9deefdfSMatthew G. Knepley 
65d9deefdfSMatthew G. Knepley #undef __FUNCT__
66d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMPlexInvertCells_Internal"
67d9deefdfSMatthew G. Knepley /* This is to fix the tetrahedron orientation from TetGen */
68d9deefdfSMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexInvertCells_Internal(PetscInt dim, PetscInt numCells, PetscInt numCorners, int cells[])
69d9deefdfSMatthew G. Knepley {
70d9deefdfSMatthew G. Knepley   PetscInt       bound = numCells*numCorners, coff;
71d9deefdfSMatthew G. Knepley   PetscErrorCode ierr;
72d9deefdfSMatthew G. Knepley 
73d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
74d9deefdfSMatthew G. Knepley   for (coff = 0; coff < bound; coff += numCorners) {
75d9deefdfSMatthew G. Knepley     ierr = DMPlexInvertCell(dim, numCorners, &cells[coff]);CHKERRQ(ierr);
76d9deefdfSMatthew G. Knepley   }
77d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
78d9deefdfSMatthew G. Knepley }
79d9deefdfSMatthew G. Knepley 
80d9deefdfSMatthew G. Knepley #undef __FUNCT__
81d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMPlexTriangleSetOptions"
82d9deefdfSMatthew G. Knepley /*@
83d9deefdfSMatthew G. Knepley   DMPlexTriangleSetOptions - Set the options used for the Triangle mesh generator
84d9deefdfSMatthew G. Knepley 
85d9deefdfSMatthew G. Knepley   Not Collective
86d9deefdfSMatthew G. Knepley 
87d9deefdfSMatthew G. Knepley   Inputs Parameters:
88d9deefdfSMatthew G. Knepley + dm - The DMPlex object
89d9deefdfSMatthew G. Knepley - opts - The command line options
90d9deefdfSMatthew G. Knepley 
91d9deefdfSMatthew G. Knepley   Level: developer
92d9deefdfSMatthew G. Knepley 
93d9deefdfSMatthew G. Knepley .keywords: mesh, points
94d9deefdfSMatthew G. Knepley .seealso: DMPlexTetgenSetOptions(), DMPlexGenerate()
95d9deefdfSMatthew G. Knepley @*/
96d9deefdfSMatthew G. Knepley PetscErrorCode DMPlexTriangleSetOptions(DM dm, const char *opts)
97d9deefdfSMatthew G. Knepley {
98d9deefdfSMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
99d9deefdfSMatthew G. Knepley   PetscErrorCode ierr;
100d9deefdfSMatthew G. Knepley 
101d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
102d9deefdfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
103d9deefdfSMatthew G. Knepley   PetscValidPointer(opts, 2);
104606ac3a5SMatthew G. Knepley   ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr);
105606ac3a5SMatthew G. Knepley   ierr = PetscStrallocpy(opts, &mesh->triangleOpts);CHKERRQ(ierr);
106d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
107d9deefdfSMatthew G. Knepley }
108d9deefdfSMatthew G. Knepley 
109d9deefdfSMatthew G. Knepley #undef __FUNCT__
110d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMPlexTetgenSetOptions"
111d9deefdfSMatthew G. Knepley /*@
112d9deefdfSMatthew G. Knepley   DMPlexTetgenSetOptions - Set the options used for the Tetgen mesh generator
113d9deefdfSMatthew G. Knepley 
114d9deefdfSMatthew G. Knepley   Not Collective
115d9deefdfSMatthew G. Knepley 
116d9deefdfSMatthew G. Knepley   Inputs Parameters:
117d9deefdfSMatthew G. Knepley + dm - The DMPlex object
118d9deefdfSMatthew G. Knepley - opts - The command line options
119d9deefdfSMatthew G. Knepley 
120d9deefdfSMatthew G. Knepley   Level: developer
121d9deefdfSMatthew G. Knepley 
122d9deefdfSMatthew G. Knepley .keywords: mesh, points
123d9deefdfSMatthew G. Knepley .seealso: DMPlexTriangleSetOptions(), DMPlexGenerate()
124d9deefdfSMatthew G. Knepley @*/
125d9deefdfSMatthew G. Knepley PetscErrorCode DMPlexTetgenSetOptions(DM dm, const char *opts)
126d9deefdfSMatthew G. Knepley {
127d9deefdfSMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
128d9deefdfSMatthew G. Knepley   PetscErrorCode ierr;
129d9deefdfSMatthew G. Knepley 
130d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
131d9deefdfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
132d9deefdfSMatthew G. Knepley   PetscValidPointer(opts, 2);
133606ac3a5SMatthew G. Knepley   ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr);
134606ac3a5SMatthew G. Knepley   ierr = PetscStrallocpy(opts, &mesh->tetgenOpts);CHKERRQ(ierr);
135d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
136d9deefdfSMatthew G. Knepley }
137d9deefdfSMatthew G. Knepley 
138d9deefdfSMatthew G. Knepley #if defined(PETSC_HAVE_TRIANGLE)
139d9deefdfSMatthew G. Knepley #include <triangle.h>
140d9deefdfSMatthew G. Knepley 
141d9deefdfSMatthew G. Knepley #undef __FUNCT__
142d9deefdfSMatthew G. Knepley #define __FUNCT__ "InitInput_Triangle"
143d9deefdfSMatthew G. Knepley PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx)
144d9deefdfSMatthew G. Knepley {
145d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
146d9deefdfSMatthew G. Knepley   inputCtx->numberofpoints             = 0;
147d9deefdfSMatthew G. Knepley   inputCtx->numberofpointattributes    = 0;
148d9deefdfSMatthew G. Knepley   inputCtx->pointlist                  = NULL;
149d9deefdfSMatthew G. Knepley   inputCtx->pointattributelist         = NULL;
150d9deefdfSMatthew G. Knepley   inputCtx->pointmarkerlist            = NULL;
151d9deefdfSMatthew G. Knepley   inputCtx->numberofsegments           = 0;
152d9deefdfSMatthew G. Knepley   inputCtx->segmentlist                = NULL;
153d9deefdfSMatthew G. Knepley   inputCtx->segmentmarkerlist          = NULL;
154d9deefdfSMatthew G. Knepley   inputCtx->numberoftriangleattributes = 0;
155d9deefdfSMatthew G. Knepley   inputCtx->trianglelist               = NULL;
156d9deefdfSMatthew G. Knepley   inputCtx->numberofholes              = 0;
157d9deefdfSMatthew G. Knepley   inputCtx->holelist                   = NULL;
158d9deefdfSMatthew G. Knepley   inputCtx->numberofregions            = 0;
159d9deefdfSMatthew G. Knepley   inputCtx->regionlist                 = NULL;
160d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
161d9deefdfSMatthew G. Knepley }
162d9deefdfSMatthew G. Knepley 
163d9deefdfSMatthew G. Knepley #undef __FUNCT__
164d9deefdfSMatthew G. Knepley #define __FUNCT__ "InitOutput_Triangle"
165d9deefdfSMatthew G. Knepley PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx)
166d9deefdfSMatthew G. Knepley {
167d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
168d9deefdfSMatthew G. Knepley   outputCtx->numberofpoints        = 0;
169d9deefdfSMatthew G. Knepley   outputCtx->pointlist             = NULL;
170d9deefdfSMatthew G. Knepley   outputCtx->pointattributelist    = NULL;
171d9deefdfSMatthew G. Knepley   outputCtx->pointmarkerlist       = NULL;
172d9deefdfSMatthew G. Knepley   outputCtx->numberoftriangles     = 0;
173d9deefdfSMatthew G. Knepley   outputCtx->trianglelist          = NULL;
174d9deefdfSMatthew G. Knepley   outputCtx->triangleattributelist = NULL;
175d9deefdfSMatthew G. Knepley   outputCtx->neighborlist          = NULL;
176d9deefdfSMatthew G. Knepley   outputCtx->segmentlist           = NULL;
177d9deefdfSMatthew G. Knepley   outputCtx->segmentmarkerlist     = NULL;
178d9deefdfSMatthew G. Knepley   outputCtx->numberofedges         = 0;
179d9deefdfSMatthew G. Knepley   outputCtx->edgelist              = NULL;
180d9deefdfSMatthew G. Knepley   outputCtx->edgemarkerlist        = NULL;
181d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
182d9deefdfSMatthew G. Knepley }
183d9deefdfSMatthew G. Knepley 
184d9deefdfSMatthew G. Knepley #undef __FUNCT__
185d9deefdfSMatthew G. Knepley #define __FUNCT__ "FiniOutput_Triangle"
186d9deefdfSMatthew G. Knepley PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx)
187d9deefdfSMatthew G. Knepley {
188d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
189d9deefdfSMatthew G. Knepley   free(outputCtx->pointlist);
190d9deefdfSMatthew G. Knepley   free(outputCtx->pointmarkerlist);
191d9deefdfSMatthew G. Knepley   free(outputCtx->segmentlist);
192d9deefdfSMatthew G. Knepley   free(outputCtx->segmentmarkerlist);
193d9deefdfSMatthew G. Knepley   free(outputCtx->edgelist);
194d9deefdfSMatthew G. Knepley   free(outputCtx->edgemarkerlist);
195d9deefdfSMatthew G. Knepley   free(outputCtx->trianglelist);
196d9deefdfSMatthew G. Knepley   free(outputCtx->neighborlist);
197d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
198d9deefdfSMatthew G. Knepley }
199d9deefdfSMatthew G. Knepley 
200d9deefdfSMatthew G. Knepley #undef __FUNCT__
201d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMPlexGenerate_Triangle"
202d9deefdfSMatthew G. Knepley PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm)
203d9deefdfSMatthew G. Knepley {
204d9deefdfSMatthew G. Knepley   MPI_Comm             comm;
205d9deefdfSMatthew G. Knepley   DM_Plex             *mesh             = (DM_Plex *) boundary->data;
206d9deefdfSMatthew G. Knepley   PetscInt             dim              = 2;
207d9deefdfSMatthew G. Knepley   const PetscBool      createConvexHull = PETSC_FALSE;
208d9deefdfSMatthew G. Knepley   const PetscBool      constrained      = PETSC_FALSE;
209d988aadeSMatthew G. Knepley   const char          *labelName        = "marker";
210d9deefdfSMatthew G. Knepley   struct triangulateio in;
211d9deefdfSMatthew G. Knepley   struct triangulateio out;
212d988aadeSMatthew G. Knepley   DMLabel              label;
213d9deefdfSMatthew G. Knepley   PetscInt             vStart, vEnd, v, eStart, eEnd, e;
214d9deefdfSMatthew G. Knepley   PetscMPIInt          rank;
215d9deefdfSMatthew G. Knepley   PetscErrorCode       ierr;
216d9deefdfSMatthew G. Knepley 
217d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
218d9deefdfSMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr);
219d9deefdfSMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
220d9deefdfSMatthew G. Knepley   ierr = InitInput_Triangle(&in);CHKERRQ(ierr);
221d9deefdfSMatthew G. Knepley   ierr = InitOutput_Triangle(&out);CHKERRQ(ierr);
222d9deefdfSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr);
223c58f1c22SToby Isaac   ierr = DMGetLabel(boundary, labelName, &label);CHKERRQ(ierr);
224d9deefdfSMatthew G. Knepley 
225d9deefdfSMatthew G. Knepley   in.numberofpoints = vEnd - vStart;
226d9deefdfSMatthew G. Knepley   if (in.numberofpoints > 0) {
227d9deefdfSMatthew G. Knepley     PetscSection coordSection;
228d9deefdfSMatthew G. Knepley     Vec          coordinates;
229d9deefdfSMatthew G. Knepley     PetscScalar *array;
230d9deefdfSMatthew G. Knepley 
231d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in.numberofpoints*dim, &in.pointlist);CHKERRQ(ierr);
232d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in.numberofpoints, &in.pointmarkerlist);CHKERRQ(ierr);
233d9deefdfSMatthew G. Knepley     ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr);
234d9deefdfSMatthew G. Knepley     ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr);
235d9deefdfSMatthew G. Knepley     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
236d9deefdfSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
237d9deefdfSMatthew G. Knepley       const PetscInt idx = v - vStart;
238d9deefdfSMatthew G. Knepley       PetscInt       off, d;
239d9deefdfSMatthew G. Knepley 
240d9deefdfSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
241d9deefdfSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
242d9deefdfSMatthew G. Knepley         in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
243d9deefdfSMatthew G. Knepley       }
244d988aadeSMatthew G. Knepley       if (label) {ierr = DMLabelGetValue(label, v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);}
245d9deefdfSMatthew G. Knepley     }
246d9deefdfSMatthew G. Knepley     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
247d9deefdfSMatthew G. Knepley   }
248d9deefdfSMatthew G. Knepley   ierr  = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr);
249d9deefdfSMatthew G. Knepley   in.numberofsegments = eEnd - eStart;
250d9deefdfSMatthew G. Knepley   if (in.numberofsegments > 0) {
251d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in.numberofsegments*2, &in.segmentlist);CHKERRQ(ierr);
252d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in.numberofsegments, &in.segmentmarkerlist);CHKERRQ(ierr);
253d9deefdfSMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
254d9deefdfSMatthew G. Knepley       const PetscInt  idx = e - eStart;
255d9deefdfSMatthew G. Knepley       const PetscInt *cone;
256d9deefdfSMatthew G. Knepley 
257d9deefdfSMatthew G. Knepley       ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr);
258d9deefdfSMatthew G. Knepley 
259d9deefdfSMatthew G. Knepley       in.segmentlist[idx*2+0] = cone[0] - vStart;
260d9deefdfSMatthew G. Knepley       in.segmentlist[idx*2+1] = cone[1] - vStart;
261d9deefdfSMatthew G. Knepley 
262d988aadeSMatthew G. Knepley       if (label) {ierr = DMLabelGetValue(label, e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr);}
263d9deefdfSMatthew G. Knepley     }
264d9deefdfSMatthew G. Knepley   }
265d9deefdfSMatthew G. Knepley #if 0 /* Do not currently support holes */
266d9deefdfSMatthew G. Knepley   PetscReal *holeCoords;
267d9deefdfSMatthew G. Knepley   PetscInt   h, d;
268d9deefdfSMatthew G. Knepley 
269d9deefdfSMatthew G. Knepley   ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr);
270d9deefdfSMatthew G. Knepley   if (in.numberofholes > 0) {
271d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in.numberofholes*dim, &in.holelist);CHKERRQ(ierr);
272d9deefdfSMatthew G. Knepley     for (h = 0; h < in.numberofholes; ++h) {
273d9deefdfSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
274d9deefdfSMatthew G. Knepley         in.holelist[h*dim+d] = holeCoords[h*dim+d];
275d9deefdfSMatthew G. Knepley       }
276d9deefdfSMatthew G. Knepley     }
277d9deefdfSMatthew G. Knepley   }
278d9deefdfSMatthew G. Knepley #endif
279d9deefdfSMatthew G. Knepley   if (!rank) {
280d9deefdfSMatthew G. Knepley     char args[32];
281d9deefdfSMatthew G. Knepley 
282d9deefdfSMatthew G. Knepley     /* Take away 'Q' for verbose output */
283d9deefdfSMatthew G. Knepley     ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr);
284d9deefdfSMatthew G. Knepley     if (createConvexHull)   {ierr = PetscStrcat(args, "c");CHKERRQ(ierr);}
285d9deefdfSMatthew G. Knepley     if (constrained)        {ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr);}
286d9deefdfSMatthew G. Knepley     if (mesh->triangleOpts) {triangulate(mesh->triangleOpts, &in, &out, NULL);}
287d9deefdfSMatthew G. Knepley     else                    {triangulate(args, &in, &out, NULL);}
288d9deefdfSMatthew G. Knepley   }
289d9deefdfSMatthew G. Knepley   ierr = PetscFree(in.pointlist);CHKERRQ(ierr);
290d9deefdfSMatthew G. Knepley   ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr);
291d9deefdfSMatthew G. Knepley   ierr = PetscFree(in.segmentlist);CHKERRQ(ierr);
292d9deefdfSMatthew G. Knepley   ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr);
293d9deefdfSMatthew G. Knepley   ierr = PetscFree(in.holelist);CHKERRQ(ierr);
294d9deefdfSMatthew G. Knepley 
295d9deefdfSMatthew G. Knepley   {
296d988aadeSMatthew G. Knepley     DMLabel        glabel      = NULL;
297d9deefdfSMatthew G. Knepley     const PetscInt numCorners  = 3;
298d9deefdfSMatthew G. Knepley     const PetscInt numCells    = out.numberoftriangles;
299d9deefdfSMatthew G. Knepley     const PetscInt numVertices = out.numberofpoints;
300d9deefdfSMatthew G. Knepley     const int     *cells      = out.trianglelist;
301d9deefdfSMatthew G. Knepley     const double  *meshCoords = out.pointlist;
302d9deefdfSMatthew G. Knepley 
303d9deefdfSMatthew G. Knepley     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr);
304c58f1c22SToby Isaac     if (label) {ierr = DMCreateLabel(*dm, labelName); ierr = DMGetLabel(*dm, labelName, &glabel);}
305d9deefdfSMatthew G. Knepley     /* Set labels */
306d9deefdfSMatthew G. Knepley     for (v = 0; v < numVertices; ++v) {
307d9deefdfSMatthew G. Knepley       if (out.pointmarkerlist[v]) {
308d988aadeSMatthew G. Knepley         if (glabel) {ierr = DMLabelSetValue(glabel, v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);}
309d9deefdfSMatthew G. Knepley       }
310d9deefdfSMatthew G. Knepley     }
311d9deefdfSMatthew G. Knepley     if (interpolate) {
312d9deefdfSMatthew G. Knepley       for (e = 0; e < out.numberofedges; e++) {
313d9deefdfSMatthew G. Knepley         if (out.edgemarkerlist[e]) {
314d9deefdfSMatthew G. Knepley           const PetscInt  vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
315d9deefdfSMatthew G. Knepley           const PetscInt *edges;
316d9deefdfSMatthew G. Knepley           PetscInt        numEdges;
317d9deefdfSMatthew G. Knepley 
318d9deefdfSMatthew G. Knepley           ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
319d9deefdfSMatthew G. Knepley           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
320d988aadeSMatthew G. Knepley           if (glabel) {ierr = DMLabelSetValue(glabel, edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);}
321d9deefdfSMatthew G. Knepley           ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
322d9deefdfSMatthew G. Knepley         }
323d9deefdfSMatthew G. Knepley       }
324d9deefdfSMatthew G. Knepley     }
325d9deefdfSMatthew G. Knepley     ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr);
326d9deefdfSMatthew G. Knepley   }
327d9deefdfSMatthew G. Knepley #if 0 /* Do not currently support holes */
328d9deefdfSMatthew G. Knepley   ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr);
329d9deefdfSMatthew G. Knepley #endif
330d9deefdfSMatthew G. Knepley   ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr);
331d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
332d9deefdfSMatthew G. Knepley }
333d9deefdfSMatthew G. Knepley 
334d9deefdfSMatthew G. Knepley #undef __FUNCT__
335d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMPlexRefine_Triangle"
336d9deefdfSMatthew G. Knepley PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined)
337d9deefdfSMatthew G. Knepley {
338d9deefdfSMatthew G. Knepley   MPI_Comm             comm;
339d9deefdfSMatthew G. Knepley   PetscInt             dim       = 2;
340d988aadeSMatthew G. Knepley   const char          *labelName = "marker";
341d9deefdfSMatthew G. Knepley   struct triangulateio in;
342d9deefdfSMatthew G. Knepley   struct triangulateio out;
343d988aadeSMatthew G. Knepley   DMLabel              label;
344d9deefdfSMatthew G. Knepley   PetscInt             vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal;
345d9deefdfSMatthew G. Knepley   PetscMPIInt          rank;
346d9deefdfSMatthew G. Knepley   PetscErrorCode       ierr;
347d9deefdfSMatthew G. Knepley 
348d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
349d9deefdfSMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
350d9deefdfSMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
351d9deefdfSMatthew G. Knepley   ierr = InitInput_Triangle(&in);CHKERRQ(ierr);
352d9deefdfSMatthew G. Knepley   ierr = InitOutput_Triangle(&out);CHKERRQ(ierr);
353d9deefdfSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
354b2566f29SBarry Smith   ierr = MPIU_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr);
355d9deefdfSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
356c58f1c22SToby Isaac   ierr = DMGetLabel(dm, labelName, &label);CHKERRQ(ierr);
357d9deefdfSMatthew G. Knepley 
358d9deefdfSMatthew G. Knepley   in.numberofpoints = vEnd - vStart;
359d9deefdfSMatthew G. Knepley   if (in.numberofpoints > 0) {
360d9deefdfSMatthew G. Knepley     PetscSection coordSection;
361d9deefdfSMatthew G. Knepley     Vec          coordinates;
362d9deefdfSMatthew G. Knepley     PetscScalar *array;
363d9deefdfSMatthew G. Knepley 
364d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in.numberofpoints*dim, &in.pointlist);CHKERRQ(ierr);
365d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in.numberofpoints, &in.pointmarkerlist);CHKERRQ(ierr);
366d9deefdfSMatthew G. Knepley     ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
367d9deefdfSMatthew G. Knepley     ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
368d9deefdfSMatthew G. Knepley     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
369d9deefdfSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
370d9deefdfSMatthew G. Knepley       const PetscInt idx = v - vStart;
371d9deefdfSMatthew G. Knepley       PetscInt       off, d;
372d9deefdfSMatthew G. Knepley 
373d9deefdfSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
374d9deefdfSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
375d9deefdfSMatthew G. Knepley         in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
376d9deefdfSMatthew G. Knepley       }
377d988aadeSMatthew G. Knepley       if (label) {ierr = DMLabelGetValue(label, v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);}
378d9deefdfSMatthew G. Knepley     }
379d9deefdfSMatthew G. Knepley     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
380d9deefdfSMatthew G. Knepley   }
381d9deefdfSMatthew G. Knepley   ierr  = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
382d9deefdfSMatthew G. Knepley 
383d9deefdfSMatthew G. Knepley   in.numberofcorners   = 3;
384d9deefdfSMatthew G. Knepley   in.numberoftriangles = cEnd - cStart;
385d9deefdfSMatthew G. Knepley 
386d9deefdfSMatthew G. Knepley   in.trianglearealist  = (double*) maxVolumes;
387d9deefdfSMatthew G. Knepley   if (in.numberoftriangles > 0) {
388d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in.numberoftriangles*in.numberofcorners, &in.trianglelist);CHKERRQ(ierr);
389d9deefdfSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
390d9deefdfSMatthew G. Knepley       const PetscInt idx      = c - cStart;
391d9deefdfSMatthew G. Knepley       PetscInt      *closure = NULL;
392d9deefdfSMatthew G. Knepley       PetscInt       closureSize;
393d9deefdfSMatthew G. Knepley 
394d9deefdfSMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
395d9deefdfSMatthew G. Knepley       if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize);
396d9deefdfSMatthew G. Knepley       for (v = 0; v < 3; ++v) {
397d9deefdfSMatthew G. Knepley         in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart;
398d9deefdfSMatthew G. Knepley       }
399d9deefdfSMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
400d9deefdfSMatthew G. Knepley     }
401d9deefdfSMatthew G. Knepley   }
402d9deefdfSMatthew G. Knepley   /* TODO: Segment markers are missing on input */
403d9deefdfSMatthew G. Knepley #if 0 /* Do not currently support holes */
404d9deefdfSMatthew G. Knepley   PetscReal *holeCoords;
405d9deefdfSMatthew G. Knepley   PetscInt   h, d;
406d9deefdfSMatthew G. Knepley 
407d9deefdfSMatthew G. Knepley   ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr);
408d9deefdfSMatthew G. Knepley   if (in.numberofholes > 0) {
409d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in.numberofholes*dim, &in.holelist);CHKERRQ(ierr);
410d9deefdfSMatthew G. Knepley     for (h = 0; h < in.numberofholes; ++h) {
411d9deefdfSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
412d9deefdfSMatthew G. Knepley         in.holelist[h*dim+d] = holeCoords[h*dim+d];
413d9deefdfSMatthew G. Knepley       }
414d9deefdfSMatthew G. Knepley     }
415d9deefdfSMatthew G. Knepley   }
416d9deefdfSMatthew G. Knepley #endif
417d9deefdfSMatthew G. Knepley   if (!rank) {
418d9deefdfSMatthew G. Knepley     char args[32];
419d9deefdfSMatthew G. Knepley 
420d9deefdfSMatthew G. Knepley     /* Take away 'Q' for verbose output */
421d9deefdfSMatthew G. Knepley     ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr);
422d9deefdfSMatthew G. Knepley     triangulate(args, &in, &out, NULL);
423d9deefdfSMatthew G. Knepley   }
424d9deefdfSMatthew G. Knepley   ierr = PetscFree(in.pointlist);CHKERRQ(ierr);
425d9deefdfSMatthew G. Knepley   ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr);
426d9deefdfSMatthew G. Knepley   ierr = PetscFree(in.segmentlist);CHKERRQ(ierr);
427d9deefdfSMatthew G. Knepley   ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr);
428d9deefdfSMatthew G. Knepley   ierr = PetscFree(in.trianglelist);CHKERRQ(ierr);
429d9deefdfSMatthew G. Knepley 
430d9deefdfSMatthew G. Knepley   {
431d988aadeSMatthew G. Knepley     DMLabel        rlabel      = NULL;
432d9deefdfSMatthew G. Knepley     const PetscInt numCorners  = 3;
433d9deefdfSMatthew G. Knepley     const PetscInt numCells    = out.numberoftriangles;
434d9deefdfSMatthew G. Knepley     const PetscInt numVertices = out.numberofpoints;
435d9deefdfSMatthew G. Knepley     const int     *cells      = out.trianglelist;
436d9deefdfSMatthew G. Knepley     const double  *meshCoords = out.pointlist;
437d9deefdfSMatthew G. Knepley     PetscBool      interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE;
438d9deefdfSMatthew G. Knepley 
439d9deefdfSMatthew G. Knepley     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr);
440c58f1c22SToby Isaac     if (label) {ierr = DMCreateLabel(*dmRefined, labelName); ierr = DMGetLabel(*dmRefined, labelName, &rlabel);}
441d9deefdfSMatthew G. Knepley     /* Set labels */
442d9deefdfSMatthew G. Knepley     for (v = 0; v < numVertices; ++v) {
443d9deefdfSMatthew G. Knepley       if (out.pointmarkerlist[v]) {
444d988aadeSMatthew G. Knepley         if (rlabel) {ierr = DMLabelSetValue(rlabel, v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);}
445d9deefdfSMatthew G. Knepley       }
446d9deefdfSMatthew G. Knepley     }
447d9deefdfSMatthew G. Knepley     if (interpolate) {
448d9deefdfSMatthew G. Knepley       PetscInt e;
449d9deefdfSMatthew G. Knepley 
450d9deefdfSMatthew G. Knepley       for (e = 0; e < out.numberofedges; e++) {
451d9deefdfSMatthew G. Knepley         if (out.edgemarkerlist[e]) {
452d9deefdfSMatthew G. Knepley           const PetscInt  vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
453d9deefdfSMatthew G. Knepley           const PetscInt *edges;
454d9deefdfSMatthew G. Knepley           PetscInt        numEdges;
455d9deefdfSMatthew G. Knepley 
456d9deefdfSMatthew G. Knepley           ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
457d9deefdfSMatthew G. Knepley           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
458d988aadeSMatthew G. Knepley           if (rlabel) {ierr = DMLabelSetValue(rlabel, edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);}
459d9deefdfSMatthew G. Knepley           ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
460d9deefdfSMatthew G. Knepley         }
461d9deefdfSMatthew G. Knepley       }
462d9deefdfSMatthew G. Knepley     }
463d9deefdfSMatthew G. Knepley     ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr);
464d9deefdfSMatthew G. Knepley   }
465d9deefdfSMatthew G. Knepley #if 0 /* Do not currently support holes */
466d9deefdfSMatthew G. Knepley   ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr);
467d9deefdfSMatthew G. Knepley #endif
468d9deefdfSMatthew G. Knepley   ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr);
469d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
470d9deefdfSMatthew G. Knepley }
471d9deefdfSMatthew G. Knepley #endif /* PETSC_HAVE_TRIANGLE */
472d9deefdfSMatthew G. Knepley 
473d9deefdfSMatthew G. Knepley #if defined(PETSC_HAVE_TETGEN)
474d9deefdfSMatthew G. Knepley #include <tetgen.h>
475d9deefdfSMatthew G. Knepley #undef __FUNCT__
476d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMPlexGenerate_Tetgen"
477d9deefdfSMatthew G. Knepley PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm)
478d9deefdfSMatthew G. Knepley {
479d9deefdfSMatthew G. Knepley   MPI_Comm       comm;
4803d8f7108SMatthew G. Knepley   DM_Plex       *mesh      = (DM_Plex *) boundary->data;
481d9deefdfSMatthew G. Knepley   const PetscInt dim       = 3;
482d988aadeSMatthew G. Knepley   const char    *labelName = "marker";
483d9deefdfSMatthew G. Knepley   ::tetgenio     in;
484d9deefdfSMatthew G. Knepley   ::tetgenio     out;
485d988aadeSMatthew G. Knepley   DMLabel        label;
486d9deefdfSMatthew G. Knepley   PetscInt       vStart, vEnd, v, fStart, fEnd, f;
487d9deefdfSMatthew G. Knepley   PetscMPIInt    rank;
488d9deefdfSMatthew G. Knepley   PetscErrorCode ierr;
489d9deefdfSMatthew G. Knepley 
490d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
491d9deefdfSMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr);
492d9deefdfSMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
493d9deefdfSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr);
494c58f1c22SToby Isaac   ierr = DMGetLabel(boundary, labelName, &label);CHKERRQ(ierr);
495d988aadeSMatthew G. Knepley 
496d9deefdfSMatthew G. Knepley   in.numberofpoints = vEnd - vStart;
497d9deefdfSMatthew G. Knepley   if (in.numberofpoints > 0) {
498d9deefdfSMatthew G. Knepley     PetscSection coordSection;
499d9deefdfSMatthew G. Knepley     Vec          coordinates;
500d9deefdfSMatthew G. Knepley     PetscScalar *array;
501d9deefdfSMatthew G. Knepley 
502d9deefdfSMatthew G. Knepley     in.pointlist       = new double[in.numberofpoints*dim];
503d9deefdfSMatthew G. Knepley     in.pointmarkerlist = new int[in.numberofpoints];
504d9deefdfSMatthew G. Knepley 
505d9deefdfSMatthew G. Knepley     ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr);
506d9deefdfSMatthew G. Knepley     ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr);
507d9deefdfSMatthew G. Knepley     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
508d9deefdfSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
509d9deefdfSMatthew G. Knepley       const PetscInt idx = v - vStart;
510d9deefdfSMatthew G. Knepley       PetscInt       off, d;
511d9deefdfSMatthew G. Knepley 
512d9deefdfSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
513d9deefdfSMatthew G. Knepley       for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
514d988aadeSMatthew G. Knepley       if (label) {ierr = DMLabelGetValue(label, v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);}
515d9deefdfSMatthew G. Knepley     }
516d9deefdfSMatthew G. Knepley     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
517d9deefdfSMatthew G. Knepley   }
518d9deefdfSMatthew G. Knepley   ierr  = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr);
519d9deefdfSMatthew G. Knepley 
520d9deefdfSMatthew G. Knepley   in.numberoffacets = fEnd - fStart;
521d9deefdfSMatthew G. Knepley   if (in.numberoffacets > 0) {
522d9deefdfSMatthew G. Knepley     in.facetlist       = new tetgenio::facet[in.numberoffacets];
523d9deefdfSMatthew G. Knepley     in.facetmarkerlist = new int[in.numberoffacets];
524d9deefdfSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
525d9deefdfSMatthew G. Knepley       const PetscInt idx     = f - fStart;
526d9deefdfSMatthew G. Knepley       PetscInt      *points = NULL, numPoints, p, numVertices = 0, v;
527d9deefdfSMatthew G. Knepley 
528d9deefdfSMatthew G. Knepley       in.facetlist[idx].numberofpolygons = 1;
529d9deefdfSMatthew G. Knepley       in.facetlist[idx].polygonlist      = new tetgenio::polygon[in.facetlist[idx].numberofpolygons];
530d9deefdfSMatthew G. Knepley       in.facetlist[idx].numberofholes    = 0;
531d9deefdfSMatthew G. Knepley       in.facetlist[idx].holelist         = NULL;
532d9deefdfSMatthew G. Knepley 
533d9deefdfSMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
534d9deefdfSMatthew G. Knepley       for (p = 0; p < numPoints*2; p += 2) {
535d9deefdfSMatthew G. Knepley         const PetscInt point = points[p];
536d9deefdfSMatthew G. Knepley         if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point;
537d9deefdfSMatthew G. Knepley       }
538d9deefdfSMatthew G. Knepley 
539d9deefdfSMatthew G. Knepley       tetgenio::polygon *poly = in.facetlist[idx].polygonlist;
540d9deefdfSMatthew G. Knepley       poly->numberofvertices = numVertices;
541d9deefdfSMatthew G. Knepley       poly->vertexlist       = new int[poly->numberofvertices];
542d9deefdfSMatthew G. Knepley       for (v = 0; v < numVertices; ++v) {
543d9deefdfSMatthew G. Knepley         const PetscInt vIdx = points[v] - vStart;
544d9deefdfSMatthew G. Knepley         poly->vertexlist[v] = vIdx;
545d9deefdfSMatthew G. Knepley       }
546d988aadeSMatthew G. Knepley       if (label) {ierr = DMLabelGetValue(label, f, &in.facetmarkerlist[idx]);CHKERRQ(ierr);}
547d9deefdfSMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
548d9deefdfSMatthew G. Knepley     }
549d9deefdfSMatthew G. Knepley   }
550d9deefdfSMatthew G. Knepley   if (!rank) {
551d9deefdfSMatthew G. Knepley     char args[32];
552d9deefdfSMatthew G. Knepley 
553d9deefdfSMatthew G. Knepley     /* Take away 'Q' for verbose output */
554d9deefdfSMatthew G. Knepley     ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr);
555d9deefdfSMatthew G. Knepley     if (mesh->tetgenOpts) {::tetrahedralize(mesh->tetgenOpts, &in, &out);}
556d9deefdfSMatthew G. Knepley     else                  {::tetrahedralize(args, &in, &out);}
557d9deefdfSMatthew G. Knepley   }
558d9deefdfSMatthew G. Knepley   {
559d988aadeSMatthew G. Knepley     DMLabel        glabel      = NULL;
560d9deefdfSMatthew G. Knepley     const PetscInt numCorners  = 4;
561d9deefdfSMatthew G. Knepley     const PetscInt numCells    = out.numberoftetrahedra;
562d9deefdfSMatthew G. Knepley     const PetscInt numVertices = out.numberofpoints;
563d9deefdfSMatthew G. Knepley     const double   *meshCoords = out.pointlist;
564d9deefdfSMatthew G. Knepley     int            *cells      = out.tetrahedronlist;
565d9deefdfSMatthew G. Knepley 
566d9deefdfSMatthew G. Knepley     ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr);
567d9deefdfSMatthew G. Knepley     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr);
568c58f1c22SToby Isaac     if (label) {ierr = DMCreateLabel(*dm, labelName); ierr = DMGetLabel(*dm, labelName, &glabel);}
569d9deefdfSMatthew G. Knepley     /* Set labels */
570d9deefdfSMatthew G. Knepley     for (v = 0; v < numVertices; ++v) {
571d9deefdfSMatthew G. Knepley       if (out.pointmarkerlist[v]) {
572d988aadeSMatthew G. Knepley         if (glabel) {ierr = DMLabelSetValue(glabel, v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);}
573d9deefdfSMatthew G. Knepley       }
574d9deefdfSMatthew G. Knepley     }
575d9deefdfSMatthew G. Knepley     if (interpolate) {
576d9deefdfSMatthew G. Knepley       PetscInt e;
577d9deefdfSMatthew G. Knepley 
578d9deefdfSMatthew G. Knepley       for (e = 0; e < out.numberofedges; e++) {
579d9deefdfSMatthew G. Knepley         if (out.edgemarkerlist[e]) {
580d9deefdfSMatthew G. Knepley           const PetscInt  vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
581d9deefdfSMatthew G. Knepley           const PetscInt *edges;
582d9deefdfSMatthew G. Knepley           PetscInt        numEdges;
583d9deefdfSMatthew G. Knepley 
584d9deefdfSMatthew G. Knepley           ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
585d9deefdfSMatthew G. Knepley           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
586d988aadeSMatthew G. Knepley           if (glabel) {ierr = DMLabelSetValue(glabel, edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);}
587d9deefdfSMatthew G. Knepley           ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
588d9deefdfSMatthew G. Knepley         }
589d9deefdfSMatthew G. Knepley       }
590d9deefdfSMatthew G. Knepley       for (f = 0; f < out.numberoftrifaces; f++) {
591d9deefdfSMatthew G. Knepley         if (out.trifacemarkerlist[f]) {
592d9deefdfSMatthew G. Knepley           const PetscInt  vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells};
593d9deefdfSMatthew G. Knepley           const PetscInt *faces;
594d9deefdfSMatthew G. Knepley           PetscInt        numFaces;
595d9deefdfSMatthew G. Knepley 
596d9deefdfSMatthew G. Knepley           ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
597d9deefdfSMatthew G. Knepley           if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces);
59835b814a0SMatthew G. Knepley           if (glabel) {ierr = DMLabelSetValue(glabel, faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr);}
599d9deefdfSMatthew G. Knepley           ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
600d9deefdfSMatthew G. Knepley         }
601d9deefdfSMatthew G. Knepley       }
602d9deefdfSMatthew G. Knepley     }
603d9deefdfSMatthew G. Knepley     ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr);
604d9deefdfSMatthew G. Knepley   }
605d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
606d9deefdfSMatthew G. Knepley }
607d9deefdfSMatthew G. Knepley 
608d9deefdfSMatthew G. Knepley #undef __FUNCT__
609d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMPlexRefine_Tetgen"
610d9deefdfSMatthew G. Knepley PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined)
611d9deefdfSMatthew G. Knepley {
612d9deefdfSMatthew G. Knepley   MPI_Comm       comm;
613d9deefdfSMatthew G. Knepley   const PetscInt dim       = 3;
614d988aadeSMatthew G. Knepley   const char    *labelName = "marker";
615d9deefdfSMatthew G. Knepley   ::tetgenio     in;
616d9deefdfSMatthew G. Knepley   ::tetgenio     out;
617d988aadeSMatthew G. Knepley   DMLabel        label;
618d9deefdfSMatthew G. Knepley   PetscInt       vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal;
619d9deefdfSMatthew G. Knepley   PetscMPIInt    rank;
620d9deefdfSMatthew G. Knepley   PetscErrorCode ierr;
621d9deefdfSMatthew G. Knepley 
622d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
623d9deefdfSMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
624d9deefdfSMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
625d9deefdfSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
626b2566f29SBarry Smith   ierr = MPIU_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr);
627d9deefdfSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
628c58f1c22SToby Isaac   ierr = DMGetLabel(dm, labelName, &label);CHKERRQ(ierr);
629d9deefdfSMatthew G. Knepley 
630d9deefdfSMatthew G. Knepley   in.numberofpoints = vEnd - vStart;
631d9deefdfSMatthew G. Knepley   if (in.numberofpoints > 0) {
632d9deefdfSMatthew G. Knepley     PetscSection coordSection;
633d9deefdfSMatthew G. Knepley     Vec          coordinates;
634d9deefdfSMatthew G. Knepley     PetscScalar *array;
635d9deefdfSMatthew G. Knepley 
636d9deefdfSMatthew G. Knepley     in.pointlist       = new double[in.numberofpoints*dim];
637d9deefdfSMatthew G. Knepley     in.pointmarkerlist = new int[in.numberofpoints];
638d9deefdfSMatthew G. Knepley 
639d9deefdfSMatthew G. Knepley     ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
640d9deefdfSMatthew G. Knepley     ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
641d9deefdfSMatthew G. Knepley     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
642d9deefdfSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
643d9deefdfSMatthew G. Knepley       const PetscInt idx = v - vStart;
644d9deefdfSMatthew G. Knepley       PetscInt       off, d;
645d9deefdfSMatthew G. Knepley 
646d9deefdfSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
647d9deefdfSMatthew G. Knepley       for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
648d988aadeSMatthew G. Knepley       if (label) {ierr = DMLabelGetValue(label, v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);}
649d9deefdfSMatthew G. Knepley     }
650d9deefdfSMatthew G. Knepley     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
651d9deefdfSMatthew G. Knepley   }
652d9deefdfSMatthew G. Knepley   ierr  = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
653d9deefdfSMatthew G. Knepley 
654d9deefdfSMatthew G. Knepley   in.numberofcorners       = 4;
655d9deefdfSMatthew G. Knepley   in.numberoftetrahedra    = cEnd - cStart;
656d9deefdfSMatthew G. Knepley   in.tetrahedronvolumelist = (double*) maxVolumes;
657d9deefdfSMatthew G. Knepley   if (in.numberoftetrahedra > 0) {
658d9deefdfSMatthew G. Knepley     in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners];
659d9deefdfSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
660d9deefdfSMatthew G. Knepley       const PetscInt idx      = c - cStart;
661d9deefdfSMatthew G. Knepley       PetscInt      *closure = NULL;
662d9deefdfSMatthew G. Knepley       PetscInt       closureSize;
663d9deefdfSMatthew G. Knepley 
664d9deefdfSMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
665d9deefdfSMatthew G. Knepley       if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize);
666d9deefdfSMatthew G. Knepley       for (v = 0; v < 4; ++v) {
667d9deefdfSMatthew G. Knepley         in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart;
668d9deefdfSMatthew G. Knepley       }
669d9deefdfSMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
670d9deefdfSMatthew G. Knepley     }
671d9deefdfSMatthew G. Knepley   }
672d9deefdfSMatthew G. Knepley   /* TODO: Put in boundary faces with markers */
673d9deefdfSMatthew G. Knepley   if (!rank) {
674d9deefdfSMatthew G. Knepley     char args[32];
675d9deefdfSMatthew G. Knepley 
676d9deefdfSMatthew G. Knepley     /* Take away 'Q' for verbose output */
677d9deefdfSMatthew G. Knepley     /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */
678d9deefdfSMatthew G. Knepley     ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr);
679d9deefdfSMatthew G. Knepley     ::tetrahedralize(args, &in, &out);
680d9deefdfSMatthew G. Knepley   }
681d9deefdfSMatthew G. Knepley   in.tetrahedronvolumelist = NULL;
682d9deefdfSMatthew G. Knepley 
683d9deefdfSMatthew G. Knepley   {
684d988aadeSMatthew G. Knepley     DMLabel        rlabel      = NULL;
685d9deefdfSMatthew G. Knepley     const PetscInt numCorners  = 4;
686d9deefdfSMatthew G. Knepley     const PetscInt numCells    = out.numberoftetrahedra;
687d9deefdfSMatthew G. Knepley     const PetscInt numVertices = out.numberofpoints;
688d9deefdfSMatthew G. Knepley     const double   *meshCoords = out.pointlist;
689d9deefdfSMatthew G. Knepley     int            *cells      = out.tetrahedronlist;
690d9deefdfSMatthew G. Knepley 
691d9deefdfSMatthew G. Knepley     PetscBool      interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE;
692d9deefdfSMatthew G. Knepley 
693d9deefdfSMatthew G. Knepley     ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr);
694d9deefdfSMatthew G. Knepley     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr);
695c58f1c22SToby Isaac     if (label) {ierr = DMCreateLabel(*dmRefined, labelName); ierr = DMGetLabel(*dmRefined, labelName, &rlabel);}
696d9deefdfSMatthew G. Knepley     /* Set labels */
697d9deefdfSMatthew G. Knepley     for (v = 0; v < numVertices; ++v) {
698d9deefdfSMatthew G. Knepley       if (out.pointmarkerlist[v]) {
699d988aadeSMatthew G. Knepley         if (rlabel) {ierr = DMLabelSetValue(rlabel, v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);}
700d9deefdfSMatthew G. Knepley       }
701d9deefdfSMatthew G. Knepley     }
702d9deefdfSMatthew G. Knepley     if (interpolate) {
703d9deefdfSMatthew G. Knepley       PetscInt e, f;
704d9deefdfSMatthew G. Knepley 
705d9deefdfSMatthew G. Knepley       for (e = 0; e < out.numberofedges; e++) {
706d9deefdfSMatthew G. Knepley         if (out.edgemarkerlist[e]) {
707d9deefdfSMatthew G. Knepley           const PetscInt  vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
708d9deefdfSMatthew G. Knepley           const PetscInt *edges;
709d9deefdfSMatthew G. Knepley           PetscInt        numEdges;
710d9deefdfSMatthew G. Knepley 
711d9deefdfSMatthew G. Knepley           ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
712d9deefdfSMatthew G. Knepley           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
713d988aadeSMatthew G. Knepley           if (rlabel) {ierr = DMLabelSetValue(rlabel, edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);}
714d9deefdfSMatthew G. Knepley           ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
715d9deefdfSMatthew G. Knepley         }
716d9deefdfSMatthew G. Knepley       }
717d9deefdfSMatthew G. Knepley       for (f = 0; f < out.numberoftrifaces; f++) {
718d9deefdfSMatthew G. Knepley         if (out.trifacemarkerlist[f]) {
719d9deefdfSMatthew G. Knepley           const PetscInt  vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells};
720d9deefdfSMatthew G. Knepley           const PetscInt *faces;
721d9deefdfSMatthew G. Knepley           PetscInt        numFaces;
722d9deefdfSMatthew G. Knepley 
723d9deefdfSMatthew G. Knepley           ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
724d9deefdfSMatthew G. Knepley           if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces);
725d988aadeSMatthew G. Knepley           if (rlabel) {ierr = DMLabelSetValue(rlabel, faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr);}
726d9deefdfSMatthew G. Knepley           ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
727d9deefdfSMatthew G. Knepley         }
728d9deefdfSMatthew G. Knepley       }
729d9deefdfSMatthew G. Knepley     }
730d9deefdfSMatthew G. Knepley     ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr);
731d9deefdfSMatthew G. Knepley   }
732d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
733d9deefdfSMatthew G. Knepley }
734d9deefdfSMatthew G. Knepley #endif /* PETSC_HAVE_TETGEN */
735d9deefdfSMatthew G. Knepley 
736d9deefdfSMatthew G. Knepley #if defined(PETSC_HAVE_CTETGEN)
737d9deefdfSMatthew G. Knepley #include <ctetgen.h>
738d9deefdfSMatthew G. Knepley 
739d9deefdfSMatthew G. Knepley #undef __FUNCT__
740d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMPlexGenerate_CTetgen"
741d9deefdfSMatthew G. Knepley PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm)
742d9deefdfSMatthew G. Knepley {
743d9deefdfSMatthew G. Knepley   MPI_Comm       comm;
744d9deefdfSMatthew G. Knepley   const PetscInt dim       = 3;
745d988aadeSMatthew G. Knepley   const char    *labelName = "marker";
746d9deefdfSMatthew G. Knepley   PLC           *in, *out;
747d988aadeSMatthew G. Knepley   DMLabel        label;
748d9deefdfSMatthew G. Knepley   PetscInt       verbose = 0, vStart, vEnd, v, fStart, fEnd, f;
749d9deefdfSMatthew G. Knepley   PetscMPIInt    rank;
750d9deefdfSMatthew G. Knepley   PetscErrorCode ierr;
751d9deefdfSMatthew G. Knepley 
752d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
753d9deefdfSMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr);
754c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr);
755d9deefdfSMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
756d9deefdfSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr);
757c58f1c22SToby Isaac   ierr = DMGetLabel(boundary, labelName, &label);CHKERRQ(ierr);
758d9deefdfSMatthew G. Knepley   ierr = PLCCreate(&in);CHKERRQ(ierr);
759d9deefdfSMatthew G. Knepley   ierr = PLCCreate(&out);CHKERRQ(ierr);
760d9deefdfSMatthew G. Knepley 
761d9deefdfSMatthew G. Knepley   in->numberofpoints = vEnd - vStart;
762d9deefdfSMatthew G. Knepley   if (in->numberofpoints > 0) {
763d9deefdfSMatthew G. Knepley     PetscSection coordSection;
764d9deefdfSMatthew G. Knepley     Vec          coordinates;
765d9deefdfSMatthew G. Knepley     PetscScalar *array;
766d9deefdfSMatthew G. Knepley 
767d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in->numberofpoints*dim, &in->pointlist);CHKERRQ(ierr);
768d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in->numberofpoints,       &in->pointmarkerlist);CHKERRQ(ierr);
769d9deefdfSMatthew G. Knepley     ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr);
770d9deefdfSMatthew G. Knepley     ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr);
771d9deefdfSMatthew G. Knepley     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
772d9deefdfSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
773d9deefdfSMatthew G. Knepley       const PetscInt idx = v - vStart;
774a9a51d2cSMatthew G. Knepley       PetscInt       off, d, m = -1;
775d9deefdfSMatthew G. Knepley 
776d9deefdfSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
777d9deefdfSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
778d9deefdfSMatthew G. Knepley         in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
779d9deefdfSMatthew G. Knepley       }
780d988aadeSMatthew G. Knepley       if (label) {ierr = DMLabelGetValue(label, v, &m);CHKERRQ(ierr);}
781d9deefdfSMatthew G. Knepley 
782d9deefdfSMatthew G. Knepley       in->pointmarkerlist[idx] = (int) m;
783d9deefdfSMatthew G. Knepley     }
784d9deefdfSMatthew G. Knepley     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
785d9deefdfSMatthew G. Knepley   }
786d9deefdfSMatthew G. Knepley   ierr  = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr);
787d9deefdfSMatthew G. Knepley 
788d9deefdfSMatthew G. Knepley   in->numberoffacets = fEnd - fStart;
789d9deefdfSMatthew G. Knepley   if (in->numberoffacets > 0) {
790d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in->numberoffacets, &in->facetlist);CHKERRQ(ierr);
791d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in->numberoffacets,   &in->facetmarkerlist);CHKERRQ(ierr);
792d9deefdfSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
793d9deefdfSMatthew G. Knepley       const PetscInt idx     = f - fStart;
794a9a51d2cSMatthew G. Knepley       PetscInt      *points = NULL, numPoints, p, numVertices = 0, v, m = -1;
795d9deefdfSMatthew G. Knepley       polygon       *poly;
796d9deefdfSMatthew G. Knepley 
797d9deefdfSMatthew G. Knepley       in->facetlist[idx].numberofpolygons = 1;
798d9deefdfSMatthew G. Knepley 
799d9deefdfSMatthew G. Knepley       ierr = PetscMalloc1(in->facetlist[idx].numberofpolygons, &in->facetlist[idx].polygonlist);CHKERRQ(ierr);
800d9deefdfSMatthew G. Knepley 
801d9deefdfSMatthew G. Knepley       in->facetlist[idx].numberofholes    = 0;
802d9deefdfSMatthew G. Knepley       in->facetlist[idx].holelist         = NULL;
803d9deefdfSMatthew G. Knepley 
804d9deefdfSMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
805d9deefdfSMatthew G. Knepley       for (p = 0; p < numPoints*2; p += 2) {
806d9deefdfSMatthew G. Knepley         const PetscInt point = points[p];
807d9deefdfSMatthew G. Knepley         if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point;
808d9deefdfSMatthew G. Knepley       }
809d9deefdfSMatthew G. Knepley 
810d9deefdfSMatthew G. Knepley       poly                   = in->facetlist[idx].polygonlist;
811d9deefdfSMatthew G. Knepley       poly->numberofvertices = numVertices;
812d9deefdfSMatthew G. Knepley       ierr                   = PetscMalloc1(poly->numberofvertices, &poly->vertexlist);CHKERRQ(ierr);
813d9deefdfSMatthew G. Knepley       for (v = 0; v < numVertices; ++v) {
814d9deefdfSMatthew G. Knepley         const PetscInt vIdx = points[v] - vStart;
815d9deefdfSMatthew G. Knepley         poly->vertexlist[v] = vIdx;
816d9deefdfSMatthew G. Knepley       }
817d988aadeSMatthew G. Knepley       if (label) {ierr = DMLabelGetValue(label, f, &m);CHKERRQ(ierr);}
818d9deefdfSMatthew G. Knepley       in->facetmarkerlist[idx] = (int) m;
819d9deefdfSMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
820d9deefdfSMatthew G. Knepley     }
821d9deefdfSMatthew G. Knepley   }
822d9deefdfSMatthew G. Knepley   if (!rank) {
823d9deefdfSMatthew G. Knepley     TetGenOpts t;
824d9deefdfSMatthew G. Knepley 
825d9deefdfSMatthew G. Knepley     ierr        = TetGenOptsInitialize(&t);CHKERRQ(ierr);
826d9deefdfSMatthew G. Knepley     t.in        = boundary; /* Should go away */
827d9deefdfSMatthew G. Knepley     t.plc       = 1;
828d9deefdfSMatthew G. Knepley     t.quality   = 1;
829d9deefdfSMatthew G. Knepley     t.edgesout  = 1;
830d9deefdfSMatthew G. Knepley     t.zeroindex = 1;
831d9deefdfSMatthew G. Knepley     t.quiet     = 1;
832d9deefdfSMatthew G. Knepley     t.verbose   = verbose;
833d9deefdfSMatthew G. Knepley     ierr        = TetGenCheckOpts(&t);CHKERRQ(ierr);
834d9deefdfSMatthew G. Knepley     ierr        = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr);
835d9deefdfSMatthew G. Knepley   }
836d9deefdfSMatthew G. Knepley   {
837d988aadeSMatthew G. Knepley     DMLabel        glabel      = NULL;
838d9deefdfSMatthew G. Knepley     const PetscInt numCorners  = 4;
839d9deefdfSMatthew G. Knepley     const PetscInt numCells    = out->numberoftetrahedra;
840d9deefdfSMatthew G. Knepley     const PetscInt numVertices = out->numberofpoints;
841d9deefdfSMatthew G. Knepley     const double   *meshCoords = out->pointlist;
842d9deefdfSMatthew G. Knepley     int            *cells      = out->tetrahedronlist;
843d9deefdfSMatthew G. Knepley 
844d9deefdfSMatthew G. Knepley     ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr);
845d9deefdfSMatthew G. Knepley     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr);
846c58f1c22SToby Isaac     if (label) {ierr = DMCreateLabel(*dm, labelName); ierr = DMGetLabel(*dm, labelName, &glabel);}
847d9deefdfSMatthew G. Knepley     /* Set labels */
848d9deefdfSMatthew G. Knepley     for (v = 0; v < numVertices; ++v) {
849d9deefdfSMatthew G. Knepley       if (out->pointmarkerlist[v]) {
850d988aadeSMatthew G. Knepley         if (glabel) {ierr = DMLabelSetValue(glabel, v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);}
851d9deefdfSMatthew G. Knepley       }
852d9deefdfSMatthew G. Knepley     }
853d9deefdfSMatthew G. Knepley     if (interpolate) {
854d9deefdfSMatthew G. Knepley       PetscInt e;
855d9deefdfSMatthew G. Knepley 
856d9deefdfSMatthew G. Knepley       for (e = 0; e < out->numberofedges; e++) {
857d9deefdfSMatthew G. Knepley         if (out->edgemarkerlist[e]) {
858d9deefdfSMatthew G. Knepley           const PetscInt  vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells};
859d9deefdfSMatthew G. Knepley           const PetscInt *edges;
860d9deefdfSMatthew G. Knepley           PetscInt        numEdges;
861d9deefdfSMatthew G. Knepley 
862d9deefdfSMatthew G. Knepley           ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
863d9deefdfSMatthew G. Knepley           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
864d988aadeSMatthew G. Knepley           if (glabel) {ierr = DMLabelSetValue(glabel, edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);}
865d9deefdfSMatthew G. Knepley           ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
866d9deefdfSMatthew G. Knepley         }
867d9deefdfSMatthew G. Knepley       }
868d9deefdfSMatthew G. Knepley       for (f = 0; f < out->numberoftrifaces; f++) {
869d9deefdfSMatthew G. Knepley         if (out->trifacemarkerlist[f]) {
870d9deefdfSMatthew G. Knepley           const PetscInt  vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells};
871d9deefdfSMatthew G. Knepley           const PetscInt *faces;
872d9deefdfSMatthew G. Knepley           PetscInt        numFaces;
873d9deefdfSMatthew G. Knepley 
874d9deefdfSMatthew G. Knepley           ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
875d9deefdfSMatthew G. Knepley           if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces);
876d988aadeSMatthew G. Knepley           if (glabel) {ierr = DMLabelSetValue(glabel, faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);}
877d9deefdfSMatthew G. Knepley           ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
878d9deefdfSMatthew G. Knepley         }
879d9deefdfSMatthew G. Knepley       }
880d9deefdfSMatthew G. Knepley     }
881d9deefdfSMatthew G. Knepley     ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr);
882d9deefdfSMatthew G. Knepley   }
883d9deefdfSMatthew G. Knepley 
884d9deefdfSMatthew G. Knepley   ierr = PLCDestroy(&in);CHKERRQ(ierr);
885d9deefdfSMatthew G. Knepley   ierr = PLCDestroy(&out);CHKERRQ(ierr);
886d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
887d9deefdfSMatthew G. Knepley }
888d9deefdfSMatthew G. Knepley 
889d9deefdfSMatthew G. Knepley #undef __FUNCT__
890d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMPlexRefine_CTetgen"
891d9deefdfSMatthew G. Knepley PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined)
892d9deefdfSMatthew G. Knepley {
893d9deefdfSMatthew G. Knepley   MPI_Comm       comm;
894d9deefdfSMatthew G. Knepley   const PetscInt dim       = 3;
895d988aadeSMatthew G. Knepley   const char    *labelName = "marker";
896d9deefdfSMatthew G. Knepley   PLC           *in, *out;
897d988aadeSMatthew G. Knepley   DMLabel        label;
898d9deefdfSMatthew G. Knepley   PetscInt       verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal;
899d9deefdfSMatthew G. Knepley   PetscMPIInt    rank;
900d9deefdfSMatthew G. Knepley   PetscErrorCode ierr;
901d9deefdfSMatthew G. Knepley 
902d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
903d9deefdfSMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
904c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr);
905d9deefdfSMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
906d9deefdfSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
907b2566f29SBarry Smith   ierr = MPIU_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr);
908d9deefdfSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
909c58f1c22SToby Isaac   ierr = DMGetLabel(dm, labelName, &label);CHKERRQ(ierr);
910d9deefdfSMatthew G. Knepley   ierr = PLCCreate(&in);CHKERRQ(ierr);
911d9deefdfSMatthew G. Knepley   ierr = PLCCreate(&out);CHKERRQ(ierr);
912d9deefdfSMatthew G. Knepley 
913d9deefdfSMatthew G. Knepley   in->numberofpoints = vEnd - vStart;
914d9deefdfSMatthew G. Knepley   if (in->numberofpoints > 0) {
915d9deefdfSMatthew G. Knepley     PetscSection coordSection;
916d9deefdfSMatthew G. Knepley     Vec          coordinates;
917d9deefdfSMatthew G. Knepley     PetscScalar *array;
918d9deefdfSMatthew G. Knepley 
919d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in->numberofpoints*dim, &in->pointlist);CHKERRQ(ierr);
920d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in->numberofpoints,       &in->pointmarkerlist);CHKERRQ(ierr);
921d9deefdfSMatthew G. Knepley     ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
922d9deefdfSMatthew G. Knepley     ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
923d9deefdfSMatthew G. Knepley     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
924d9deefdfSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
925d9deefdfSMatthew G. Knepley       const PetscInt idx = v - vStart;
926a9a51d2cSMatthew G. Knepley       PetscInt       off, d, m = -1;
927d9deefdfSMatthew G. Knepley 
928d9deefdfSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
929d9deefdfSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
930d9deefdfSMatthew G. Knepley         in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
931d9deefdfSMatthew G. Knepley       }
932d988aadeSMatthew G. Knepley       if (label) {ierr = DMLabelGetValue(label, v, &m);CHKERRQ(ierr);}
933d9deefdfSMatthew G. Knepley 
934d9deefdfSMatthew G. Knepley       in->pointmarkerlist[idx] = (int) m;
935d9deefdfSMatthew G. Knepley     }
936d9deefdfSMatthew G. Knepley     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
937d9deefdfSMatthew G. Knepley   }
938d9deefdfSMatthew G. Knepley   ierr  = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
939d9deefdfSMatthew G. Knepley 
940d9deefdfSMatthew G. Knepley   in->numberofcorners       = 4;
941d9deefdfSMatthew G. Knepley   in->numberoftetrahedra    = cEnd - cStart;
942d9deefdfSMatthew G. Knepley   in->tetrahedronvolumelist = maxVolumes;
943d9deefdfSMatthew G. Knepley   if (in->numberoftetrahedra > 0) {
944d9deefdfSMatthew G. Knepley     ierr = PetscMalloc1(in->numberoftetrahedra*in->numberofcorners, &in->tetrahedronlist);CHKERRQ(ierr);
945d9deefdfSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
946d9deefdfSMatthew G. Knepley       const PetscInt idx      = c - cStart;
947d9deefdfSMatthew G. Knepley       PetscInt      *closure = NULL;
948d9deefdfSMatthew G. Knepley       PetscInt       closureSize;
949d9deefdfSMatthew G. Knepley 
950d9deefdfSMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
951d9deefdfSMatthew G. Knepley       if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize);
952d9deefdfSMatthew G. Knepley       for (v = 0; v < 4; ++v) {
953d9deefdfSMatthew G. Knepley         in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart;
954d9deefdfSMatthew G. Knepley       }
955d9deefdfSMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
956d9deefdfSMatthew G. Knepley     }
957d9deefdfSMatthew G. Knepley   }
958d9deefdfSMatthew G. Knepley   if (!rank) {
959d9deefdfSMatthew G. Knepley     TetGenOpts t;
960d9deefdfSMatthew G. Knepley 
961d9deefdfSMatthew G. Knepley     ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr);
962d9deefdfSMatthew G. Knepley 
963d9deefdfSMatthew G. Knepley     t.in        = dm; /* Should go away */
964d9deefdfSMatthew G. Knepley     t.refine    = 1;
965d9deefdfSMatthew G. Knepley     t.varvolume = 1;
966d9deefdfSMatthew G. Knepley     t.quality   = 1;
967d9deefdfSMatthew G. Knepley     t.edgesout  = 1;
968d9deefdfSMatthew G. Knepley     t.zeroindex = 1;
969d9deefdfSMatthew G. Knepley     t.quiet     = 1;
970d9deefdfSMatthew G. Knepley     t.verbose   = verbose; /* Change this */
971d9deefdfSMatthew G. Knepley 
972d9deefdfSMatthew G. Knepley     ierr = TetGenCheckOpts(&t);CHKERRQ(ierr);
973d9deefdfSMatthew G. Knepley     ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr);
974d9deefdfSMatthew G. Knepley   }
975d9deefdfSMatthew G. Knepley   {
976d988aadeSMatthew G. Knepley     DMLabel        rlabel      = NULL;
977d9deefdfSMatthew G. Knepley     const PetscInt numCorners  = 4;
978d9deefdfSMatthew G. Knepley     const PetscInt numCells    = out->numberoftetrahedra;
979d9deefdfSMatthew G. Knepley     const PetscInt numVertices = out->numberofpoints;
980d9deefdfSMatthew G. Knepley     const double   *meshCoords = out->pointlist;
981d9deefdfSMatthew G. Knepley     int            *cells      = out->tetrahedronlist;
982d9deefdfSMatthew G. Knepley     PetscBool      interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE;
983d9deefdfSMatthew G. Knepley 
984d9deefdfSMatthew G. Knepley     ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr);
985d9deefdfSMatthew G. Knepley     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr);
986c58f1c22SToby Isaac     if (label) {ierr = DMCreateLabel(*dmRefined, labelName); ierr = DMGetLabel(*dmRefined, labelName, &rlabel);}
987d9deefdfSMatthew G. Knepley     /* Set labels */
988d9deefdfSMatthew G. Knepley     for (v = 0; v < numVertices; ++v) {
989d9deefdfSMatthew G. Knepley       if (out->pointmarkerlist[v]) {
990d988aadeSMatthew G. Knepley         if (rlabel) {ierr = DMLabelSetValue(rlabel, v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);}
991d9deefdfSMatthew G. Knepley       }
992d9deefdfSMatthew G. Knepley     }
993d9deefdfSMatthew G. Knepley     if (interpolate) {
994d9deefdfSMatthew G. Knepley       PetscInt e, f;
995d9deefdfSMatthew G. Knepley 
996d9deefdfSMatthew G. Knepley       for (e = 0; e < out->numberofedges; e++) {
997d9deefdfSMatthew G. Knepley         if (out->edgemarkerlist[e]) {
998d9deefdfSMatthew G. Knepley           const PetscInt  vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells};
999d9deefdfSMatthew G. Knepley           const PetscInt *edges;
1000d9deefdfSMatthew G. Knepley           PetscInt        numEdges;
1001d9deefdfSMatthew G. Knepley 
1002d9deefdfSMatthew G. Knepley           ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
1003d9deefdfSMatthew G. Knepley           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
1004d988aadeSMatthew G. Knepley           if (rlabel) {ierr = DMLabelSetValue(rlabel, edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);}
1005d9deefdfSMatthew G. Knepley           ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
1006d9deefdfSMatthew G. Knepley         }
1007d9deefdfSMatthew G. Knepley       }
1008d9deefdfSMatthew G. Knepley       for (f = 0; f < out->numberoftrifaces; f++) {
1009d9deefdfSMatthew G. Knepley         if (out->trifacemarkerlist[f]) {
1010d9deefdfSMatthew G. Knepley           const PetscInt  vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells};
1011d9deefdfSMatthew G. Knepley           const PetscInt *faces;
1012d9deefdfSMatthew G. Knepley           PetscInt        numFaces;
1013d9deefdfSMatthew G. Knepley 
1014d9deefdfSMatthew G. Knepley           ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
1015d9deefdfSMatthew G. Knepley           if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces);
1016d988aadeSMatthew G. Knepley           if (rlabel) {ierr = DMLabelSetValue(rlabel, faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);}
1017d9deefdfSMatthew G. Knepley           ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
1018d9deefdfSMatthew G. Knepley         }
1019d9deefdfSMatthew G. Knepley       }
1020d9deefdfSMatthew G. Knepley     }
1021d9deefdfSMatthew G. Knepley     ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr);
1022d9deefdfSMatthew G. Knepley   }
1023d9deefdfSMatthew G. Knepley   ierr = PLCDestroy(&in);CHKERRQ(ierr);
1024d9deefdfSMatthew G. Knepley   ierr = PLCDestroy(&out);CHKERRQ(ierr);
1025d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
1026d9deefdfSMatthew G. Knepley }
1027d9deefdfSMatthew G. Knepley #endif /* PETSC_HAVE_CTETGEN */
1028d9deefdfSMatthew G. Knepley 
1029d9deefdfSMatthew G. Knepley #undef __FUNCT__
1030d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMPlexGenerate"
1031d9deefdfSMatthew G. Knepley /*@C
1032d9deefdfSMatthew G. Knepley   DMPlexGenerate - Generates a mesh.
1033d9deefdfSMatthew G. Knepley 
1034d9deefdfSMatthew G. Knepley   Not Collective
1035d9deefdfSMatthew G. Knepley 
1036d9deefdfSMatthew G. Knepley   Input Parameters:
1037d9deefdfSMatthew G. Knepley + boundary - The DMPlex boundary object
1038d9deefdfSMatthew G. Knepley . name - The mesh generation package name
1039d9deefdfSMatthew G. Knepley - interpolate - Flag to create intermediate mesh elements
1040d9deefdfSMatthew G. Knepley 
1041d9deefdfSMatthew G. Knepley   Output Parameter:
1042d9deefdfSMatthew G. Knepley . mesh - The DMPlex object
1043d9deefdfSMatthew G. Knepley 
1044d9deefdfSMatthew G. Knepley   Level: intermediate
1045d9deefdfSMatthew G. Knepley 
1046d9deefdfSMatthew G. Knepley .keywords: mesh, elements
1047d9deefdfSMatthew G. Knepley .seealso: DMPlexCreate(), DMRefine()
1048d9deefdfSMatthew G. Knepley @*/
1049d9deefdfSMatthew G. Knepley PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh)
1050d9deefdfSMatthew G. Knepley {
1051d9deefdfSMatthew G. Knepley   PetscInt       dim;
1052d9deefdfSMatthew G. Knepley   char           genname[1024];
1053d9deefdfSMatthew G. Knepley   PetscBool      isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg;
1054d9deefdfSMatthew G. Knepley   PetscErrorCode ierr;
1055d9deefdfSMatthew G. Knepley 
1056d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
1057d9deefdfSMatthew G. Knepley   PetscValidHeaderSpecific(boundary, DM_CLASSID, 1);
1058d9deefdfSMatthew G. Knepley   PetscValidLogicalCollectiveBool(boundary, interpolate, 2);
1059d9deefdfSMatthew G. Knepley   ierr = DMGetDimension(boundary, &dim);CHKERRQ(ierr);
1060c5929fdfSBarry Smith   ierr = PetscOptionsGetString(((PetscObject) boundary)->options,((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr);
1061d9deefdfSMatthew G. Knepley   if (flg) name = genname;
1062d9deefdfSMatthew G. Knepley   if (name) {
1063d9deefdfSMatthew G. Knepley     ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr);
1064d9deefdfSMatthew G. Knepley     ierr = PetscStrcmp(name, "tetgen",   &isTetgen);CHKERRQ(ierr);
1065d9deefdfSMatthew G. Knepley     ierr = PetscStrcmp(name, "ctetgen",  &isCTetgen);CHKERRQ(ierr);
1066d9deefdfSMatthew G. Knepley   }
1067d9deefdfSMatthew G. Knepley   switch (dim) {
1068d9deefdfSMatthew G. Knepley   case 1:
1069d9deefdfSMatthew G. Knepley     if (!name || isTriangle) {
1070d9deefdfSMatthew G. Knepley #if defined(PETSC_HAVE_TRIANGLE)
1071d9deefdfSMatthew G. Knepley       ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr);
1072d9deefdfSMatthew G. Knepley #else
1073d9deefdfSMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle.");
1074d9deefdfSMatthew G. Knepley #endif
1075d9deefdfSMatthew G. Knepley     } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name);
1076d9deefdfSMatthew G. Knepley     break;
1077d9deefdfSMatthew G. Knepley   case 2:
1078d9deefdfSMatthew G. Knepley     if (!name || isCTetgen) {
1079d9deefdfSMatthew G. Knepley #if defined(PETSC_HAVE_CTETGEN)
1080d9deefdfSMatthew G. Knepley       ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr);
1081d9deefdfSMatthew G. Knepley #else
1082d9deefdfSMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen.");
1083d9deefdfSMatthew G. Knepley #endif
1084d9deefdfSMatthew G. Knepley     } else if (isTetgen) {
1085d9deefdfSMatthew G. Knepley #if defined(PETSC_HAVE_TETGEN)
1086d9deefdfSMatthew G. Knepley       ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr);
1087d9deefdfSMatthew G. Knepley #else
1088*2ca110d9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --download-tetgen.");
1089d9deefdfSMatthew G. Knepley #endif
1090d9deefdfSMatthew G. Knepley     } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name);
1091d9deefdfSMatthew G. Knepley     break;
1092d9deefdfSMatthew G. Knepley   default:
1093d9deefdfSMatthew G. Knepley     SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim);
1094d9deefdfSMatthew G. Knepley   }
1095d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
1096d9deefdfSMatthew G. Knepley }
1097d9deefdfSMatthew G. Knepley 
1098d9deefdfSMatthew G. Knepley #undef __FUNCT__
1099d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMRefine_Plex"
1100d9deefdfSMatthew G. Knepley PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined)
1101d9deefdfSMatthew G. Knepley {
1102b28003e6SMatthew G. Knepley   PetscErrorCode (*refinementFunc)(const PetscReal [], PetscReal *);
1103d9deefdfSMatthew G. Knepley   PetscReal        refinementLimit;
1104d9deefdfSMatthew G. Knepley   PetscInt         dim, cStart, cEnd;
1105d9deefdfSMatthew G. Knepley   char             genname[1024], *name = NULL;
110636447a5eSToby Isaac   PetscBool        isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg, localized;
1107d9deefdfSMatthew G. Knepley   PetscErrorCode   ierr;
1108d9deefdfSMatthew G. Knepley 
1109d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
111036447a5eSToby Isaac   ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
1111d9deefdfSMatthew G. Knepley   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
1112d9deefdfSMatthew G. Knepley   if (isUniform) {
1113d9deefdfSMatthew G. Knepley     CellRefiner cellRefiner;
1114d9deefdfSMatthew G. Knepley 
1115d9deefdfSMatthew G. Knepley     ierr = DMPlexGetCellRefiner_Internal(dm, &cellRefiner);CHKERRQ(ierr);
1116d9deefdfSMatthew G. Knepley     ierr = DMPlexRefineUniform_Internal(dm, cellRefiner, dmRefined);CHKERRQ(ierr);
1117a6ba4734SToby Isaac     ierr = DMCopyBoundary(dm, *dmRefined);CHKERRQ(ierr);
111836447a5eSToby Isaac     if (localized) {
111936447a5eSToby Isaac       ierr = DMLocalizeCoordinates(*dmRefined);CHKERRQ(ierr);
112036447a5eSToby Isaac     }
1121d9deefdfSMatthew G. Knepley     PetscFunctionReturn(0);
1122d9deefdfSMatthew G. Knepley   }
1123d9deefdfSMatthew G. Knepley   ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr);
1124b28003e6SMatthew G. Knepley   ierr = DMPlexGetRefinementFunction(dm, &refinementFunc);CHKERRQ(ierr);
1125b28003e6SMatthew G. Knepley   if (refinementLimit == 0.0 && !refinementFunc) PetscFunctionReturn(0);
1126d9deefdfSMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1127d9deefdfSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1128c5929fdfSBarry Smith   ierr = PetscOptionsGetString(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr);
1129d9deefdfSMatthew G. Knepley   if (flg) name = genname;
1130d9deefdfSMatthew G. Knepley   if (name) {
1131d9deefdfSMatthew G. Knepley     ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr);
1132d9deefdfSMatthew G. Knepley     ierr = PetscStrcmp(name, "tetgen",   &isTetgen);CHKERRQ(ierr);
1133d9deefdfSMatthew G. Knepley     ierr = PetscStrcmp(name, "ctetgen",  &isCTetgen);CHKERRQ(ierr);
1134d9deefdfSMatthew G. Knepley   }
1135d9deefdfSMatthew G. Knepley   switch (dim) {
1136d9deefdfSMatthew G. Knepley   case 2:
1137d9deefdfSMatthew G. Knepley     if (!name || isTriangle) {
1138d9deefdfSMatthew G. Knepley #if defined(PETSC_HAVE_TRIANGLE)
1139d9deefdfSMatthew G. Knepley       double  *maxVolumes;
1140d9deefdfSMatthew G. Knepley       PetscInt c;
1141d9deefdfSMatthew G. Knepley 
1142854ce69bSBarry Smith       ierr = PetscMalloc1(cEnd - cStart, &maxVolumes);CHKERRQ(ierr);
1143b28003e6SMatthew G. Knepley       if (refinementFunc) {
1144b28003e6SMatthew G. Knepley         for (c = cStart; c < cEnd; ++c) {
1145b28003e6SMatthew G. Knepley           PetscReal vol, centroid[3];
1146b28003e6SMatthew G. Knepley 
1147b28003e6SMatthew G. Knepley           ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, centroid, NULL);CHKERRQ(ierr);
1148b28003e6SMatthew G. Knepley           ierr = (*refinementFunc)(centroid, &maxVolumes[c-cStart]);CHKERRQ(ierr);
1149b28003e6SMatthew G. Knepley         }
1150b28003e6SMatthew G. Knepley       } else {
1151d9deefdfSMatthew G. Knepley         for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit;
1152b28003e6SMatthew G. Knepley       }
1153d9deefdfSMatthew G. Knepley       ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr);
1154d9deefdfSMatthew G. Knepley       ierr = PetscFree(maxVolumes);CHKERRQ(ierr);
1155d9deefdfSMatthew G. Knepley #else
1156d9deefdfSMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle.");
1157d9deefdfSMatthew G. Knepley #endif
1158d9deefdfSMatthew G. Knepley     } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name);
1159d9deefdfSMatthew G. Knepley     break;
1160d9deefdfSMatthew G. Knepley   case 3:
1161d9deefdfSMatthew G. Knepley     if (!name || isCTetgen) {
1162d9deefdfSMatthew G. Knepley #if defined(PETSC_HAVE_CTETGEN)
1163d9deefdfSMatthew G. Knepley       PetscReal *maxVolumes;
1164d9deefdfSMatthew G. Knepley       PetscInt   c;
1165d9deefdfSMatthew G. Knepley 
1166854ce69bSBarry Smith       ierr = PetscMalloc1(cEnd - cStart, &maxVolumes);CHKERRQ(ierr);
1167b28003e6SMatthew G. Knepley       if (refinementFunc) {
1168b28003e6SMatthew G. Knepley         for (c = cStart; c < cEnd; ++c) {
1169b28003e6SMatthew G. Knepley           PetscReal vol, centroid[3];
1170b28003e6SMatthew G. Knepley 
1171b28003e6SMatthew G. Knepley           ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, centroid, NULL);CHKERRQ(ierr);
1172b28003e6SMatthew G. Knepley           ierr = (*refinementFunc)(centroid, &maxVolumes[c-cStart]);CHKERRQ(ierr);
1173b28003e6SMatthew G. Knepley         }
1174b28003e6SMatthew G. Knepley       } else {
1175d9deefdfSMatthew G. Knepley         for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit;
1176b28003e6SMatthew G. Knepley       }
1177d9deefdfSMatthew G. Knepley       ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr);
1178d9deefdfSMatthew G. Knepley #else
1179d9deefdfSMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen.");
1180d9deefdfSMatthew G. Knepley #endif
1181d9deefdfSMatthew G. Knepley     } else if (isTetgen) {
1182d9deefdfSMatthew G. Knepley #if defined(PETSC_HAVE_TETGEN)
1183d9deefdfSMatthew G. Knepley       double  *maxVolumes;
1184d9deefdfSMatthew G. Knepley       PetscInt c;
1185d9deefdfSMatthew G. Knepley 
1186854ce69bSBarry Smith       ierr = PetscMalloc1(cEnd - cStart, &maxVolumes);CHKERRQ(ierr);
1187b28003e6SMatthew G. Knepley       if (refinementFunc) {
1188b28003e6SMatthew G. Knepley         for (c = cStart; c < cEnd; ++c) {
1189b28003e6SMatthew G. Knepley           PetscReal vol, centroid[3];
1190b28003e6SMatthew G. Knepley 
1191b28003e6SMatthew G. Knepley           ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, centroid, NULL);CHKERRQ(ierr);
1192b28003e6SMatthew G. Knepley           ierr = (*refinementFunc)(centroid, &maxVolumes[c-cStart]);CHKERRQ(ierr);
1193b28003e6SMatthew G. Knepley         }
1194b28003e6SMatthew G. Knepley       } else {
1195d9deefdfSMatthew G. Knepley         for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit;
1196b28003e6SMatthew G. Knepley       }
1197d9deefdfSMatthew G. Knepley       ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr);
1198d9deefdfSMatthew G. Knepley #else
1199d9deefdfSMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen.");
1200d9deefdfSMatthew G. Knepley #endif
1201d9deefdfSMatthew G. Knepley     } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name);
1202d9deefdfSMatthew G. Knepley     break;
1203d9deefdfSMatthew G. Knepley   default:
1204d9deefdfSMatthew G. Knepley     SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim);
1205d9deefdfSMatthew G. Knepley   }
1206a6ba4734SToby Isaac   ierr = DMCopyBoundary(dm, *dmRefined);CHKERRQ(ierr);
120736447a5eSToby Isaac   if (localized) {
120836447a5eSToby Isaac     ierr = DMLocalizeCoordinates(*dmRefined);CHKERRQ(ierr);
120936447a5eSToby Isaac   }
1210d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
1211d9deefdfSMatthew G. Knepley }
1212d9deefdfSMatthew G. Knepley 
1213d9deefdfSMatthew G. Knepley #undef __FUNCT__
1214d9deefdfSMatthew G. Knepley #define __FUNCT__ "DMRefineHierarchy_Plex"
1215d9deefdfSMatthew G. Knepley PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM dmRefined[])
1216d9deefdfSMatthew G. Knepley {
1217d9deefdfSMatthew G. Knepley   DM             cdm = dm;
1218d9deefdfSMatthew G. Knepley   PetscInt       r;
121936447a5eSToby Isaac   PetscBool      isUniform, localized;
1220d9deefdfSMatthew G. Knepley   PetscErrorCode ierr;
1221d9deefdfSMatthew G. Knepley 
1222d9deefdfSMatthew G. Knepley   PetscFunctionBegin;
1223d9deefdfSMatthew G. Knepley   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
122436447a5eSToby Isaac   ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
1225d9deefdfSMatthew G. Knepley   if (!isUniform) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Non-uniform refinement is incompatible with the hierarchy");
1226d9deefdfSMatthew G. Knepley   for (r = 0; r < nlevels; ++r) {
1227d9deefdfSMatthew G. Knepley     CellRefiner cellRefiner;
1228d9deefdfSMatthew G. Knepley 
1229d9deefdfSMatthew G. Knepley     ierr = DMPlexGetCellRefiner_Internal(cdm, &cellRefiner);CHKERRQ(ierr);
1230d9deefdfSMatthew G. Knepley     ierr = DMPlexRefineUniform_Internal(cdm, cellRefiner, &dmRefined[r]);CHKERRQ(ierr);
1231a6ba4734SToby Isaac     ierr = DMCopyBoundary(cdm, dmRefined[r]);CHKERRQ(ierr);
123236447a5eSToby Isaac     if (localized) {
123336447a5eSToby Isaac       ierr = DMLocalizeCoordinates(dmRefined[r]);CHKERRQ(ierr);
123436447a5eSToby Isaac     }
1235a8fb8f29SToby Isaac     ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr);
12360aef6b92SMatthew G. Knepley     ierr = DMPlexSetRegularRefinement(dmRefined[r], PETSC_TRUE);CHKERRQ(ierr);
1237d9deefdfSMatthew G. Knepley     cdm  = dmRefined[r];
1238d9deefdfSMatthew G. Knepley   }
1239d9deefdfSMatthew G. Knepley   PetscFunctionReturn(0);
1240d9deefdfSMatthew G. Knepley }
1241