xref: /petsc/src/dm/impls/plex/plexply.c (revision f972091302c596e33e2f505caf9b0a44f6f2de12)
1*f9720913SMatthew G. Knepley #define PETSCDM_DLL
2*f9720913SMatthew G. Knepley #include <petsc/private/dmpleximpl.h>    /*I   "petscdmplex.h"   I*/
3*f9720913SMatthew G. Knepley 
4*f9720913SMatthew G. Knepley /*@C
5*f9720913SMatthew G. Knepley   DMPlexCreatePLYFromFile - Create a DMPlex mesh from a PLY file.
6*f9720913SMatthew G. Knepley 
7*f9720913SMatthew G. Knepley + comm        - The MPI communicator
8*f9720913SMatthew G. Knepley . filename    - Name of the .med file
9*f9720913SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
10*f9720913SMatthew G. Knepley 
11*f9720913SMatthew G. Knepley   Output Parameter:
12*f9720913SMatthew G. Knepley . dm  - The DM object representing the mesh
13*f9720913SMatthew G. Knepley 
14*f9720913SMatthew G. Knepley   Note: https://en.wikipedia.org/wiki/PLY_(file_format)
15*f9720913SMatthew G. Knepley 
16*f9720913SMatthew G. Knepley   Level: beginner
17*f9720913SMatthew G. Knepley 
18*f9720913SMatthew G. Knepley .seealso: DMPlexCreateFromFile(), DMPlexCreateMedFromFile(), DMPlexCreateGmsh(), DMPlexCreate()
19*f9720913SMatthew G. Knepley @*/
20*f9720913SMatthew G. Knepley PetscErrorCode DMPlexCreatePLYFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
21*f9720913SMatthew G. Knepley {
22*f9720913SMatthew G. Knepley   PetscViewer     viewer;
23*f9720913SMatthew G. Knepley   Vec             coordinates;
24*f9720913SMatthew G. Knepley   PetscSection    coordSection;
25*f9720913SMatthew G. Knepley   PetscScalar    *coords;
26*f9720913SMatthew G. Knepley   char            line[PETSC_MAX_PATH_LEN], ntype[16], itype[16], name[1024], vtype[16];
27*f9720913SMatthew G. Knepley   PetscBool       match, byteSwap = PETSC_FALSE;
28*f9720913SMatthew G. Knepley   PetscInt        dim = 2, cdim = 3, Nvp = 0, coordSize, xi, yi, zi, v, c, p;
29*f9720913SMatthew G. Knepley   PetscMPIInt     rank;
30*f9720913SMatthew G. Knepley   int             snum, Nv, Nc;
31*f9720913SMatthew G. Knepley   PetscErrorCode  ierr;
32*f9720913SMatthew G. Knepley 
33*f9720913SMatthew G. Knepley   PetscFunctionBegin;
34*f9720913SMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
35*f9720913SMatthew G. Knepley   ierr = PetscViewerCreate(comm, &viewer);CHKERRQ(ierr);
36*f9720913SMatthew G. Knepley   ierr = PetscViewerSetType(viewer, PETSCVIEWERBINARY);CHKERRQ(ierr);
37*f9720913SMatthew G. Knepley   ierr = PetscViewerFileSetMode(viewer, FILE_MODE_READ);CHKERRQ(ierr);
38*f9720913SMatthew G. Knepley   ierr = PetscViewerFileSetName(viewer, filename);CHKERRQ(ierr);
39*f9720913SMatthew G. Knepley   if (!rank) {
40*f9720913SMatthew G. Knepley     PetscBool isAscii, isBinaryBig, isBinaryLittle;
41*f9720913SMatthew G. Knepley 
42*f9720913SMatthew G. Knepley     /* Check for PLY file */
43*f9720913SMatthew G. Knepley     ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
44*f9720913SMatthew G. Knepley     ierr = PetscStrncmp(line, "ply", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
45*f9720913SMatthew G. Knepley     if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid PLY file");
46*f9720913SMatthew G. Knepley     /* Check PLY format */
47*f9720913SMatthew G. Knepley     ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
48*f9720913SMatthew G. Knepley     ierr = PetscStrncmp(line, "format", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
49*f9720913SMatthew G. Knepley     if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid PLY file");
50*f9720913SMatthew G. Knepley     ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
51*f9720913SMatthew G. Knepley     ierr = PetscStrncmp(line, "ascii", PETSC_MAX_PATH_LEN, &isAscii);CHKERRQ(ierr);
52*f9720913SMatthew G. Knepley     ierr = PetscStrncmp(line, "binary_big_endian", PETSC_MAX_PATH_LEN, &isBinaryBig);CHKERRQ(ierr);
53*f9720913SMatthew G. Knepley     ierr = PetscStrncmp(line, "binary_little_endian", PETSC_MAX_PATH_LEN, &isBinaryLittle);CHKERRQ(ierr);
54*f9720913SMatthew G. Knepley     if (isAscii) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "PLY ascii format not yet supported");
55*f9720913SMatthew G. Knepley     else if (isBinaryLittle) byteSwap = PETSC_TRUE;
56*f9720913SMatthew G. Knepley     ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
57*f9720913SMatthew G. Knepley     ierr = PetscStrncmp(line, "1.0", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
58*f9720913SMatthew G. Knepley     if (!match) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid version of PLY file, %s", line);
59*f9720913SMatthew G. Knepley     /* Ignore comments */
60*f9720913SMatthew G. Knepley     match = PETSC_TRUE;
61*f9720913SMatthew G. Knepley     while (match) {
62*f9720913SMatthew G. Knepley       char buf = '\0';
63*f9720913SMatthew G. Knepley       ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
64*f9720913SMatthew G. Knepley       ierr = PetscStrncmp(line, "comment", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
65*f9720913SMatthew G. Knepley       if (match) while (buf != '\n') {ierr = PetscViewerRead(viewer, &buf, 1, NULL, PETSC_CHAR);CHKERRQ(ierr);}
66*f9720913SMatthew G. Knepley     }
67*f9720913SMatthew G. Knepley     /* Read vertex information */
68*f9720913SMatthew G. Knepley     ierr = PetscStrncmp(line, "element", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
69*f9720913SMatthew G. Knepley     if (!match) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse PLY file header: %s", line);
70*f9720913SMatthew G. Knepley     ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
71*f9720913SMatthew G. Knepley     ierr = PetscStrncmp(line, "vertex", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
72*f9720913SMatthew G. Knepley     if (!match) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse PLY file header: %s", line);
73*f9720913SMatthew G. Knepley     ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
74*f9720913SMatthew G. Knepley     snum = sscanf(line, "%d", &Nv);
75*f9720913SMatthew G. Knepley     if (snum != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse PLY file header: %s", line);
76*f9720913SMatthew G. Knepley     match = PETSC_TRUE;
77*f9720913SMatthew G. Knepley     while (match) {
78*f9720913SMatthew G. Knepley       ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
79*f9720913SMatthew G. Knepley       ierr = PetscStrncmp(line, "property", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
80*f9720913SMatthew G. Knepley       if (match) {
81*f9720913SMatthew G. Knepley         PetscBool matchB;
82*f9720913SMatthew G. Knepley 
83*f9720913SMatthew G. Knepley         ierr = PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING);CHKERRQ(ierr);
84*f9720913SMatthew G. Knepley         if (Nvp >= 16) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot handle more than 16 property statements in PLY file header: %s", line);
85*f9720913SMatthew G. Knepley         snum = sscanf(line, "%s %s", ntype, name);
86*f9720913SMatthew G. Knepley         if (snum != 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse PLY file header: %s", line);
87*f9720913SMatthew G. Knepley         ierr = PetscStrncmp(ntype, "float32", 16, &matchB);CHKERRQ(ierr);
88*f9720913SMatthew G. Knepley         if (matchB) {
89*f9720913SMatthew G. Knepley           vtype[Nvp] = 'f';
90*f9720913SMatthew G. Knepley         } else {
91*f9720913SMatthew G. Knepley           ierr = PetscStrncmp(ntype, "int32", 16, &matchB);CHKERRQ(ierr);
92*f9720913SMatthew G. Knepley           if (matchB) {
93*f9720913SMatthew G. Knepley             vtype[Nvp] = 'd';
94*f9720913SMatthew G. Knepley           } else {
95*f9720913SMatthew G. Knepley             ierr = PetscStrncmp(ntype, "uint8", 16, &matchB);CHKERRQ(ierr);
96*f9720913SMatthew G. Knepley             if (matchB) {
97*f9720913SMatthew G. Knepley               vtype[Nvp] = 'c';
98*f9720913SMatthew G. Knepley             } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse type in PLY file header: %s", line);
99*f9720913SMatthew G. Knepley           }
100*f9720913SMatthew G. Knepley         }
101*f9720913SMatthew G. Knepley         ierr = PetscStrncmp(name, "x", 16, &matchB);CHKERRQ(ierr);
102*f9720913SMatthew G. Knepley         if (matchB) {xi = Nvp;}
103*f9720913SMatthew G. Knepley         ierr = PetscStrncmp(name, "y", 16, &matchB);CHKERRQ(ierr);
104*f9720913SMatthew G. Knepley         if (matchB) {yi = Nvp;}
105*f9720913SMatthew G. Knepley         ierr = PetscStrncmp(name, "z", 16, &matchB);CHKERRQ(ierr);
106*f9720913SMatthew G. Knepley         if (matchB) {zi = Nvp;}
107*f9720913SMatthew G. Knepley         ++Nvp;
108*f9720913SMatthew G. Knepley       }
109*f9720913SMatthew G. Knepley     }
110*f9720913SMatthew G. Knepley     /* Read cell information */
111*f9720913SMatthew G. Knepley     ierr = PetscStrncmp(line, "element", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
112*f9720913SMatthew G. Knepley     if (!match) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse PLY file header: %s", line);
113*f9720913SMatthew G. Knepley     ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
114*f9720913SMatthew G. Knepley     ierr = PetscStrncmp(line, "face", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
115*f9720913SMatthew G. Knepley     if (!match) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse PLY file header: %s", line);
116*f9720913SMatthew G. Knepley     ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
117*f9720913SMatthew G. Knepley     snum = sscanf(line, "%d", &Nc);
118*f9720913SMatthew G. Knepley     if (snum != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse PLY file header: %s", line);
119*f9720913SMatthew G. Knepley     ierr = PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING);CHKERRQ(ierr);
120*f9720913SMatthew G. Knepley     snum = sscanf(line, "property list %s %s %s", ntype, itype, name);
121*f9720913SMatthew G. Knepley     if (snum != 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse PLY file header: %s", line);
122*f9720913SMatthew G. Knepley     ierr = PetscStrncmp(ntype, "uint8", 1024, &match);CHKERRQ(ierr);
123*f9720913SMatthew G. Knepley     if (!match) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid size type in PLY file header: %s", line);
124*f9720913SMatthew G. Knepley     ierr = PetscStrncmp(name, "vertex_indices", 1024, &match);CHKERRQ(ierr);
125*f9720913SMatthew G. Knepley     if (!match) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid property in PLY file header: %s", line);
126*f9720913SMatthew G. Knepley     /* Header should terminate */
127*f9720913SMatthew G. Knepley     ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
128*f9720913SMatthew G. Knepley     ierr = PetscStrncmp(line, "end_header", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr);
129*f9720913SMatthew G. Knepley     if (!match) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid PLY file: %s", line);
130*f9720913SMatthew G. Knepley   }
131*f9720913SMatthew G. Knepley   ierr = DMCreate(comm, dm);CHKERRQ(ierr);
132*f9720913SMatthew G. Knepley   ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr);
133*f9720913SMatthew G. Knepley   ierr = DMPlexSetChart(*dm, 0, Nc+Nv);CHKERRQ(ierr);
134*f9720913SMatthew G. Knepley   ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr);
135*f9720913SMatthew G. Knepley   ierr = DMSetCoordinateDim(*dm, cdim);CHKERRQ(ierr);
136*f9720913SMatthew G. Knepley   /* Read coordinates */
137*f9720913SMatthew G. Knepley   ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr);
138*f9720913SMatthew G. Knepley   ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr);
139*f9720913SMatthew G. Knepley   ierr = PetscSectionSetFieldComponents(coordSection, 0, cdim);CHKERRQ(ierr);
140*f9720913SMatthew G. Knepley   ierr = PetscSectionSetChart(coordSection, Nc, Nc + Nv);CHKERRQ(ierr);
141*f9720913SMatthew G. Knepley   for (v = Nc; v < Nc+Nv; ++v) {
142*f9720913SMatthew G. Knepley     ierr = PetscSectionSetDof(coordSection, v, cdim);CHKERRQ(ierr);
143*f9720913SMatthew G. Knepley     ierr = PetscSectionSetFieldDof(coordSection, v, 0, cdim);CHKERRQ(ierr);
144*f9720913SMatthew G. Knepley   }
145*f9720913SMatthew G. Knepley   ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr);
146*f9720913SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr);
147*f9720913SMatthew G. Knepley   ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr);
148*f9720913SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr);
149*f9720913SMatthew G. Knepley   ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr);
150*f9720913SMatthew G. Knepley   ierr = VecSetBlockSize(coordinates, cdim);CHKERRQ(ierr);
151*f9720913SMatthew G. Knepley   ierr = VecSetType(coordinates, VECSTANDARD);CHKERRQ(ierr);
152*f9720913SMatthew G. Knepley   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
153*f9720913SMatthew G. Knepley   if (!rank) {
154*f9720913SMatthew G. Knepley     float rbuf[1];
155*f9720913SMatthew G. Knepley     int   ibuf[1];
156*f9720913SMatthew G. Knepley 
157*f9720913SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
158*f9720913SMatthew G. Knepley       for (p = 0; p < Nvp; ++p) {
159*f9720913SMatthew G. Knepley         if (vtype[p] == 'f') {
160*f9720913SMatthew G. Knepley           ierr = PetscViewerRead(viewer, &rbuf, 1, NULL, PETSC_FLOAT);CHKERRQ(ierr);
161*f9720913SMatthew G. Knepley           if (byteSwap) ierr = PetscByteSwap(&rbuf, PETSC_FLOAT, 1);CHKERRQ(ierr);
162*f9720913SMatthew G. Knepley           if      (p == xi) coords[v*cdim+0] = rbuf[0];
163*f9720913SMatthew G. Knepley           else if (p == yi) coords[v*cdim+1] = rbuf[0];
164*f9720913SMatthew G. Knepley           else if (p == zi) coords[v*cdim+2] = rbuf[0];
165*f9720913SMatthew G. Knepley         } else if (vtype[p] == 'd') {
166*f9720913SMatthew G. Knepley           ierr = PetscViewerRead(viewer, &ibuf, 1, NULL, PETSC_INT);CHKERRQ(ierr);
167*f9720913SMatthew G. Knepley           if (byteSwap) ierr = PetscByteSwap(&ibuf, PETSC_INT, 1);CHKERRQ(ierr);
168*f9720913SMatthew G. Knepley         } else if (vtype[p] == 'c') {
169*f9720913SMatthew G. Knepley           ierr = PetscViewerRead(viewer, &ibuf, 1, NULL, PETSC_CHAR);CHKERRQ(ierr);
170*f9720913SMatthew G. Knepley         } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid vertex property type in PLY file");
171*f9720913SMatthew G. Knepley       }
172*f9720913SMatthew G. Knepley     }
173*f9720913SMatthew G. Knepley   }
174*f9720913SMatthew G. Knepley   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
175*f9720913SMatthew G. Knepley   ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr);
176*f9720913SMatthew G. Knepley   ierr = VecDestroy(&coordinates);CHKERRQ(ierr);
177*f9720913SMatthew G. Knepley   /* Read topology */
178*f9720913SMatthew G. Knepley   if (!rank) {
179*f9720913SMatthew G. Knepley     char     ibuf[1];
180*f9720913SMatthew G. Knepley     PetscInt vbuf[16], corners;
181*f9720913SMatthew G. Knepley 
182*f9720913SMatthew G. Knepley     /* Assume same cells */
183*f9720913SMatthew G. Knepley     ierr = PetscViewerRead(viewer, &ibuf, 1, NULL, PETSC_CHAR);CHKERRQ(ierr);
184*f9720913SMatthew G. Knepley     corners = ibuf[0];
185*f9720913SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {ierr = DMPlexSetConeSize(*dm, c, corners);CHKERRQ(ierr);}
186*f9720913SMatthew G. Knepley     ierr = DMSetUp(*dm);CHKERRQ(ierr);
187*f9720913SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
188*f9720913SMatthew G. Knepley       if (c > 0) {
189*f9720913SMatthew G. Knepley         ierr = PetscViewerRead(viewer, &ibuf, 1, NULL, PETSC_CHAR);CHKERRQ(ierr);
190*f9720913SMatthew G. Knepley       }
191*f9720913SMatthew G. Knepley       if (ibuf[0] != corners) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "All cells must have the same number of vertices in PLY file: %D != %D", ibuf[0], corners);
192*f9720913SMatthew G. Knepley       ierr = PetscViewerRead(viewer, &vbuf, ibuf[0], NULL, PETSC_INT);CHKERRQ(ierr);
193*f9720913SMatthew G. Knepley       if (byteSwap) ierr = PetscByteSwap(&vbuf, PETSC_INT, ibuf[0]);CHKERRQ(ierr);
194*f9720913SMatthew G. Knepley       for (v = 0; v < ibuf[0]; ++v) vbuf[v] += Nc;
195*f9720913SMatthew G. Knepley       ierr = DMPlexSetCone(*dm, c, vbuf);CHKERRQ(ierr);
196*f9720913SMatthew G. Knepley     }
197*f9720913SMatthew G. Knepley   }
198*f9720913SMatthew G. Knepley   ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr);
199*f9720913SMatthew G. Knepley   ierr = DMPlexStratify(*dm);CHKERRQ(ierr);
200*f9720913SMatthew G. Knepley   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
201*f9720913SMatthew G. Knepley   if (interpolate) {
202*f9720913SMatthew G. Knepley     DM idm = NULL;
203*f9720913SMatthew G. Knepley 
204*f9720913SMatthew G. Knepley     ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr);
205*f9720913SMatthew G. Knepley     ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr);
206*f9720913SMatthew G. Knepley     ierr = DMDestroy(dm);CHKERRQ(ierr);
207*f9720913SMatthew G. Knepley     *dm  = idm;
208*f9720913SMatthew G. Knepley   }
209*f9720913SMatthew G. Knepley   PetscFunctionReturn(0);
210*f9720913SMatthew G. Knepley }
211