Actual source code: meshpylith.c
1: #include <petscmesh_formats.hh> /*I "petscmesh.h" I*/
3: #include<list>
4: #include<map>
6: namespace ALE {
7: namespace PyLith {
8: //
9: // Builder methods
10: //
11: inline void Builder::ignoreComments(char *buf, PetscInt bufSize, FILE *f) {
12: while((fgets(buf, bufSize, f) != NULL) && ((buf[0] == '#') || (buf[0] == '\0'))) {}
13: };
14: void Builder::readConnectivity(MPI_Comm comm, const std::string& filename, int& corners, const bool useZeroBase, int& numElements, int *vertices[], int *materials[]) {
15: PetscViewer viewer;
16: FILE *f;
17: PetscInt maxCells = 1024, cellCount = 0;
18: PetscInt *verts;
19: PetscInt *mats;
20: char buf[2048];
21: PetscInt c;
22: PetscInt commRank;
25: MPI_Comm_rank(comm, &commRank);
26: if (commRank != 0) return;
27: PetscViewerCreate(PETSC_COMM_SELF, &viewer);
28: PetscViewerSetType(viewer, PETSC_VIEWER_ASCII);
29: PetscViewerFileSetMode(viewer, FILE_MODE_READ);
30: PetscViewerFileSetName(viewer, filename.c_str());
31: PetscViewerASCIIGetPointer(viewer, &f);
32: /* Ignore comments */
33: ignoreComments(buf, 2048, f);
34: do {
35: const char *v = strtok(buf, " ");
36: int elementType;
38: if (cellCount == maxCells) {
39: PetscInt *vtmp, *mtmp;
41: vtmp = verts;
42: mtmp = mats;
43: PetscMalloc2(maxCells*2*corners,PetscInt,&verts,maxCells*2,PetscInt,&mats);
44: PetscMemcpy(verts, vtmp, maxCells*corners * sizeof(PetscInt));
45: PetscMemcpy(mats, mtmp, maxCells * sizeof(PetscInt));
46: PetscFree2(vtmp,mtmp);
47: maxCells *= 2;
48: }
49: /* Ignore cell number */
50: v = strtok(NULL, " ");
51: /* Get element type */
52: elementType = atoi(v);
53: if (elementType == 1) {
54: corners = 8;
55: } else if (elementType == 5) {
56: corners = 4;
57: } else {
58: ostringstream msg;
60: msg << "We do not accept element type " << elementType << " right now";
61: throw ALE::Exception(msg.str().c_str());
62: }
63: if (cellCount == 0) {
64: PetscMalloc2(maxCells*corners,PetscInt,&verts,maxCells,PetscInt,&mats);
65: }
66: v = strtok(NULL, " ");
67: /* Store material type */
68: mats[cellCount] = atoi(v);
69: v = strtok(NULL, " ");
70: /* Ignore infinite domain element code */
71: v = strtok(NULL, " ");
72: for(c = 0; c < corners; c++) {
73: int vertex = atoi(v);
74:
75: if (!useZeroBase) vertex -= 1;
76: verts[cellCount*corners+c] = vertex;
77: v = strtok(NULL, " ");
78: }
79: cellCount++;
80: } while(fgets(buf, 2048, f) != NULL);
81: PetscViewerDestroy(viewer);
82: numElements = cellCount;
83: *vertices = verts;
84: *materials = mats;
85: };
86: void Builder::readCoordinates(MPI_Comm comm, const std::string& filename, const int dim, int& numVertices, double *coordinates[]) {
87: PetscViewer viewer;
88: FILE *f;
89: PetscInt maxVerts = 1024, vertexCount = 0;
90: PetscReal *coords;
91: double scaleFactor = 1.0;
92: char buf[2048];
93: PetscInt c;
94: PetscInt commRank;
97: MPI_Comm_rank(comm, &commRank);
98: if (commRank == 0) {
99: PetscViewerCreate(PETSC_COMM_SELF, &viewer);
100: PetscViewerSetType(viewer, PETSC_VIEWER_ASCII);
101: PetscViewerFileSetMode(viewer, FILE_MODE_READ);
102: PetscViewerFileSetName(viewer, filename.c_str());
103: PetscViewerASCIIGetPointer(viewer, &f);
104: /* Ignore comments */
105: ignoreComments(buf, 2048, f);
106: PetscMalloc(maxVerts*dim * sizeof(PetscReal), &coords);
107: /* Read units */
108: const char *units = strtok(buf, " ");
109: if (strcmp(units, "coord_units")) {
110: throw ALE::Exception("Invalid coordinate units line");
111: }
112: units = strtok(NULL, " ");
113: if (strcmp(units, "=")) {
114: throw ALE::Exception("Invalid coordinate units line");
115: }
116: units = strtok(NULL, " ");
117: if (!strcmp(units, "km")) {
118: /* Should use Pythia to do units conversion */
119: scaleFactor = 1000.0;
120: }
121: /* Ignore comments */
122: ignoreComments(buf, 2048, f);
123: do {
124: const char *x = strtok(buf, " ");
126: if (vertexCount == maxVerts) {
127: PetscReal *ctmp;
129: ctmp = coords;
130: PetscMalloc(maxVerts*2*dim * sizeof(PetscReal), &coords);
131: PetscMemcpy(coords, ctmp, maxVerts*dim * sizeof(PetscReal));
132: PetscFree(ctmp);
133: maxVerts *= 2;
134: }
135: /* Ignore vertex number */
136: x = strtok(NULL, " ");
137: for(c = 0; c < dim; c++) {
138: coords[vertexCount*dim+c] = atof(x)*scaleFactor;
139: x = strtok(NULL, " ");
140: }
141: vertexCount++;
142: } while(fgets(buf, 2048, f) != NULL);
143: PetscViewerDestroy(viewer);
144: numVertices = vertexCount;
145: *coordinates = coords;
146: }
147: };
148: // numSplit is the number of split node entries (lines in the file)
149: // splitInd[] is an array of numSplit pairs, <element, vertex>
150: // splitValues[] is an array of numSplit*dim displacements
151: void Builder::readSplit(MPI_Comm comm, const std::string& filename, const int dim, const bool useZeroBase, int& numSplit, int *splitInd[], int *loadHistory[], double *splitValues[]) {
152: PetscViewer viewer;
153: FILE *f;
154: PetscInt maxSplit = 1024, splitCount = 0;
155: PetscInt *splitId;
156: PetscInt *loadHist;
157: PetscReal *splitVal;
158: char buf[2048];
159: PetscInt c;
160: PetscInt commRank;
163: MPI_Comm_rank(comm, &commRank);
164: if (dim != 3) {
165: throw ALE::Exception("PyLith only works in 3D");
166: }
167: if (commRank != 0) return;
168: PetscViewerCreate(PETSC_COMM_SELF, &viewer);
169: PetscViewerSetType(viewer, PETSC_VIEWER_ASCII);
170: PetscViewerFileSetMode(viewer, FILE_MODE_READ);
171: PetscExceptionTry1(PetscViewerFileSetName(viewer, filename.c_str()), PETSC_ERR_FILE_OPEN);
172: if (PetscExceptionValue(ierr)) {
173: // this means that a caller above me has also tryed this exception so I don't handle it here, pass it up
174: } else if (PetscExceptionCaught(ierr,PETSC_ERR_FILE_OPEN)) {
175: // File does not exist
176: return;
177: }
178: PetscViewerASCIIGetPointer(viewer, &f);
179: /* Ignore comments */
180: ignoreComments(buf, 2048, f);
181: PetscMalloc3(maxSplit*2,PetscInt,&splitId,maxSplit,PetscInt,&loadHist,maxSplit*dim,PetscReal,&splitVal);
182: do {
183: const char *s = strtok(buf, " ");
185: if (splitCount == maxSplit) {
186: PetscInt *sitmp;
187: PetscInt *lhtmp;
188: PetscReal *svtmp;
190: sitmp = splitId;
191: lhtmp = loadHist;
192: svtmp = splitVal;
193: PetscMalloc3(maxSplit*2*2,PetscInt,&splitId,maxSplit*2,PetscInt,&loadHist,maxSplit*dim*2,PetscScalar,&splitVal);
194: PetscMemcpy(splitId, sitmp, maxSplit*2 * sizeof(PetscInt));
195: PetscMemcpy(loadHist, lhtmp, maxSplit * sizeof(PetscInt));
196: PetscMemcpy(splitVal, svtmp, maxSplit*dim * sizeof(PetscReal));
197: PetscFree3(sitmp,lhtmp,svtmp);
198: maxSplit *= 2;
199: }
200: /* Get element number */
201: int elem = atoi(s);
202: if (!useZeroBase) elem -= 1;
203: splitId[splitCount*2+0] = elem;
204: s = strtok(NULL, " ");
205: /* Get node number */
206: int node = atoi(s);
207: if (!useZeroBase) node -= 1;
208: splitId[splitCount*2+1] = node;
209: s = strtok(NULL, " ");
210: /* Ignore load history number */
211: loadHist[splitCount] = atoi(s);
212: s = strtok(NULL, " ");
213: /* Get split values */
214: for(c = 0; c < dim; c++) {
215: splitVal[splitCount*dim+c] = atof(s);
216: s = strtok(NULL, " ");
217: }
218: splitCount++;
219: } while(fgets(buf, 2048, f) != NULL);
220: PetscViewerDestroy(viewer);
221: numSplit = splitCount;
222: *splitInd = splitId;
223: *loadHistory = loadHist;
224: *splitValues = splitVal;
225: };
226: #if 0
227: void Builder::buildSplit(const Obj<pair_section_type>& splitField, const Obj<int_section_type>& loadField, int numCells, int numSplit, int splitInd[], int loadHistory[], double splitVals[]) {
228: const pair_section_type::patch_type patch = 0;
229: pair_section_type::value_type *values;
230: int_section_type::value_type *history;
231: std::map<pair_section_type::point_type, std::set<int> > elem2index;
232: int numValues = 0;
234: splitField->setName("split");
235: for(int e = 0; e < numSplit; e++) {
236: splitField->addFiberDimension(patch, splitInd[e*2+0], 1);
237: loadField->addFiberDimension(patch, splitInd[e*2+0], 1);
238: elem2index[splitInd[e*2+0]].insert(e);
239: }
240: splitField->allocate();
241: loadField->allocate();
242: for(std::map<pair_section_type::point_type, std::set<int> >::const_iterator e_iter = elem2index.begin(); e_iter != elem2index.end(); ++e_iter) {
243: numValues = std::max(numValues, (int) e_iter->second.size());
244: }
245: values = new pair_section_type::value_type[numValues];
246: history = new int_section_type::value_type[numValues];
247: for(std::map<pair_section_type::point_type, std::set<int> >::const_iterator e_iter = elem2index.begin(); e_iter != elem2index.end(); ++e_iter) {
248: const pair_section_type::point_type& e = e_iter->first;
249: int k = 0;
251: for(std::set<int>::const_iterator i_iter = e_iter->second.begin(); i_iter != e_iter->second.end(); ++i_iter, ++k) {
252: const int& i = *i_iter;
254: if (k >= numValues) {throw ALE::Exception("Invalid split node input");}
255: values[k].first = splitInd[i*2+1] + numCells;
256: values[k].second.x = splitVals[i*3+0];
257: values[k].second.y = splitVals[i*3+1];
258: values[k].second.z = splitVals[i*3+2];
259: history[k] = loadHistory[i];
260: }
261: splitField->updatePoint(patch, e, values);
262: loadField->updatePoint(patch, e, history);
263: }
264: delete [] values;
265: };
266: #endif
267: #ifdef PETSC_OPT_SIEVE
268: void Builder::readTractions(MPI_Comm comm, const std::string& filename, const int dim, const int& corners, const bool useZeroBase, int& numTractions, int& vertsPerFace, int *tractionVertices[], double *tractionValues[]) {
269: throw ALE::Exception("Not implemented for optimized sieves");
270: };
271: void Builder::buildTractions(const Obj<real_section_type>& tractionField, const Obj<Mesh>& boundaryMesh, int numCells, int numTractions, int vertsPerFace, int tractionVertices[], double tractionValues[]) {
272: throw ALE::Exception("Not implemented for optimized sieves");
273: };
274: void Builder::buildMaterials(const Obj<Mesh>& mesh, const Obj<int_section_type>& matField, const int materials[]) {
275: throw ALE::Exception("Not implemented for optimized sieves");
276: };
277: Obj<Builder::Mesh> Builder::readMesh(MPI_Comm comm, const int dim, const std::string& basename, const bool useZeroBase = false, const bool interpolate = false, const int debug = 0) {
278: throw ALE::Exception("Not implemented for optimized sieves");
279: };
280: Obj<Builder::Mesh> Builder::createTraction(const Obj<Mesh>& mesh, const std::string& basename, const bool useZeroBase = false) {
281: throw ALE::Exception("Not implemented for optimized sieves");
282: };
283: void Builder::createCohesiveElements(const Obj<Mesh>& mesh, const std::set<Mesh::point_type>& faultVertices) {
284: throw ALE::Exception("Not implemented for optimized sieves");
285: };
286: PetscErrorCode Viewer::writeVertices(const Obj<Mesh>& mesh, PetscViewer viewer) {
287: throw ALE::Exception("Not implemented for optimized sieves");
288: };
289: PetscErrorCode Viewer::writeElements(const Obj<Mesh>& mesh, const Obj<Builder::int_section_type>& materialField, PetscViewer viewer) {
290: throw ALE::Exception("Not implemented for optimized sieves");
291: };
292: PetscErrorCode Viewer::writeVerticesLocal(const Obj<Mesh>& mesh, PetscViewer viewer) {
293: throw ALE::Exception("Not implemented for optimized sieves");
294: };
295: PetscErrorCode Viewer::writeElementsLocal(const Obj<Mesh>& mesh, const Obj<Builder::int_section_type>& materialField, PetscViewer viewer) {
296: throw ALE::Exception("Not implemented for optimized sieves");
297: };
298: PetscErrorCode Viewer::writeTractionsLocal(const Obj<Mesh>& mesh, const Obj<Mesh>& tractionMesh, const Obj<Builder::real_section_type>& tractionField, PetscViewer viewer) {
299: throw ALE::Exception("Not implemented for optimized sieves");
300: };
301: #else
302: void Builder::readTractions(MPI_Comm comm, const std::string& filename, const int dim, const int& corners, const bool useZeroBase, int& numTractions, int& vertsPerFace, int *tractionVertices[], double *tractionValues[]) {
303: PetscViewer viewer;
304: FILE *f;
305: PetscInt maxTractions = 1024, tractionCount = 0;
306: PetscInt *tractionVerts;
307: PetscScalar *tractionVals;
308: double scaleFactor = 1.0;
309: char buf[2048];
310: PetscInt c;
311: PetscInt commRank;
314: MPI_Comm_rank(comm, &commRank);
315: if (dim != 3) {
316: throw ALE::Exception("PyLith only works in 3D");
317: }
318: if (commRank != 0) return;
319: PetscViewerCreate(PETSC_COMM_SELF, &viewer);
320: PetscViewerSetType(viewer, PETSC_VIEWER_ASCII);
321: PetscViewerFileSetMode(viewer, FILE_MODE_READ);
322: PetscExceptionTry1(PetscViewerFileSetName(viewer, filename.c_str()), PETSC_ERR_FILE_OPEN);
323: if (PetscExceptionValue(ierr)) {
324: // this means that a caller above me has also tryed this exception so I don't handle it here, pass it up
325: } else if (PetscExceptionCaught(ierr,PETSC_ERR_FILE_OPEN)) {
326: // File does not exist
327: return;
328: }
329: /* Logic right now is only good for linear tets and hexes, and should be fixed in the future. */
330: if (corners == 4) {
331: vertsPerFace = 3;
332: } else if (corners == 8) {
333: vertsPerFace = 4;
334: } else {
335: throw ALE::Exception("Unrecognized element type");
336: }
338: PetscViewerASCIIGetPointer(viewer, &f);
339: /* Ignore comments */
340: ignoreComments(buf, 2048, f);
341: /* Read units */
342: const char *units = strtok(buf, " ");
343: if (strcmp(units, "traction_units")) {
344: throw ALE::Exception("Invalid traction units line");
345: }
346: units = strtok(NULL, " ");
347: if (strcmp(units, "=")) {
348: throw ALE::Exception("Invalid traction units line");
349: }
350: units = strtok(NULL, " ");
351: if (!strcmp(units, "MPa")) {
352: /* Should use Pythia to do units conversion */
353: scaleFactor = 1.0e6;
354: }
355: /* Ignore comments */
356: ignoreComments(buf, 2048, f);
357: // Allocate memory.
358: PetscMalloc2(maxTractions*vertsPerFace,PetscInt,&tractionVerts,maxTractions*dim,PetscScalar,&tractionVals);
359: do {
360: const char *s = strtok(buf, " ");
362: if (tractionCount == maxTractions) {
363: PetscInt *titmp;
364: PetscScalar *tvtmp;
366: titmp = tractionVerts;
367: tvtmp = tractionVals;
368: PetscMalloc2(maxTractions*vertsPerFace*2,PetscInt,&tractionVerts,maxTractions*dim*2,PetscScalar,&tractionVals);
369: PetscMemcpy(tractionVerts, titmp, maxTractions*vertsPerFace * sizeof(PetscInt));
370: PetscMemcpy(tractionVals, tvtmp, maxTractions*dim * sizeof(PetscScalar));
371: PetscFree2(titmp,tvtmp);
372: maxTractions *= 2;
373: }
374: /* Get vertices */
375: int v1 = atoi(s);
376: if (!useZeroBase) v1 -= 1;
377: tractionVerts[tractionCount*vertsPerFace+0] = v1;
378: s = strtok(NULL, " ");
379: int v2 = atoi(s);
380: if (!useZeroBase) v2 -= 1;
381: tractionVerts[tractionCount*vertsPerFace+1] = v2;
382: s = strtok(NULL, " ");
383: int v3 = atoi(s);
384: if (!useZeroBase) v3 -= 1;
385: tractionVerts[tractionCount*vertsPerFace+2] = v3;
386: s = strtok(NULL, " ");
387: if (vertsPerFace > 3) {
388: int v4 = atoi(s);
389: if (!useZeroBase) v4 -= 1;
390: tractionVerts[tractionCount*vertsPerFace+3] = v4;
391: s = strtok(NULL, " ");
392: }
393: /* Get traction values */
394: for(c = 0; c < dim; c++) {
395: tractionVals[tractionCount*dim+c] = atof(s);
396: s = strtok(NULL, " ");
397: }
398: tractionCount++;
399: } while(fgets(buf, 2048, f) != NULL);
400: PetscViewerDestroy(viewer);
401: numTractions = tractionCount;
402: *tractionVertices = tractionVerts;
403: *tractionValues = tractionVals;
404: };
405: void Builder::buildTractions(const Obj<real_section_type>& tractionField, const Obj<Mesh>& boundaryMesh, int numCells, int numTractions, int vertsPerFace, int tractionVertices[], double tractionValues[]) {
406: real_section_type::value_type values[3];
407: // Make boundary topology
408: Obj<sieve_type> boundarySieve = new sieve_type(tractionField->comm(), tractionField->debug());
410: ALE::SieveBuilder<Mesh>::buildTopology(boundarySieve, 2, numTractions, tractionVertices, 0, false, vertsPerFace, numCells);
411: boundaryMesh->setSieve(boundarySieve);
412: boundaryMesh->stratify();
413: // Make traction field
414: tractionField->setName("traction");
415: tractionField->setFiberDimension(boundaryMesh->heightStratum(0), 3);
416: boundaryMesh->allocate(tractionField);
417: const Obj<Mesh::label_sequence>& faces = boundaryMesh->heightStratum(0);
418: int k = 0;
420: for(Mesh::label_sequence::iterator f_iter = faces->begin(); f_iter != faces->end(); ++f_iter) {
421: const Mesh::point_type& face = *f_iter;
423: values[0] = tractionValues[k*3+0];
424: values[1] = tractionValues[k*3+1];
425: values[2] = tractionValues[k*3+2];
426: k++;
427: tractionField->updatePoint(face, values);
428: }
429: };
430: void Builder::buildMaterials(const Obj<Mesh>& mesh, const Obj<int_section_type>& matField, const int materials[]) {
431: const Obj<Mesh::label_sequence>& elements = mesh->heightStratum(0);
433: matField->setName("material");
434: matField->setFiberDimension(elements, 1);
435: mesh->allocate(matField);
436: for(Mesh::label_sequence::iterator e_iter = elements->begin(); e_iter != elements->end(); ++e_iter) {
437: matField->updatePoint(*e_iter, &materials[*e_iter]);
438: }
439: };
440: Obj<Builder::Mesh> Builder::readMesh(MPI_Comm comm, const int dim, const std::string& basename, const bool useZeroBase = false, const bool interpolate = false, const int debug = 0) {
441: Obj<Mesh> mesh = new Mesh(comm, dim, debug);
442: Obj<sieve_type> sieve = new sieve_type(comm, debug);
443: int *cells, *materials;
444: double *coordinates;
445: int numCells = 0, numVertices = 0, numCorners = dim+1;
447: ALE::PyLith::Builder::readConnectivity(comm, basename+".connect", numCorners, useZeroBase, numCells, &cells, &materials);
448: ALE::PyLith::Builder::readCoordinates(comm, basename+".coord", dim, numVertices, &coordinates);
449: ALE::SieveBuilder<Mesh>::buildTopology(sieve, dim, numCells, cells, numVertices, interpolate, numCorners);
450: mesh->setSieve(sieve);
451: mesh->stratify();
452: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, dim, coordinates);
453: Obj<int_section_type> material = mesh->getIntSection("material");
454: buildMaterials(mesh, material, materials);
455: Obj<PETSC_MESH_TYPE> tractionMesh = createTraction(mesh, basename, useZeroBase);
456: if (!tractionMesh.isNull()) {/* Have to carry tractions around somehow */}
457: return mesh;
458: };
459: Obj<Builder::Mesh> Builder::createTraction(const Obj<Mesh>& mesh, const std::string& basename, const bool useZeroBase = false) {
460: Obj<Mesh> tractionMesh = NULL;
461: MPI_Comm comm = mesh->comm();
462: int debug = mesh->debug();
463: int dim = mesh->getDimension();
464: int numCells = mesh->heightStratum(0)->size();
465: int numCorners = mesh->getSieve()->cone(*mesh->heightStratum(0)->begin())->size();
466: int *tractionVertices;
467: double *tractionValues;
468: int numTractions = 0, vertsPerFace = 0, hasTractions;
470: ALE::PyLith::Builder::readTractions(comm, basename+".traction", dim, numCorners, useZeroBase, numTractions, vertsPerFace, &tractionVertices, &tractionValues);
471: MPI_Allreduce(&numTractions, &hasTractions, 1, MPI_INT, MPI_MAX, comm);
472: if (hasTractions) {
473: tractionMesh = new Mesh(comm, debug);
475: const Obj<Mesh::real_section_type>& traction = tractionMesh->getRealSection("traction");
476: buildTractions(traction, tractionMesh, numCells, numTractions, vertsPerFace, tractionVertices, tractionValues);
477: }
478: return tractionMesh;
479: };
480: void Builder::createCohesiveElements(const Obj<Mesh>& mesh, const std::set<Mesh::point_type>& faultVertices) {
481: typedef std::vector<Mesh::point_type> PointArray;
482: const Obj<Mesh::sieve_type> sieve = mesh->getSieve();
483: const Obj<Mesh> fault = new Mesh(mesh->comm(), mesh->debug());
484: const Obj<Mesh::sieve_type> faultSieve = new Mesh::sieve_type(sieve->comm(), sieve->debug());
485: const std::set<Mesh::point_type>::const_iterator fvBegin = faultVertices.begin();
486: const std::set<Mesh::point_type>::const_iterator fvEnd = faultVertices.end();
487: // There should be logic here to determine this
488: const unsigned int faceSize = 3;
489: int f = 0;
490: int debug = mesh->debug();
491: Obj<PointArray> face = new PointArray();
492: std::set<Mesh::point_type> faultCells;
494: // Create a sieve which captures the fault
495: for(std::set<int>::const_iterator fv_iter = fvBegin; fv_iter != fvEnd; ++fv_iter) {
496: const Obj<Mesh::sieve_type::traits::supportSequence>& cells = sieve->support(*fv_iter);
497: const Mesh::sieve_type::traits::supportSequence::iterator cBegin = cells->begin();
498: const Mesh::sieve_type::traits::supportSequence::iterator cEnd = cells->end();
500: if (debug) {std::cout << "Checking fault vertex " << *fv_iter << std::endl;}
501: for(Mesh::sieve_type::traits::supportSequence::iterator c_iter = cBegin; c_iter != cEnd; ++c_iter) {
502: if (debug) {std::cout << " Checking cell " << *c_iter << std::endl;}
503: if (faultCells.find(*c_iter) != faultCells.end()) continue;
504: const Obj<Mesh::sieve_type::traits::coneSequence>& cone = sieve->cone(*c_iter);
505: const Mesh::sieve_type::traits::coneSequence::iterator vBegin = cone->begin();
506: const Mesh::sieve_type::traits::coneSequence::iterator vEnd = cone->end();
508: face->clear();
509: for(Mesh::sieve_type::traits::coneSequence::iterator v_iter = vBegin; v_iter != vEnd; ++v_iter) {
510: if (faultVertices.find(*v_iter) != fvEnd) {
511: if (debug) {std::cout << " contains fault vertex " << *v_iter << std::endl;}
512: face->insert(face->end(), *v_iter);
513: }
514: }
515: if (face->size() > faceSize) throw ALE::Exception("Invalid fault mesh: Too many vertices of an element on the fault");
516: if (face->size() == faceSize) {
517: if (debug) {std::cout << " Contains a face on the fault" << std::endl;}
518: const Obj<sieve_type::supportSet> preFace = faultSieve->nJoin1(face);
520: if (preFace->size() > 1) {
521: throw ALE::Exception("Invalid fault sieve: Multiple faces from vertex set");
522: } else if (preFace->size() == 1) {
523: faultSieve->addArrow(*preFace->begin(), *c_iter);
524: } else if (preFace->size() == 0) {
525: if (debug) {std::cout << " Adding face " << f << std::endl;}
526: int color = 0;
527: for(PointArray::const_iterator f_iter = face->begin(); f_iter != face->end(); ++f_iter) {
528: if (debug) {std::cout << " vertex " << *f_iter << std::endl;}
529: faultSieve->addArrow(*f_iter, f, color++);
530: }
531: faultSieve->addArrow(f, *c_iter);
532: f++;
533: }
534: faultCells.insert(*c_iter);
535: }
536: }
537: }
538: fault->setSieve(faultSieve);
539: fault->stratify();
540: faultCells.clear();
541: if (debug) {fault->view("Fault mesh");}
542: // Add new shadow vertices
543: const Obj<Mesh::label_sequence>& fVertices = fault->depthStratum(0);
544: const Obj<Mesh::label_sequence>& vertices = mesh->depthStratum(0);
545: Mesh::point_type newVertex = *vertices->begin() + vertices->size();
546: std::map<int,int> vertexRenumber;
548: for(Mesh::label_sequence::iterator v_iter = fVertices->begin(); v_iter != fVertices->end(); ++v_iter) {
549: if (debug) {std::cout << "Duplicating " << *v_iter << " to " << vertexRenumber[*v_iter] << std::endl;}
550: vertexRenumber[*v_iter] = newVertex++;
551: }
552: // Split the mesh along the fault sieve and create cohesive elements
553: const Obj<Mesh::label_sequence>& faces = fault->depthStratum(1);
554: PointArray newVertices;
556: for(Mesh::label_sequence::iterator f_iter = faces->begin(); f_iter != faces->end(); ++f_iter) {
557: if (debug) {std::cout << "Considering fault face " << *f_iter << std::endl;}
558: const Obj<Mesh::sieve_type::traits::supportSequence>& cells = faultSieve->support(*f_iter);
559: Mesh::point_type cell = std::max(*cells->begin(), *(++cells->begin()));
560: const Obj<Mesh::sieve_type::traits::coneSequence>& cone = sieve->cone(cell);
562: if (debug) {std::cout << " Replacing cell " << cell << std::endl;}
563: newVertices.clear();
564: for(PETSC_MESH_TYPE::sieve_type::traits::coneSequence::iterator v_iter = cone->begin(); v_iter != cone->end(); ++v_iter) {
565: if (vertexRenumber.find(*v_iter) != vertexRenumber.end()) {
566: if (debug) {std::cout << " vertex " << vertexRenumber[*v_iter] << std::endl;}
567: newVertices.insert(newVertices.end(), vertexRenumber[*v_iter]);
568: } else {
569: if (debug) {std::cout << " vertex " << *v_iter << std::endl;}
570: newVertices.insert(newVertices.end(), *v_iter);
571: }
572: }
573: sieve->clearCone(cell);
574: int color = 0;
575: for(PointArray::const_iterator v_iter = newVertices.begin(); v_iter != newVertices.end(); ++v_iter) {
576: sieve->addArrow(*v_iter, cell, color++);
577: }
578: }
579: // Fix coordinates
580: const Obj<Mesh::real_section_type>& coordinates = mesh->getRealSection("coordinates");
581: const Obj<Mesh::label_sequence>& fVertices2 = fault->depthStratum(0);
583: for(Mesh::label_sequence::iterator v_iter = fVertices2->begin(); v_iter != fVertices2->end(); ++v_iter) {
584: coordinates->addPoint(vertexRenumber[*v_iter], coordinates->getFiberDimension(*v_iter));
585: }
586: mesh->reallocate(coordinates);
587: for(Mesh::label_sequence::iterator v_iter = fVertices2->begin(); v_iter != fVertices2->end(); ++v_iter) {
588: coordinates->updatePoint(vertexRenumber[*v_iter], coordinates->restrictPoint(*v_iter));
589: }
590: };
591: //
592: // Viewer methods
593: //
596: PetscErrorCode Viewer::writeVertices(const Obj<Mesh>& mesh, PetscViewer viewer) {
597: Obj<Builder::real_section_type> coordinates = mesh->getRealSection("coordinates");
598: //Mesh::section_type::patch_type patch;
599: //const double *array = coordinates->restrict(Mesh::section_type::patch_type());
600: //int dim = mesh->getDimension();
601: //int numVertices;
605: #if 0
606: //FIX:
607: if (vertexBundle->getGlobalOffsets()) {
608: numVertices = vertexBundle->getGlobalOffsets()[mesh->commSize()];
609: } else {
610: numVertices = mesh->getTopology()->depthStratum(0)->size();
611: }
612: PetscViewerASCIIPrintf(viewer,"#\n");
613: PetscViewerASCIIPrintf(viewer,"coord_units = m\n");
614: PetscViewerASCIIPrintf(viewer,"#\n");
615: PetscViewerASCIIPrintf(viewer,"#\n");
616: PetscViewerASCIIPrintf(viewer,"# Node X-coord Y-coord Z-coord\n");
617: PetscViewerASCIIPrintf(viewer,"#\n");
618: if (mesh->commRank() == 0) {
619: int numLocalVertices = mesh->getTopology()->depthStratum(0)->size();
620: int vertexCount = 1;
622: for(int v = 0; v < numLocalVertices; v++) {
623: PetscViewerASCIIPrintf(viewer,"%7D ", vertexCount++);
624: for(int d = 0; d < dim; d++) {
625: if (d > 0) {
626: PetscViewerASCIIPrintf(viewer," ");
627: }
628: PetscViewerASCIIPrintf(viewer,"% 16.8E", array[v*dim+d]);
629: }
630: PetscViewerASCIIPrintf(viewer,"\n");
631: }
632: for(int p = 1; p < mesh->commSize(); p++) {
633: double *remoteCoords;
634: MPI_Status status;
636: MPI_Recv(&numLocalVertices, 1, MPI_INT, p, 1, mesh->comm(), &status);
637: PetscMalloc(numLocalVertices*dim * sizeof(double), &remoteCoords);
638: MPI_Recv(remoteCoords, numLocalVertices*dim, MPI_DOUBLE, p, 1, mesh->comm(), &status);
639: for(int v = 0; v < numLocalVertices; v++) {
640: PetscViewerASCIIPrintf(viewer,"%7D ", vertexCount++);
641: for(int d = 0; d < dim; d++) {
642: if (d > 0) {
643: PetscViewerASCIIPrintf(viewer, " ");
644: }
645: PetscViewerASCIIPrintf(viewer, "% 16.8E", remoteCoords[v*dim+d]);
646: }
647: PetscViewerASCIIPrintf(viewer, "\n");
648: }
649: }
650: } else {
651: Obj<Mesh::bundle_type> globalOrder = coordinates->getGlobalOrder();
652: Obj<Mesh::field_type::order_type::coneSequence> cone = globalOrder->getPatch(patch);
653: const int *offsets = coordinates->getGlobalOffsets();
654: int numLocalVertices = (offsets[mesh->commRank()+1] - offsets[mesh->commRank()])/dim;
655: double *localCoords;
656: int k = 0;
658: PetscMalloc(numLocalVertices*dim * sizeof(double), &localCoords);
659: for(Mesh::field_type::order_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
660: int dim = globalOrder->getFiberDimension(patch, *p_iter);
662: if (dim > 0) {
663: int offset = coordinates->getFiberOffset(patch, *p_iter);
665: for(int i = offset; i < offset+dim; ++i) {
666: localCoords[k++] = array[i];
667: }
668: }
669: }
670: if (k != numLocalVertices*dim) {
671: SETERRQ2(PETSC_ERR_PLIB, "Invalid number of coordinates to send %d should be %d", k, numLocalVertices*dim);
672: }
673: MPI_Send(&numLocalVertices, 1, MPI_INT, 0, 1, mesh->comm());
674: MPI_Send(localCoords, numLocalVertices*dim, MPI_DOUBLE, 0, 1, mesh->comm());
675: PetscFree(localCoords);
676: }
677: #endif
678: return(0);
679: };
682: PetscErrorCode Viewer::writeElements(const Obj<Mesh>& mesh, const Obj<Builder::int_section_type>& materialField, PetscViewer viewer) {
683: #if 0
684: Obj<Mesh::sieve_type::traits::heightSequence> elements = topology->heightStratum(0);
685: Obj<Mesh::bundle_type> elementBundle = mesh->getBundle(topology->depth());
686: Obj<Mesh::bundle_type> vertexBundle = mesh->getBundle(0);
687: Obj<Mesh::bundle_type> globalVertex = vertexBundle->getGlobalOrder();
688: Obj<Mesh::bundle_type> globalElement = elementBundle->getGlobalOrder();
689: Mesh::bundle_type::patch_type patch;
690: std::string orderName("element");
691: bool hasMaterial = !materialField.isNull();
692: int dim = mesh->getDimension();
693: int corners = topology->nCone(*elements->begin(), topology->depth())->size();
694: int elementType = -1;
698: if (dim != 3) {
699: SETERRQ(PETSC_ERR_SUP, "PyLith only supports 3D meshes.");
700: }
701: if (corners == 4) {
702: // Linear tetrahedron
703: elementType = 5;
704: } else if (corners == 8) {
705: // Linear hexahedron
706: elementType = 1;
707: } else {
708: SETERRQ1(PETSC_ERR_SUP, "PyLith Error: Unsupported number of elements vertices: %d", corners);
709: }
710: PetscViewerASCIIPrintf(viewer,"#\n");
711: PetscViewerASCIIPrintf(viewer,"# N ETP MAT INF N1 N2 N3 N4 N5 N6 N7 N8\n");
712: PetscViewerASCIIPrintf(viewer,"#\n");
713: if (mesh->commRank() == 0) {
714: int elementCount = 1;
716: for(Mesh::sieve_type::traits::heightSequence::iterator e_itor = elements->begin(); e_itor != elements->end(); ++e_itor) {
717: Obj<Mesh::bundle_type::order_type::coneSequence> cone = vertexBundle->getPatch(orderName, *e_itor);
719: PetscViewerASCIIPrintf(viewer, "%7d %3d", elementCount++, elementType);
720: if (hasMaterial) {
721: // No infinite elements
722: PetscViewerASCIIPrintf(viewer, " %3d %3d", (int) materialField->restrict(patch, *e_itor)[0], 0);
723: } else {
724: // No infinite elements
725: PetscViewerASCIIPrintf(viewer, " %3d %3d", 1, 0);
726: }
727: for(Mesh::bundle_type::order_type::coneSequence::iterator c_itor = cone->begin(); c_itor != cone->end(); ++c_itor) {
728: PetscViewerASCIIPrintf(viewer, " %6d", globalVertex->getIndex(patch, *c_itor).prefix+1);
729: }
730: PetscViewerASCIIPrintf(viewer, "\n");
731: }
732: for(int p = 1; p < mesh->commSize(); p++) {
733: int numLocalElements;
734: int *remoteVertices;
735: MPI_Status status;
737: MPI_Recv(&numLocalElements, 1, MPI_INT, p, 1, mesh->comm(), &status);
738: PetscMalloc(numLocalElements*(corners+1) * sizeof(int), &remoteVertices);
739: MPI_Recv(remoteVertices, numLocalElements*(corners+1), MPI_INT, p, 1, mesh->comm(), &status);
740: for(int e = 0; e < numLocalElements; e++) {
741: // Only linear tetrahedra, material, no infinite elements
742: int mat = remoteVertices[e*(corners+1)+corners];
744: PetscViewerASCIIPrintf(viewer, "%7d %3d %3d %3d", elementCount++, elementType, mat, 0);
745: for(int c = 0; c < corners; c++) {
746: PetscViewerASCIIPrintf(viewer, " %6d", remoteVertices[e*(corners+1)+c]);
747: }
748: PetscViewerASCIIPrintf(viewer, "\n");
749: }
750: PetscFree(remoteVertices);
751: }
752: } else {
753: const int *offsets = elementBundle->getGlobalOffsets();
754: int numLocalElements = offsets[mesh->commRank()+1] - offsets[mesh->commRank()];
755: int *localVertices;
756: int k = 0;
758: PetscMalloc(numLocalElements*(corners+1) * sizeof(int), &localVertices);
759: for(Mesh::sieve_type::traits::heightSequence::iterator e_itor = elements->begin(); e_itor != elements->end(); ++e_itor) {
760: Obj<Mesh::bundle_type::order_type::coneSequence> cone = vertexBundle->getPatch(orderName, *e_itor);
762: if (globalElement->getFiberDimension(patch, *e_itor) > 0) {
763: for(Mesh::bundle_type::order_type::coneSequence::iterator c_itor = cone->begin(); c_itor != cone->end(); ++c_itor) {
764: localVertices[k++] = globalVertex->getIndex(patch, *c_itor).prefix;
765: }
766: if (hasMaterial) {
767: localVertices[k++] = (int) materialField->restrict(patch, *e_itor)[0];
768: } else {
769: localVertices[k++] = 1;
770: }
771: }
772: }
773: if (k != numLocalElements*corners) {
774: SETERRQ2(PETSC_ERR_PLIB, "Invalid number of vertices to send %d should be %d", k, numLocalElements*corners);
775: }
776: MPI_Send(&numLocalElements, 1, MPI_INT, 0, 1, mesh->comm());
777: MPI_Send(localVertices, numLocalElements*(corners+1), MPI_INT, 0, 1, mesh->comm());
778: PetscFree(localVertices);
779: }
780: #endif
781: return(0);
782: };
785: PetscErrorCode Viewer::writeVerticesLocal(const Obj<Mesh>& mesh, PetscViewer viewer) {
786: const Obj<Mesh::real_section_type>& coordinates = mesh->getRealSection("coordinates");
787: const Obj<Mesh::label_sequence>& vertices = mesh->depthStratum(0);
788: const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(mesh, 0);
789: int embedDim = coordinates->getFiberDimension(*vertices->begin());
793: PetscViewerASCIIPrintf(viewer,"#\n");
794: PetscViewerASCIIPrintf(viewer,"coord_units = m\n");
795: PetscViewerASCIIPrintf(viewer,"#\n");
796: PetscViewerASCIIPrintf(viewer,"#\n");
797: PetscViewerASCIIPrintf(viewer,"# Node X-coord Y-coord Z-coord\n");
798: PetscViewerASCIIPrintf(viewer,"#\n");
800: for(Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
801: const Mesh::real_section_type::value_type *array = coordinates->restrictPoint(*v_iter);
803: PetscViewerASCIIPrintf(viewer, "%7D ", vNumbering->getIndex(*v_iter)+1);
804: for(int d = 0; d < embedDim; d++) {
805: if (d > 0) {
806: PetscViewerASCIIPrintf(viewer, " ");
807: }
808: PetscViewerASCIIPrintf(viewer, "% 16.8E", array[d]);
809: }
810: PetscViewerASCIIPrintf(viewer, "\n");
811: }
812: return(0);
813: };
816: PetscErrorCode Viewer::writeElementsLocal(const Obj<Mesh>& mesh, const Obj<Builder::int_section_type>& materialField, PetscViewer viewer) {
817: const Obj<Mesh::sieve_type>& sieve = mesh->getSieve();
818: const Obj<Mesh::label_sequence>& elements = mesh->heightStratum(0);
819: const Obj<Mesh::numbering_type>& eNumbering = mesh->getFactory()->getLocalNumbering(mesh, mesh->depth());
820: const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(mesh, 0);
821: int dim = mesh->getDimension();
822: //int corners = sieve->nCone(*elements->begin(), topology->depth())->size();
823: int corners = sieve->cone(*elements->begin())->size();
824: bool hasMaterial = !materialField.isNull();
825: int elementType = -1;
829: if (dim != 3) {
830: SETERRQ(PETSC_ERR_SUP, "PyLith only supports 3D meshes.");
831: }
832: if (corners == 4) {
833: // Linear tetrahedron
834: elementType = 5;
835: } else if (corners == 8) {
836: // Linear hexahedron
837: elementType = 1;
838: } else {
839: SETERRQ1(PETSC_ERR_SUP, "PyLith Error: Unsupported number of elements vertices: %d", corners);
840: }
841: PetscViewerASCIIPrintf(viewer,"#\n");
842: PetscViewerASCIIPrintf(viewer,"# N ETP MAT INF N1 N2 N3 N4 N5 N6 N7 N8\n");
843: PetscViewerASCIIPrintf(viewer,"#\n");
844: for(Mesh::label_sequence::iterator e_iter = elements->begin(); e_iter != elements->end(); ++e_iter) {
845: const Obj<Mesh::sieve_type::traits::coneSequence> cone = sieve->cone(*e_iter);
846: Mesh::sieve_type::traits::coneSequence::iterator begin = cone->begin();
847: Mesh::sieve_type::traits::coneSequence::iterator end = cone->end();
849: PetscViewerASCIIPrintf(viewer, "%7d %3d", eNumbering->getIndex(*e_iter)+1, elementType);
850: if (hasMaterial) {
851: // No infinite elements
852: PetscViewerASCIIPrintf(viewer, " %3d %3d", (int) materialField->restrictPoint(*e_iter)[0], 0);
853: } else {
854: // No infinite elements
855: PetscViewerASCIIPrintf(viewer, " %3d %3d", 1, 0);
856: }
857: for(Mesh::sieve_type::traits::coneSequence::iterator c_iter = begin; c_iter != end; ++c_iter) {
858: //FIX: Need a global ordering here
859: PetscViewerASCIIPrintf(viewer, " %6d", vNumbering->getIndex(*c_iter)+1);
860: }
861: PetscViewerASCIIPrintf(viewer, "\n");
862: }
863: return(0);
864: };
865: #if 0
868: // The elements seem to be implicitly numbered by appearance, which makes it impossible to
869: // number here by bundle, but we can fix it by traversing the elements like the vertices
870: PetscErrorCode Viewer::writeSplitLocal(const Obj<Mesh>& mesh, const Obj<Builder::pair_section_type>& splitField, PetscViewer viewer) {
871: const Obj<Mesh::topology_type>& topology = mesh->getTopology();
872: Builder::pair_section_type::patch_type patch = 0;
873: const Obj<Mesh::numbering_type>& eNumbering = mesh->getFactory()->getLocalNumbering(topology, patch, topology->depth());
874: const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(topology, patch, 0);
878: const Builder::pair_section_type::atlas_type::chart_type& chart = splitField->getPatch(patch);
880: for(Builder::pair_section_type::atlas_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
881: const Builder::pair_section_type::point_type& e = *c_iter;
882: const Builder::pair_section_type::value_type *values = splitField->restrict(patch, e);
883: const int size = splitField->getFiberDimension(patch, e);
885: for(int i = 0; i < size; i++) {
886: const Builder::pair_section_type::point_type& v = values[i].first;
887: const PETSC_MESH_TYPE::base_type::split_value& split = values[i].second;
889: // No time history
890: PetscViewerASCIIPrintf(viewer, "%6d %6d 0 %15.9g %15.9g %15.9g\n", eNumbering->getIndex(e)+1, vNumbering->getIndex(v)+1, split.x, split.y, split.z);
891: }
892: }
893: return(0);
894: };
895: #endif
898: PetscErrorCode Viewer::writeTractionsLocal(const Obj<Mesh>& mesh, const Obj<Mesh>& tractionMesh, const Obj<Builder::real_section_type>& tractionField, PetscViewer viewer) {
899: const Obj<Mesh::sieve_type>& sieve = tractionMesh->getSieve();
900: const Obj<Mesh::label_sequence>& faces = tractionMesh->heightStratum(0);
901: const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(mesh, 0);
905: PetscViewerASCIIPrintf(viewer,"#\n");
906: PetscViewerASCIIPrintf(viewer,"traction_units = Pa\n");
907: PetscViewerASCIIPrintf(viewer,"#\n");
908: PetscViewerASCIIPrintf(viewer,"#\n");
909: for(Mesh::label_sequence::iterator f_iter = faces->begin(); f_iter != faces->end(); ++f_iter) {
910: const Mesh::point_type& face = *f_iter;
911: const Obj<Mesh::sieve_type::traits::coneSequence>& cone = sieve->cone(face);
913: for(Mesh::sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter) {
914: const Mesh::point_type& vertex = *c_iter;
916: PetscViewerASCIIPrintf(viewer, "%6d", vNumbering->getIndex(vertex)+1);
917: std::cout << vNumbering->getIndex(vertex) << " ("<<vertex<<") ";
918: }
919: const Mesh::real_section_type::value_type *values = tractionField->restrictPoint(face);
921: for(int i = 0; i < mesh->getDimension(); ++i) {
922: if (i > 0) {
923: PetscViewerASCIIPrintf(viewer, " ");
924: std::cout << " ";
925: }
926: PetscViewerASCIIPrintf(viewer, "%15.9g", values[i]);
927: std::cout << values[i];
928: }
929: PetscViewerASCIIPrintf(viewer,"\n");
930: std::cout << std::endl;
931: }
932: return(0);
933: };
934: #endif
935: };
936: };