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