Actual source code: meshpcice.c

  1: #include "src/dm/mesh/meshpcice.h"   /*I      "petscmesh.h"   I*/

  5: /*@
  6:   PCICERenumberBoundary - Change global element names into offsets

  8:   Collective on Mesh

 10:   Input Parameters:
 11: . mesh - the mesh

 13:   Level: advanced

 15:   .seealso: MeshCreate()
 16: @*/
 17: PetscErrorCode  PCICERenumberBoundary(Mesh mesh)
 18: {
 19:   ALE::Obj<ALE::Mesh> m;
 20:   PetscErrorCode      ierr;

 23:   MeshGetMesh(mesh, m);
 24:   try {
 25:     ALE::PCICE::fuseBoundary(m);
 26:   } catch(ALE::Exception e) {
 27:     SETERRQ(100, e.msg().c_str());
 28:   }
 29:   return(0);
 30: }

 34: /*@C
 35:   BCSectionGetArray - Returns the array underlying the BCSection.

 37:   Not Collective

 39:   Input Parameters:
 40: + mesh - The Mesh object
 41: - name - The section name

 43:   Output Parameters:
 44: + numElements - The number of mesh element with values
 45: . fiberDim - The number of values per element
 46: - array - The array

 48:   Level: intermediate

 50: .keywords: mesh, elements
 51: .seealso: MeshCreate()
 52: @*/
 53: PetscErrorCode BCSectionGetArray(Mesh mesh, const char name[], PetscInt *numElements, PetscInt *fiberDim, PetscInt *array[])
 54: {
 55:   ALE::Obj<ALE::Mesh> m;
 56:   PetscErrorCode      ierr;

 59:   MeshGetMesh(mesh, m);
 60:   const ALE::Obj<ALE::Mesh::int_section_type>& section = m->getIntSection(std::string(name));
 61:   if (!section->size()) {
 62:     *numElements = 0;
 63:     *fiberDim    = 0;
 64:     *array       = NULL;
 65:     return(0);
 66:   }
 67:   const ALE::Mesh::int_section_type::chart_type& chart = section->getChart();
 68:   int fiberDimMin = section->getFiberDimension(*chart.begin());
 69:   int numElem     = 0;

 71:   for(ALE::Mesh::int_section_type::chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
 72:     const int fiberDim = section->getFiberDimension(*c_iter);

 74:     if (fiberDim < fiberDimMin) fiberDimMin = fiberDim;
 75:   }
 76:   for(ALE::Mesh::int_section_type::chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
 77:     const int fiberDim = section->getFiberDimension(*c_iter);

 79:     numElem += fiberDim/fiberDimMin;
 80:   }
 81:   *numElements = numElem;
 82:   *fiberDim    = fiberDimMin;
 83:   *array       = (PetscInt *) section->restrict();
 84:   return(0);
 85: }

 89: /*@C
 90:   BCSectionRealCreate - Creates a BCSection.

 92:   Not Collective

 94:   Input Parameters:
 95: + mesh - The Mesh object
 96: . name - The section name
 97: - fiberDim - The number of values per element

 99:   Level: intermediate

101: .keywords: mesh, elements
102: .seealso: MeshCreate()
103: @*/
104: PetscErrorCode BCSectionRealCreate(Mesh mesh, const char name[], PetscInt fiberDim)
105: {
106:   ALE::Obj<ALE::Mesh> m;
107:   PetscErrorCode      ierr;

110:   MeshGetMesh(mesh, m);
111:   const ALE::Obj<ALE::Mesh::real_section_type>&  section = m->getRealSection(std::string(name));
112:   const ALE::Obj<ALE::Mesh::int_section_type>&   ibc     = m->getIntSection("IBC");
113:   const ALE::Mesh::int_section_type::chart_type& chart   = ibc->getChart();

115:   for(ALE::Mesh::int_section_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
116:     section->setFiberDimension(*p_iter, ibc->getFiberDimension(*p_iter));
117:   }
118:   m->allocate(section);
119:   return(0);
120: }

124: /*@C
125:   BCSectionRealGetArray - Returns the array underlying the BCSection.

127:   Not Collective

129:   Input Parameters:
130: + mesh - The Mesh object
131: - name - The section name

133:   Output Parameters:
134: + numElements - The number of mesh element with values
135: . fiberDim - The number of values per element
136: - array - The array

138:   Level: intermediate

140: .keywords: mesh, elements
141: .seealso: MeshCreate()
142: @*/
143: PetscErrorCode BCSectionRealGetArray(Mesh mesh, const char name[], PetscInt *numElements, PetscInt *fiberDim, PetscReal *array[])
144: {
145:   ALE::Obj<ALE::Mesh> m;
146:   PetscErrorCode      ierr;

149:   MeshGetMesh(mesh, m);
150:   const ALE::Obj<ALE::Mesh::real_section_type>& section = m->getRealSection(std::string(name));
151:   if (!section->size()) {
152:     *numElements = 0;
153:     *fiberDim    = 0;
154:     *array       = NULL;
155:     return(0);
156:   }
157:   const ALE::Mesh::real_section_type::chart_type& chart = section->getChart();
158:   int fiberDimMin = section->getFiberDimension(*chart.begin());
159:   int numElem     = 0;

161:   for(ALE::Mesh::real_section_type::chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
162:     const int fiberDim = section->getFiberDimension(*c_iter);

164:     if (fiberDim < fiberDimMin) fiberDimMin = fiberDim;
165:   }
166:   for(ALE::Mesh::real_section_type::chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
167:     const int fiberDim = section->getFiberDimension(*c_iter);

169:     numElem += fiberDim/fiberDimMin;
170:   }
171:   *numElements = numElem;
172:   *fiberDim    = fiberDimMin;
173:   *array       = (PetscReal *) section->restrict();
174:   return(0);
175: }

179: PetscErrorCode BCFUNCGetArray(Mesh mesh, PetscInt *numElements, PetscInt *fiberDim, PetscScalar *array[])
180: {
181:   ALE::Obj<ALE::Mesh> m;
182:   PetscErrorCode      ierr;

185:   MeshGetMesh(mesh, m);
186: #if 0
187:   ALE::Mesh::bc_values_type& bcValues = m->getBCValues();
188:   *numElements = bcValues.size();
189:   *fiberDim    = 4;
190:   *array       = new PetscScalar[(*numElements)*(*fiberDim)];
191:   for(int bcf = 1; bcf <= (int) bcValues.size(); ++bcf) {
192:     (*array)[(bcf-1)*4+0] = bcValues[bcf].rho;
193:     (*array)[(bcf-1)*4+1] = bcValues[bcf].u;
194:     (*array)[(bcf-1)*4+2] = bcValues[bcf].v;
195:     (*array)[(bcf-1)*4+3] = bcValues[bcf].p;
196:   }
197: #else
198:   *numElements = 0;
199:   *fiberDim    = 0;
200:   *array       = NULL;
201: #endif
202:   return(0);
203: }

205: namespace ALE {
206:   namespace PCICE {
207:     //
208:     // Builder methods
209:     //
210:     void Builder::readConnectivity(MPI_Comm comm, const std::string& filename, int& corners, const bool useZeroBase, int& numElements, int *vertices[]) {
211:       PetscViewer    viewer;
212:       FILE          *f;
213:       PetscInt       numCells, cellCount = 0;
214:       PetscInt      *verts;
215:       char           buf[2048];
216:       PetscInt       c;
217:       PetscInt       commRank;

220:       MPI_Comm_rank(comm, &commRank);

222:       if (commRank != 0) return;
223:       PetscViewerCreate(PETSC_COMM_SELF, &viewer);
224:       PetscViewerSetType(viewer, PETSC_VIEWER_ASCII);
225:       PetscViewerFileSetMode(viewer, FILE_MODE_READ);
226:       PetscViewerFileSetName(viewer, filename.c_str());
227:       if (ierr) {
228:         ostringstream txt;
229:         txt << "Could not open PCICE connectivity file: " << filename;
230:         throw ALE::Exception(txt.str().c_str());
231:       }
232:       PetscViewerASCIIGetPointer(viewer, &f);
233:       if (fgets(buf, 2048, f) == NULL) {
234:         throw ALE::Exception("Invalid connectivity file: Missing number of elements");
235:       }
236:       const char *sizes = strtok(buf, " ");
237:       numCells = atoi(sizes);
238:       sizes = strtok(NULL, " ");
239:       if (sizes != NULL) {
240:         corners = atoi(sizes);
241:         std::cout << "Reset corners to " << corners << std::endl;
242:       }
243:       PetscMalloc(numCells*corners * sizeof(PetscInt), &verts);
244:       while(fgets(buf, 2048, f) != NULL) {
245:         const char *v = strtok(buf, " ");
246: 
247:         /* Ignore cell number */
248:         v = strtok(NULL, " ");
249:         for(c = 0; c < corners; c++) {
250:           int vertex = atoi(v);
251: 
252:           if (!useZeroBase) vertex -= 1;
253:           verts[cellCount*corners+c] = vertex;
254:           v = strtok(NULL, " ");
255:         }
256:         cellCount++;
257:       }
258:       PetscViewerDestroy(viewer);
259:       numElements = numCells;
260:       *vertices = verts;
261:     };
262:     void Builder::readCoordinates(MPI_Comm comm, const std::string& filename, const int dim, int& numVertices, double *coordinates[]) {
263:       PetscViewer    viewer;
264:       FILE          *f;
265:       PetscInt       numVerts, vertexCount = 0;
266:       PetscScalar   *coords;
267:       char           buf[2048];
268:       PetscInt       c;
269:       PetscInt       commRank;

272:       MPI_Comm_rank(comm, &commRank);

274:       if (commRank != 0) return;
275:       PetscViewerCreate(PETSC_COMM_SELF, &viewer);
276:       PetscViewerSetType(viewer, PETSC_VIEWER_ASCII);
277:       PetscViewerFileSetMode(viewer, FILE_MODE_READ);
278:       PetscViewerFileSetName(viewer, filename.c_str());
279:       if (ierr) {
280:         ostringstream txt;
281:         txt << "Could not open PCICE coordinate file: " << filename;
282:         throw ALE::Exception(txt.str().c_str());
283:       }
284:       PetscViewerASCIIGetPointer(viewer, &f);
285:       numVerts = atoi(fgets(buf, 2048, f));
286:       PetscMalloc(numVerts*dim * sizeof(PetscScalar), &coords);
287:       while(fgets(buf, 2048, f) != NULL) {
288:         const char *x = strtok(buf, " ");
289: 
290:         /* Ignore vertex number */
291:         x = strtok(NULL, " ");
292:         for(c = 0; c < dim; c++) {
293:           coords[vertexCount*dim+c] = atof(x);
294:           x = strtok(NULL, " ");
295:         }
296:         vertexCount++;
297:       }
298:       PetscViewerDestroy(viewer);
299:       numVertices = numVerts;
300:       *coordinates = coords;
301:     };
302:     Obj<ALE::Mesh> Builder::readMesh(MPI_Comm comm, const int dim, const std::string& basename, const bool useZeroBase = true, const bool interpolate = true, const int debug = 0) {
303:       return readMesh(comm, dim, basename+".nodes", basename+".lcon", useZeroBase, interpolate, debug);
304:     };
305:     Obj<ALE::Mesh> Builder::readMesh(MPI_Comm comm, const int dim, const std::string& coordFilename, const std::string& adjFilename, const bool useZeroBase = true, const bool interpolate = true, const int debug = 0) {
306:       Obj<Mesh>          mesh     = new Mesh(comm, dim, debug);
307:       Obj<sieve_type>    sieve    = new sieve_type(comm, debug);
308:       int    *cells = NULL;
309:       double *coordinates = NULL;
310:       int     numCells = 0, numVertices = 0, numCorners = dim+1;

313:       ALE::PCICE::Builder::readConnectivity(comm, adjFilename, numCorners, useZeroBase, numCells, &cells);
314:       ALE::PCICE::Builder::readCoordinates(comm, coordFilename, dim, numVertices, &coordinates);
315:       ALE::SieveBuilder<ALE::Mesh>::buildTopology(sieve, dim, numCells, cells, numVertices, interpolate, numCorners, -1, mesh->getArrowSection("orientation"));
316:       mesh->setSieve(sieve);
317:       mesh->stratify();
318:       ALE::SieveBuilder<ALE::Mesh>::buildCoordinates(mesh, dim, coordinates);
319:       if (cells) {PetscFree(cells);}
320:       if (coordinates) {PetscFree(coordinates);}
321:       return mesh;
322:     };
323:     // Creates boundary sections:
324:     //   IBC[NBFS,2]:     ALL
325:     //     BL[NBFS,1]:
326:     //     BNVEC[NBFS,2]:
327:     //   BCFUNC[NBCF,NV]: ALL
328:     //   IBNDFS[NBN,2]:   STILL NEED 4-5
329:     //     BNNV[NBN,2]
330:     void Builder::readBoundary(const Obj<Mesh>& mesh, const std::string& bcFilename) {
331:       PetscViewer    viewer;
332:       FILE          *f;
333:       char           buf[2048];

336:       const Obj<Mesh::int_section_type>&  ibc    = mesh->getIntSection("IBC");
337:       const Obj<Mesh::int_section_type>&  ibndfs = mesh->getIntSection("IBNDFS");
338:       const Obj<Mesh::int_section_type>&  ibcnum = mesh->getIntSection("IBCNUM");
339:       const Obj<Mesh::int_section_type>&  ibfcon = mesh->getIntSection("IBFCON");
340:       const Obj<Mesh::real_section_type>& bl     = mesh->getRealSection("BL");
341:       const Obj<Mesh::real_section_type>& bnvec  = mesh->getRealSection("BNVEC");
342:       const Obj<Mesh::real_section_type>& bnnv   = mesh->getRealSection("BNNV");
343:       if (mesh->commRank() != 0) {
344: #if 0
345:         mesh->distributeBCValues();
346: #endif
347:         return;
348:       }
349:       PetscViewerCreate(PETSC_COMM_SELF, &viewer);
350:       PetscViewerSetType(viewer, PETSC_VIEWER_ASCII);
351:       PetscViewerFileSetMode(viewer, FILE_MODE_READ);
352:       PetscViewerFileSetName(viewer, bcFilename.c_str());
353:       PetscViewerASCIIGetPointer(viewer, &f);
354:       // Create IBC section
355:       int  numBdFaces = atoi(strtok(fgets(buf, 2048, f), " "));
356:       int *tmpIBC     = new int[numBdFaces*4];
357:       std::map<int,std::set<int> > elem2Idx;
358:       std::map<int,int> bfReorder;
359:       for(int bf = 0; bf < numBdFaces; bf++) {
360:         const char *x = strtok(fgets(buf, 2048, f), " ");

362:         // Ignore boundary face number
363:         x = strtok(NULL, " ");
364:         tmpIBC[bf*4+0] = atoi(x);
365:         x = strtok(NULL, " ");
366:         tmpIBC[bf*4+1] = atoi(x);
367:         x = strtok(NULL, " ");
368:         tmpIBC[bf*4+2] = atoi(x);
369:         x = strtok(NULL, " ");
370:         tmpIBC[bf*4+3] = atoi(x);
371:         const int elem = tmpIBC[bf*4+0]-1;

373:         ibc->addFiberDimension(elem, 4);
374:         ibcnum->addFiberDimension(elem, 1);
375:         ibfcon->addFiberDimension(elem, 2);
376:         bl->addFiberDimension(elem, 1);
377:         bnvec->addFiberDimension(elem, 2);
378:         elem2Idx[elem].insert(bf);
379:       }
380:       mesh->allocate(ibc);
381:       mesh->allocate(ibcnum);
382:       mesh->allocate(ibfcon);
383:       mesh->allocate(bl);
384:       mesh->allocate(bnvec);
385:       const Mesh::int_section_type::chart_type& chart = ibc->getChart();
386:       int num = 1;

388:       for(Mesh::int_section_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
389:         const int elem = *p_iter;
390:         int bfNum[2];
391:         int k = 0;

393:         for(std::set<int>::const_iterator i_iter = elem2Idx[elem].begin(); i_iter != elem2Idx[elem].end(); ++i_iter) {
394:           bfReorder[(*i_iter)+1] = num;
395:           bfNum[k++] = num;
396:           num++;
397:         }
398:         ibcnum->updatePoint(elem, bfNum);
399:       }
400:       for(int bf = 0; bf < numBdFaces; bf++) {
401:         const int elem = tmpIBC[bf*4]-1;

403:         if (elem2Idx[elem].size() > 1) {
404:           if (*elem2Idx[elem].begin() == bf) {
405:             int values[8];
406:             int k = 0;

408:             for(std::set<int>::const_iterator i_iter = elem2Idx[elem].begin(); i_iter != elem2Idx[elem].end(); ++i_iter) {
409:               for(int v = 0; v < 4; ++v) {
410:                 values[k*4+v] = tmpIBC[*i_iter*4+v];
411:               }
412:               k++;
413:             }
414:             ibc->updatePoint(elem, values);
415:           }
416:         } else {
417:           ibc->updatePoint(elem, &tmpIBC[bf*4]);
418:         }
419:       }
420:       delete [] tmpIBC;
421:       // Create BCFUNC section
422:       int numBcFunc = atoi(strtok(fgets(buf, 2048, f), " "));
423:       if (numBcFunc != 0) {throw ALE::Exception("Cannot handle BCFUNCS after rewrite");}
424:       for(int bc = 0; bc < numBcFunc; bc++) {
425: #if 0
426:         const char *x = strtok(fgets(buf, 2048, f), " ");
427:         Mesh::bc_value_type value;

429:         // Ignore function number
430:         x = strtok(NULL, " ");
431:         value.rho = atof(x);
432:         x = strtok(NULL, " ");
433:         value.u   = atof(x);
434:         x = strtok(NULL, " ");
435:         value.v   = atof(x);
436:         x = strtok(NULL, " ");
437:         value.p   = atof(x);
438:         mesh->setBCValue(bc+1, value);
439: #endif
440:       }
441: #if 0
442:       mesh->distributeBCValues();
443: #endif
444:       // Create IBNDFS section
445:       int       numBdVertices = atoi(strtok(fgets(buf, 2048, f), " "));
446:       const int numElements   = mesh->heightStratum(0)->size();
447:       int      *tmpIBNDFS     = new int[numBdVertices*3];

449:       for(int bv = 0; bv < numBdVertices; bv++) {
450:         const char *x = strtok(fgets(buf, 2048, f), " ");

452:         // Ignore boundary node number
453:         x = strtok(NULL, " ");
454:         tmpIBNDFS[bv*3+0] = atoi(x);
455:         x = strtok(NULL, " ");
456:         tmpIBNDFS[bv*3+1] = atoi(x);
457:         x = strtok(NULL, " ");
458:         tmpIBNDFS[bv*3+2] = atoi(x);
459:         ibndfs->setFiberDimension(tmpIBNDFS[bv*3+0]-1+numElements, 6);
460:       }
461:       mesh->allocate(ibndfs);
462:       for(int bv = 0; bv < numBdVertices; bv++) {
463:         int values[5];

465:         values[0] = tmpIBNDFS[bv*3+0];
466:         // Covert to new boundary face numbers
467:         values[1] = bfReorder[tmpIBNDFS[bv*3+1]];
468:         values[2] = bfReorder[tmpIBNDFS[bv*3+2]];
469:         values[3] = 0;
470:         values[4] = 0;
471:         ibndfs->updatePoint(values[0]-1+numElements, values);
472:       }
473:       PetscViewerDestroy(viewer);
474:       // Create BNNV[NBN,2]
475:       const int dim = mesh->getDimension();

477:       for(int bv = 0; bv < numBdVertices; bv++) {
478:         bnnv->setFiberDimension(tmpIBNDFS[bv*3+0]-1+numElements, dim);
479:       }
480:       mesh->allocate(bnnv);
481:       delete [] tmpIBNDFS;
482:     };
483:     void Builder::outputVerticesLocal(const Obj<Mesh>& mesh, int *numVertices, int *dim, double *coordinates[], const bool columnMajor) {
484:       const Obj<Mesh::real_section_type>& coordSec = mesh->getRealSection("coordinates");
485:       if (!coordSec->size()) {
486:         *numVertices = 0;
487:         *dim         = 0;
488:         *coordinates = NULL;
489:         return;
490:       }
491:       const Obj<Mesh::label_sequence>& vertices   = mesh->depthStratum(0);
492:       const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(mesh, 0);
493:       int            size     = vertices->size();
494:       int            embedDim = coordSec->getFiberDimension(*vertices->begin());
495:       double        *coords;

498:       PetscMalloc(vertices->size()*embedDim * sizeof(double), &coords);
499:       for(Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
500:         const Mesh::real_section_type::value_type *array = coordSec->restrictPoint(*v_iter);
501:         const int                                  row   = vNumbering->getIndex(*v_iter);

503:         if (columnMajor) {
504:           for(int d = 0; d < embedDim; d++) {
505:             coords[d*size + row] = array[d];
506:           }
507:         } else {
508:           for(int d = 0; d < embedDim; d++) {
509:             coords[row*embedDim + d] = array[d];
510:           }
511:         }
512:       }
513:       *numVertices = size;
514:       *dim         = embedDim;
515:       *coordinates = coords;
516:     };
517:     void Builder::outputElementsLocal(const Obj<Mesh>& mesh, int *numElements, int *numCorners, int *vertices[], const bool columnMajor) {
518:       if (!mesh->heightStratum(0)->size()) {
519:         *numElements = 0;
520:         *numCorners  = 0;
521:         *vertices    = NULL;
522:         return;
523:       }
524:       const Obj<Mesh::sieve_type>&     sieve      = mesh->getSieve();
525:       const Obj<Mesh::label_sequence>& elements   = mesh->heightStratum(0);
526:       const Obj<Mesh::numbering_type>& eNumbering = mesh->getFactory()->getLocalNumbering(mesh, mesh->depth());
527:       const Obj<Mesh::numbering_type>& vNumbering = mesh->getFactory()->getLocalNumbering(mesh, 0);
528:       int            size         = elements->size();
529:       //int            corners      = sieve->nCone(*elements->begin(), topology->depth())->size();
530:       int            corners      = sieve->cone(*elements->begin())->size();
531:       int           *v;

534:       PetscMalloc(elements->size()*corners * sizeof(int), &v);
535:       for(Mesh::label_sequence::iterator e_iter = elements->begin(); e_iter != elements->end(); ++e_iter) {
536:         const Obj<Mesh::sieve_type::traits::coneSequence> cone  = sieve->cone(*e_iter);
537:         Mesh::sieve_type::traits::coneSequence::iterator  begin = cone->begin();
538:         Mesh::sieve_type::traits::coneSequence::iterator  end   = cone->end();

540:         const int row = eNumbering->getIndex(*e_iter);
541:         int       c   = -1;
542:         if (columnMajor) {
543:           for(Mesh::sieve_type::traits::coneSequence::iterator c_iter = begin; c_iter != end; ++c_iter) {
544:             v[(++c)*size + row] = vNumbering->getIndex(*c_iter)+1;
545:           }
546:         } else {
547:           for(Mesh::sieve_type::traits::coneSequence::iterator c_iter = begin; c_iter != end; ++c_iter) {
548:             v[row*corners + ++c] = vNumbering->getIndex(*c_iter)+1;
549:           }
550:         }
551:       }
552:       *numElements = size;
553:       *numCorners  = corners;
554:       *vertices    = v;
555:     };
558:     PetscErrorCode Viewer::writeVertices(const ALE::Obj<Mesh>& mesh, PetscViewer viewer) {
559:       ALE::Obj<Mesh::real_section_type> coordinates = mesh->getRealSection("coordinates");
560: #if 0
561:       Mesh::field_type::patch_type patch;
562:       const double  *array = coordinates->restrict(patch);
563:       int            numVertices;

567:       //FIX:
568:       if (vertexBundle->getGlobalOffsets()) {
569:         numVertices = vertexBundle->getGlobalOffsets()[mesh->commSize()];
570:       } else {
571:         numVertices = mesh->getTopology()->depthStratum(0)->size();
572:       }
573:       PetscViewerASCIIPrintf(viewer, "%D\n", numVertices);
574:       if (mesh->commRank() == 0) {
575:         int numLocalVertices = mesh->getTopology()->depthStratum(0)->size();
576:         int embedDim = coordinates->getFiberDimension(patch, *mesh->getTopology()->depthStratum(0)->begin());
577:         int vertexCount = 1;

579:         for(int v = 0; v < numLocalVertices; v++) {
580:           PetscViewerASCIIPrintf(viewer, "%7D   ", vertexCount++);
581:           for(int d = 0; d < embedDim; d++) {
582:             if (d > 0) {
583:               PetscViewerASCIIPrintf(viewer, " ");
584:             }
585:             PetscViewerASCIIPrintf(viewer, "% 12.5E", array[v*embedDim+d]);
586:           }
587:           PetscViewerASCIIPrintf(viewer, "\n");
588:         }
589:         for(int p = 1; p < mesh->commSize(); p++) {
590:           double    *remoteCoords;
591:           MPI_Status status;

593:           MPI_Recv(&numLocalVertices, 1, MPI_INT, p, 1, mesh->comm(), &status);
594:           PetscMalloc(numLocalVertices*embedDim * sizeof(double), &remoteCoords);
595:           MPI_Recv(remoteCoords, numLocalVertices*embedDim, MPI_DOUBLE, p, 1, mesh->comm(), &status);
596:           for(int v = 0; v < numLocalVertices; v++) {
597:             PetscViewerASCIIPrintf(viewer,"%7D   ", vertexCount++);
598:             for(int d = 0; d < embedDim; d++) {
599:               if (d > 0) {
600:                 PetscViewerASCIIPrintf(viewer, " ");
601:               }
602:               PetscViewerASCIIPrintf(viewer, "% 12.5E", remoteCoords[v*embedDim+d]);
603:             }
604:             PetscViewerASCIIPrintf(viewer, "\n");
605:           }
606:         }
607:       } else {
608:         ALE::Obj<Mesh::bundle_type>                           globalOrder = coordinates->getGlobalOrder();
609:         ALE::Obj<Mesh::bundle_type::order_type::coneSequence> cone        = globalOrder->getPatch(patch);
610:         const int *offsets = coordinates->getGlobalOffsets();
611:         int        embedDim = coordinates->getFiberDimension(patch, *mesh->getTopology()->depthStratum(0)->begin());
612:         int        numLocalVertices = (offsets[mesh->commRank()+1] - offsets[mesh->commRank()])/embedDim;
613:         double    *localCoords;
614:         int        k = 0;

616:         PetscMalloc(numLocalVertices*embedDim * sizeof(double), &localCoords);
617:         for(Mesh::bundle_type::order_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
618:           int dim = globalOrder->getFiberDimension(patch, *p_iter);

620:           if (dim > 0) {
621:             int offset = coordinates->getFiberOffset(patch, *p_iter);

623:             for(int i = offset; i < offset+dim; ++i) {
624:               localCoords[k++] = array[i];
625:             }
626:           }
627:         }
628:         if (k != numLocalVertices*embedDim) {
629:           SETERRQ2(PETSC_ERR_PLIB, "Invalid number of coordinates to send %d should be %d", k, numLocalVertices*embedDim);
630:         }
631:         MPI_Send(&numLocalVertices, 1, MPI_INT, 0, 1, mesh->comm());
632:         MPI_Send(localCoords, numLocalVertices*embedDim, MPI_DOUBLE, 0, 1, mesh->comm());
633:         PetscFree(localCoords);
634:       }
635: #endif
636:       return(0);
637:     };
640:     PetscErrorCode Viewer::writeElements(const ALE::Obj<Mesh>& mesh, PetscViewer viewer) {
641: #if 0
642:       ALE::Obj<Mesh::sieve_type::traits::heightSequence> elements = topology->heightStratum(0);
643:       ALE::Obj<Mesh::bundle_type> elementBundle = mesh->getBundle(topology->depth());
644:       ALE::Obj<Mesh::bundle_type> vertexBundle = mesh->getBundle(0);
645:       ALE::Obj<Mesh::bundle_type> globalVertex = vertexBundle->getGlobalOrder();
646:       ALE::Obj<Mesh::bundle_type> globalElement = elementBundle->getGlobalOrder();
647:       Mesh::bundle_type::patch_type patch;
648:       std::string    orderName("element");
649:       int            dim  = mesh->getDimension();
650:       int            corners = topology->nCone(*elements->begin(), topology->depth())->size();
651:       int            numElements;

655:       if (corners != dim+1) {
656:         SETERRQ(PETSC_ERR_SUP, "PCICE only supports simplicies");
657:       }
658:       if (!globalVertex) {
659:         globalVertex = vertexBundle;
660:       }
661:       if (elementBundle->getGlobalOffsets()) {
662:         numElements = elementBundle->getGlobalOffsets()[mesh->commSize()];
663:       } else {
664:         numElements = mesh->getTopology()->heightStratum(0)->size();
665:       }
666:       if (mesh->commRank() == 0) {
667:         int elementCount = 1;

669:         PetscViewerASCIIPrintf(viewer, "%d\n", numElements);
670:         for(Mesh::sieve_type::traits::heightSequence::iterator e_itor = elements->begin(); e_itor != elements->end(); ++e_itor) {
671:           ALE::Obj<Mesh::bundle_type::order_type::coneSequence> cone = vertexBundle->getPatch(orderName, *e_itor);

673:           PetscViewerASCIIPrintf(viewer, "%7d", elementCount++);
674:           for(Mesh::bundle_type::order_type::coneSequence::iterator c_itor = cone->begin(); c_itor != cone->end(); ++c_itor) {
675:             PetscViewerASCIIPrintf(viewer, " %7d", globalVertex->getIndex(patch, *c_itor).prefix);
676:           }
677:           PetscViewerASCIIPrintf(viewer, "\n");
678:         }
679:         for(int p = 1; p < mesh->commSize(); p++) {
680:           int        numLocalElements;
681:           int       *remoteVertices;
682:           MPI_Status status;

684:           MPI_Recv(&numLocalElements, 1, MPI_INT, p, 1, mesh->comm(), &status);
685:           PetscMalloc(numLocalElements*corners * sizeof(int), &remoteVertices);
686:           MPI_Recv(remoteVertices, numLocalElements*corners, MPI_INT, p, 1, mesh->comm(), &status);
687:           for(int e = 0; e < numLocalElements; e++) {
688:             PetscViewerASCIIPrintf(viewer, "%7d", elementCount++);
689:             for(int c = 0; c < corners; c++) {
690:               PetscViewerASCIIPrintf(viewer, " %7d", remoteVertices[e*corners+c]);
691:             }
692:             PetscViewerASCIIPrintf(viewer, "\n");
693:           }
694:           PetscFree(remoteVertices);
695:         }
696:       } else {
697:         const int *offsets = elementBundle->getGlobalOffsets();
698:         int        numLocalElements = offsets[mesh->commRank()+1] - offsets[mesh->commRank()];
699:         int       *localVertices;
700:         int        k = 0;

702:         PetscMalloc(numLocalElements*corners * sizeof(int), &localVertices);
703:         for(Mesh::sieve_type::traits::heightSequence::iterator e_itor = elements->begin(); e_itor != elements->end(); ++e_itor) {
704:           ALE::Obj<Mesh::bundle_type::order_type::coneSequence> cone = vertexBundle->getPatch(orderName, *e_itor);

706:           if (globalElement->getFiberDimension(patch, *e_itor) > 0) {
707:             for(Mesh::bundle_type::order_type::coneSequence::iterator c_itor = cone->begin(); c_itor != cone->end(); ++c_itor) {
708:               localVertices[k++] = globalVertex->getIndex(patch, *c_itor).prefix;
709:             }
710:           }
711:         }
712:         if (k != numLocalElements*corners) {
713:           SETERRQ2(PETSC_ERR_PLIB, "Invalid number of vertices to send %d should be %d", k, numLocalElements*corners);
714:         }
715:         MPI_Send(&numLocalElements, 1, MPI_INT, 0, 1, mesh->comm());
716:         MPI_Send(localVertices, numLocalElements*corners, MPI_INT, 0, 1, mesh->comm());
717:         PetscFree(localVertices);
718:       }
719: #endif
720:       return(0);
721:     };
724:     PetscErrorCode Viewer::writeVerticesLocal(const Obj<Mesh>& mesh, PetscViewer viewer) {
725:       Obj<Mesh::real_section_type>     coordinates = mesh->getRealSection("coordinates");
726:       const Obj<Mesh::label_sequence>& vertices    = mesh->depthStratum(0);
727:       const Obj<Mesh::numbering_type>& vNumbering  = mesh->getFactory()->getLocalNumbering(mesh, 0);
728:       int            embedDim = coordinates->getFiberDimension(*vertices->begin());

732:       PetscViewerASCIIPrintf(viewer, "%D\n", vertices->size());
733:       for(Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
734:         const Mesh::real_section_type::value_type *array = coordinates->restrictPoint(*v_iter);

736:         PetscViewerASCIIPrintf(viewer, "%7D   ", vNumbering->getIndex(*v_iter)+1);
737:         for(int d = 0; d < embedDim; d++) {
738:           if (d > 0) {
739:             PetscViewerASCIIPrintf(viewer, " ");
740:           }
741:           PetscViewerASCIIPrintf(viewer, "% 12.5E", array[d]);
742:         }
743:         PetscViewerASCIIPrintf(viewer, "\n");
744:       }
745:       return(0);
746:     };
749:     PetscErrorCode Viewer::writeRestart(const Obj<Mesh>& mesh, PetscViewer viewer) {
750:       const Obj<Mesh::real_section_type>&   velocity    = mesh->getRealSection("VELN");
751:       const Obj<Mesh::real_section_type>&   pressure    = mesh->getRealSection("PN");
752:       const Obj<Mesh::real_section_type>&   temperature = mesh->getRealSection("TN");
753:       const Obj<Mesh::numbering_type>& cNumbering  = mesh->getFactory()->getNumbering(mesh, mesh->depth());
754:       const Obj<Mesh::numbering_type>& vNumbering  = mesh->getFactory()->getNumbering(mesh, 0);
755:       const int                        numCells    = cNumbering->getGlobalSize();

759:       int          blen[2];
760:       MPI_Aint     indices[2];
761:       MPI_Datatype oldtypes[2], newtype;
762:       blen[0] = 1; indices[0] = 0;           oldtypes[0] = MPI_INT;
763:       blen[1] = 4; indices[1] = sizeof(int); oldtypes[1] = MPI_DOUBLE;
764:       MPI_Type_struct(2, blen, indices, oldtypes, &newtype);
765:       MPI_Type_commit(&newtype);

767:       if (mesh->commRank() == 0) {
768:         const Obj<Mesh::label_sequence>& vertices = mesh->depthStratum(0);

770:         for(Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
771:           if (vNumbering->isLocal(*v_iter)) {
772:             const Mesh::real_section_type::value_type *veln = velocity->restrictPoint(*v_iter);
773:             const Mesh::real_section_type::value_type *pn   = pressure->restrictPoint(*v_iter);
774:             const Mesh::real_section_type::value_type *tn   = temperature->restrictPoint(*v_iter);

776:             PetscViewerASCIIPrintf(viewer, "%6d% 16.8E% 16.8E% 16.8E% 16.8E\n", *v_iter-numCells+1, veln[0], veln[1], pn[0], tn[0]);
777:           }
778:         }
779:         for(int p = 1; p < mesh->commSize(); p++) {
780:           RestartType *remoteValues;
781:           int          numLocalElements;
782:           MPI_Status   status;

784:           MPI_Recv(&numLocalElements, 1, MPI_INT, p, 1, mesh->comm(), &status);
785:           PetscMalloc(numLocalElements * sizeof(RestartType), &remoteValues);
786:           MPI_Recv(remoteValues, numLocalElements, newtype, p, 1, mesh->comm(), &status);
787:           for(int e = 0; e < numLocalElements; e++) {
788:             PetscViewerASCIIPrintf(viewer, "%6d% 16.8E% 16.8E% 16.8E% 16.8E\n", remoteValues[e].vertex-numCells+1, remoteValues[e].veln_x, remoteValues[e].veln_y, remoteValues[e].pn, remoteValues[e].tn);
789:           }
790:         }
791:       } else {
792:         const Obj<Mesh::label_sequence>& vertices = mesh->depthStratum(0);
793:         RestartType *localValues;
794:         int numLocalElements = vNumbering->getLocalSize();
795:         int k = 0;

797:         PetscMalloc(numLocalElements * sizeof(RestartType), &localValues);
798:         for(Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
799:           if (vNumbering->isLocal(*v_iter)) {
800:             const Mesh::real_section_type::value_type *veln = velocity->restrictPoint(*v_iter);
801:             const Mesh::real_section_type::value_type *pn   = pressure->restrictPoint(*v_iter);
802:             const Mesh::real_section_type::value_type *tn   = temperature->restrictPoint(*v_iter);

804:             localValues[k].vertex = *v_iter;
805:             localValues[k].veln_x = veln[0];
806:             localValues[k].veln_y = veln[1];
807:             localValues[k].pn     = pn[0];
808:             localValues[k].tn     = tn[0];
809:             k++;
810:           }
811:         }
812:         if (k != numLocalElements) {
813:           SETERRQ2(PETSC_ERR_PLIB, "Invalid number of values to send for field, %d should be %d", k, numLocalElements);
814:         }
815:         MPI_Send(&numLocalElements, 1, MPI_INT, 0, 1, mesh->comm());
816:         MPI_Send(localValues, numLocalElements, newtype, 0, 1, mesh->comm());
817:         PetscFree(localValues);
818:       }
819:       MPI_Type_free(&newtype);
820:       return(0);
821:     };

823:     //   This class reconstructs the local pieces of the boundary that distributed PCICE needs.
824:     // The boundary along with the boundary conditions is encoded in a collection of sections
825:     // over the PCICE mesh.  These sections contain a description of the boundary topology
826:     // using elements' global names.  This is unacceptable for PCICE, since it interprets
827:     // elements of the connectivity data arrays as local offsets into (some other of) these arrays.
828:     //   This subroutine performs the renumbering based on the local numbering on the distributed
829:     // mesh.  Essentially, we replace each global element id by its local number.
830:     //
831:     // Note: Any vertex or element number from PCICE is 1-based, but in Sieve we are 0-based. Thus
832:     //       we add and subtract 1 during conversion. Also, Sieve vertices are numbered after cells.
833:     void fuseBoundary(const ALE::Obj<ALE::Mesh>& mesh) {
834:       // Extract PCICE boundary sections
835:       ALE::Obj<ALE::Mesh::int_section_type> IBCsec    = mesh->getIntSection("IBC");
836:       ALE::Obj<ALE::Mesh::int_section_type> IBNDFSsec = mesh->getIntSection("IBNDFS");
837:       ALE::Obj<ALE::Mesh::int_section_type> IBCNUMsec = mesh->getIntSection("IBCNUM");

839:       // Look at the sections, if debugging
840:       if (mesh->debug()) {
841:         IBCsec->view("IBCsec", mesh->comm());
842:         IBNDFSsec->view("IBNDFSsec", mesh->comm());
843:       }

845:       // Extract the local numberings
846:       ALE::Obj<ALE::Mesh::numbering_type> vertexNum  = mesh->getFactory()->getLocalNumbering(mesh, 0);
847:       ALE::Obj<ALE::Mesh::numbering_type> elementNum = mesh->getFactory()->getLocalNumbering(mesh, mesh->depth());
848:       const int numElements = mesh->getFactory()->getNumbering(mesh, mesh->depth())->getGlobalSize();
849:       std::map<int,int> bfMap;
850:       // Declare points to the extracted numbering data
851:       const ALE::Mesh::numbering_type::value_type *vNum, *eNum;

853:       // Create map from serial bdFace numbers to local bdFace numbers
854:       {
855:         const ALE::Mesh::int_section_type::chart_type     chart = IBCNUMsec->getChart();
856:         ALE::Mesh::int_section_type::chart_type::iterator begin = chart.begin();
857:         ALE::Mesh::int_section_type::chart_type::iterator end   = chart.end();
858:         int num = 0;

860:         for(ALE::Mesh::int_section_type::chart_type::iterator p_iter = begin; p_iter != end; ++p_iter) {
861:           const int  fiberDim  = IBCNUMsec->getFiberDimension(*p_iter);
862:           const int *globalNum = IBCNUMsec->restrictPoint(*p_iter);

864:           for(int n = 0; n < fiberDim; ++n) {
865:             bfMap[globalNum[n]] = ++num;
866:           }
867:         }
868:       }
869:       // Renumber vertex section IBC
870:       {
871:         const ALE::Mesh::int_section_type::chart_type     IBCchart = IBCsec->getChart();
872:         ALE::Mesh::int_section_type::chart_type::iterator begin    = IBCchart.begin();
873:         ALE::Mesh::int_section_type::chart_type::iterator end      = IBCchart.end();
874:         for(ALE::Mesh::int_section_type::chart_type::iterator p_iter = begin; p_iter != end; ++p_iter) {
875:           ALE::Mesh::point_type p = *p_iter;
876:           const ALE::Mesh::int_section_type::value_type *ibc_in = IBCsec->restrictPoint(p);
877:           int fiberDimension = IBCsec->getFiberDimension(p);
878:           ALE::Mesh::int_section_type::value_type ibc_out[8];
879:           // k controls the update of edge connectivity for each containing element;
880:           // if fiberDimension is 4, only one boundary face is connected to the element, and that edge's data
881:           // are contained in entries 0 - 3 of the section over the element p;
882:           // if fiberDimension is 8, two boundary faces are connected to the element, so the second edge's data
883:           // are contained in entries 4 - 7
884:           for(int k = 0; k < fiberDimension/4; k++) {
885:             // Extract IBC entry 1 (entry kk*4) for edge kk connected to element p.
886:             // This is the entry that needs renumbering for renumbering (2,3 & 4 are invariant under distribution),
887:             // see IBC's description.
888:             // Here we assume that elementNum's domain contains all boundary elements found in IBC,
889:             // so we can restrict to the extracted entry.
890:             eNum = elementNum->restrictPoint((ALE::Mesh::numbering_type::point_type) ibc_in[k*4]-1);
891:             ibc_out[k*4+0] = eNum[0]+1;
892:             // Copy the other entries right over
893:             ibc_out[k*4+1] = ibc_in[k*4+1];
894:             ibc_out[k*4+2] = ibc_in[k*4+2];
895:             ibc_out[k*4+3] = ibc_in[k*4+3];
896:           }
897:           // Update IBC
898:           IBCsec->updatePoint(p, ibc_out);
899:         }
900:       }
901:       {
902:         // Renumber vertex section IBNDFS
903:         const ALE::Mesh::int_section_type::chart_type     IBNDFSchart = IBNDFSsec->getChart();
904:         ALE::Mesh::int_section_type::chart_type::iterator begin       = IBNDFSchart.begin();
905:         ALE::Mesh::int_section_type::chart_type::iterator end         = IBNDFSchart.end();
906:         for(ALE::Mesh::int_section_type::chart_type::iterator p_iter = begin; p_iter != end; ++p_iter) {
907:           ALE::Mesh::point_type p = *p_iter;
908:           const ALE::Mesh::int_section_type::value_type *ibndfs_in = IBNDFSsec->restrictPoint(p);
909:           // Here we assume the fiber dimension is 5
910:           ALE::Mesh::int_section_type::value_type ibndfs_out[5];
911:           // Renumber entries 1,2 & 3 (4 & 5 are invariant under distribution), see IBNDFS's description
912:           // Here we assume that vertexNum's domain contains all boundary verticies found in IBNDFS, so we can restrict to the first extracted entry
913:           vNum= vertexNum->restrictPoint((ALE::Mesh::numbering_type::point_type)ibndfs_in[0]-1+numElements);
914:           ibndfs_out[0] = vNum[0]+1;
915:           // Map serial bdFace numbers to local bdFace numbers
916:           ibndfs_out[1] = bfMap[ibndfs_in[1]];
917:           ibndfs_out[2] = bfMap[ibndfs_in[2]];
918:           // Copy the other entries right over
919:           ibndfs_out[3] = ibndfs_in[3];
920:           ibndfs_out[4] = ibndfs_in[4];
921:           // Update IBNDFS
922:           IBNDFSsec->updatePoint(p,ibndfs_out);
923:         }
924:       }
925:       if (mesh->debug()) {
926:         IBCsec->view("Renumbered IBCsec", mesh->comm());
927:         IBNDFSsec->view("Renumbered IBNDFSsec", mesh->comm());
928:       }
929:       // It's not clear whether IBFCON needs to be renumbered (what does it mean that its entries are not "GLOBAL NODE NUMBER(s)" -- see IBFCON's descriptions
930:     };
931:   };
932: };