Actual source code: mesh.c

  1: #include <private/meshimpl.h>   /*I      "petscdmmesh.h"   I*/
  2: #include <petscdmmesh_viewers.hh>
  3: #include <petscdmmesh_formats.hh>

  5: /* Logging support */
  6: PetscLogEvent DMMesh_View, DMMesh_GetGlobalScatter, DMMesh_restrictVector, DMMesh_assembleVector, DMMesh_assembleVectorComplete, DMMesh_assembleMatrix, DMMesh_updateOperator;

  8: ALE::MemoryLogger Petsc_MemoryLogger;

 13: /*
 14:    Private routine to delete internal tag storage when a communicator is freed.

 16:    This is called by MPI, not by users.


 20:          we do not use PetscFree() since it is unsafe after PetscFinalize()
 21: */
 22: PetscMPIInt DMMesh_DelTag(MPI_Comm comm,PetscMPIInt keyval,void* attr_val,void* extra_state)
 23: {
 24:   free(attr_val);
 25:   return(MPI_SUCCESS);
 26: }

 31: PetscErrorCode DMMeshFinalize()
 32: {
 34:   PETSC_MESH_TYPE::MeshNumberingFactory::singleton(0, 0, true);
 35:   return(0);
 36: }

 40: /*@C
 41:   DMMeshGetMesh - Gets the internal mesh object

 43:   Not collective

 45:   Input Parameter:
 46: . mesh - the mesh object

 48:   Output Parameter:
 49: . m - the internal mesh object

 51:   Level: advanced

 53: .seealso DMMeshCreate(), DMMeshSetMesh()
 54: @*/
 55: PetscErrorCode DMMeshGetMesh(DM dm, ALE::Obj<PETSC_MESH_TYPE>& m)
 56: {
 59:   m = ((DM_Mesh*) dm->data)->m;
 60:   return(0);
 61: }

 65: /*@C
 66:   DMMeshSetMesh - Sets the internal mesh object

 68:   Not collective

 70:   Input Parameters:
 71: + mesh - the mesh object
 72: - m - the internal mesh object

 74:   Level: advanced

 76: .seealso DMMeshCreate(), DMMeshGetMesh()
 77: @*/
 78: PetscErrorCode DMMeshSetMesh(DM dm, const ALE::Obj<PETSC_MESH_TYPE>& m)
 79: {
 80:   DM_Mesh        *mesh = (DM_Mesh *) dm->data;

 85:   mesh->m = m;
 86:   VecScatterDestroy(&mesh->globalScatter);
 87:   return(0);
 88: }

 92: PetscErrorCode DMMeshView_Sieve_Ascii(const ALE::Obj<PETSC_MESH_TYPE>& mesh, PetscViewer viewer)
 93: {
 94:   PetscViewerFormat format;
 95:   PetscErrorCode    ierr;

 98:   PetscViewerGetFormat(viewer, &format);
 99:   if (format == PETSC_VIEWER_ASCII_VTK) {
100:     VTKViewer::writeHeader(mesh, viewer);
101:     VTKViewer::writeVertices(mesh, viewer);
102:     VTKViewer::writeElements(mesh, viewer);
103:     const ALE::Obj<PETSC_MESH_TYPE::int_section_type>& p     = mesh->getIntSection("Partition");
104:     const ALE::Obj<PETSC_MESH_TYPE::label_sequence>&   cells = mesh->heightStratum(0);
105:     const PETSC_MESH_TYPE::label_sequence::iterator    end   = cells->end();
106:     const int                                          rank  = mesh->commRank();

108:     p->setChart(PETSC_MESH_TYPE::int_section_type::chart_type(*cells));
109:     p->setFiberDimension(cells, 1);
110:     p->allocatePoint();
111:     for(PETSC_MESH_TYPE::label_sequence::iterator c_iter = cells->begin(); c_iter != end; ++c_iter) {
112:       p->updatePoint(*c_iter, &rank);
113:     }
114:     PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_VTK_CELL);
115:     SectionView_Sieve_Ascii(mesh, p, "Partition", viewer);
116:     PetscViewerPopFormat(viewer);
117:   } else if (format == PETSC_VIEWER_ASCII_PCICE) {
118:     char      *filename;
119:     char       coordFilename[2048];
120:     PetscBool  isConnect;
121:     size_t     len;

123:     PetscViewerFileGetName(viewer, (const char **) &filename);
124:     PetscStrlen(filename, &len);
125:     PetscStrcmp(&(filename[len-5]), ".lcon", &isConnect);
126:     if (!isConnect) {
127:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Invalid element connectivity filename: %s", filename);
128:     }
129:     ALE::PCICE::Viewer::writeElements(mesh, viewer);
130:     PetscStrncpy(coordFilename, filename, len-5);
131:     coordFilename[len-5] = '\0';
132:     PetscStrcat(coordFilename, ".nodes");
133:     PetscViewerFileSetName(viewer, coordFilename);
134:     ALE::PCICE::Viewer::writeVertices(mesh, viewer);
135:   } else if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
136:     mesh->view("");
137:   } else {
138:     int dim = mesh->getDimension();

140:     PetscViewerASCIIPrintf(viewer, "Mesh in %d dimensions:\n", dim);
141:     if (mesh->depth() == 1) {
142:       PetscViewerASCIIPrintf(viewer, "  %d %d-cells\n", mesh->depthStratum(0)->size(), 0);
143:       PetscViewerASCIIPrintf(viewer, "  %d %d-cells\n", mesh->heightStratum(0)->size(), dim);
144:     } else {
145:       for(int d = 0; d <= dim; d++) {
146:         // FIX: Need to globalize
147:         PetscViewerASCIIPrintf(viewer, "  %d %d-cells\n", mesh->depthStratum(d)->size(), d);
148:       }
149:     }
150:   }
151:   PetscViewerFlush(viewer);
152:   return(0);
153: }


158: PetscErrorCode DMMeshView_Sieve_Binary(const ALE::Obj<PETSC_MESH_TYPE>& mesh, PetscViewer viewer)
159: {
160:   char           *filename;
161:   PetscErrorCode  ierr;

164:   PetscViewerFileGetName(viewer, (const char **) &filename);
165:   ALE::MeshSerializer::writeMesh(filename, *mesh);
166:   return(0);
167: }

171: PetscErrorCode DMMeshView_Sieve(const ALE::Obj<PETSC_MESH_TYPE>& mesh, PetscViewer viewer)
172: {
173:   PetscBool      iascii, isbinary, isdraw;

177:   PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);
178:   PetscTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);
179:   PetscTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);

181:   if (iascii){
182:     DMMeshView_Sieve_Ascii(mesh, viewer);
183:   } else if (isbinary) {
184:     DMMeshView_Sieve_Binary(mesh, viewer);
185:   } else if (isdraw){
186:     SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP, "Draw viewer not implemented for DMMesh");
187:   } else {
188:     SETERRQ1(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Viewer type %s not supported by this mesh object", ((PetscObject)viewer)->type_name);
189:   }
190:   return(0);
191: }

195: PetscErrorCode DMView_Mesh(DM dm, PetscViewer viewer)
196: {
197:   DM_Mesh       *mesh = (DM_Mesh *) dm->data;

201:   DMMeshView_Sieve(mesh->m, viewer);
202:   return(0);
203: }

207: /*@
208:   DMMeshLoad - Create a mesh topology from the saved data in a viewer.

210:   Collective on Viewer

212:   Input Parameter:
213: . viewer - The viewer containing the data

215:   Output Parameters:
216: . mesh - the mesh object

218:   Level: advanced

220: .seealso DMView()
221: @*/
222: PetscErrorCode DMMeshLoad(PetscViewer viewer, DM dm)
223: {
224:   DM_Mesh       *mesh = (DM_Mesh *) dm->data;
225:   char          *filename;

229:   if (!mesh->m) {
230:     MPI_Comm comm;

232:     PetscObjectGetComm((PetscObject) viewer, &comm);
233:     ALE::Obj<PETSC_MESH_TYPE> m = new PETSC_MESH_TYPE(comm, 1);
234:     DMMeshSetMesh(dm, m);
235:   }
236:   PetscViewerFileGetName(viewer, (const char **) &filename);
237:   ALE::MeshSerializer::loadMesh(filename, *mesh->m);
238:   return(0);
239: }

243: /*@C
244:   DMMeshCreateMatrix - Creates a matrix with the correct parallel layout required for
245:     computing the Jacobian on a function defined using the information in the Section.

247:   Collective on DMMesh

249:   Input Parameters:
250: + mesh    - the mesh object
251: . section - the section which determines data layout
252: - mtype   - Supported types are MATSEQAIJ, MATMPIAIJ, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ,
253:             or any type which inherits from one of these (such as MATAIJ, MATLUSOL, etc.).

255:   Output Parameter:
256: . J  - matrix with the correct nonzero preallocation
257:        (obviously without the correct Jacobian values)

259:   Level: advanced

261:   Notes: This properly preallocates the number of nonzeros in the sparse matrix so you
262:        do not need to do it yourself.

264: .seealso ISColoringView(), ISColoringGetIS(), MatFDColoringCreate(), DMDASetBlockFills()
265: @*/
266: PetscErrorCode DMMeshCreateMatrix(DM dm, SectionReal section, const MatType mtype, Mat *J)
267: {
268:   ALE::Obj<PETSC_MESH_TYPE> m;
269:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;

273: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
274:   MatInitializePackage(PETSC_NULL);
275: #endif
276:   if (!mtype) mtype = MATAIJ;
277:   DMMeshGetMesh(dm, m);
278:   SectionRealGetSection(section, s);
279:   try {
280:     DMMeshCreateMatrix(m, s, mtype, J, -1, !dm->prealloc_only);
281:   } catch(ALE::Exception e) {
282:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB, e.message());
283:   }
284:   PetscObjectCompose((PetscObject) *J, "DM", (PetscObject) dm);
285:   return(0);
286: }

290: PetscErrorCode DMMeshGetVertexMatrix(DM dm, const MatType mtype, Mat *J)
291: {
292:   SectionReal    section;

296:   DMMeshGetVertexSectionReal(dm, "default", 1, &section);
297:   DMMeshCreateMatrix(dm, section, mtype, J);
298:   SectionRealDestroy(&section);
299:   return(0);
300: }

304: PetscErrorCode DMMeshGetCellMatrix(DM dm, const MatType mtype, Mat *J)
305: {
306:   SectionReal    section;

310:   DMMeshGetCellSectionReal(dm, "default", 1, &section);
311:   DMMeshCreateMatrix(dm, section, mtype, J);
312:   SectionRealDestroy(&section);
313:   return(0);
314: }

318: PetscErrorCode DMGetMatrix_Mesh(DM dm, const MatType mtype, Mat *J)
319: {
320:   SectionReal            section;
321:   ISLocalToGlobalMapping ltog;
322:   PetscBool              flag;
323:   PetscErrorCode         ierr;

326:   DMMeshHasSectionReal(dm, "default", &flag);
327:   if (!flag) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Must set default section");
328:   DMMeshGetSectionReal(dm, "default", &section);
329:   DMMeshCreateMatrix(dm, section, mtype, J);
330:   DMGetLocalToGlobalMapping(dm, &ltog);
331:   MatSetLocalToGlobalMapping(*J, ltog, ltog);
332:   SectionRealDestroy(&section);
333:   return(0);
334: }

338: PetscErrorCode DMDestroy_Mesh(DM dm)
339: {
340:   DM_Mesh       *mesh = (DM_Mesh *) dm->data;

344:   mesh->m = PETSC_NULL;
345:   VecScatterDestroy(&mesh->globalScatter);
346:   return(0);
347: }

351: PetscErrorCode DMCreateGlobalVector_Mesh(DM dm, Vec *gvec)
352: {
353:   ALE::Obj<PETSC_MESH_TYPE> m;
354:   PetscBool      flag;

358:   DMMeshHasSectionReal(dm, "default", &flag);
359:   if (!flag) SETERRQ(((PetscObject) dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Must set default section");
360:   DMMeshGetMesh(dm, m);
361:   const ALE::Obj<PETSC_MESH_TYPE::order_type>& order = m->getFactory()->getGlobalOrder(m, "default", m->getRealSection("default"));

363:   VecCreate(((PetscObject) dm)->comm, gvec);
364:   VecSetSizes(*gvec, order->getLocalSize(), order->getGlobalSize());
365:   VecSetFromOptions(*gvec);
366:   PetscObjectCompose((PetscObject) *gvec, "DM", (PetscObject) dm);
367:   return(0);
368: }

372: /*@
373:   DMMeshCreateVector - Creates a global vector matching the input section

375:   Collective on DMMesh

377:   Input Parameters:
378: + mesh - the DMMesh
379: - section - the Section

381:   Output Parameter:
382: . vec - the global vector

384:   Level: advanced

386:   Notes: The vector can safely be destroyed using VecDestroy().
387: .seealso DMMeshCreate()
388: @*/
389: PetscErrorCode DMMeshCreateVector(DM mesh, SectionReal section, Vec *vec)
390: {
391:   ALE::Obj<PETSC_MESH_TYPE> m;
392:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;

396:   DMMeshGetMesh(mesh, m);
397:   SectionRealGetSection(section, s);
398:   const ALE::Obj<PETSC_MESH_TYPE::order_type>& order = m->getFactory()->getGlobalOrder(m, s->getName(), s);

400:   VecCreate(m->comm(), vec);
401:   VecSetSizes(*vec, order->getLocalSize(), order->getGlobalSize());
402:   VecSetFromOptions(*vec);
403:   return(0);
404: }

408: PetscErrorCode DMCreateLocalVector_Mesh(DM dm, Vec *lvec)
409: {
410:   ALE::Obj<PETSC_MESH_TYPE> m;
411:   PetscBool      flag;

415:   DMMeshHasSectionReal(dm, "default", &flag);
416:   if (!flag) SETERRQ(((PetscObject) dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Must set default section");
417:   DMMeshGetMesh(dm, m);
418:   const int size = m->getRealSection("default")->getStorageSize();

420:   VecCreate(PETSC_COMM_SELF, lvec);
421:   VecSetSizes(*lvec, size, size);
422:   VecSetFromOptions(*lvec);
423:   PetscObjectCompose((PetscObject) *lvec, "DM", (PetscObject) dm);
424:   return(0);
425: }

429: PetscErrorCode DMCreateLocalToGlobalMapping_Mesh(DM dm)
430: {
431:   ALE::Obj<PETSC_MESH_TYPE> m;
432:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;
433:   SectionReal    section;
434:   PetscBool      flag;

438:   DMMeshHasSectionReal(dm, "default", &flag);
439:   if (!flag) SETERRQ(((PetscObject) dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Must set default section");
440:   DMMeshGetSectionReal(dm ,"default", &section);
441:   DMMeshGetMesh(dm, m);
442:   SectionRealGetSection(section, s);
443:   const ALE::Obj<PETSC_MESH_TYPE::order_type>& globalOrder = m->getFactory()->getGlobalOrder(m, s->getName(), s);
444:   PetscInt *ltog;

446:   PetscMalloc(s->size() * sizeof(PetscInt), &ltog); // We want the local+overlap size
447:   for(PetscInt p = s->getChart().min(), l = 0; p < s->getChart().max(); ++p) {
448:     PetscInt g = globalOrder->getIndex(p);

450:     for(PetscInt c = 0; c < s->getConstrainedFiberDimension(p); ++c, ++l) {
451:       ltog[l] = g+c;
452:     }
453:   }
454:   ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, s->size(), ltog, PETSC_OWN_POINTER, &dm->ltogmap);
455:   PetscLogObjectParent(dm, dm->ltogmap);
456:   SectionRealDestroy(&section);
457:   return(0);
458: }

462: /*@
463:   DMMeshCreateGlobalScatter - Create a VecScatter which maps from local, overlapping
464:   storage in the Section to a global Vec

466:   Collective on DMMesh

468:   Input Parameters:
469: + mesh - the mesh object
470: - section - The Scetion which determines data layout

472:   Output Parameter:
473: . scatter - the VecScatter

475:   Level: advanced

477: .seealso DMDestroy(), DMMeshCreateGlobalRealVector(), DMMeshCreate()
478: @*/
479: PetscErrorCode DMMeshCreateGlobalScatter(DM dm, SectionReal section, VecScatter *scatter)
480: {
481:   ALE::Obj<PETSC_MESH_TYPE> m;
482:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;

486:   DMMeshGetMesh(dm, m);
487:   SectionRealGetSection(section, s);
488:   if (m->hasLabel("marker")) {
489:     DMMeshCreateGlobalScatter(m, s, m->getLabel("marker"), scatter);
490:   } else {
491:     DMMeshCreateGlobalScatter(m, s, scatter);
492:   }
493:   return(0);
494: }

498: /*@
499:   DMMeshGetGlobalScatter - Retrieve the VecScatter which maps from local, overlapping storage in the default Section to a global Vec

501:   Collective on DMMesh

503:   Input Parameters:
504: . mesh - the mesh object

506:   Output Parameter:
507: . scatter - the VecScatter

509:   Level: advanced

511: .seealso MeshDestroy(), DMMeshCreateGlobalrealVector(), DMMeshCreate()
512: @*/
513: PetscErrorCode DMMeshGetGlobalScatter(DM dm, VecScatter *scatter)
514: {
515:   DM_Mesh       *mesh = (DM_Mesh *) dm->data;

521:   if (!mesh->globalScatter) {
522:     SectionReal section;

524:     DMMeshGetSectionReal(dm, "default", &section);
525:     DMMeshCreateGlobalScatter(dm, section, &mesh->globalScatter);
526:     SectionRealDestroy(&section);
527:   }
528:   *scatter = mesh->globalScatter;
529:   return(0);
530: }

534: PetscErrorCode  DMGlobalToLocalBegin_Mesh(DM dm, Vec g, InsertMode mode, Vec l)
535: {
536:   VecScatter     injection;

540:   DMMeshGetGlobalScatter(dm, &injection);
541:   VecScatterBegin(injection, g, l, mode, SCATTER_REVERSE);
542:   return(0);
543: }

547: PetscErrorCode  DMGlobalToLocalEnd_Mesh(DM dm, Vec g, InsertMode mode, Vec l)
548: {
549:   VecScatter     injection;

553:   DMMeshGetGlobalScatter(dm, &injection);
554:   VecScatterEnd(injection, g, l, mode, SCATTER_REVERSE);
555:   return(0);
556: }

560: PetscErrorCode  DMLocalToGlobalBegin_Mesh(DM dm, Vec l, InsertMode mode, Vec g)
561: {
562:   VecScatter     injection;

566:   DMMeshGetGlobalScatter(dm, &injection);
567:   VecScatterBegin(injection, l, g, mode, SCATTER_FORWARD);
568:   return(0);
569: }

573: PetscErrorCode  DMLocalToGlobalEnd_Mesh(DM dm, Vec l, InsertMode mode, Vec g)
574: {
575:   VecScatter     injection;

579:   DMMeshGetGlobalScatter(dm, &injection);
580:   VecScatterEnd(injection, l, g, mode, SCATTER_FORWARD);
581:   return(0);
582: }

586: PetscErrorCode DMMeshGetLocalFunction(DM dm, PetscErrorCode (**lf)(DM, Vec, Vec, void *))
587: {
588:   DM_Mesh *mesh = (DM_Mesh *) dm->data;

592:   if (lf) *lf = mesh->lf;
593:   return(0);
594: }

598: PetscErrorCode DMMeshSetLocalFunction(DM dm, PetscErrorCode (*lf)(DM, Vec, Vec, void *))
599: {
600:   DM_Mesh *mesh = (DM_Mesh *) dm->data;

604:   mesh->lf = lf;
605:   return(0);
606: }

610: PetscErrorCode DMMeshGetLocalJacobian(DM dm, PetscErrorCode (**lj)(DM, Vec, Mat, void *))
611: {
612:   DM_Mesh *mesh = (DM_Mesh *) dm->data;

616:   if (lj) *lj = mesh->lj;
617:   return(0);
618: }

622: PetscErrorCode DMMeshSetLocalJacobian(DM dm, PetscErrorCode (*lj)(DM, Vec, Mat, void *))
623: {
624:   DM_Mesh *mesh = (DM_Mesh *) dm->data;

628:   mesh->lj = lj;
629:   return(0);
630: }

634: // Here we assume:
635: //  - Assumes 3D and tetrahedron
636: //  - The section takes values on vertices and is P1
637: //  - Points have the same dimension as the mesh
638: //  - All values have the same dimension
639: PetscErrorCode DMMeshInterpolatePoints(DM dm, SectionReal section, int numPoints, PetscReal *points, PetscScalar **values)
640: {
641:   Obj<PETSC_MESH_TYPE> m;
642:   Obj<PETSC_MESH_TYPE::real_section_type> s;
643:   PetscReal     *v0, *J, *invJ, detJ;

647:   DMMeshGetMesh(dm, m);
648:   SectionRealGetSection(section, s);
649:   const Obj<PETSC_MESH_TYPE::real_section_type>& coordinates = m->getRealSection("coordinates");
650:   int embedDim = coordinates->getFiberDimension(*m->depthStratum(0)->begin());
651:   int dim      = s->getFiberDimension(*m->depthStratum(0)->begin());

653:   PetscMalloc3(embedDim,double,&v0,embedDim*embedDim,double,&J,embedDim*embedDim,double,&invJ);
654:   PetscMalloc(numPoints*dim * sizeof(PetscScalar), &values);
655:   for(int p = 0; p < numPoints; p++) {
656:     PetscReal *point = &points[p*embedDim];

658:     PETSC_MESH_TYPE::point_type e = m->locatePoint(point);
659:     const PETSC_MESH_TYPE::real_section_type::value_type *coeff = s->restrictPoint(e);

661:     m->computeElementGeometry(coordinates, e, v0, J, invJ, detJ);
662:     double xi   = (invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]) + invJ[0*embedDim+2]*(point[2] - v0[2]))*0.5;
663:     double eta  = (invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]) + invJ[1*embedDim+2]*(point[2] - v0[2]))*0.5;
664:     double zeta = (invJ[2*embedDim+0]*(point[0] - v0[0]) + invJ[2*embedDim+1]*(point[1] - v0[1]) + invJ[2*embedDim+2]*(point[2] - v0[2]))*0.5;

666:     for(int d = 0; d < dim; d++) {
667:       (*values)[p*dim+d] = coeff[0*dim+d]*(1 - xi - eta - zeta) + coeff[1*dim+d]*xi + coeff[2*dim+d]*eta + coeff[3*dim+d]*zeta;
668:     }
669:   }
670:   PetscFree3(v0, J, invJ);
671:   return(0);
672: }

676: /*@
677:   DMMeshGetDimension - Return the topological mesh dimension

679:   Collective on mesh

681:   Input Parameter:
682: . mesh - The DMMesh

684:   Output Parameter:
685: . dim - The topological mesh dimension

687:   Level: beginner

689: .seealso: DMMeshCreate()
690: @*/
691: PetscErrorCode DMMeshGetDimension(DM dm, PetscInt *dim)
692: {
693:   Obj<PETSC_MESH_TYPE> m;

697:   DMMeshGetMesh(dm, m);
698:   *dim = m->getDimension();
699:   return(0);
700: }

704: /*@C
705:   DMMeshGetMaximumDegree - Return the maximum degree of any mesh vertex

707:   Collective on mesh

709:   Input Parameter:
710: . mesh - The DMMesh

712:   Output Parameter:
713: . maxDegree - The maximum number of edges at any vertex

715:    Level: beginner

717: .seealso: DMMeshCreate()
718: @*/
719: PetscErrorCode DMMeshGetMaximumDegree(DM dm, PetscInt *maxDegree)
720: {
721:   Obj<PETSC_MESH_TYPE> m;

725:   DMMeshGetMesh(dm, m);
726:   const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& vertices = m->depthStratum(0);
727:   const ALE::Obj<PETSC_MESH_TYPE::sieve_type>&     sieve    = m->getSieve();
728:   PetscInt                                         maxDeg   = -1;

730:   for(PETSC_MESH_TYPE::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
731:     maxDeg = PetscMax(maxDeg, (PetscInt) sieve->getSupportSize(*v_iter));
732:   }
733:   *maxDegree = maxDeg;
734:   return(0);
735: }


741: /*@
742:   DMMeshRestrictVector - Insert values from a global vector into a local ghosted vector

744:   Collective on g

746:   Input Parameters:
747: + g - The global vector
748: . l - The local vector
749: - mode - either ADD_VALUES or INSERT_VALUES, where
750:    ADD_VALUES adds values to any existing entries, and
751:    INSERT_VALUES replaces existing entries with new values

753:    Level: beginner

755: .seealso: MatSetOption()
756: @*/
757: PetscErrorCode DMMeshRestrictVector(Vec g, Vec l, InsertMode mode)
758: {
759:   VecScatter     injection;

763:   PetscLogEventBegin(DMMesh_restrictVector,0,0,0,0);
764:   PetscObjectQuery((PetscObject) g, "injection", (PetscObject *) &injection);
765:   if (injection) {
766:     VecScatterBegin(injection, g, l, mode, SCATTER_REVERSE);
767:     VecScatterEnd(injection, g, l, mode, SCATTER_REVERSE);
768:   } else {
769:     if (mode == INSERT_VALUES) {
770:       VecCopy(g, l);
771:     } else {
772:       VecAXPY(l, 1.0, g);
773:     }
774:   }
775:   PetscLogEventEnd(DMMesh_restrictVector,0,0,0,0);
776:   return(0);
777: }

781: /*@
782:   DMMeshAssembleVectorComplete - Insert values from a local ghosted vector into a global vector

784:   Collective on g

786:   Input Parameters:
787: + g - The global vector
788: . l - The local vector
789: - mode - either ADD_VALUES or INSERT_VALUES, where
790:    ADD_VALUES adds values to any existing entries, and
791:    INSERT_VALUES replaces existing entries with new values

793:    Level: beginner

795: .seealso: MatSetOption()
796: @*/
797: PetscErrorCode DMMeshAssembleVectorComplete(Vec g, Vec l, InsertMode mode)
798: {
799:   VecScatter     injection;

803:   PetscLogEventBegin(DMMesh_assembleVectorComplete,0,0,0,0);
804:   PetscObjectQuery((PetscObject) g, "injection", (PetscObject *) &injection);
805:   if (injection) {
806:     VecScatterBegin(injection, l, g, mode, SCATTER_FORWARD);
807:     VecScatterEnd(injection, l, g, mode, SCATTER_FORWARD);
808:   } else {
809:     if (mode == INSERT_VALUES) {
810:       VecCopy(l, g);
811:     } else {
812:       VecAXPY(g, 1.0, l);
813:     }
814:   }
815:   PetscLogEventEnd(DMMesh_assembleVectorComplete,0,0,0,0);
816:   return(0);
817: }

821: /*@
822:   DMMeshAssembleVector - Insert values into a vector

824:   Collective on A

826:   Input Parameters:
827: + b - the vector
828: . e - The element number
829: . v - The values
830: - mode - either ADD_VALUES or INSERT_VALUES, where
831:    ADD_VALUES adds values to any existing entries, and
832:    INSERT_VALUES replaces existing entries with new values

834:    Level: beginner

836: .seealso: VecSetOption()
837: @*/
838: PetscErrorCode DMMeshAssembleVector(Vec b, PetscInt e, PetscScalar v[], InsertMode mode)
839: {
840:   DM             dm;
841:   SectionReal    section;

845:   PetscObjectQuery((PetscObject) b, "DM", (PetscObject *) &dm);
846:   DMMeshGetSectionReal(dm, "x", &section);
847:   DMMeshAssembleVector(b, dm, section, e, v, mode);
848:   SectionRealDestroy(&section);
849:   return(0);
850: }

852: PetscErrorCode DMMeshAssembleVector(Vec b, DM dm, SectionReal section, PetscInt e, PetscScalar v[], InsertMode mode)
853: {
854:   ALE::Obj<PETSC_MESH_TYPE> m;
855:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;
856:   PetscInt                  firstElement;
857:   PetscErrorCode            ierr;

860:   PetscLogEventBegin(DMMesh_assembleVector,0,0,0,0);
861:   DMMeshGetMesh(dm, m);
862:   SectionRealGetSection(section, s);
863:   //firstElement = elementBundle->getLocalSizes()[bundle->getCommRank()];
864:   firstElement = 0;
865: #ifdef PETSC_USE_COMPLEX
866:   SETERRQ(((PetscObject)mesh)->comm,PETSC_ERR_SUP, "SectionReal does not support complex update");
867: #else
868:   if (mode == INSERT_VALUES) {
869:     m->update(s, PETSC_MESH_TYPE::point_type(e + firstElement), v);
870:   } else {
871:     m->updateAdd(s, PETSC_MESH_TYPE::point_type(e + firstElement), v);
872:   }
873: #endif
874:   PetscLogEventEnd(DMMesh_assembleVector,0,0,0,0);
875:   return(0);
876: }

880: /*@C
881:   MatSetValuesTopology - Sets values in a matrix using DM Mesh points rather than indices

883:   Not Collective

885:   Input Parameters:
886: + mat - the matrix
887: . dmr - The row DM
888: . nrow, rowPoints - number of rows and their local Sieve points
889: . dmc - The column DM
890: . ncol, colPoints - number of columns and their local Sieve points
891: . v -  a logically two-dimensional array of values
892: - mode - either ADD_VALUES or INSERT_VALUES, where
893:    ADD_VALUES adds values to any existing entries, and
894:    INSERT_VALUES replaces existing entries with new values

896:    Level: intermediate

898: .seealso: DMMeshCreate(), MatSetValuesStencil()
899: @*/
900: PetscErrorCode MatSetValuesTopology(Mat mat, DM dmr, PetscInt nrow, const PetscInt rowPoints[], DM dmc, PetscInt ncol, const PetscInt colPoints[], const PetscScalar v[], InsertMode mode)
901: {
902:   ALE::Obj<PETSC_MESH_TYPE> mr;
903:   ALE::Obj<PETSC_MESH_TYPE> mc;

909:   if (!nrow || !ncol) return(0); /* no values to insert */
915:   DMMeshGetMesh(dmr, mr);
916:   DMMeshGetMesh(dmc, mc);
917:   typedef ALE::ISieveVisitor::IndicesVisitor<PETSC_MESH_TYPE::real_section_type,PETSC_MESH_TYPE::order_type,PetscInt> visitor_type;
918:   visitor_type rV(*mr->getRealSection("default"), *mr->getFactory()->getLocalOrder(mr, "default", mr->getRealSection("default")),
919:                   (int) pow((double) mr->getSieve()->getMaxConeSize(), mr->depth())*mr->getMaxDof()*nrow, mr->depth() > 1);
920:   visitor_type cV(*mc->getRealSection("default"), *mc->getFactory()->getLocalOrder(mc, "default", mc->getRealSection("default")),
921:                   (int) pow((double) mc->getSieve()->getMaxConeSize(), mc->depth())*mc->getMaxDof()*ncol, mc->depth() > 1);

923:   try {
924:     for(PetscInt r = 0; r < nrow; ++r) {
925:       ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*mr->getSieve(), rowPoints[r], rV);
926:     }
927:   } catch(ALE::Exception e) {
928:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB, e.message());
929:   }
930:   const PetscInt *rowIndices    = rV.getValues();
931:   const int       numRowIndices = rV.getSize();
932:   try {
933:     for(PetscInt c = 0; c < ncol; ++c) {
934:       ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*mc->getSieve(), colPoints[c], cV);
935:     }
936:   } catch(ALE::Exception e) {
937:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB, e.message());
938:   }
939:   const PetscInt *colIndices    = cV.getValues();
940:   const int       numColIndices = cV.getSize();

942:   MatSetValuesLocal(mat, numRowIndices, rowIndices, numColIndices, colIndices, v, mode);
943:   return(0);
944: }

948: PetscErrorCode DMMeshUpdateOperator(Mat A, const ALE::Obj<PETSC_MESH_TYPE>& m, const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& section, const ALE::Obj<PETSC_MESH_TYPE::order_type>& globalOrder, const PETSC_MESH_TYPE::point_type& e, PetscScalar array[], InsertMode mode)
949: {

953:   typedef ALE::ISieveVisitor::IndicesVisitor<PETSC_MESH_TYPE::real_section_type,PETSC_MESH_TYPE::order_type,PetscInt> visitor_type;
954:   visitor_type iV(*section, *globalOrder, (int) pow((double) m->getSieve()->getMaxConeSize(), m->depth())*m->getMaxDof(), m->depth() > 1);

956:   updateOperator(A, *m->getSieve(), iV, e, array, mode);
957:   return(0);
958: }

962: PetscErrorCode DMMeshUpdateOperatorGeneral(Mat A, const ALE::Obj<PETSC_MESH_TYPE>& rowM, const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& rowSection, const ALE::Obj<PETSC_MESH_TYPE::order_type>& rowGlobalOrder, const PETSC_MESH_TYPE::point_type& rowE, const ALE::Obj<PETSC_MESH_TYPE>& colM, const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& colSection, const ALE::Obj<PETSC_MESH_TYPE::order_type>& colGlobalOrder, const PETSC_MESH_TYPE::point_type& colE, PetscScalar array[], InsertMode mode)
963: {
964:   typedef ALE::ISieveVisitor::IndicesVisitor<PETSC_MESH_TYPE::real_section_type,PETSC_MESH_TYPE::order_type,PetscInt> visitor_type;
965:   visitor_type iVr(*rowSection, *rowGlobalOrder, (int) pow((double) rowM->getSieve()->getMaxConeSize(), rowM->depth())*rowM->getMaxDof(), rowM->depth() > 1);
966:   visitor_type iVc(*colSection, *colGlobalOrder, (int) pow((double) colM->getSieve()->getMaxConeSize(), colM->depth())*colM->getMaxDof(), colM->depth() > 1);

968:   PetscErrorCode updateOperator(A, *rowM->getSieve(), iVr, rowE, *colM->getSieve(), iVc, colE, array, mode);
969:   return(0);
970: }

974: /*@
975:   DMMeshSetMaxDof - Sets the maximum number of degrees of freedom on any sieve point

977:   Logically Collective on A

979:   Input Parameters:
980: + A - the matrix
981: . mesh - DMMesh needed for orderings
982: . section - A Section which describes the layout
983: . e - The element number
984: . v - The values
985: - mode - either ADD_VALUES or INSERT_VALUES, where
986:    ADD_VALUES adds values to any existing entries, and
987:    INSERT_VALUES replaces existing entries with new values

989:    Notes: This is used by routines like DMMeshUpdateOperator() to bound buffer sizes

991:    Level: developer

993: .seealso: DMMeshUpdateOperator(), DMMeshAssembleMatrix()
994: @*/
995: PetscErrorCode DMMeshSetMaxDof(DM dm, PetscInt maxDof)
996: {
997:   Obj<PETSC_MESH_TYPE> m;
998:   PetscErrorCode       ierr;

1001:   DMMeshGetMesh(dm, m);
1002:   m->setMaxDof(maxDof);
1003:   return(0);
1004: }

1008: /*@
1009:   DMMeshAssembleMatrix - Insert values into a matrix

1011:   Collective on A

1013:   Input Parameters:
1014: + A - the matrix
1015: . dm - DMMesh needed for orderings
1016: . section - A Section which describes the layout
1017: . e - The element
1018: . v - The values
1019: - mode - either ADD_VALUES or INSERT_VALUES, where
1020:    ADD_VALUES adds values to any existing entries, and
1021:    INSERT_VALUES replaces existing entries with new values

1023:    Level: beginner

1025: .seealso: MatSetOption()
1026: @*/
1027: PetscErrorCode DMMeshAssembleMatrix(Mat A, DM dm, SectionReal section, PetscInt e, PetscScalar v[], InsertMode mode)
1028: {

1032:   PetscLogEventBegin(DMMesh_assembleMatrix,0,0,0,0);
1033:   try {
1034:     Obj<PETSC_MESH_TYPE> m;
1035:     Obj<PETSC_MESH_TYPE::real_section_type> s;

1037:     DMMeshGetMesh(dm, m);
1038:     SectionRealGetSection(section, s);
1039:     const ALE::Obj<PETSC_MESH_TYPE::order_type>& globalOrder = m->getFactory()->getGlobalOrder(m, s->getName(), s);

1041:     if (m->debug()) {
1042:       std::cout << "Assembling matrix for element number " << e << " --> point " << e << std::endl;
1043:     }
1044:     DMMeshUpdateOperator(A, m, s, globalOrder, e, v, mode);
1045:   } catch (ALE::Exception e) {
1046:     std::cout << e.msg() << std::endl;
1047:   }
1048:   PetscLogEventEnd(DMMesh_assembleMatrix,0,0,0,0);
1049:   return(0);
1050: }

1052: /******************************** C Wrappers **********************************/

1056: /*@C
1057:   DMMeshGetLabelSize - Get the number of different integer ids in a Label

1059:   Not Collective

1061:   Input Parameters:
1062: + dm   - The DMMesh object
1063: - name - The label name

1065:   Output Parameter:
1066: . size - The label size (number of different integer ids)

1068:   Level: beginner

1070: .keywords: mesh, ExodusII
1071: .seealso: DMMeshCreateExodus()
1072: @*/
1073: PetscErrorCode DMMeshGetLabelSize(DM dm, const char name[], PetscInt *size)
1074: {
1075:   ALE::Obj<PETSC_MESH_TYPE> m;
1076:   PetscErrorCode            ierr;

1079:   DMMeshGetMesh(dm, m);
1080:   *size = m->getLabel(name)->getCapSize();
1081:   return(0);
1082: }

1086: /*@C
1087:   DMMeshGetLabelIds - Get the integer ids in a label

1089:   Not Collective

1091:   Input Parameters:
1092: + mesh - The DMMesh object
1093: . name - The label name
1094: - ids - The id storage array

1096:   Output Parameter:
1097: . ids - The integer ids

1099:   Level: beginner

1101: .keywords: mesh, ExodusII
1102: .seealso: DMMeshCreateExodus()
1103: @*/
1104: PetscErrorCode DMMeshGetLabelIds(DM dm, const char name[], PetscInt *ids)
1105: {
1106:   ALE::Obj<PETSC_MESH_TYPE> m;
1107:   PetscErrorCode            ierr;

1110:   DMMeshGetMesh(dm, m);
1111:   const ALE::Obj<PETSC_MESH_TYPE::label_type::capSequence>&      labelIds = m->getLabel(name)->cap();
1112:   const PETSC_MESH_TYPE::label_type::capSequence::const_iterator iEnd     = labelIds->end();
1113:   PetscInt                                                       i        = 0;

1115:   for(PETSC_MESH_TYPE::label_type::capSequence::const_iterator i_iter = labelIds->begin(); i_iter != iEnd; ++i_iter, ++i) {
1116:     ids[i] = *i_iter;
1117:   }
1118:   return(0);
1119: }

1123: /*@C
1124:   DMMeshGetStratumSize - Get the number of points in a label stratum

1126:   Not Collective

1128:   Input Parameters:
1129: + dm - The DMMesh object
1130: . name - The label name
1131: - value - The stratum value

1133:   Output Parameter:
1134: . size - The stratum size

1136:   Level: beginner

1138: .keywords: mesh, ExodusII
1139: .seealso: DMMeshCreateExodus()
1140: @*/
1141: PetscErrorCode DMMeshGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
1142: {
1143:   ALE::Obj<PETSC_MESH_TYPE> m;
1144:   PetscErrorCode            ierr;

1147:   DMMeshGetMesh(dm, m);
1148:   *size = m->getLabelStratum(name, value)->size();
1149:   return(0);
1150: }

1154: /*@C
1155:   DMMeshGetStratum - Get the points in a label stratum

1157:   Not Collective

1159:   Input Parameters:
1160: + dm - The DMMesh object
1161: . name - The label name
1162: . value - The stratum value
1163: - points - The stratum points storage array

1165:   Output Parameter:
1166: . points - The stratum points

1168:   Level: beginner

1170: .keywords: mesh, ExodusII
1171: .seealso: DMMeshCreateExodus()
1172: @*/
1173: PetscErrorCode DMMeshGetStratum(DM dm, const char name[], PetscInt value, PetscInt *points)
1174: {
1175:   ALE::Obj<PETSC_MESH_TYPE> m;
1176:   PetscErrorCode            ierr;

1179:   DMMeshGetMesh(dm, m);
1180:   const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& stratum = m->getLabelStratum(name, value);
1181:   const PETSC_MESH_TYPE::label_sequence::iterator  sEnd    = stratum->end();
1182:   PetscInt                                         s       = 0;

1184:   for(PETSC_MESH_TYPE::label_sequence::iterator s_iter = stratum->begin(); s_iter != sEnd; ++s_iter, ++s) {
1185:     points[s] = *s_iter;
1186:   }
1187:   return(0);
1188: }

1192: PetscErrorCode WriteVTKHeader(DM dm, PetscViewer viewer)
1193: {
1194:   ALE::Obj<PETSC_MESH_TYPE> m;

1197:   DMMeshGetMesh(dm, m);
1198:   return VTKViewer::writeHeader(m, viewer);
1199: }

1203: PetscErrorCode WriteVTKVertices(DM dm, PetscViewer viewer)
1204: {
1205:   ALE::Obj<PETSC_MESH_TYPE> m;

1208:   DMMeshGetMesh(dm, m);
1209:   return VTKViewer::writeVertices(m, viewer);
1210: }

1214: PetscErrorCode WriteVTKElements(DM dm, PetscViewer viewer)
1215: {
1216:   ALE::Obj<PETSC_MESH_TYPE> m;

1219:   DMMeshGetMesh(dm, m);
1220:   return VTKViewer::writeElements(m, viewer);
1221: }

1225: /*@C
1226:   DMMeshGetCoordinates - Creates an array holding the coordinates.

1228:   Not Collective

1230:   Input Parameter:
1231: + dm - The DMMesh object
1232: - columnMajor - Flag for column major order

1234:   Output Parameter:
1235: + numVertices - The number of vertices
1236: . dim - The embedding dimension
1237: - coords - The array holding local coordinates

1239:   Level: intermediate

1241: .keywords: mesh, coordinates
1242: .seealso: DMMeshCreate()
1243: @*/
1244: PetscErrorCode DMMeshGetCoordinates(DM dm, PetscBool  columnMajor, PetscInt *numVertices, PetscInt *dim, PetscReal *coords[])
1245: {
1246:   ALE::Obj<PETSC_MESH_TYPE> m;
1247:   PetscErrorCode      ierr;

1250:   DMMeshGetMesh(dm, m);
1251:   ALE::PCICE::Builder::outputVerticesLocal(m, numVertices, dim, coords, columnMajor);
1252:   return(0);
1253: }

1257: /*@C
1258:   DMMeshGetElements - Creates an array holding the vertices on each element.

1260:   Not Collective

1262:   Input Parameters:
1263: + dm - The DMMesh object
1264: - columnMajor - Flag for column major order

1266:   Output Parameters:
1267: + numElements - The number of elements
1268: . numCorners - The number of vertices per element
1269: - vertices - The array holding vertices on each local element

1271:   Level: intermediate

1273: .keywords: mesh, elements
1274: .seealso: DMMeshCreate()
1275: @*/
1276: PetscErrorCode DMMeshGetElements(DM dm, PetscBool  columnMajor, PetscInt *numElements, PetscInt *numCorners, PetscInt *vertices[])
1277: {
1278:   ALE::Obj<PETSC_MESH_TYPE> m;
1279:   PetscErrorCode      ierr;

1282:   DMMeshGetMesh(dm, m);
1283:   ALE::PCICE::Builder::outputElementsLocal(m, numElements, numCorners, vertices, columnMajor);
1284:   return(0);
1285: }

1289: /*@C
1290:   DMMeshGetCone - Creates an array holding the cone of a given point

1292:   Not Collective

1294:   Input Parameters:
1295: + dm - The DMMesh object
1296: - p - The mesh point

1298:   Output Parameters:
1299: + numPoints - The number of points in the cone
1300: - points - The array holding the cone points

1302:   Level: intermediate

1304: .keywords: mesh, cone
1305: .seealso: DMMeshCreate()
1306: @*/
1307: PetscErrorCode DMMeshGetCone(DM dm, PetscInt p, PetscInt *numPoints, PetscInt *points[])
1308: {
1309:   ALE::Obj<PETSC_MESH_TYPE> m;
1310:   PetscErrorCode      ierr;

1313:   DMMeshGetMesh(dm, m);
1314:   *numPoints = m->getSieve()->getConeSize(p);
1315:   ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> v(*numPoints);

1317:   m->getSieve()->cone(p, v);
1318:   *points = const_cast<PetscInt*>(v.getPoints());
1319:   return(0);
1320: }

1324: /*@C
1325:   DMMeshDistribute - Distributes the mesh and any associated sections.

1327:   Not Collective

1329:   Input Parameter:
1330: + serialMesh  - The original DMMesh object
1331: - partitioner - The partitioning package, or NULL for the default

1333:   Output Parameter:
1334: . parallelMesh - The distributed DMMesh object

1336:   Level: intermediate

1338: .keywords: mesh, elements

1340: .seealso: DMMeshCreate(), DMMeshDistributeByFace()
1341: @*/
1342: PetscErrorCode DMMeshDistribute(DM serialMesh, const char partitioner[], DM *parallelMesh)
1343: {
1344:   ALE::Obj<PETSC_MESH_TYPE> oldMesh;
1345:   PetscMPIInt         commSize;
1346:   PetscErrorCode      ierr;

1349:   MPI_Comm_size(((PetscObject) serialMesh)->comm, &commSize);
1350:   if (commSize == 1) return(0);
1351:   DMMeshGetMesh(serialMesh, oldMesh);
1352:   DMMeshCreate(oldMesh->comm(), parallelMesh);
1353:   const Obj<PETSC_MESH_TYPE>             newMesh  = new PETSC_MESH_TYPE(oldMesh->comm(), oldMesh->getDimension(), oldMesh->debug());
1354:   const Obj<PETSC_MESH_TYPE::sieve_type> newSieve = new PETSC_MESH_TYPE::sieve_type(oldMesh->comm(), oldMesh->debug());

1356:   newMesh->setSieve(newSieve);
1357:   ALE::DistributionNew<PETSC_MESH_TYPE>::distributeMeshAndSectionsV(oldMesh, newMesh);
1358:   DMMeshSetMesh(*parallelMesh, newMesh);
1359:   return(0);
1360: }

1364: /*@C
1365:   DMMeshDistribute - Distributes the mesh and any associated sections.

1367:   Not Collective

1369:   Input Parameter:
1370: + serialMesh  - The original DMMesh object
1371: - partitioner - The partitioning package, or NULL for the default

1373:   Output Parameter:
1374: . parallelMesh - The distributed DMMesh object

1376:   Level: intermediate

1378: .keywords: mesh, elements

1380: .seealso: DMMeshCreate(), DMMeshDistribute()
1381: @*/
1382: PetscErrorCode DMMeshDistributeByFace(DM serialMesh, const char partitioner[], DM *parallelMesh)
1383: {
1384:   ALE::Obj<PETSC_MESH_TYPE> oldMesh;
1385:   PetscErrorCode      ierr;

1388:   DMMeshGetMesh(serialMesh, oldMesh);
1389:   DMMeshCreate(oldMesh->comm(), parallelMesh);
1390:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "I am being lazy, bug me.");
1391: #if 0
1392:   ALE::DistributionNew<PETSC_MESH_TYPE>::distributeMeshAndSectionsV(oldMesh, newMesh, height = 1);
1393: #endif
1394:   return(0);
1395: }

1399: /*@C
1400:   DMMeshGenerate - Generates a mesh.

1402:   Not Collective

1404:   Input Parameters:
1405: + boundary - The DMMesh boundary object
1406: - interpolate - Flag to create intermediate mesh elements

1408:   Output Parameter:
1409: . mesh - The DMMesh object

1411:   Level: intermediate

1413: .keywords: mesh, elements
1414: .seealso: DMMeshCreate(), DMMeshRefine()
1415: @*/
1416: PetscErrorCode DMMeshGenerate(DM boundary, PetscBool  interpolate, DM *mesh)
1417: {
1418:   ALE::Obj<PETSC_MESH_TYPE> mB;
1419:   PetscErrorCode      ierr;

1422:   DMMeshGetMesh(boundary, mB);
1423:   DMMeshCreate(mB->comm(), mesh);
1424:   ALE::Obj<PETSC_MESH_TYPE> m = ALE::Generator<PETSC_MESH_TYPE>::generateMeshV(mB, interpolate);
1425:   DMMeshSetMesh(*mesh, m);
1426:   return(0);
1427: }

1431: /*@C
1432:   DMMeshRefine - Refines the mesh.

1434:   Not Collective

1436:   Input Parameters:
1437: + mesh - The original DMMesh object
1438: . refinementLimit - The maximum size of any cell
1439: - interpolate - Flag to create intermediate mesh elements

1441:   Output Parameter:
1442: . refinedMesh - The refined DMMesh object

1444:   Level: intermediate

1446: .keywords: mesh, elements
1447: .seealso: DMMeshCreate(), DMMeshGenerate()
1448: @*/
1449: PetscErrorCode DMMeshRefine(DM mesh, double refinementLimit, PetscBool  interpolate, DM *refinedMesh)
1450: {
1451:   ALE::Obj<PETSC_MESH_TYPE> oldMesh;

1455:   if (refinementLimit == 0.0) return(0);
1456:   DMMeshGetMesh(mesh, oldMesh);
1457:   DMMeshCreate(oldMesh->comm(), refinedMesh);
1458:   ALE::Obj<PETSC_MESH_TYPE> newMesh = ALE::Generator<PETSC_MESH_TYPE>::refineMeshV(oldMesh, refinementLimit, interpolate);
1459:   DMMeshSetMesh(*refinedMesh, newMesh);
1460:   return(0);
1461: }

1465: PetscErrorCode DMRefine_Mesh(DM dm, MPI_Comm comm, DM *dmRefined)
1466: {
1467:   ALE::Obj<PETSC_MESH_TYPE> oldMesh;
1468:   double                    refinementLimit;
1469:   PetscErrorCode            ierr;

1472:   DMMeshGetMesh(dm, oldMesh);
1473:   DMMeshCreate(comm, dmRefined);
1474:   refinementLimit = oldMesh->getMaxVolume()/2.0;
1475:   ALE::Obj<PETSC_MESH_TYPE> newMesh = ALE::Generator<PETSC_MESH_TYPE>::refineMeshV(oldMesh, refinementLimit, true);
1476:   DMMeshSetMesh(*dmRefined, newMesh);
1477:   return(0);
1478: }

1482: PetscErrorCode DMCoarsenHierarchy_Mesh(DM mesh, int numLevels, DM *coarseHierarchy)
1483: {
1484:   PetscReal      cfactor = 1.5;

1488:   PetscOptionsReal("-dmmg_coarsen_factor", "The coarsening factor", PETSC_NULL, cfactor, &cfactor, PETSC_NULL);
1489:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Peter needs to incorporate his code.");
1490:   return(0);
1491: }

1495: PetscErrorCode DMGetInterpolation_Mesh(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) {
1496:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Peter needs to incorporate his code.");
1497: }

1501: PetscErrorCode DMMeshMarkBoundaryCells(DM dm, const char labelName[], PetscInt marker, PetscInt newMarker) {
1502:   ALE::Obj<PETSC_MESH_TYPE> mesh;

1506:   DMMeshGetMesh(dm, mesh);
1507:   mesh->markBoundaryCells(labelName, marker, newMarker);
1508:   return(0);
1509: }

1513: PetscErrorCode DMMeshGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) {
1514:   ALE::Obj<PETSC_MESH_TYPE> mesh;

1518:   DMMeshGetMesh(dm, mesh);
1519:   {
1520:     if (stratumValue < 0) {
1521:       if (start) *start = mesh->getSieve()->getChart().min();
1522:       if (end)   *end   = mesh->getSieve()->getChart().max();
1523:     } else {
1524:       const Obj<PETSC_MESH_TYPE::label_sequence>& stratum = mesh->depthStratum(stratumValue);
1525:       if (start) *start = *stratum->begin();
1526:       if (end)   *end   = *stratum->rbegin()+1;
1527:     }
1528:   }
1529:   return(0);
1530: }

1534: PetscErrorCode DMMeshGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) {
1535:   ALE::Obj<PETSC_MESH_TYPE> mesh;

1539:   DMMeshGetMesh(dm, mesh);
1540:   {
1541:     const Obj<PETSC_MESH_TYPE::label_sequence>& stratum = mesh->heightStratum(stratumValue);
1542:     if (start) *start = *stratum->begin();
1543:     if (end)   *end   = *stratum->rbegin()+1;
1544:   }
1545:   return(0);
1546: }

1550: PetscErrorCode DMMeshCreateSection(DM dm, PetscInt dim, PetscInt numDof[], const char bcName[], PetscInt bcValue, PetscSection *section) {
1551:   ALE::Obj<PETSC_MESH_TYPE> mesh;
1552:   PetscInt       pStart = 0, pEnd = 0, maxConstraints = 0;

1556:   PetscSectionCreate(((PetscObject) dm)->comm, section);
1557:   DMMeshGetDepthStratum(dm, -1, &pStart, &pEnd);
1558:   PetscSectionSetChart(*section, pStart, pEnd);
1559:   for(PetscInt d = 0; d <= dim; ++d) {
1560:     DMMeshGetDepthStratum(dm, d, &pStart, &pEnd);
1561:     for(PetscInt p = pStart; p < pEnd; ++p) {
1562:       PetscSectionSetDof(*section, p, numDof[d]);
1563:     }
1564:   }
1565:   DMMeshGetMesh(dm, mesh);
1566:   if (bcName) {
1567:     const Obj<PETSC_MESH_TYPE::label_sequence>& boundary = mesh->getLabelStratum(bcName, bcValue);

1569:     for(PETSC_MESH_TYPE::label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
1570:       const int n = numDof[mesh->depth(*e_iter)];

1572:       maxConstraints = PetscMax(maxConstraints, n);
1573:       PetscSectionSetConstraintDof(*section, *e_iter, n);
1574:     }
1575:   }
1576:   PetscSectionSetUp(*section);
1577:   if (maxConstraints) {
1578:     PetscInt *indices;

1580:     PetscMalloc(maxConstraints * sizeof(PetscInt), &indices);
1581:     PetscSectionGetChart(*section, &pStart, &pEnd);
1582:     for(PetscInt p = pStart; p < pEnd; ++p) {
1583:       PetscInt cDof;

1585:       PetscSectionGetConstraintDof(*section, p, &cDof);
1586:       if (cDof) {
1587:         if (cDof > maxConstraints) {SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, poitn %d cDof %d > maxConstraints %d", p, cDof, maxConstraints);}
1588:         for(PetscInt d = 0; d < cDof; ++d) {
1589:           indices[d] = d;
1590:         }
1591:         PetscSectionSetConstraintIndices(*section, p, indices);
1592:       }
1593:     }
1594:     PetscFree(indices);
1595:   }
1596:   return(0);
1597: }

1601: PetscErrorCode DMMeshGetSection(DM dm, const char name[], PetscSection *section) {
1602:   ALE::Obj<PETSC_MESH_TYPE> mesh;

1606:   DMMeshGetMesh(dm, mesh);
1607:   {
1608:     const Obj<PETSC_MESH_TYPE::real_section_type>& s = mesh->getRealSection(name);
1609:     const PetscInt pStart = s->getChart().min();
1610:     const PetscInt pEnd   = s->getChart().max();

1612:     PetscSectionCreate(((PetscObject) dm)->comm, section);
1613:     PetscSectionSetChart(*section, pStart, pEnd);
1614:     for(PetscInt p = pStart; p < pEnd; ++p) {
1615:       PetscSectionSetDof(*section, p, s->getFiberDimension(p));
1616:       PetscSectionSetConstraintDof(*section, p, s->getConstraintDimension(p));
1617:     }
1618:     PetscSectionSetUp(*section);
1619:     for(PetscInt p = pStart; p < pEnd; ++p) {
1620:       PetscSectionSetConstraintIndices(*section, p, (PetscInt *) s->getConstraintDof(p));
1621:     }
1622:   }
1623:   return(0);
1624: }

1628: PetscErrorCode DMMeshSetSection(DM dm, const char name[], PetscSection section) {
1629:   ALE::Obj<PETSC_MESH_TYPE> mesh;

1633:   DMMeshGetMesh(dm, mesh);
1634:   {
1635:     const Obj<PETSC_MESH_TYPE::real_section_type>& s = mesh->getRealSection(name);
1636:     PetscInt pStart, pEnd;

1638:     PetscSectionGetChart(section, &pStart, &pEnd);
1639:     s->setChart(PETSC_MESH_TYPE::real_section_type::chart_type(pStart, pEnd));
1640:     for(PetscInt p = pStart; p < pEnd; ++p) {
1641:       PetscInt fDim, cDim;

1643:       PetscSectionGetDof(section, p, &fDim);
1644:       s->setFiberDimension(p, fDim);
1645:       PetscSectionGetConstraintDof(section, p, &cDim);
1646:       if (cDim) {s->setConstraintDimension(p, cDim);}
1647:     }
1648:     s->allocatePoint();
1649:     for(PetscInt p = pStart; p < pEnd; ++p) {
1650:       PetscInt *indices;

1652:       PetscSectionGetConstraintIndices(section, p, &indices);
1653:       s->setConstraintDof(p, indices);
1654:     }
1655:     {
1656:       PetscBool isDefault;

1658:       PetscStrcmp(name, "default", &isDefault);
1659:       if (isDefault) {
1660:         PetscInt maxDof = 0;

1662:         for(PetscInt p = pStart; p < pEnd; ++p) {
1663:           PetscInt fDim;

1665:           PetscSectionGetDof(section, p, &fDim);
1666:           maxDof = PetscMax(maxDof, fDim);
1667:         }
1668:         mesh->setMaxDof(maxDof);
1669:       }
1670:     }
1671:   }
1672:   return(0);
1673: }

1677: PetscErrorCode DMMeshGetDefaultSection(DM dm, PetscSection *section) {

1681:   DMMeshGetSection(dm, "default", section);
1682:   return(0);
1683: }

1687: PetscErrorCode DMMeshGetCoordinateSection(DM dm, PetscSection *section) {

1691:   DMMeshGetSection(dm, "coordinates", section);
1692:   return(0);
1693: }

1697: PetscErrorCode DMMeshGetCoordinateVec(DM dm, Vec *coordinates) {
1698:   ALE::Obj<PETSC_MESH_TYPE> mesh;

1702:   DMMeshGetMesh(dm, mesh);
1703:   {
1704:     const Obj<PETSC_MESH_TYPE::real_section_type>& coords = mesh->getRealSection("coordinates");
1705:     VecCreateSeqWithArray(PETSC_COMM_SELF, coords->getStorageSize(), coords->restrictSpace(), coordinates);
1706:   }
1707:   return(0);
1708: }

1712: PetscErrorCode DMMeshComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) {
1713:   ALE::Obj<PETSC_MESH_TYPE> mesh;

1717:   DMMeshGetMesh(dm, mesh);
1718:   {
1719:     ALE::Obj<PETSC_MESH_TYPE::real_section_type> coordinates = mesh->getRealSection("coordinates");

1721:     mesh->computeElementGeometry(coordinates, cell, v0, J, invJ, *detJ);
1722:   }
1723:   return(0);
1724: }

1728: PetscErrorCode DMMeshVecGetClosure(DM dm, Vec v, PetscInt point, const PetscScalar *values[]) {
1729:   ALE::Obj<PETSC_MESH_TYPE> mesh;

1733: #ifdef PETSC_USE_COMPLEX
1734:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "DMMesh does not support complex closure");
1735: #else
1736:   DMMeshGetMesh(dm, mesh);
1737:   /* Peeling back IMesh::restrictClosure() */
1738:   try {
1739:     ALE::Obj<PETSC_MESH_TYPE::real_section_type> s = mesh->getRealSection("default");
1740:     const PETSC_MESH_TYPE::real_section_type::value_type *oldStorage = s->restrictSpace();
1741:     const PetscInt size = mesh->sizeWithBC(s, point);
1742:     ALE::ISieveVisitor::RestrictVisitor<PETSC_MESH_TYPE::real_section_type> rV(*s, size, s->getRawArray(size));
1743:     PetscScalar *array;

1745:     VecGetArray(v, &array);
1746:     s->setStorage(array);
1747:     if (mesh->depth() == 1) {
1748:       rV.visitPoint(point, 0);
1749:       // Cone is guarateed to be ordered correctly
1750:       mesh->getSieve()->orientedCone(point, rV);
1751:     } else {
1752:       ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type,ALE::ISieveVisitor::RestrictVisitor<PETSC_MESH_TYPE::real_section_type> > pV((int) pow((double) mesh->getSieve()->getMaxConeSize(), mesh->depth())+1, rV, true);

1754:       ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*mesh->getSieve(), point, pV);
1755:     }
1756:     s->setStorage((PETSC_MESH_TYPE::real_section_type::value_type *) oldStorage);
1757:     VecRestoreArray(v, &array);
1758:     *values = rV.getValues();
1759:   } catch(ALE::Exception e) {
1760:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid argument: %s", e.message());
1761:   }
1762: #endif
1763:   return(0);
1764: }

1768: PetscErrorCode DMMeshVecSetClosure(DM dm, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) {
1769:   ALE::Obj<PETSC_MESH_TYPE> mesh;

1773: #ifdef PETSC_USE_COMPLEX
1774:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "DMMesh does not support complex closure");
1775: #else
1776:   DMMeshGetMesh(dm, mesh);
1777:   /* Peeling back IMesh::update() and IMesh::updateAdd() */
1778:   try {
1779:     ALE::Obj<PETSC_MESH_TYPE::real_section_type> s = mesh->getRealSection("default");
1780:     const PETSC_MESH_TYPE::real_section_type::value_type *oldStorage = s->restrictSpace();
1781:     PetscScalar *array;

1783:     VecGetArray(v, &array);
1784:     s->setStorage(array);

1786:     if (mode == INSERT_VALUES) {
1787:       ALE::ISieveVisitor::UpdateVisitor<PETSC_MESH_TYPE::real_section_type> uV(*s, values);
1788:       if (mesh->depth() == 1) {
1789:         uV.visitPoint(point, 0);
1790:         // Cone is guarateed to be ordered correctly
1791:         mesh->getSieve()->orientedCone(point, uV);
1792:       } else {
1793:         ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type,ALE::ISieveVisitor::UpdateVisitor<PETSC_MESH_TYPE::real_section_type> > pV((int) pow((double) mesh->getSieve()->getMaxConeSize(), mesh->depth())+1, uV, true);

1795:         ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*mesh->getSieve(), point, pV);
1796:       }
1797:     } else {
1798:       ALE::ISieveVisitor::UpdateAddVisitor<PETSC_MESH_TYPE::real_section_type> uV(*s, values);
1799:       if (mesh->depth() == 1) {
1800:         uV.visitPoint(point, 0);
1801:         // Cone is guarateed to be ordered correctly
1802:         mesh->getSieve()->orientedCone(point, uV);
1803:       } else {
1804:         ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type,ALE::ISieveVisitor::UpdateAddVisitor<PETSC_MESH_TYPE::real_section_type> > pV((int) pow((double) mesh->getSieve()->getMaxConeSize(), mesh->depth())+1, uV, true);

1806:         ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*mesh->getSieve(), point, pV);
1807:       }
1808:     }

1810:     s->setStorage((PETSC_MESH_TYPE::real_section_type::value_type *) oldStorage);
1811:     VecRestoreArray(v, &array);
1812:   } catch(ALE::Exception e) {
1813:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid argument: %s", e.message());
1814:   }
1815: #endif
1816:   return(0);
1817: }

1821: PetscErrorCode DMMeshMatSetClosure(DM dm, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) {
1822:   ALE::Obj<PETSC_MESH_TYPE> mesh;

1826: #ifdef PETSC_USE_COMPLEX
1827:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "DMMesh does not support complex closure");
1828: #else
1829:   DMMeshGetMesh(dm, mesh);
1830:   /* Copying from updateOperator() */
1831:   try {
1832:     ALE::Obj<PETSC_MESH_TYPE::real_section_type> s = mesh->getRealSection("default");
1833:     const ALE::Obj<PETSC_MESH_TYPE::order_type>& globalOrder = mesh->getFactory()->getGlobalOrder(mesh, s->getName(), s);
1834:     typedef ALE::ISieveVisitor::IndicesVisitor<PETSC_MESH_TYPE::real_section_type,PETSC_MESH_TYPE::order_type,PetscInt> visitor_type;
1835:     visitor_type iV(*s, *globalOrder, (int) pow((double) mesh->getSieve()->getMaxConeSize(), mesh->depth())*mesh->getMaxDof(), mesh->depth() > 1);

1837:     updateOperator(A, *mesh->getSieve(), iV, point, values, mode);
1838:   } catch(ALE::Exception e) {
1839:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid argument: %s", e.message());
1840:   }
1841: #endif
1842:   return(0);
1843: }

1847: /*@C
1848:   DMMeshHasSectionReal - Determines whether this mesh has a SectionReal with the given name.

1850:   Not Collective

1852:   Input Parameters:
1853: + mesh - The DMMesh object
1854: - name - The section name

1856:   Output Parameter:
1857: . flag - True if the SectionReal is present in the DMMesh

1859:   Level: intermediate

1861: .keywords: mesh, elements
1862: .seealso: DMMeshCreate()
1863: @*/
1864: PetscErrorCode DMMeshHasSectionReal(DM dm, const char name[], PetscBool  *flag)
1865: {
1866:   ALE::Obj<PETSC_MESH_TYPE> m;

1870:   DMMeshGetMesh(dm, m);
1871:   *flag = (PetscBool) m->hasRealSection(std::string(name));
1872:   return(0);
1873: }

1877: /*@C
1878:   DMMeshGetSectionReal - Returns a SectionReal of the given name from the DMMesh.

1880:   Collective on DMMesh

1882:   Input Parameters:
1883: + mesh - The DMMesh object
1884: - name - The section name

1886:   Output Parameter:
1887: . section - The SectionReal

1889:   Note: The section is a new object, and must be destroyed by the user

1891:   Level: intermediate

1893: .keywords: mesh, elements

1895: .seealso: DMMeshCreate(), SectionRealDestroy()
1896: @*/
1897: PetscErrorCode DMMeshGetSectionReal(DM dm, const char name[], SectionReal *section)
1898: {
1899:   ALE::Obj<PETSC_MESH_TYPE> m;
1900:   bool                      has;
1901:   PetscErrorCode            ierr;

1904:   DMMeshGetMesh(dm, m);
1905:   SectionRealCreate(m->comm(), section);
1906:   PetscObjectSetName((PetscObject) *section, name);
1907:   has  = m->hasRealSection(std::string(name));
1908:   SectionRealSetSection(*section, m->getRealSection(std::string(name)));
1909:   SectionRealSetBundle(*section, m);
1910:   if (!has) {
1911:     m->getRealSection(std::string(name))->setChart(m->getSieve()->getChart());
1912:   }
1913:   return(0);
1914: }

1918: /*@C
1919:   DMMeshSetSectionReal - Puts a SectionReal of the given name into the DMMesh.

1921:   Collective on DMMesh

1923:   Input Parameters:
1924: + mesh - The DMMesh object
1925: - section - The SectionReal

1927:   Note: This takes the section name from the PETSc object

1929:   Level: intermediate

1931: .keywords: mesh, elements
1932: .seealso: DMMeshCreate()
1933: @*/
1934: PetscErrorCode DMMeshSetSectionReal(DM dm, SectionReal section)
1935: {
1936:   ALE::Obj<PETSC_MESH_TYPE> m;
1937:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;
1938:   const char    *name;

1942:   DMMeshGetMesh(dm, m);
1943:   PetscObjectGetName((PetscObject) section, &name);
1944:   SectionRealGetSection(section, s);
1945:   m->setRealSection(std::string(name), s);
1946:   return(0);
1947: }

1951: /*@C
1952:   DMMeshHasSectionInt - Determines whether this mesh has a SectionInt with the given name.

1954:   Not Collective

1956:   Input Parameters:
1957: + mesh - The DMMesh object
1958: - name - The section name

1960:   Output Parameter:
1961: . flag - True if the SectionInt is present in the DMMesh

1963:   Level: intermediate

1965: .keywords: mesh, elements
1966: .seealso: DMMeshCreate()
1967: @*/
1968: PetscErrorCode DMMeshHasSectionInt(DM dm, const char name[], PetscBool  *flag)
1969: {
1970:   ALE::Obj<PETSC_MESH_TYPE> m;

1974:   DMMeshGetMesh(dm, m);
1975:   *flag = (PetscBool) m->hasIntSection(std::string(name));
1976:   return(0);
1977: }

1981: /*@C
1982:   DMMeshGetSectionInt - Returns a SectionInt of the given name from the DMMesh.

1984:   Collective on DMMesh

1986:   Input Parameters:
1987: + mesh - The DMMesh object
1988: - name - The section name

1990:   Output Parameter:
1991: . section - The SectionInt

1993:   Note: The section is a new object, and must be destroyed by the user

1995:   Level: intermediate

1997: .keywords: mesh, elements
1998: .seealso: DMMeshCreate()
1999: @*/
2000: PetscErrorCode DMMeshGetSectionInt(DM dm, const char name[], SectionInt *section)
2001: {
2002:   ALE::Obj<PETSC_MESH_TYPE> m;
2003:   bool                      has;
2004:   PetscErrorCode            ierr;

2007:   DMMeshGetMesh(dm, m);
2008:   SectionIntCreate(m->comm(), section);
2009:   PetscObjectSetName((PetscObject) *section, name);
2010:   has  = m->hasIntSection(std::string(name));
2011:   SectionIntSetSection(*section, m->getIntSection(std::string(name)));
2012:   SectionIntSetBundle(*section, m);
2013:   if (!has) {
2014:     m->getIntSection(std::string(name))->setChart(m->getSieve()->getChart());
2015:   }
2016:   return(0);
2017: }

2021: /*@C
2022:   DMMeshSetSectionInt - Puts a SectionInt of the given name into the DMMesh.

2024:   Collective on DMMesh

2026:   Input Parameters:
2027: + mesh - The DMMesh object
2028: - section - The SectionInt

2030:   Note: This takes the section name from the PETSc object

2032:   Level: intermediate

2034: .keywords: mesh, elements
2035: .seealso: DMMeshCreate()
2036: @*/
2037: PetscErrorCode DMMeshSetSectionInt(DM dm, SectionInt section)
2038: {
2039:   ALE::Obj<PETSC_MESH_TYPE> m;
2040:   ALE::Obj<PETSC_MESH_TYPE::int_section_type> s;
2041:   const char    *name;

2045:   DMMeshGetMesh(dm, m);
2046:   PetscObjectGetName((PetscObject) section, &name);
2047:   SectionIntGetSection(section, s);
2048:   m->setIntSection(std::string(name), s);
2049:   return(0);
2050: }

2054: /*@C
2055:   SectionGetArray - Returns the array underlying the Section.

2057:   Not Collective

2059:   Input Parameters:
2060: + mesh - The DMMesh object
2061: - name - The section name

2063:   Output Parameters:
2064: + numElements - The number of mesh element with values
2065: . fiberDim - The number of values per element
2066: - array - The array

2068:   Level: intermediate

2070: .keywords: mesh, elements
2071: .seealso: DMMeshCreate()
2072: @*/
2073: PetscErrorCode SectionGetArray(DM dm, const char name[], PetscInt *numElements, PetscInt *fiberDim, PetscScalar *array[])
2074: {
2075:   ALE::Obj<PETSC_MESH_TYPE> m;
2076:   PetscErrorCode      ierr;

2079:   DMMeshGetMesh(dm, m);
2080:   const Obj<PETSC_MESH_TYPE::real_section_type>& section = m->getRealSection(std::string(name));
2081:   if (section->size() == 0) {
2082:     *numElements = 0;
2083:     *fiberDim    = 0;
2084:     *array       = NULL;
2085:     return(0);
2086:   }
2087:   const PETSC_MESH_TYPE::real_section_type::chart_type& chart = section->getChart();
2088: /*   const int                                  depth   = m->depth(*chart.begin()); */
2089: /*   *numElements = m->depthStratum(depth)->size(); */
2090: /*   *fiberDim    = section->getFiberDimension(*chart.begin()); */
2091: /*   *array       = (PetscScalar *) m->restrict(section); */
2092:   int fiberDimMin = section->getFiberDimension(*chart.begin());
2093:   int numElem     = 0;

2095:   for(PETSC_MESH_TYPE::real_section_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
2096:     const int fiberDim = section->getFiberDimension(*c_iter);

2098:     if (fiberDim < fiberDimMin) fiberDimMin = fiberDim;
2099:   }
2100:   for(PETSC_MESH_TYPE::real_section_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
2101:     const int fiberDim = section->getFiberDimension(*c_iter);

2103:     numElem += fiberDim/fiberDimMin;
2104:   }
2105:   *numElements = numElem;
2106:   *fiberDim    = fiberDimMin;
2107:   *array       = (PetscScalar *) section->restrictSpace();
2108:   return(0);
2109: }

2113: inline void ExpandInterval(const ALE::Point& interval, int indices[], int& indx)
2114: {
2115:   const int end = interval.prefix + interval.index;
2116:   for(int i = interval.index; i < end; i++) {
2117:     indices[indx++] = i;
2118:   }
2119: }

2123: inline void ExpandInterval_New(ALE::Point interval, PetscInt indices[], PetscInt *indx)
2124: {
2125:   for(int i = 0; i < interval.prefix; i++) {
2126:     indices[(*indx)++] = interval.index + i;
2127:   }
2128:   for(int i = 0; i < -interval.prefix; i++) {
2129:     indices[(*indx)++] = -1;
2130:   }
2131: }


2134: /******************************** FEM Support **********************************/

2138: PetscErrorCode DMMeshPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) {

2142:   PetscPrintf(PETSC_COMM_SELF, "Cell %d Element %s\n", c, name);
2143:   for(PetscInt f = 0; f < len; ++f) {
2144:     PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", x[f]);
2145:   }
2146:   return(0);
2147: }

2151: PetscErrorCode DMMeshPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) {

2155:   PetscPrintf(PETSC_COMM_SELF, "Cell %d Element %s\n", c, name);
2156:   for(int f = 0; f < rows; ++f) {
2157:     PetscPrintf(PETSC_COMM_SELF, "  |");
2158:     for(int g = 0; g < cols; ++g) {
2159:       PetscPrintf(PETSC_COMM_SELF, " %g", A[f*cols+g]);
2160:     }
2161:     PetscPrintf(PETSC_COMM_SELF, " |\n");
2162:   }
2163:   return(0);
2164: }