Actual source code: plexexodusii.c
petsc-3.4.5 2014-06-29
1: #define PETSCDM_DLL
2: #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/
4: #if defined(PETSC_HAVE_EXODUSII)
5: #include <netcdf.h>
6: #include <exodusII.h>
7: #endif
11: /*@
12: DMPlexCreateExodus - Create a DMPlex mesh from an ExodusII file.
14: Collective on comm
16: Input Parameters:
17: + comm - The MPI communicator
18: . exoid - The ExodusII id associated with a exodus file and obtained using ex_open
19: - interpolate - Create faces and edges in the mesh
21: Output Parameter:
22: . dm - The DM object representing the mesh
24: Level: beginner
26: .keywords: mesh,ExodusII
27: .seealso: DMPLEX, DMCreate()
28: @*/
29: PetscErrorCode DMPlexCreateExodus(MPI_Comm comm, PetscInt exoid, PetscBool interpolate, DM *dm)
30: {
31: #if defined(PETSC_HAVE_EXODUSII)
32: PetscMPIInt num_proc, rank;
33: PetscSection coordSection;
34: Vec coordinates;
35: PetscScalar *coords;
36: PetscInt coordSize, v;
38: /* Read from ex_get_init() */
39: char title[PETSC_MAX_PATH_LEN+1];
40: int dim = 0, numVertices = 0, numCells = 0;
41: int num_cs = 0, num_vs = 0, num_fs = 0;
42: #endif
45: #if defined(PETSC_HAVE_EXODUSII)
46: MPI_Comm_rank(comm, &rank);
47: MPI_Comm_size(comm, &num_proc);
48: DMCreate(comm, dm);
49: DMSetType(*dm, DMPLEX);
50: /* Open EXODUS II file and read basic informations on rank 0, then broadcast to all processors */
51: if (!rank) {
52: PetscMemzero(title,(PETSC_MAX_PATH_LEN+1)*sizeof(char));
53: ex_get_init(exoid, title, &dim, &numVertices, &numCells, &num_cs, &num_vs, &num_fs);
54: if (ierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"ExodusII ex_get_init() failed with error code %D\n",ierr);
55: if (!num_cs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Exodus file does not contain any cell set\n");
56: }
57: MPI_Bcast(title, PETSC_MAX_PATH_LEN+1, MPI_CHAR, 0, comm);
58: MPI_Bcast(&dim, 1, MPI_INT, 0, comm);
59: PetscObjectSetName((PetscObject) *dm, title);
60: DMPlexSetDimension(*dm, dim);
61: DMPlexSetChart(*dm, 0, numCells+numVertices);
63: /* Read cell sets information */
64: if (!rank) {
65: PetscInt *cone;
66: int c, cs, c_loc, v, v_loc;
67: /* Read from ex_get_elem_blk_ids() */
68: int *cs_id;
69: /* Read from ex_get_elem_block() */
70: char buffer[PETSC_MAX_PATH_LEN+1];
71: int num_cell_in_set, num_vertex_per_cell, num_attr;
72: /* Read from ex_get_elem_conn() */
73: int *cs_connect;
75: /* Get cell sets IDs */
76: PetscMalloc(num_cs * sizeof(int), &cs_id);
77: ex_get_elem_blk_ids(exoid, cs_id);
78: /* Read the cell set connectivity table and build mesh topology
79: EXO standard requires that cells in cell sets be numbered sequentially and be pairwise disjoint. */
80: /* First set sizes */
81: for (cs = 0, c = 0; cs < num_cs; cs++) {
82: ex_get_elem_block(exoid, cs_id[cs], buffer, &num_cell_in_set, &num_vertex_per_cell, &num_attr);
83: for (c_loc = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
84: DMPlexSetConeSize(*dm, c, num_vertex_per_cell);
85: }
86: }
87: DMSetUp(*dm);
88: for (cs = 0, c = 0; cs < num_cs; cs++) {
89: ex_get_elem_block(exoid, cs_id[cs], buffer, &num_cell_in_set, &num_vertex_per_cell, &num_attr);
90: PetscMalloc2(num_vertex_per_cell*num_cell_in_set,int,&cs_connect,num_vertex_per_cell,PetscInt,&cone);
91: ex_get_elem_conn(exoid, cs_id[cs], cs_connect);
92: /* EXO uses Fortran-based indexing, sieve uses C-style and numbers cell first then vertices. */
93: for (c_loc = 0, v = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
94: for (v_loc = 0; v_loc < num_vertex_per_cell; ++v_loc, ++v) {
95: cone[v_loc] = cs_connect[v]+numCells-1;
96: }
97: if (dim == 3) {
98: /* Tetrahedra are inverted */
99: if (num_vertex_per_cell == 4) {
100: PetscInt tmp = cone[0];
101: cone[0] = cone[1];
102: cone[1] = tmp;
103: }
104: /* Hexahedra are inverted */
105: if (num_vertex_per_cell == 8) {
106: PetscInt tmp = cone[1];
107: cone[1] = cone[3];
108: cone[3] = tmp;
109: }
110: }
111: DMPlexSetCone(*dm, c, cone);
112: DMPlexSetLabelValue(*dm, "Cell Sets", c, cs_id[cs]);
113: }
114: PetscFree2(cs_connect,cone);
115: }
116: PetscFree(cs_id);
117: }
118: DMPlexSymmetrize(*dm);
119: DMPlexStratify(*dm);
120: if (interpolate) {
121: DM idm;
123: DMPlexInterpolate(*dm, &idm);
124: /* Maintain Cell Sets label */
125: {
126: DMLabel label;
128: DMPlexRemoveLabel(*dm, "Cell Sets", &label);
129: if (label) {DMPlexAddLabel(idm, label);}
130: }
131: DMDestroy(dm);
132: *dm = idm;
133: }
135: /* Create vertex set label */
136: if (!rank && (num_vs > 0)) {
137: int vs, v;
138: /* Read from ex_get_node_set_ids() */
139: int *vs_id;
140: /* Read from ex_get_node_set_param() */
141: int num_vertex_in_set, num_attr;
142: /* Read from ex_get_node_set() */
143: int *vs_vertex_list;
145: /* Get vertex set ids */
146: PetscMalloc(num_vs * sizeof(int), &vs_id);
147: ex_get_node_set_ids(exoid, vs_id);
148: for (vs = 0; vs < num_vs; ++vs) {
149: ex_get_node_set_param(exoid, vs_id[vs], &num_vertex_in_set, &num_attr);
150: PetscMalloc(num_vertex_in_set * sizeof(int), &vs_vertex_list);
151: ex_get_node_set(exoid, vs_id[vs], vs_vertex_list);
152: for (v = 0; v < num_vertex_in_set; ++v) {
153: DMPlexSetLabelValue(*dm, "Vertex Sets", vs_vertex_list[v]+numCells-1, vs_id[vs]);
154: }
155: PetscFree(vs_vertex_list);
156: }
157: PetscFree(vs_id);
158: }
159: /* Read coordinates */
160: DMPlexGetCoordinateSection(*dm, &coordSection);
161: PetscSectionSetNumFields(coordSection, 1);
162: PetscSectionSetFieldComponents(coordSection, 0, dim);
163: PetscSectionSetChart(coordSection, numCells, numCells + numVertices);
164: for (v = numCells; v < numCells+numVertices; ++v) {
165: PetscSectionSetDof(coordSection, v, dim);
166: PetscSectionSetFieldDof(coordSection, v, 0, dim);
167: }
168: PetscSectionSetUp(coordSection);
169: PetscSectionGetStorageSize(coordSection, &coordSize);
170: VecCreate(comm, &coordinates);
171: PetscObjectSetName((PetscObject) coordinates, "coordinates");
172: VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);
173: VecSetFromOptions(coordinates);
174: VecGetArray(coordinates, &coords);
175: if (!rank) {
176: float *x, *y, *z;
178: PetscMalloc3(numVertices,float,&x,numVertices,float,&y,numVertices,float,&z);
179: ex_get_coord(exoid, x, y, z);
180: if (dim > 0) {
181: for (v = 0; v < numVertices; ++v) coords[v*dim+0] = x[v];
182: }
183: if (dim > 1) {
184: for (v = 0; v < numVertices; ++v) coords[v*dim+1] = y[v];
185: }
186: if (dim > 2) {
187: for (v = 0; v < numVertices; ++v) coords[v*dim+2] = z[v];
188: }
189: PetscFree3(x,y,z);
190: }
191: VecRestoreArray(coordinates, &coords);
192: DMSetCoordinatesLocal(*dm, coordinates);
193: VecDestroy(&coordinates);
195: /* Create side set label */
196: if (!rank && interpolate && (num_fs > 0)) {
197: int fs, f, voff;
198: /* Read from ex_get_side_set_ids() */
199: int *fs_id;
200: /* Read from ex_get_side_set_param() */
201: int num_side_in_set, num_dist_fact_in_set;
202: /* Read from ex_get_side_set_node_list() */
203: int *fs_vertex_count_list, *fs_vertex_list;
205: /* Get side set ids */
206: PetscMalloc(num_fs * sizeof(int), &fs_id);
207: ex_get_side_set_ids(exoid, fs_id);
208: for (fs = 0; fs < num_fs; ++fs) {
209: ex_get_side_set_param(exoid, fs_id[fs], &num_side_in_set, &num_dist_fact_in_set);
210: PetscMalloc2(num_side_in_set,int,&fs_vertex_count_list,num_side_in_set*4,int,&fs_vertex_list);
211: ex_get_side_set_node_list(exoid, fs_id[fs], fs_vertex_count_list, fs_vertex_list);
212: for (f = 0, voff = 0; f < num_side_in_set; ++f) {
213: const PetscInt *faces = NULL;
214: PetscInt faceSize = fs_vertex_count_list[f], numFaces;
215: PetscInt faceVertices[4], v;
217: if (faceSize > 4) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "ExodusII side cannot have %d > 4 vertices", faceSize);
218: for (v = 0; v < faceSize; ++v, ++voff) {
219: faceVertices[v] = fs_vertex_list[voff]+numCells-1;
220: }
221: DMPlexGetFullJoin(*dm, faceSize, faceVertices, &numFaces, &faces);
222: if (numFaces != 1) SETERRQ3(comm, PETSC_ERR_ARG_WRONG, "Invalid ExodusII side %d in set %d maps to %d faces", f, fs, numFaces);
223: DMPlexSetLabelValue(*dm, "Face Sets", faces[0], fs_id[fs]);
224: DMPlexRestoreJoin(*dm, faceSize, faceVertices, &numFaces, &faces);
225: }
226: PetscFree2(fs_vertex_count_list,fs_vertex_list);
227: }
228: PetscFree(fs_id);
229: }
230: #else
231: SETERRQ(comm, PETSC_ERR_SUP, "This method requires ExodusII support. Reconfigure using --download-exodusii");
232: #endif
233: return(0);
234: }