Actual source code: meshpylith.c
1: #include "src/dm/mesh/meshpylith.h" /*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: PetscScalar *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(PetscScalar), &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: PetscScalar *ctmp;
129: ctmp = coords;
130: PetscMalloc(maxVerts*2*dim * sizeof(PetscScalar), &coords);
131: PetscMemcpy(coords, ctmp, maxVerts*dim * sizeof(PetscScalar));
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: PetscScalar *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,PetscScalar,&splitVal);
182: do {
183: const char *s = strtok(buf, " ");
185: if (splitCount == maxSplit) {
186: PetscInt *sitmp;
187: PetscInt *lhtmp;
188: PetscScalar *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(PetscScalar));
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: 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[]) {
268: PetscViewer viewer;
269: FILE *f;
270: PetscInt maxTractions = 1024, tractionCount = 0;
271: PetscInt *tractionVerts;
272: PetscScalar *tractionVals;
273: double scaleFactor = 1.0;
274: char buf[2048];
275: PetscInt c;
276: PetscInt commRank;
279: MPI_Comm_rank(comm, &commRank);
280: if (dim != 3) {
281: throw ALE::Exception("PyLith only works in 3D");
282: }
283: if (commRank != 0) return;
284: PetscViewerCreate(PETSC_COMM_SELF, &viewer);
285: PetscViewerSetType(viewer, PETSC_VIEWER_ASCII);
286: PetscViewerFileSetMode(viewer, FILE_MODE_READ);
287: PetscExceptionTry1(PetscViewerFileSetName(viewer, filename.c_str()), PETSC_ERR_FILE_OPEN);
288: if (PetscExceptionValue(ierr)) {
289: // this means that a caller above me has also tryed this exception so I don't handle it here, pass it up
290: } else if (PetscExceptionCaught(ierr,PETSC_ERR_FILE_OPEN)) {
291: // File does not exist
292: return;
293: }
294: /* Logic right now is only good for linear tets and hexes, and should be fixed in the future. */
295: if (corners == 4) {
296: vertsPerFace = 3;
297: } else if (corners == 8) {
298: vertsPerFace = 4;
299: } else {
300: throw ALE::Exception("Unrecognized element type");
301: }
303: PetscViewerASCIIGetPointer(viewer, &f);
304: /* Ignore comments */
305: ignoreComments(buf, 2048, f);
306: /* Read units */
307: const char *units = strtok(buf, " ");
308: if (strcmp(units, "traction_units")) {
309: throw ALE::Exception("Invalid traction units line");
310: }
311: units = strtok(NULL, " ");
312: if (strcmp(units, "=")) {
313: throw ALE::Exception("Invalid traction units line");
314: }
315: units = strtok(NULL, " ");
316: if (!strcmp(units, "MPa")) {
317: /* Should use Pythia to do units conversion */
318: scaleFactor = 1.0e6;
319: }
320: /* Ignore comments */
321: ignoreComments(buf, 2048, f);
322: // Allocate memory.
323: PetscMalloc2(maxTractions*vertsPerFace,PetscInt,&tractionVerts,maxTractions*dim,PetscScalar,&tractionVals);
324: do {
325: const char *s = strtok(buf, " ");
327: if (tractionCount == maxTractions) {
328: PetscInt *titmp;
329: PetscScalar *tvtmp;
331: titmp = tractionVerts;
332: tvtmp = tractionVals;
333: PetscMalloc2(maxTractions*vertsPerFace*2,PetscInt,&tractionVerts,maxTractions*dim*2,PetscScalar,&tractionVals);
334: PetscMemcpy(tractionVerts, titmp, maxTractions*vertsPerFace * sizeof(PetscInt));
335: PetscMemcpy(tractionVals, tvtmp, maxTractions*dim * sizeof(PetscScalar));
336: PetscFree2(titmp,tvtmp);
337: maxTractions *= 2;
338: }
339: /* Get vertices */
340: int v1 = atoi(s);
341: if (!useZeroBase) v1 -= 1;
342: tractionVerts[tractionCount*vertsPerFace+0] = v1;
343: s = strtok(NULL, " ");
344: int v2 = atoi(s);
345: if (!useZeroBase) v2 -= 1;
346: tractionVerts[tractionCount*vertsPerFace+1] = v2;
347: s = strtok(NULL, " ");
348: int v3 = atoi(s);
349: if (!useZeroBase) v3 -= 1;
350: tractionVerts[tractionCount*vertsPerFace+2] = v3;
351: s = strtok(NULL, " ");
352: if (vertsPerFace > 3) {
353: int v4 = atoi(s);
354: if (!useZeroBase) v4 -= 1;
355: tractionVerts[tractionCount*vertsPerFace+3] = v4;
356: s = strtok(NULL, " ");
357: }
358: /* Get traction values */
359: for(c = 0; c < dim; c++) {
360: tractionVals[tractionCount*dim+c] = atof(s);
361: s = strtok(NULL, " ");
362: }
363: tractionCount++;
364: } while(fgets(buf, 2048, f) != NULL);
365: PetscViewerDestroy(viewer);
366: numTractions = tractionCount;
367: *tractionVertices = tractionVerts;
368: *tractionValues = tractionVals;
369: };
370: void Builder::buildTractions(const Obj<real_section_type>& tractionField, const Obj<Mesh>& boundaryMesh, int numCells, int numTractions, int vertsPerFace, int tractionVertices[], double tractionValues[]) {
371: real_section_type::value_type values[3];
372: // Make boundary topology
373: Obj<sieve_type> boundarySieve = new sieve_type(tractionField->comm(), tractionField->debug());
375: ALE::SieveBuilder<Mesh>::buildTopology(boundarySieve, 2, numTractions, tractionVertices, 0, false, vertsPerFace, numCells);
376: boundaryMesh->setSieve(boundarySieve);
377: boundaryMesh->stratify();
378: // Make traction field
379: tractionField->setName("traction");
380: tractionField->setFiberDimension(boundaryMesh->heightStratum(0), 3);
381: boundaryMesh->allocate(tractionField);
382: const Obj<Mesh::label_sequence>& faces = boundaryMesh->heightStratum(0);
383: int k = 0;
385: for(Mesh::label_sequence::iterator f_iter = faces->begin(); f_iter != faces->end(); ++f_iter) {
386: const Mesh::point_type& face = *f_iter;
388: values[0] = tractionValues[k*3+0];
389: values[1] = tractionValues[k*3+1];
390: values[2] = tractionValues[k*3+2];
391: k++;
392: tractionField->updatePoint(face, values);
393: }
394: };
395: void Builder::buildMaterials(const Obj<Mesh>& mesh, const Obj<int_section_type>& matField, const int materials[]) {
396: const Obj<Mesh::label_sequence>& elements = mesh->heightStratum(0);
398: matField->setName("material");
399: matField->setFiberDimension(elements, 1);
400: mesh->allocate(matField);
401: for(Mesh::label_sequence::iterator e_iter = elements->begin(); e_iter != elements->end(); ++e_iter) {
402: matField->updatePoint(*e_iter, &materials[*e_iter]);
403: }
404: };
405: 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) {
406: Obj<Mesh> mesh = new Mesh(comm, dim, debug);
407: Obj<sieve_type> sieve = new sieve_type(comm, debug);
408: int *cells, *materials;
409: double *coordinates;
410: int numCells = 0, numVertices = 0, numCorners = dim+1;
412: ALE::PyLith::Builder::readConnectivity(comm, basename+".connect", numCorners, useZeroBase, numCells, &cells, &materials);
413: ALE::PyLith::Builder::readCoordinates(comm, basename+".coord", dim, numVertices, &coordinates);
414: ALE::SieveBuilder<Mesh>::buildTopology(sieve, dim, numCells, cells, numVertices, interpolate, numCorners);
415: mesh->setSieve(sieve);
416: mesh->stratify();
417: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, dim, coordinates);
418: Obj<int_section_type> material = mesh->getIntSection("material");
419: buildMaterials(mesh, material, materials);
420: #if 0
421: Obj<ALE::Mesh::pair_section_type> split = createSplit(mesh, basename, useZeroBase);
422: if (!split.isNull()) {mesh->setPairSection("split", split);}
423: #endif
424: Obj<ALE::Mesh> tractionMesh = createTraction(mesh, basename, useZeroBase);
425: if (!tractionMesh.isNull()) {/* Have to carry tractions around somehow */}
426: return mesh;
427: };
428: #if 0
429: Obj<Builder::pair_section_type> Builder::createSplit(const Obj<Mesh>& mesh, const std::string& basename, const bool useZeroBase = false) {
430: Obj<pair_section_type> split = NULL;
431: MPI_Comm comm = mesh->comm();
432: int dim = mesh->getDimension();
433: int numCells = mesh->getTopology()->heightStratum(0, 0)->size();
434: int *splitInd, *loadHistory;
435: double *splitValues;
436: int numSplit = 0, hasSplit;
438: ALE::PyLith::Builder::readSplit(comm, basename+".split", dim, useZeroBase, numSplit, &splitInd, &loadHistory, &splitValues);
439: MPI_Allreduce(&numSplit, &hasSplit, 1, MPI_INT, MPI_MAX, comm);
440: if (hasSplit) {
441: split = new pair_section_type(mesh->getTopology());
442: Obj<int_section_type> loadField = mesh->getIntSection("loadHistory");
443: buildSplit(split, loadField, numCells, numSplit, splitInd, loadHistory, splitValues);
444: }
445: return split;
446: };
447: #endif
448: Obj<Builder::Mesh> Builder::createTraction(const Obj<Mesh>& mesh, const std::string& basename, const bool useZeroBase = false) {
449: Obj<Mesh> tractionMesh = NULL;
450: MPI_Comm comm = mesh->comm();
451: int debug = mesh->debug();
452: int dim = mesh->getDimension();
453: int numCells = mesh->heightStratum(0)->size();
454: int numCorners = mesh->getSieve()->cone(*mesh->heightStratum(0)->begin())->size();
455: int *tractionVertices;
456: double *tractionValues;
457: int numTractions = 0, vertsPerFace = 0, hasTractions;
459: ALE::PyLith::Builder::readTractions(comm, basename+".traction", dim, numCorners, useZeroBase, numTractions, vertsPerFace, &tractionVertices, &tractionValues);
460: MPI_Allreduce(&numTractions, &hasTractions, 1, MPI_INT, MPI_MAX, comm);
461: if (hasTractions) {
462: tractionMesh = new Mesh(comm, debug);
464: const Obj<Mesh::real_section_type>& traction = tractionMesh->getRealSection("traction");
465: buildTractions(traction, tractionMesh, numCells, numTractions, vertsPerFace, tractionVertices, tractionValues);
466: }
467: return tractionMesh;
468: };
469: void Builder::createCohesiveElements(const Obj<Mesh>& mesh, const std::set<Mesh::point_type>& faultVertices) {
470: typedef std::vector<Mesh::point_type> PointArray;
471: const Obj<Mesh::sieve_type> sieve = mesh->getSieve();
472: const Obj<Mesh> fault = new Mesh(mesh->comm(), mesh->debug());
473: const Obj<Mesh::sieve_type> faultSieve = new Mesh::sieve_type(sieve->comm(), sieve->debug());
474: const std::set<Mesh::point_type>::const_iterator fvBegin = faultVertices.begin();
475: const std::set<Mesh::point_type>::const_iterator fvEnd = faultVertices.end();
476: // There should be logic here to determine this
477: const unsigned int faceSize = 3;
478: int f = 0;
479: int debug = mesh->debug();
480: Obj<PointArray> face = new PointArray();
481: std::set<Mesh::point_type> faultCells;
483: // Create a sieve which captures the fault
484: for(std::set<int>::const_iterator fv_iter = fvBegin; fv_iter != fvEnd; ++fv_iter) {
485: const Obj<Mesh::sieve_type::traits::supportSequence>& cells = sieve->support(*fv_iter);
486: const Mesh::sieve_type::traits::supportSequence::iterator cBegin = cells->begin();
487: const Mesh::sieve_type::traits::supportSequence::iterator cEnd = cells->end();
489: if (debug) {std::cout << "Checking fault vertex " << *fv_iter << std::endl;}
490: for(Mesh::sieve_type::traits::supportSequence::iterator c_iter = cBegin; c_iter != cEnd; ++c_iter) {
491: if (debug) {std::cout << " Checking cell " << *c_iter << std::endl;}
492: if (faultCells.find(*c_iter) != faultCells.end()) continue;
493: const Obj<Mesh::sieve_type::traits::coneSequence>& cone = sieve->cone(*c_iter);
494: const Mesh::sieve_type::traits::coneSequence::iterator vBegin = cone->begin();
495: const Mesh::sieve_type::traits::coneSequence::iterator vEnd = cone->end();
497: face->clear();
498: for(Mesh::sieve_type::traits::coneSequence::iterator v_iter = vBegin; v_iter != vEnd; ++v_iter) {
499: if (faultVertices.find(*v_iter) != fvEnd) {
500: if (debug) {std::cout << " contains fault vertex " << *v_iter << std::endl;}
501: face->insert(face->end(), *v_iter);
502: }
503: }
504: if (face->size() > faceSize) throw ALE::Exception("Invalid fault mesh: Too many vertices of an element on the fault");
505: if (face->size() == faceSize) {
506: if (debug) {std::cout << " Contains a face on the fault" << std::endl;}
507: const Obj<sieve_type::supportSet> preFace = faultSieve->nJoin1(face);
509: if (preFace->size() > 1) {
510: throw ALE::Exception("Invalid fault sieve: Multiple faces from vertex set");
511: } else if (preFace->size() == 1) {
512: faultSieve->addArrow(*preFace->begin(), *c_iter);
513: } else if (preFace->size() == 0) {
514: if (debug) {std::cout << " Adding face " << f << std::endl;}
515: int color = 0;
516: for(PointArray::const_iterator f_iter = face->begin(); f_iter != face->end(); ++f_iter) {
517: if (debug) {std::cout << " vertex " << *f_iter << std::endl;}
518: faultSieve->addArrow(*f_iter, f, color++);
519: }
520: faultSieve->addArrow(f, *c_iter);
521: f++;
522: }
523: faultCells.insert(*c_iter);
524: }
525: }
526: }
527: fault->setSieve(faultSieve);
528: fault->stratify();
529: faultCells.clear();
530: if (debug) {fault->view("Fault mesh");}
531: // Add new shadow vertices
532: const Obj<Mesh::label_sequence>& fVertices = fault->depthStratum(0);
533: const Obj<Mesh::label_sequence>& vertices = mesh->depthStratum(0);
534: Mesh::point_type newVertex = *vertices->begin() + vertices->size();
535: std::map<int,int> vertexRenumber;
537: for(Mesh::label_sequence::iterator v_iter = fVertices->begin(); v_iter != fVertices->end(); ++v_iter) {
538: if (debug) {std::cout << "Duplicating " << *v_iter << " to " << vertexRenumber[*v_iter] << std::endl;}
539: vertexRenumber[*v_iter] = newVertex++;
540: }
541: // Split the mesh along the fault sieve and create cohesive elements
542: const Obj<Mesh::label_sequence>& faces = fault->depthStratum(1);
543: PointArray newVertices;
545: for(Mesh::label_sequence::iterator f_iter = faces->begin(); f_iter != faces->end(); ++f_iter) {
546: if (debug) {std::cout << "Considering fault face " << *f_iter << std::endl;}
547: const Obj<Mesh::sieve_type::traits::supportSequence>& cells = faultSieve->support(*f_iter);
548: Mesh::point_type cell = std::max(*cells->begin(), *(++cells->begin()));
549: const Obj<Mesh::sieve_type::traits::coneSequence>& cone = sieve->cone(cell);
551: if (debug) {std::cout << " Replacing cell " << cell << std::endl;}
552: newVertices.clear();
553: for(ALE::Mesh::sieve_type::traits::coneSequence::iterator v_iter = cone->begin(); v_iter != cone->end(); ++v_iter) {
554: if (vertexRenumber.find(*v_iter) != vertexRenumber.end()) {
555: if (debug) {std::cout << " vertex " << vertexRenumber[*v_iter] << std::endl;}
556: newVertices.insert(newVertices.end(), vertexRenumber[*v_iter]);
557: } else {
558: if (debug) {std::cout << " vertex " << *v_iter << std::endl;}
559: newVertices.insert(newVertices.end(), *v_iter);
560: }
561: }
562: sieve->clearCone(cell);
563: int color = 0;
564: for(PointArray::const_iterator v_iter = newVertices.begin(); v_iter != newVertices.end(); ++v_iter) {
565: sieve->addArrow(*v_iter, cell, color++);
566: }
567: }
568: // Fix coordinates
569: const Obj<Mesh::real_section_type>& coordinates = mesh->getRealSection("coordinates");
570: const Obj<Mesh::label_sequence>& fVertices2 = fault->depthStratum(0);
572: for(Mesh::label_sequence::iterator v_iter = fVertices2->begin(); v_iter != fVertices2->end(); ++v_iter) {
573: coordinates->addPoint(vertexRenumber[*v_iter], coordinates->getFiberDimension(*v_iter));
574: }
575: mesh->reallocate(coordinates);
576: for(Mesh::label_sequence::iterator v_iter = fVertices2->begin(); v_iter != fVertices2->end(); ++v_iter) {
577: coordinates->updatePoint(vertexRenumber[*v_iter], coordinates->restrictPoint(*v_iter));
578: }
579: };
580: //
581: // Viewer methods
582: //
585: PetscErrorCode Viewer::writeVertices(const Obj<Mesh>& mesh, PetscViewer viewer) {
586: Obj<Builder::real_section_type> coordinates = mesh->getRealSection("coordinates");
587: //Mesh::section_type::patch_type patch;
588: //const double *array = coordinates->restrict(Mesh::section_type::patch_type());
589: //int dim = mesh->getDimension();
590: //int numVertices;
594: #if 0
595: //FIX:
596: if (vertexBundle->getGlobalOffsets()) {
597: numVertices = vertexBundle->getGlobalOffsets()[mesh->commSize()];
598: } else {
599: numVertices = mesh->getTopology()->depthStratum(0)->size();
600: }
601: PetscViewerASCIIPrintf(viewer,"#\n");
602: PetscViewerASCIIPrintf(viewer,"coord_units = m\n");
603: PetscViewerASCIIPrintf(viewer,"#\n");
604: PetscViewerASCIIPrintf(viewer,"#\n");
605: PetscViewerASCIIPrintf(viewer,"# Node X-coord Y-coord Z-coord\n");
606: PetscViewerASCIIPrintf(viewer,"#\n");
607: if (mesh->commRank() == 0) {
608: int numLocalVertices = mesh->getTopology()->depthStratum(0)->size();
609: int vertexCount = 1;
611: for(int v = 0; v < numLocalVertices; v++) {
612: PetscViewerASCIIPrintf(viewer,"%7D ", vertexCount++);
613: for(int d = 0; d < dim; d++) {
614: if (d > 0) {
615: PetscViewerASCIIPrintf(viewer," ");
616: }
617: PetscViewerASCIIPrintf(viewer,"% 16.8E", array[v*dim+d]);
618: }
619: PetscViewerASCIIPrintf(viewer,"\n");
620: }
621: for(int p = 1; p < mesh->commSize(); p++) {
622: double *remoteCoords;
623: MPI_Status status;
625: MPI_Recv(&numLocalVertices, 1, MPI_INT, p, 1, mesh->comm(), &status);
626: PetscMalloc(numLocalVertices*dim * sizeof(double), &remoteCoords);
627: MPI_Recv(remoteCoords, numLocalVertices*dim, MPI_DOUBLE, p, 1, mesh->comm(), &status);
628: for(int v = 0; v < numLocalVertices; v++) {
629: PetscViewerASCIIPrintf(viewer,"%7D ", vertexCount++);
630: for(int d = 0; d < dim; d++) {
631: if (d > 0) {
632: PetscViewerASCIIPrintf(viewer, " ");
633: }
634: PetscViewerASCIIPrintf(viewer, "% 16.8E", remoteCoords[v*dim+d]);
635: }
636: PetscViewerASCIIPrintf(viewer, "\n");
637: }
638: }
639: } else {
640: Obj<Mesh::bundle_type> globalOrder = coordinates->getGlobalOrder();
641: Obj<Mesh::field_type::order_type::coneSequence> cone = globalOrder->getPatch(patch);
642: const int *offsets = coordinates->getGlobalOffsets();
643: int numLocalVertices = (offsets[mesh->commRank()+1] - offsets[mesh->commRank()])/dim;
644: double *localCoords;
645: int k = 0;
647: PetscMalloc(numLocalVertices*dim * sizeof(double), &localCoords);
648: for(Mesh::field_type::order_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
649: int dim = globalOrder->getFiberDimension(patch, *p_iter);
651: if (dim > 0) {
652: int offset = coordinates->getFiberOffset(patch, *p_iter);
654: for(int i = offset; i < offset+dim; ++i) {
655: localCoords[k++] = array[i];
656: }
657: }
658: }
659: if (k != numLocalVertices*dim) {
660: SETERRQ2(PETSC_ERR_PLIB, "Invalid number of coordinates to send %d should be %d", k, numLocalVertices*dim);
661: }
662: MPI_Send(&numLocalVertices, 1, MPI_INT, 0, 1, mesh->comm());
663: MPI_Send(localCoords, numLocalVertices*dim, MPI_DOUBLE, 0, 1, mesh->comm());
664: PetscFree(localCoords);
665: }
666: #endif
667: return(0);
668: };
671: PetscErrorCode Viewer::writeElements(const Obj<Mesh>& mesh, const Obj<Builder::int_section_type>& materialField, PetscViewer viewer) {
672: #if 0
673: Obj<Mesh::sieve_type::traits::heightSequence> elements = topology->heightStratum(0);
674: Obj<Mesh::bundle_type> elementBundle = mesh->getBundle(topology->depth());
675: Obj<Mesh::bundle_type> vertexBundle = mesh->getBundle(0);
676: Obj<Mesh::bundle_type> globalVertex = vertexBundle->getGlobalOrder();
677: Obj<Mesh::bundle_type> globalElement = elementBundle->getGlobalOrder();
678: Mesh::bundle_type::patch_type patch;
679: std::string orderName("element");
680: bool hasMaterial = !materialField.isNull();
681: int dim = mesh->getDimension();
682: int corners = topology->nCone(*elements->begin(), topology->depth())->size();
683: int elementType = -1;
687: if (dim != 3) {
688: SETERRQ(PETSC_ERR_SUP, "PyLith only supports 3D meshes.");
689: }
690: if (corners == 4) {
691: // Linear tetrahedron
692: elementType = 5;
693: } else if (corners == 8) {
694: // Linear hexahedron
695: elementType = 1;
696: } else {
697: SETERRQ1(PETSC_ERR_SUP, "PyLith Error: Unsupported number of elements vertices: %d", corners);
698: }
699: PetscViewerASCIIPrintf(viewer,"#\n");
700: PetscViewerASCIIPrintf(viewer,"# N ETP MAT INF N1 N2 N3 N4 N5 N6 N7 N8\n");
701: PetscViewerASCIIPrintf(viewer,"#\n");
702: if (mesh->commRank() == 0) {
703: int elementCount = 1;
705: for(Mesh::sieve_type::traits::heightSequence::iterator e_itor = elements->begin(); e_itor != elements->end(); ++e_itor) {
706: Obj<Mesh::bundle_type::order_type::coneSequence> cone = vertexBundle->getPatch(orderName, *e_itor);
708: PetscViewerASCIIPrintf(viewer, "%7d %3d", elementCount++, elementType);
709: if (hasMaterial) {
710: // No infinite elements
711: PetscViewerASCIIPrintf(viewer, " %3d %3d", (int) materialField->restrict(patch, *e_itor)[0], 0);
712: } else {
713: // No infinite elements
714: PetscViewerASCIIPrintf(viewer, " %3d %3d", 1, 0);
715: }
716: for(Mesh::bundle_type::order_type::coneSequence::iterator c_itor = cone->begin(); c_itor != cone->end(); ++c_itor) {
717: PetscViewerASCIIPrintf(viewer, " %6d", globalVertex->getIndex(patch, *c_itor).prefix+1);
718: }
719: PetscViewerASCIIPrintf(viewer, "\n");
720: }
721: for(int p = 1; p < mesh->commSize(); p++) {
722: int numLocalElements;
723: int *remoteVertices;
724: MPI_Status status;
726: MPI_Recv(&numLocalElements, 1, MPI_INT, p, 1, mesh->comm(), &status);
727: PetscMalloc(numLocalElements*(corners+1) * sizeof(int), &remoteVertices);
728: MPI_Recv(remoteVertices, numLocalElements*(corners+1), MPI_INT, p, 1, mesh->comm(), &status);
729: for(int e = 0; e < numLocalElements; e++) {
730: // Only linear tetrahedra, material, no infinite elements
731: int mat = remoteVertices[e*(corners+1)+corners];
733: PetscViewerASCIIPrintf(viewer, "%7d %3d %3d %3d", elementCount++, elementType, mat, 0);
734: for(int c = 0; c < corners; c++) {
735: PetscViewerASCIIPrintf(viewer, " %6d", remoteVertices[e*(corners+1)+c]);
736: }
737: PetscViewerASCIIPrintf(viewer, "\n");
738: }
739: PetscFree(remoteVertices);
740: }
741: } else {
742: const int *offsets = elementBundle->getGlobalOffsets();
743: int numLocalElements = offsets[mesh->commRank()+1] - offsets[mesh->commRank()];
744: int *localVertices;
745: int k = 0;
747: PetscMalloc(numLocalElements*(corners+1) * sizeof(int), &localVertices);
748: for(Mesh::sieve_type::traits::heightSequence::iterator e_itor = elements->begin(); e_itor != elements->end(); ++e_itor) {
749: Obj<Mesh::bundle_type::order_type::coneSequence> cone = vertexBundle->getPatch(orderName, *e_itor);
751: if (globalElement->getFiberDimension(patch, *e_itor) > 0) {
752: for(Mesh::bundle_type::order_type::coneSequence::iterator c_itor = cone->begin(); c_itor != cone->end(); ++c_itor) {
753: localVertices[k++] = globalVertex->getIndex(patch, *c_itor).prefix;
754: }
755: if (hasMaterial) {
756: localVertices[k++] = (int) materialField->restrict(patch, *e_itor)[0];
757: } else {
758: localVertices[k++] = 1;
759: }
760: }
761: }
762: if (k != numLocalElements*corners) {
763: SETERRQ2(PETSC_ERR_PLIB, "Invalid number of vertices to send %d should be %d", k, numLocalElements*corners);
764: }
765: MPI_Send(&numLocalElements, 1, MPI_INT, 0, 1, mesh->comm());
766: MPI_Send(localVertices, numLocalElements*(corners+1), MPI_INT, 0, 1, mesh->comm());
767: PetscFree(localVertices);
768: }
769: #endif
770: return(0);
771: };
774: PetscErrorCode Viewer::writeVerticesLocal(const Obj<Mesh>& mesh, PetscViewer viewer) {
775: const Obj<Mesh::real_section_type>& coordinates = mesh->getRealSection("coordinates");
776: const Obj<Mesh::label_sequence>& vertices = mesh->depthStratum(0);
777: const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(mesh, 0);
778: int embedDim = coordinates->getFiberDimension(*vertices->begin());
782: PetscViewerASCIIPrintf(viewer,"#\n");
783: PetscViewerASCIIPrintf(viewer,"coord_units = m\n");
784: PetscViewerASCIIPrintf(viewer,"#\n");
785: PetscViewerASCIIPrintf(viewer,"#\n");
786: PetscViewerASCIIPrintf(viewer,"# Node X-coord Y-coord Z-coord\n");
787: PetscViewerASCIIPrintf(viewer,"#\n");
789: for(Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
790: const Mesh::real_section_type::value_type *array = coordinates->restrictPoint(*v_iter);
792: PetscViewerASCIIPrintf(viewer, "%7D ", vNumbering->getIndex(*v_iter)+1);
793: for(int d = 0; d < embedDim; d++) {
794: if (d > 0) {
795: PetscViewerASCIIPrintf(viewer, " ");
796: }
797: PetscViewerASCIIPrintf(viewer, "% 16.8E", array[d]);
798: }
799: PetscViewerASCIIPrintf(viewer, "\n");
800: }
801: return(0);
802: };
805: PetscErrorCode Viewer::writeElementsLocal(const Obj<Mesh>& mesh, const Obj<Builder::int_section_type>& materialField, PetscViewer viewer) {
806: const Obj<Mesh::sieve_type>& sieve = mesh->getSieve();
807: const Obj<Mesh::label_sequence>& elements = mesh->heightStratum(0);
808: const Obj<Mesh::numbering_type>& eNumbering = mesh->getFactory()->getLocalNumbering(mesh, mesh->depth());
809: const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(mesh, 0);
810: int dim = mesh->getDimension();
811: //int corners = sieve->nCone(*elements->begin(), topology->depth())->size();
812: int corners = sieve->cone(*elements->begin())->size();
813: bool hasMaterial = !materialField.isNull();
814: int elementType = -1;
818: if (dim != 3) {
819: SETERRQ(PETSC_ERR_SUP, "PyLith only supports 3D meshes.");
820: }
821: if (corners == 4) {
822: // Linear tetrahedron
823: elementType = 5;
824: } else if (corners == 8) {
825: // Linear hexahedron
826: elementType = 1;
827: } else {
828: SETERRQ1(PETSC_ERR_SUP, "PyLith Error: Unsupported number of elements vertices: %d", corners);
829: }
830: PetscViewerASCIIPrintf(viewer,"#\n");
831: PetscViewerASCIIPrintf(viewer,"# N ETP MAT INF N1 N2 N3 N4 N5 N6 N7 N8\n");
832: PetscViewerASCIIPrintf(viewer,"#\n");
833: for(Mesh::label_sequence::iterator e_iter = elements->begin(); e_iter != elements->end(); ++e_iter) {
834: const Obj<Mesh::sieve_type::traits::coneSequence> cone = sieve->cone(*e_iter);
835: Mesh::sieve_type::traits::coneSequence::iterator begin = cone->begin();
836: Mesh::sieve_type::traits::coneSequence::iterator end = cone->end();
838: PetscViewerASCIIPrintf(viewer, "%7d %3d", eNumbering->getIndex(*e_iter)+1, elementType);
839: if (hasMaterial) {
840: // No infinite elements
841: PetscViewerASCIIPrintf(viewer, " %3d %3d", (int) materialField->restrictPoint(*e_iter)[0], 0);
842: } else {
843: // No infinite elements
844: PetscViewerASCIIPrintf(viewer, " %3d %3d", 1, 0);
845: }
846: for(Mesh::sieve_type::traits::coneSequence::iterator c_iter = begin; c_iter != end; ++c_iter) {
847: //FIX: Need a global ordering here
848: PetscViewerASCIIPrintf(viewer, " %6d", vNumbering->getIndex(*c_iter)+1);
849: }
850: PetscViewerASCIIPrintf(viewer, "\n");
851: }
852: return(0);
853: };
854: #if 0
857: // The elements seem to be implicitly numbered by appearance, which makes it impossible to
858: // number here by bundle, but we can fix it by traversing the elements like the vertices
859: PetscErrorCode Viewer::writeSplitLocal(const Obj<Mesh>& mesh, const Obj<Builder::pair_section_type>& splitField, PetscViewer viewer) {
860: const Obj<Mesh::topology_type>& topology = mesh->getTopology();
861: Builder::pair_section_type::patch_type patch = 0;
862: const Obj<Mesh::numbering_type>& eNumbering = mesh->getFactory()->getLocalNumbering(topology, patch, topology->depth());
863: const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(topology, patch, 0);
867: const Builder::pair_section_type::atlas_type::chart_type& chart = splitField->getPatch(patch);
869: for(Builder::pair_section_type::atlas_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
870: const Builder::pair_section_type::point_type& e = *c_iter;
871: const Builder::pair_section_type::value_type *values = splitField->restrict(patch, e);
872: const int size = splitField->getFiberDimension(patch, e);
874: for(int i = 0; i < size; i++) {
875: const Builder::pair_section_type::point_type& v = values[i].first;
876: const ALE::Mesh::base_type::split_value& split = values[i].second;
878: // No time history
879: 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);
880: }
881: }
882: return(0);
883: };
884: #endif
887: PetscErrorCode Viewer::writeTractionsLocal(const Obj<Mesh>& mesh, const Obj<Mesh>& tractionMesh, const Obj<Builder::real_section_type>& tractionField, PetscViewer viewer) {
888: const Obj<Mesh::sieve_type>& sieve = tractionMesh->getSieve();
889: const Obj<Mesh::label_sequence>& faces = tractionMesh->heightStratum(0);
890: const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(mesh, 0);
894: PetscViewerASCIIPrintf(viewer,"#\n");
895: PetscViewerASCIIPrintf(viewer,"traction_units = Pa\n");
896: PetscViewerASCIIPrintf(viewer,"#\n");
897: PetscViewerASCIIPrintf(viewer,"#\n");
898: for(Mesh::label_sequence::iterator f_iter = faces->begin(); f_iter != faces->end(); ++f_iter) {
899: const Mesh::point_type& face = *f_iter;
900: const Obj<Mesh::sieve_type::traits::coneSequence>& cone = sieve->cone(face);
902: for(Mesh::sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter) {
903: const Mesh::point_type& vertex = *c_iter;
905: PetscViewerASCIIPrintf(viewer, "%6d", vNumbering->getIndex(vertex)+1);
906: std::cout << vNumbering->getIndex(vertex) << " ("<<vertex<<") ";
907: }
908: const Mesh::real_section_type::value_type *values = tractionField->restrictPoint(face);
910: for(int i = 0; i < mesh->getDimension(); ++i) {
911: if (i > 0) {
912: PetscViewerASCIIPrintf(viewer, " ");
913: std::cout << " ";
914: }
915: PetscViewerASCIIPrintf(viewer, "%15.9g", values[i]);
916: std::cout << values[i];
917: }
918: PetscViewerASCIIPrintf(viewer,"\n");
919: std::cout << std::endl;
920: }
921: return(0);
922: };
923: };
924: };
926: namespace ALECompat {
927: namespace PyLith {
928: using ALECompat::Mesh;
929: //
930: // Builder methods
931: //
932: char *Builder::coord_units = NULL;
933: char *Builder::traction_units = NULL;
934: void Builder::broadcastString(const MPI_Comm comm, const int rank, const char *input, char **output) {
935: int len;
937: if (rank == 0) {
938: len = strlen(input);
939: }
940: MPI_Bcast(&len, 1, MPI_INT, 0, comm);
941: *output = new char[len+1];
942: if (rank == 0) {
943: strcpy(*output, input);
944: }
945: MPI_Bcast(*output, len+1, MPI_CHAR, 0, comm);
946: };
947: inline void Builder::ignoreComments(char *buf, PetscInt bufSize, FILE *f) {
948: while((fgets(buf, bufSize, f) != NULL) && ((buf[0] == '#') || (buf[0] == '\0'))) {}
949: };
950: void Builder::readConnectivity(MPI_Comm comm, const std::string& filename, int& corners, const bool useZeroBase, int& numElements, int *vertices[], int *materials[]) {
951: PetscViewer viewer;
952: FILE *f;
953: PetscInt maxCells = 1024, cellCount = 0;
954: PetscInt *verts;
955: PetscInt *mats;
956: char buf[2048];
957: PetscInt c;
958: PetscInt commRank;
961: MPI_Comm_rank(comm, &commRank);
962: if (commRank != 0) return;
963: PetscViewerCreate(PETSC_COMM_SELF, &viewer);
964: PetscViewerSetType(viewer, PETSC_VIEWER_ASCII);
965: PetscViewerFileSetMode(viewer, FILE_MODE_READ);
966: PetscViewerFileSetName(viewer, filename.c_str());
967: PetscViewerASCIIGetPointer(viewer, &f);
968: /* Ignore comments */
969: ignoreComments(buf, 2048, f);
970: do {
971: const char *v = strtok(buf, " ");
972: int elementType;
974: if (cellCount == maxCells) {
975: PetscInt *vtmp, *mtmp;
977: vtmp = verts;
978: mtmp = mats;
979: PetscMalloc2(maxCells*2*corners,PetscInt,&verts,maxCells*2,PetscInt,&mats);
980: PetscMemcpy(verts, vtmp, maxCells*corners * sizeof(PetscInt));
981: PetscMemcpy(mats, mtmp, maxCells * sizeof(PetscInt));
982: PetscFree2(vtmp,mtmp);
983: maxCells *= 2;
984: }
985: /* Ignore cell number */
986: v = strtok(NULL, " ");
987: /* Get element type */
988: elementType = atoi(v);
989: if (elementType == 1) {
990: corners = 8;
991: } else if (elementType == 5) {
992: corners = 4;
993: } else {
994: ostringstream msg;
996: msg << "We do not accept element type " << elementType << " right now";
997: throw ALE::Exception(msg.str().c_str());
998: }
999: if (cellCount == 0) {
1000: PetscMalloc2(maxCells*corners,PetscInt,&verts,maxCells,PetscInt,&mats);
1001: }
1002: v = strtok(NULL, " ");
1003: /* Store material type */
1004: mats[cellCount] = atoi(v);
1005: v = strtok(NULL, " ");
1006: /* Ignore infinite domain element code */
1007: v = strtok(NULL, " ");
1008: for(c = 0; c < corners; c++) {
1009: int vertex = atoi(v);
1010:
1011: if (!useZeroBase) vertex -= 1;
1012: verts[cellCount*corners+c] = vertex;
1013: v = strtok(NULL, " ");
1014: }
1015: cellCount++;
1016: } while(fgets(buf, 2048, f) != NULL);
1017: PetscViewerDestroy(viewer);
1018: numElements = cellCount;
1019: *vertices = verts;
1020: *materials = mats;
1021: };
1022: void Builder::readCoordinates(MPI_Comm comm, const std::string& filename, const int dim, int& numVertices, double *coordinates[]) {
1023: PetscViewer viewer;
1024: FILE *f;
1025: PetscInt maxVerts = 1024, vertexCount = 0;
1026: PetscScalar *coords;
1027: const char *units = NULL;
1028: double scaleFactor = 1.0;
1029: char buf[2048];
1030: PetscInt c;
1031: PetscInt commRank;
1034: MPI_Comm_rank(comm, &commRank);
1035: if (commRank == 0) {
1036: PetscViewerCreate(PETSC_COMM_SELF, &viewer);
1037: PetscViewerSetType(viewer, PETSC_VIEWER_ASCII);
1038: PetscViewerFileSetMode(viewer, FILE_MODE_READ);
1039: PetscViewerFileSetName(viewer, filename.c_str());
1040: PetscViewerASCIIGetPointer(viewer, &f);
1041: /* Ignore comments */
1042: ignoreComments(buf, 2048, f);
1043: PetscMalloc(maxVerts*dim * sizeof(PetscScalar), &coords);
1044: /* Read units */
1045: units = strtok(buf, " ");
1046: if (strcmp(units, "coord_units")) {
1047: throw ALE::Exception("Invalid coordinate units line");
1048: }
1049: units = strtok(NULL, " ");
1050: if (strcmp(units, "=")) {
1051: throw ALE::Exception("Invalid coordinate units line");
1052: }
1053: units = strtok(NULL, " ");
1054: }
1055: /* Should use Pythia to do units conversion */
1056: Builder::broadcastString(comm, commRank, units, &Builder::coord_units);
1057: if (commRank == 0) {
1058: /* Ignore comments */
1059: ignoreComments(buf, 2048, f);
1060: do {
1061: const char *x = strtok(buf, " ");
1063: if (vertexCount == maxVerts) {
1064: PetscScalar *ctmp;
1066: ctmp = coords;
1067: PetscMalloc(maxVerts*2*dim * sizeof(PetscScalar), &coords);
1068: PetscMemcpy(coords, ctmp, maxVerts*dim * sizeof(PetscScalar));
1069: PetscFree(ctmp);
1070: maxVerts *= 2;
1071: }
1072: /* Ignore vertex number */
1073: x = strtok(NULL, " ");
1074: for(c = 0; c < dim; c++) {
1075: coords[vertexCount*dim+c] = atof(x)*scaleFactor;
1076: x = strtok(NULL, " ");
1077: }
1078: vertexCount++;
1079: } while(fgets(buf, 2048, f) != NULL);
1080: PetscViewerDestroy(viewer);
1081: numVertices = vertexCount;
1082: *coordinates = coords;
1083: }
1084: };
1085: // numSplit is the number of split node entries (lines in the file)
1086: // splitInd[] is an array of numSplit pairs, <element, vertex>
1087: // splitValues[] is an array of numSplit*dim displacements
1088: void Builder::readSplit(MPI_Comm comm, const std::string& filename, const int dim, const bool useZeroBase, int& numSplit, int *splitInd[], int *loadHistory[], double *splitValues[]) {
1089: PetscViewer viewer;
1090: FILE *f;
1091: PetscInt maxSplit = 1024, splitCount = 0;
1092: PetscInt *splitId;
1093: PetscInt *loadHist;
1094: PetscScalar *splitVal;
1095: char buf[2048];
1096: PetscInt c;
1097: PetscInt commRank;
1100: MPI_Comm_rank(comm, &commRank);
1101: if (dim != 3) {
1102: throw ALE::Exception("PyLith only works in 3D");
1103: }
1104: if (commRank != 0) return;
1105: PetscViewerCreate(PETSC_COMM_SELF, &viewer);
1106: PetscViewerSetType(viewer, PETSC_VIEWER_ASCII);
1107: PetscViewerFileSetMode(viewer, FILE_MODE_READ);
1108: PetscExceptionTry1(PetscViewerFileSetName(viewer, filename.c_str()), PETSC_ERR_FILE_OPEN);
1109: if (PetscExceptionValue(ierr)) {
1110: // this means that a caller above me has also tryed this exception so I don't handle it here, pass it up
1111: } else if (PetscExceptionCaught(ierr,PETSC_ERR_FILE_OPEN)) {
1112: // File does not exist
1113: return;
1114: }
1115: PetscViewerASCIIGetPointer(viewer, &f);
1116: /* Ignore comments */
1117: ignoreComments(buf, 2048, f);
1118: PetscMalloc3(maxSplit*2,PetscInt,&splitId,maxSplit,PetscInt,&loadHist,maxSplit*dim,PetscScalar,&splitVal);
1119: do {
1120: const char *s = strtok(buf, " ");
1122: if (splitCount == maxSplit) {
1123: PetscInt *sitmp;
1124: PetscInt *lhtmp;
1125: PetscScalar *svtmp;
1127: sitmp = splitId;
1128: lhtmp = loadHist;
1129: svtmp = splitVal;
1130: PetscMalloc3(maxSplit*2*2,PetscInt,&splitId,maxSplit*2,PetscInt,&loadHist,maxSplit*dim*2,PetscScalar,&splitVal);
1131: PetscMemcpy(splitId, sitmp, maxSplit*2 * sizeof(PetscInt));
1132: PetscMemcpy(loadHist, lhtmp, maxSplit * sizeof(PetscInt));
1133: PetscMemcpy(splitVal, svtmp, maxSplit*dim * sizeof(PetscScalar));
1134: PetscFree3(sitmp,lhtmp,svtmp);
1135: maxSplit *= 2;
1136: }
1137: /* Get element number */
1138: int elem = atoi(s);
1139: if (!useZeroBase) elem -= 1;
1140: splitId[splitCount*2+0] = elem;
1141: s = strtok(NULL, " ");
1142: /* Get node number */
1143: int node = atoi(s);
1144: if (!useZeroBase) node -= 1;
1145: splitId[splitCount*2+1] = node;
1146: s = strtok(NULL, " ");
1147: /* Ignore load history number */
1148: loadHist[splitCount] = atoi(s);
1149: s = strtok(NULL, " ");
1150: /* Get split values */
1151: for(c = 0; c < dim; c++) {
1152: splitVal[splitCount*dim+c] = atof(s);
1153: s = strtok(NULL, " ");
1154: }
1155: splitCount++;
1156: } while(fgets(buf, 2048, f) != NULL);
1157: PetscViewerDestroy(viewer);
1158: numSplit = splitCount;
1159: *splitInd = splitId;
1160: *loadHistory = loadHist;
1161: *splitValues = splitVal;
1162: };
1163: 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[]) {
1164: const pair_section_type::patch_type patch = 0;
1165: pair_section_type::value_type *values;
1166: int_section_type::value_type *history;
1167: std::map<pair_section_type::point_type, std::set<int> > elem2index;
1168: int numValues = 0;
1170: splitField->setName("split");
1171: for(int e = 0; e < numSplit; e++) {
1172: splitField->addFiberDimension(patch, splitInd[e*2+0], 1);
1173: loadField->addFiberDimension(patch, splitInd[e*2+0], 1);
1174: elem2index[splitInd[e*2+0]].insert(e);
1175: }
1176: splitField->allocate();
1177: loadField->allocate();
1178: for(std::map<pair_section_type::point_type, std::set<int> >::const_iterator e_iter = elem2index.begin(); e_iter != elem2index.end(); ++e_iter) {
1179: numValues = std::max(numValues, (int) e_iter->second.size());
1180: }
1181: values = new pair_section_type::value_type[numValues];
1182: history = new int_section_type::value_type[numValues];
1183: for(std::map<pair_section_type::point_type, std::set<int> >::const_iterator e_iter = elem2index.begin(); e_iter != elem2index.end(); ++e_iter) {
1184: const pair_section_type::point_type& e = e_iter->first;
1185: int k = 0;
1187: for(std::set<int>::const_iterator i_iter = e_iter->second.begin(); i_iter != e_iter->second.end(); ++i_iter, ++k) {
1188: const int& i = *i_iter;
1190: if (k >= numValues) {throw ALE::Exception("Invalid split node input");}
1191: values[k].first = splitInd[i*2+1] + numCells;
1192: values[k].second.x = splitVals[i*3+0];
1193: values[k].second.y = splitVals[i*3+1];
1194: values[k].second.z = splitVals[i*3+2];
1195: history[k] = loadHistory[i];
1196: }
1197: splitField->updatePoint(patch, e, values);
1198: loadField->updatePoint(patch, e, history);
1199: }
1200: delete [] values;
1201: };
1202: 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[]) {
1203: PetscViewer viewer;
1204: FILE *f;
1205: PetscInt maxTractions = 1024, tractionCount = 0;
1206: PetscInt *tractionVerts;
1207: PetscScalar *tractionVals;
1208: const char *units = NULL;
1209: char buf[2048];
1210: PetscInt c;
1211: PetscInt commRank;
1212: PetscTruth found = PETSC_TRUE;
1215: MPI_Comm_rank(comm, &commRank);
1216: if (dim != 3) {
1217: throw ALE::Exception("PyLith only works in 3D");
1218: }
1219: if (commRank == 0) {
1220: PetscViewerCreate(PETSC_COMM_SELF, &viewer);
1221: PetscViewerSetType(viewer, PETSC_VIEWER_ASCII);
1222: PetscViewerFileSetMode(viewer, FILE_MODE_READ);
1223: PetscExceptionTry1(PetscViewerFileSetName(viewer, filename.c_str()), PETSC_ERR_FILE_OPEN);
1224: if (PetscExceptionValue(ierr)) {
1225: // this means that a caller above me has also tryed this exception so I don't handle it here, pass it up
1226: } else if (PetscExceptionCaught(ierr,PETSC_ERR_FILE_OPEN)) {
1227: // File does not exist
1228: found = PETSC_FALSE;
1229: }
1230: /* Logic right now is only good for linear tets and hexes, and should be fixed in the future. */
1231: if (corners == 4) {
1232: vertsPerFace = 3;
1233: } else if (corners == 8) {
1234: vertsPerFace = 4;
1235: } else {
1236: throw ALE::Exception("Unrecognized element type");
1237: }
1238: }
1239: MPI_Bcast(&found, 1, MPI_INT, 0, comm);
1240: if (!found) return;
1241: if (commRank == 0) {
1242: PetscViewerASCIIGetPointer(viewer, &f);
1243: /* Ignore comments */
1244: ignoreComments(buf, 2048, f);
1245: /* Read units */
1246: units = strtok(buf, " ");
1247: if (strcmp(units, "traction_units")) {
1248: throw ALE::Exception("Invalid traction units line");
1249: }
1250: units = strtok(NULL, " ");
1251: if (strcmp(units, "=")) {
1252: throw ALE::Exception("Invalid traction units line");
1253: }
1254: units = strtok(NULL, " ");
1255: }
1256: /* Should use Pythia to do units conversion */
1257: Builder::broadcastString(comm, commRank, units, &Builder::traction_units);
1258: if (commRank == 0) {
1259: /* Ignore comments */
1260: ignoreComments(buf, 2048, f);
1261: // Allocate memory.
1262: PetscMalloc2(maxTractions*vertsPerFace,PetscInt,&tractionVerts,maxTractions*dim,PetscScalar,&tractionVals);
1263: do {
1264: const char *s = strtok(buf, " ");
1266: if (tractionCount == maxTractions) {
1267: PetscInt *titmp;
1268: PetscScalar *tvtmp;
1270: titmp = tractionVerts;
1271: tvtmp = tractionVals;
1272: PetscMalloc2(maxTractions*vertsPerFace*2,PetscInt,&tractionVerts,maxTractions*dim*2,PetscScalar,&tractionVals);
1273: PetscMemcpy(tractionVerts, titmp, maxTractions*vertsPerFace * sizeof(PetscInt));
1274: PetscMemcpy(tractionVals, tvtmp, maxTractions*dim * sizeof(PetscScalar));
1275: PetscFree2(titmp,tvtmp);
1276: maxTractions *= 2;
1277: }
1278: /* Get vertices */
1279: int v1 = atoi(s);
1280: if (!useZeroBase) v1 -= 1;
1281: tractionVerts[tractionCount*vertsPerFace+0] = v1;
1282: s = strtok(NULL, " ");
1283: int v2 = atoi(s);
1284: if (!useZeroBase) v2 -= 1;
1285: tractionVerts[tractionCount*vertsPerFace+1] = v2;
1286: s = strtok(NULL, " ");
1287: int v3 = atoi(s);
1288: if (!useZeroBase) v3 -= 1;
1289: tractionVerts[tractionCount*vertsPerFace+2] = v3;
1290: s = strtok(NULL, " ");
1291: if (vertsPerFace > 3) {
1292: int v4 = atoi(s);
1293: if (!useZeroBase) v4 -= 1;
1294: tractionVerts[tractionCount*vertsPerFace+3] = v4;
1295: s = strtok(NULL, " ");
1296: }
1297: /* Get traction values */
1298: for(c = 0; c < dim; c++) {
1299: tractionVals[tractionCount*dim+c] = atof(s);
1300: s = strtok(NULL, " ");
1301: }
1302: tractionCount++;
1303: } while(fgets(buf, 2048, f) != NULL);
1304: PetscViewerDestroy(viewer);
1305: numTractions = tractionCount;
1306: *tractionVertices = tractionVerts;
1307: *tractionValues = tractionVals;
1308: }
1309: };
1310: void Builder::buildTractions(const Obj<real_section_type>& tractionField, const Obj<topology_type>& boundaryTopology, int numCells, int numTractions, int vertsPerFace, int tractionVertices[], double tractionValues[]) {
1311: const real_section_type::patch_type patch = 0;
1312: real_section_type::value_type values[3];
1313: // Make boundary topology
1314: Obj<sieve_type> boundarySieve = new sieve_type(tractionField->comm(), tractionField->debug());
1316: ALECompat::New::SieveBuilder<Mesh>::buildTopology(boundarySieve, 2, numTractions, tractionVertices, 0, false, vertsPerFace, numCells);
1317: boundaryTopology->setPatch(patch, boundarySieve);
1318: boundaryTopology->stratify();
1319: // Make traction field
1320: tractionField->setName("traction");
1321: tractionField->setTopology(boundaryTopology);
1322: tractionField->setFiberDimensionByHeight(patch, 0, 3);
1323: tractionField->allocate();
1324: const Obj<topology_type::label_sequence>& faces = boundaryTopology->heightStratum(patch, 0);
1325: int k = 0;
1327: for(topology_type::label_sequence::iterator f_iter = faces->begin(); f_iter != faces->end(); ++f_iter) {
1328: const topology_type::point_type& face = *f_iter;
1330: values[0] = tractionValues[k*3+0];
1331: values[1] = tractionValues[k*3+1];
1332: values[2] = tractionValues[k*3+2];
1333: k++;
1334: tractionField->updatePoint(patch, face, values);
1335: }
1336: };
1337: void Builder::buildMaterials(const Obj<int_section_type>& matField, const int materials[]) {
1338: const int_section_type::patch_type patch = 0;
1339: const Obj<topology_type::label_sequence>& elements = matField->getTopology()->heightStratum(patch, 0);
1341: matField->setName("material");
1342: matField->setFiberDimensionByHeight(patch, 0, 1);
1343: matField->allocate();
1344: for(topology_type::label_sequence::iterator e_iter = elements->begin(); e_iter != elements->end(); ++e_iter) {
1345: matField->updatePoint(patch, *e_iter, &materials[*e_iter]);
1346: }
1347: };
1348: Obj<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) {
1349: Obj<Mesh> mesh = new Mesh(comm, dim, debug);
1350: Obj<sieve_type> sieve = new sieve_type(comm, debug);
1351: Obj<topology_type> topology = new topology_type(comm, debug);
1352: int *cells, *materials;
1353: double *coordinates;
1354: int numCells = 0, numVertices = 0, numCorners = dim+1;
1356: ALECompat::PyLith::Builder::readConnectivity(comm, basename+".connect", numCorners, useZeroBase, numCells, &cells, &materials);
1357: ALECompat::PyLith::Builder::readCoordinates(comm, basename+".coord", dim, numVertices, &coordinates);
1358: ALECompat::New::SieveBuilder<Mesh>::buildTopology(sieve, dim, numCells, cells, numVertices, interpolate, numCorners);
1359: sieve->stratify();
1360: topology->setPatch(0, sieve);
1361: topology->stratify();
1362: mesh->setTopology(topology);
1363: ALECompat::New::SieveBuilder<Mesh>::buildCoordinates(mesh->getRealSection("coordinates"), dim, coordinates);
1364: Obj<int_section_type> material = mesh->getIntSection("material");
1365: buildMaterials(material, materials);
1366: Obj<ALECompat::Mesh::pair_section_type> split = createSplit(mesh, basename, useZeroBase);
1367: if (!split.isNull()) {mesh->setPairSection("split", split);}
1368: Obj<ALECompat::Mesh::real_section_type> traction = createTraction(mesh, basename, useZeroBase);
1369: if (!traction.isNull()) {mesh->setRealSection("traction", traction);}
1370: return mesh;
1371: };
1372: Obj<Builder::pair_section_type> Builder::createSplit(const Obj<Mesh>& mesh, const std::string& basename, const bool useZeroBase = false) {
1373: Obj<pair_section_type> split = NULL;
1374: MPI_Comm comm = mesh->comm();
1375: int dim = mesh->getDimension();
1376: int numCells = mesh->getTopology()->heightStratum(0, 0)->size();
1377: int *splitInd, *loadHistory;
1378: double *splitValues;
1379: int numSplit = 0, hasSplit;
1381: ALECompat::PyLith::Builder::readSplit(comm, basename+".split", dim, useZeroBase, numSplit, &splitInd, &loadHistory, &splitValues);
1382: MPI_Allreduce(&numSplit, &hasSplit, 1, MPI_INT, MPI_MAX, comm);
1383: if (hasSplit) {
1384: split = new pair_section_type(mesh->getTopology());
1385: Obj<int_section_type> loadField = mesh->getIntSection("loadHistory");
1386: buildSplit(split, loadField, numCells, numSplit, splitInd, loadHistory, splitValues);
1387: }
1388: return split;
1389: };
1390: Obj<Mesh::real_section_type> Builder::createTraction(const Obj<Mesh>& mesh, const std::string& basename, const bool useZeroBase = false) {
1391: Obj<real_section_type> traction = NULL;
1392: MPI_Comm comm = mesh->comm();
1393: int debug = mesh->debug();
1394: int dim = mesh->getDimension();
1395: int numCells = mesh->getTopology()->heightStratum(0, 0)->size();
1396: int numCorners = mesh->getTopology()->getPatch(0)->cone(*mesh->getTopology()->heightStratum(0, 0)->begin())->size();
1397: int *tractionVertices;
1398: double *tractionValues;
1399: int numTractions = 0, vertsPerFace = 0, hasTractions;
1401: ALECompat::PyLith::Builder::readTractions(comm, basename+".traction", dim, numCorners, useZeroBase, numTractions, vertsPerFace, &tractionVertices, &tractionValues);
1402: MPI_Allreduce(&numTractions, &hasTractions, 1, MPI_INT, MPI_MAX, comm);
1403: if (hasTractions) {
1404: Obj<topology_type> boundaryTopology = new topology_type(mesh->comm(), debug);
1406: traction = new real_section_type(boundaryTopology);
1407: buildTractions(traction, boundaryTopology, numCells, numTractions, vertsPerFace, tractionVertices, tractionValues);
1408: }
1409: return traction;
1410: };
1411: void Builder::createCohesiveElements(const Obj<Mesh>& mesh, const std::set<Mesh::point_type>& faultVertices) {
1412: typedef std::vector<Mesh::point_type> PointArray;
1413: const Mesh::real_section_type::patch_type patch = 0;
1414: const Obj<Mesh::sieve_type> sieve = mesh->getTopology()->getPatch(patch);
1415: const Obj<Mesh::topology_type> fault = new Mesh::topology_type(sieve->comm(), sieve->debug());
1416: const Obj<Mesh::sieve_type> faultSieve = new Mesh::sieve_type(sieve->comm(), sieve->debug());
1417: const std::set<Mesh::point_type>::const_iterator fvBegin = faultVertices.begin();
1418: const std::set<Mesh::point_type>::const_iterator fvEnd = faultVertices.end();
1419: // There should be logic here to determine this
1420: const unsigned int faceSize = 3;
1421: int f = 0;
1422: int debug = mesh->debug();
1423: Obj<PointArray> face = new PointArray();
1424: std::set<Mesh::point_type> faultCells;
1426: // Create a sieve which captures the fault
1427: for(std::set<int>::const_iterator fv_iter = fvBegin; fv_iter != fvEnd; ++fv_iter) {
1428: const Obj<Mesh::sieve_type::traits::supportSequence>& cells = sieve->support(*fv_iter);
1429: const Mesh::sieve_type::traits::supportSequence::iterator cBegin = cells->begin();
1430: const Mesh::sieve_type::traits::supportSequence::iterator cEnd = cells->end();
1432: if (debug) {std::cout << "Checking fault vertex " << *fv_iter << std::endl;}
1433: for(ALECompat::Mesh::sieve_type::traits::supportSequence::iterator c_iter = cBegin; c_iter != cEnd; ++c_iter) {
1434: if (debug) {std::cout << " Checking cell " << *c_iter << std::endl;}
1435: if (faultCells.find(*c_iter) != faultCells.end()) continue;
1436: const Obj<ALECompat::Mesh::sieve_type::traits::coneSequence>& cone = sieve->cone(*c_iter);
1437: const Mesh::sieve_type::traits::coneSequence::iterator vBegin = cone->begin();
1438: const Mesh::sieve_type::traits::coneSequence::iterator vEnd = cone->end();
1440: face->clear();
1441: for(ALECompat::Mesh::sieve_type::traits::coneSequence::iterator v_iter = vBegin; v_iter != vEnd; ++v_iter) {
1442: if (faultVertices.find(*v_iter) != fvEnd) {
1443: if (debug) {std::cout << " contains fault vertex " << *v_iter << std::endl;}
1444: face->insert(face->end(), *v_iter);
1445: }
1446: }
1447: if (face->size() > faceSize) throw ALE::Exception("Invalid fault mesh: Too many vertices of an element on the fault");
1448: if (face->size() == faceSize) {
1449: if (debug) {std::cout << " Contains a face on the fault" << std::endl;}
1450: const Obj<sieve_type::supportSet> preFace = faultSieve->nJoin1(face);
1452: if (preFace->size() > 1) {
1453: throw ALE::Exception("Invalid fault sieve: Multiple faces from vertex set");
1454: } else if (preFace->size() == 1) {
1455: faultSieve->addArrow(*preFace->begin(), *c_iter);
1456: } else if (preFace->size() == 0) {
1457: if (debug) {std::cout << " Adding face " << f << std::endl;}
1458: int color = 0;
1459: for(PointArray::const_iterator f_iter = face->begin(); f_iter != face->end(); ++f_iter) {
1460: if (debug) {std::cout << " vertex " << *f_iter << std::endl;}
1461: faultSieve->addArrow(*f_iter, f, color++);
1462: }
1463: faultSieve->addArrow(f, *c_iter);
1464: f++;
1465: }
1466: faultCells.insert(*c_iter);
1467: }
1468: }
1469: }
1470: fault->setPatch(patch, faultSieve);
1471: fault->stratify();
1472: faultCells.clear();
1473: if (debug) {fault->view("Fault sieve");}
1474: // Add new shadow vertices
1475: const Obj<Mesh::topology_type::label_sequence>& fVertices = fault->depthStratum(patch, 0);
1476: const Obj<Mesh::topology_type::label_sequence>& vertices = mesh->getTopology()->depthStratum(patch, 0);
1477: Mesh::topology_type::point_type newVertex = *vertices->begin() + vertices->size();
1478: std::map<int,int> vertexRenumber;
1480: for(Mesh::topology_type::label_sequence::iterator v_iter = fVertices->begin(); v_iter != fVertices->end(); ++v_iter) {
1481: if (debug) {std::cout << "Duplicating " << *v_iter << " to " << vertexRenumber[*v_iter] << std::endl;}
1482: vertexRenumber[*v_iter] = newVertex++;
1483: }
1484: // Split the mesh along the fault sieve and create cohesive elements
1485: const Obj<Mesh::topology_type::label_sequence>& faces = fault->depthStratum(patch, 1);
1486: PointArray newVertices;
1488: for(Mesh::topology_type::label_sequence::iterator f_iter = faces->begin(); f_iter != faces->end(); ++f_iter) {
1489: if (debug) {std::cout << "Considering fault face " << *f_iter << std::endl;}
1490: const Obj<Mesh::sieve_type::traits::supportSequence>& cells = faultSieve->support(*f_iter);
1491: Mesh::topology_type::point_type cell = std::max(*cells->begin(), *(++cells->begin()));
1492: const Obj<Mesh::sieve_type::traits::coneSequence>& cone = sieve->cone(cell);
1494: if (debug) {std::cout << " Replacing cell " << cell << std::endl;}
1495: newVertices.clear();
1496: for(ALECompat::Mesh::sieve_type::traits::coneSequence::iterator v_iter = cone->begin(); v_iter != cone->end(); ++v_iter) {
1497: if (vertexRenumber.find(*v_iter) != vertexRenumber.end()) {
1498: if (debug) {std::cout << " vertex " << vertexRenumber[*v_iter] << std::endl;}
1499: newVertices.insert(newVertices.end(), vertexRenumber[*v_iter]);
1500: } else {
1501: if (debug) {std::cout << " vertex " << *v_iter << std::endl;}
1502: newVertices.insert(newVertices.end(), *v_iter);
1503: }
1504: }
1505: sieve->clearCone(cell);
1506: int color = 0;
1507: for(PointArray::const_iterator v_iter = newVertices.begin(); v_iter != newVertices.end(); ++v_iter) {
1508: sieve->addArrow(*v_iter, cell, color++);
1509: }
1510: }
1511: // Fix coordinates
1512: const Obj<Mesh::real_section_type>& coordinates = mesh->getRealSection("coordinates");
1513: const Obj<Mesh::topology_type::label_sequence>& fVertices2 = fault->depthStratum(patch, 0);
1515: for(Mesh::topology_type::label_sequence::iterator v_iter = fVertices2->begin(); v_iter != fVertices2->end(); ++v_iter) {
1516: coordinates->addPoint(patch, vertexRenumber[*v_iter], coordinates->getFiberDimension(patch, *v_iter));
1517: }
1518: coordinates->reallocate();
1519: for(Mesh::topology_type::label_sequence::iterator v_iter = fVertices2->begin(); v_iter != fVertices2->end(); ++v_iter) {
1520: coordinates->updatePoint(patch, vertexRenumber[*v_iter], coordinates->restrictPoint(patch, *v_iter));
1521: }
1522: };
1523: //
1524: // Viewer methods
1525: //
1528: PetscErrorCode Viewer::writeVertices(const Obj<Mesh>& mesh, PetscViewer viewer) {
1529: Obj<Builder::real_section_type> coordinates = mesh->getRealSection("coordinates");
1530: //Mesh::section_type::patch_type patch;
1531: //const double *array = coordinates->restrict(Mesh::section_type::patch_type());
1532: //int dim = mesh->getDimension();
1533: //int numVertices;
1537: #if 0
1538: //FIX:
1539: if (vertexBundle->getGlobalOffsets()) {
1540: numVertices = vertexBundle->getGlobalOffsets()[mesh->commSize()];
1541: } else {
1542: numVertices = mesh->getTopology()->depthStratum(0)->size();
1543: }
1544: PetscViewerASCIIPrintf(viewer,"#\n");
1545: PetscViewerASCIIPrintf(viewer,"coord_units = %s\n", Builder::coord_units);
1546: PetscViewerASCIIPrintf(viewer,"#\n");
1547: PetscViewerASCIIPrintf(viewer,"#\n");
1548: PetscViewerASCIIPrintf(viewer,"# Node X-coord Y-coord Z-coord\n");
1549: PetscViewerASCIIPrintf(viewer,"#\n");
1550: if (mesh->commRank() == 0) {
1551: int numLocalVertices = mesh->getTopology()->depthStratum(0)->size();
1552: int vertexCount = 1;
1554: for(int v = 0; v < numLocalVertices; v++) {
1555: PetscViewerASCIIPrintf(viewer,"%7D ", vertexCount++);
1556: for(int d = 0; d < dim; d++) {
1557: if (d > 0) {
1558: PetscViewerASCIIPrintf(viewer," ");
1559: }
1560: PetscViewerASCIIPrintf(viewer,"% 16.8E", array[v*dim+d]);
1561: }
1562: PetscViewerASCIIPrintf(viewer,"\n");
1563: }
1564: for(int p = 1; p < mesh->commSize(); p++) {
1565: double *remoteCoords;
1566: MPI_Status status;
1568: MPI_Recv(&numLocalVertices, 1, MPI_INT, p, 1, mesh->comm(), &status);
1569: PetscMalloc(numLocalVertices*dim * sizeof(double), &remoteCoords);
1570: MPI_Recv(remoteCoords, numLocalVertices*dim, MPI_DOUBLE, p, 1, mesh->comm(), &status);
1571: for(int v = 0; v < numLocalVertices; v++) {
1572: PetscViewerASCIIPrintf(viewer,"%7D ", vertexCount++);
1573: for(int d = 0; d < dim; d++) {
1574: if (d > 0) {
1575: PetscViewerASCIIPrintf(viewer, " ");
1576: }
1577: PetscViewerASCIIPrintf(viewer, "% 16.8E", remoteCoords[v*dim+d]);
1578: }
1579: PetscViewerASCIIPrintf(viewer, "\n");
1580: }
1581: }
1582: } else {
1583: Obj<Mesh::bundle_type> globalOrder = coordinates->getGlobalOrder();
1584: Obj<Mesh::field_type::order_type::coneSequence> cone = globalOrder->getPatch(patch);
1585: const int *offsets = coordinates->getGlobalOffsets();
1586: int numLocalVertices = (offsets[mesh->commRank()+1] - offsets[mesh->commRank()])/dim;
1587: double *localCoords;
1588: int k = 0;
1590: PetscMalloc(numLocalVertices*dim * sizeof(double), &localCoords);
1591: for(Mesh::field_type::order_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
1592: int dim = globalOrder->getFiberDimension(patch, *p_iter);
1594: if (dim > 0) {
1595: int offset = coordinates->getFiberOffset(patch, *p_iter);
1597: for(int i = offset; i < offset+dim; ++i) {
1598: localCoords[k++] = array[i];
1599: }
1600: }
1601: }
1602: if (k != numLocalVertices*dim) {
1603: SETERRQ2(PETSC_ERR_PLIB, "Invalid number of coordinates to send %d should be %d", k, numLocalVertices*dim);
1604: }
1605: MPI_Send(&numLocalVertices, 1, MPI_INT, 0, 1, mesh->comm());
1606: MPI_Send(localCoords, numLocalVertices*dim, MPI_DOUBLE, 0, 1, mesh->comm());
1607: PetscFree(localCoords);
1608: }
1609: #endif
1610: return(0);
1611: };
1614: PetscErrorCode Viewer::writeElements(const Obj<Mesh>& mesh, const Obj<Builder::int_section_type>& materialField, PetscViewer viewer) {
1615: Obj<Mesh::topology_type> topology = mesh->getTopology();
1616: #if 0
1617: Obj<Mesh::sieve_type::traits::heightSequence> elements = topology->heightStratum(0);
1618: Obj<Mesh::bundle_type> elementBundle = mesh->getBundle(topology->depth());
1619: Obj<Mesh::bundle_type> vertexBundle = mesh->getBundle(0);
1620: Obj<Mesh::bundle_type> globalVertex = vertexBundle->getGlobalOrder();
1621: Obj<Mesh::bundle_type> globalElement = elementBundle->getGlobalOrder();
1622: Mesh::bundle_type::patch_type patch;
1623: std::string orderName("element");
1624: bool hasMaterial = !materialField.isNull();
1625: int dim = mesh->getDimension();
1626: int corners = topology->nCone(*elements->begin(), topology->depth())->size();
1627: int elementType = -1;
1631: if (dim != 3) {
1632: SETERRQ(PETSC_ERR_SUP, "PyLith only supports 3D meshes.");
1633: }
1634: if (corners == 4) {
1635: // Linear tetrahedron
1636: elementType = 5;
1637: } else if (corners == 8) {
1638: // Linear hexahedron
1639: elementType = 1;
1640: } else {
1641: SETERRQ1(PETSC_ERR_SUP, "PyLith Error: Unsupported number of elements vertices: %d", corners);
1642: }
1643: PetscViewerASCIIPrintf(viewer,"#\n");
1644: PetscViewerASCIIPrintf(viewer,"# N ETP MAT INF N1 N2 N3 N4 N5 N6 N7 N8\n");
1645: PetscViewerASCIIPrintf(viewer,"#\n");
1646: if (mesh->commRank() == 0) {
1647: int elementCount = 1;
1649: for(Mesh::sieve_type::traits::heightSequence::iterator e_itor = elements->begin(); e_itor != elements->end(); ++e_itor) {
1650: Obj<Mesh::bundle_type::order_type::coneSequence> cone = vertexBundle->getPatch(orderName, *e_itor);
1652: PetscViewerASCIIPrintf(viewer, "%7d %3d", elementCount++, elementType);
1653: if (hasMaterial) {
1654: // No infinite elements
1655: PetscViewerASCIIPrintf(viewer, " %3d %3d", (int) materialField->restrict(patch, *e_itor)[0], 0);
1656: } else {
1657: // No infinite elements
1658: PetscViewerASCIIPrintf(viewer, " %3d %3d", 1, 0);
1659: }
1660: for(Mesh::bundle_type::order_type::coneSequence::iterator c_itor = cone->begin(); c_itor != cone->end(); ++c_itor) {
1661: PetscViewerASCIIPrintf(viewer, " %6d", globalVertex->getIndex(patch, *c_itor).prefix+1);
1662: }
1663: PetscViewerASCIIPrintf(viewer, "\n");
1664: }
1665: for(int p = 1; p < mesh->commSize(); p++) {
1666: int numLocalElements;
1667: int *remoteVertices;
1668: MPI_Status status;
1670: MPI_Recv(&numLocalElements, 1, MPI_INT, p, 1, mesh->comm(), &status);
1671: PetscMalloc(numLocalElements*(corners+1) * sizeof(int), &remoteVertices);
1672: MPI_Recv(remoteVertices, numLocalElements*(corners+1), MPI_INT, p, 1, mesh->comm(), &status);
1673: for(int e = 0; e < numLocalElements; e++) {
1674: // Only linear tetrahedra, material, no infinite elements
1675: int mat = remoteVertices[e*(corners+1)+corners];
1677: PetscViewerASCIIPrintf(viewer, "%7d %3d %3d %3d", elementCount++, elementType, mat, 0);
1678: for(int c = 0; c < corners; c++) {
1679: PetscViewerASCIIPrintf(viewer, " %6d", remoteVertices[e*(corners+1)+c]);
1680: }
1681: PetscViewerASCIIPrintf(viewer, "\n");
1682: }
1683: PetscFree(remoteVertices);
1684: }
1685: } else {
1686: const int *offsets = elementBundle->getGlobalOffsets();
1687: int numLocalElements = offsets[mesh->commRank()+1] - offsets[mesh->commRank()];
1688: int *localVertices;
1689: int k = 0;
1691: PetscMalloc(numLocalElements*(corners+1) * sizeof(int), &localVertices);
1692: for(Mesh::sieve_type::traits::heightSequence::iterator e_itor = elements->begin(); e_itor != elements->end(); ++e_itor) {
1693: Obj<Mesh::bundle_type::order_type::coneSequence> cone = vertexBundle->getPatch(orderName, *e_itor);
1695: if (globalElement->getFiberDimension(patch, *e_itor) > 0) {
1696: for(Mesh::bundle_type::order_type::coneSequence::iterator c_itor = cone->begin(); c_itor != cone->end(); ++c_itor) {
1697: localVertices[k++] = globalVertex->getIndex(patch, *c_itor).prefix;
1698: }
1699: if (hasMaterial) {
1700: localVertices[k++] = (int) materialField->restrict(patch, *e_itor)[0];
1701: } else {
1702: localVertices[k++] = 1;
1703: }
1704: }
1705: }
1706: if (k != numLocalElements*corners) {
1707: SETERRQ2(PETSC_ERR_PLIB, "Invalid number of vertices to send %d should be %d", k, numLocalElements*corners);
1708: }
1709: MPI_Send(&numLocalElements, 1, MPI_INT, 0, 1, mesh->comm());
1710: MPI_Send(localVertices, numLocalElements*(corners+1), MPI_INT, 0, 1, mesh->comm());
1711: PetscFree(localVertices);
1712: }
1713: #endif
1714: return(0);
1715: };
1718: PetscErrorCode Viewer::writeVerticesLocal(const Obj<Mesh>& mesh, PetscViewer viewer) {
1719: const Builder::real_section_type::patch_type patch = 0;
1720: const Obj<Builder::real_section_type>& coordinates = mesh->getRealSection("coordinates");
1721: const Obj<Builder::topology_type>& topology = mesh->getTopology();
1722: const Obj<Builder::topology_type::label_sequence>& vertices = topology->depthStratum(patch, 0);
1723: const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(topology, patch, 0);
1724: int embedDim = coordinates->getFiberDimension(patch, *vertices->begin());
1728: PetscViewerASCIIPrintf(viewer,"#\n");
1729: PetscViewerASCIIPrintf(viewer,"coord_units = %s\n", Builder::coord_units);
1730: PetscViewerASCIIPrintf(viewer,"#\n");
1731: PetscViewerASCIIPrintf(viewer,"#\n");
1732: PetscViewerASCIIPrintf(viewer,"# Node X-coord Y-coord Z-coord\n");
1733: PetscViewerASCIIPrintf(viewer,"#\n");
1735: for(Mesh::topology_type::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
1736: const Builder::real_section_type::value_type *array = coordinates->restrict(patch, *v_iter);
1738: PetscViewerASCIIPrintf(viewer, "%7D ", vNumbering->getIndex(*v_iter)+1);
1739: for(int d = 0; d < embedDim; d++) {
1740: if (d > 0) {
1741: PetscViewerASCIIPrintf(viewer, " ");
1742: }
1743: PetscViewerASCIIPrintf(viewer, "% 16.8E", array[d]);
1744: }
1745: PetscViewerASCIIPrintf(viewer, "\n");
1746: }
1747: return(0);
1748: };
1751: PetscErrorCode Viewer::writeElementsLocal(const Obj<Mesh>& mesh, const Obj<Builder::int_section_type>& materialField, PetscViewer viewer) {
1752: const Mesh::topology_type::patch_type patch = 0;
1753: const Obj<Mesh::topology_type>& topology = mesh->getTopology();
1754: const Obj<Mesh::sieve_type>& sieve = topology->getPatch(patch);
1755: const Obj<Mesh::topology_type::label_sequence>& elements = topology->heightStratum(patch, 0);
1756: const Obj<Mesh::numbering_type>& eNumbering = mesh->getFactory()->getLocalNumbering(topology, patch, topology->depth());
1757: const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(topology, patch, 0);
1758: int dim = mesh->getDimension();
1759: //int corners = sieve->nCone(*elements->begin(), topology->depth())->size();
1760: int corners = sieve->cone(*elements->begin())->size();
1761: bool hasMaterial = !materialField.isNull();
1762: int elementType = -1;
1766: if (dim != 3) {
1767: SETERRQ(PETSC_ERR_SUP, "PyLith only supports 3D meshes.");
1768: }
1769: if (corners == 4) {
1770: // Linear tetrahedron
1771: elementType = 5;
1772: } else if (corners == 8) {
1773: // Linear hexahedron
1774: elementType = 1;
1775: } else {
1776: SETERRQ1(PETSC_ERR_SUP, "PyLith Error: Unsupported number of elements vertices: %d", corners);
1777: }
1778: PetscViewerASCIIPrintf(viewer,"#\n");
1779: PetscViewerASCIIPrintf(viewer,"# N ETP MAT INF N1 N2 N3 N4 N5 N6 N7 N8\n");
1780: PetscViewerASCIIPrintf(viewer,"#\n");
1781: for(Mesh::topology_type::label_sequence::iterator e_iter = elements->begin(); e_iter != elements->end(); ++e_iter) {
1782: const Obj<Mesh::sieve_type::traits::coneSequence> cone = sieve->cone(*e_iter);
1783: Mesh::sieve_type::traits::coneSequence::iterator begin = cone->begin();
1784: Mesh::sieve_type::traits::coneSequence::iterator end = cone->end();
1786: PetscViewerASCIIPrintf(viewer, "%7d %3d", eNumbering->getIndex(*e_iter)+1, elementType);
1787: if (hasMaterial) {
1788: // No infinite elements
1789: PetscViewerASCIIPrintf(viewer, " %3d %3d", (int) materialField->restrict(patch, *e_iter)[0], 0);
1790: } else {
1791: // No infinite elements
1792: PetscViewerASCIIPrintf(viewer, " %3d %3d", 1, 0);
1793: }
1794: for(Mesh::sieve_type::traits::coneSequence::iterator c_iter = begin; c_iter != end; ++c_iter) {
1795: //FIX: Need a global ordering here
1796: PetscViewerASCIIPrintf(viewer, " %6d", vNumbering->getIndex(*c_iter)+1);
1797: }
1798: PetscViewerASCIIPrintf(viewer, "\n");
1799: }
1800: return(0);
1801: };
1804: // The elements seem to be implicitly numbered by appearance, which makes it impossible to
1805: // number here by bundle, but we can fix it by traversing the elements like the vertices
1806: PetscErrorCode Viewer::writeSplitLocal(const Obj<Mesh>& mesh, const Obj<Builder::pair_section_type>& splitField, PetscViewer viewer) {
1807: const Obj<Mesh::topology_type>& topology = mesh->getTopology();
1808: Builder::pair_section_type::patch_type patch = 0;
1809: const Obj<Mesh::numbering_type>& eNumbering = mesh->getFactory()->getLocalNumbering(topology, patch, topology->depth());
1810: const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(topology, patch, 0);
1814: const Builder::pair_section_type::atlas_type::chart_type& chart = splitField->getPatch(patch);
1816: for(Builder::pair_section_type::atlas_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
1817: const Builder::pair_section_type::point_type& e = *c_iter;
1818: const Builder::pair_section_type::value_type *values = splitField->restrict(patch, e);
1819: const int size = splitField->getFiberDimension(patch, e);
1821: for(int i = 0; i < size; i++) {
1822: const Builder::pair_section_type::point_type& v = values[i].first;
1823: const ALECompat::Mesh::base_type::split_value& split = values[i].second;
1825: // No time history
1826: 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);
1827: }
1828: }
1829: return(0);
1830: };
1833: PetscErrorCode Viewer::writeTractionsLocal(const Obj<Mesh>& mesh, const Obj<Builder::real_section_type>& tractionField, PetscViewer viewer) {
1834: typedef Builder::topology_type topology_type;
1835: typedef Builder::real_section_type section_type;
1836: const section_type::patch_type patch = 0;
1837: const Obj<topology_type>& boundaryTopology = tractionField->getTopology();
1838: const Obj<topology_type::sieve_type>& sieve = boundaryTopology->getPatch(patch);
1839: const Obj<topology_type::label_sequence>& faces = boundaryTopology->heightStratum(patch, 0);
1840: const Obj<Mesh::topology_type>& topology = mesh->getTopology();
1841: const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(topology, patch, 0);
1845: PetscViewerASCIIPrintf(viewer,"#\n");
1846: PetscViewerASCIIPrintf(viewer,"traction_units = %s\n", Builder::traction_units);
1847: PetscViewerASCIIPrintf(viewer,"#\n");
1848: PetscViewerASCIIPrintf(viewer,"#\n");
1849: for(topology_type::label_sequence::iterator f_iter = faces->begin(); f_iter != faces->end(); ++f_iter) {
1850: const topology_type::point_type& face = *f_iter;
1851: const Obj<topology_type::sieve_type::traits::coneSequence>& cone = sieve->cone(face);
1853: for(topology_type::sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter) {
1854: const topology_type::point_type& vertex = *c_iter;
1856: PetscViewerASCIIPrintf(viewer, "%6d", vNumbering->getIndex(vertex)+1);
1857: std::cout << vNumbering->getIndex(vertex) << " ("<<vertex<<") ";
1858: }
1859: const section_type::value_type *values = tractionField->restrict(patch, face);
1861: for(int i = 0; i < mesh->getDimension(); ++i) {
1862: if (i > 0) {
1863: PetscViewerASCIIPrintf(viewer, " ");
1864: std::cout << " ";
1865: }
1866: PetscViewerASCIIPrintf(viewer, "%15.9g", values[i]);
1867: std::cout << values[i];
1868: }
1869: PetscViewerASCIIPrintf(viewer,"\n");
1870: std::cout << std::endl;
1871: }
1872: return(0);
1873: };
1874: };
1875: };