Actual source code: mesh.c

petsc-3.4.5 2014-06-29
  1: #include <petsc-private/meshimpl.h>   /*I      "petscdmmesh.h"   I*/
  2: #include <petscdmmesh_viewers.hh>
  3: #include <petscdmmesh_formats.hh>
  4: #include <petscsf.h>

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

  9: ALE::MemoryLogger Petsc_MemoryLogger;

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

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

 19:    Note: this is declared extern "C" because it is passed to MPI_Keyval_create

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

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

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

 44:   Not collective

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

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

 52:   Level: advanced

 54: .seealso DMMeshCreate(), DMMeshSetMesh()
 55: @*/
 56: PetscErrorCode DMMeshGetMesh(DM dm, ALE::Obj<PETSC_MESH_TYPE>& m)
 57: {
 58:   DM_Mesh *mesh = (DM_Mesh*) dm->data;

 62:   if (mesh->useNewImpl) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This method is only valid for C++ implementation meshes.");
 63:   m = mesh->m;
 64:   return(0);
 65: }

 69: /*@C
 70:   DMMeshSetMesh - Sets the internal mesh object

 72:   Not collective

 74:   Input Parameters:
 75: + mesh - the mesh object
 76: - m - the internal mesh object

 78:   Level: advanced

 80: .seealso DMMeshCreate(), DMMeshGetMesh()
 81: @*/
 82: PetscErrorCode DMMeshSetMesh(DM dm, const ALE::Obj<PETSC_MESH_TYPE>& m)
 83: {
 84:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

 89:   mesh->m = m;
 90:   VecScatterDestroy(&mesh->globalScatter);
 91:   return(0);
 92: }

 96: PetscErrorCode DMMeshView_Sieve_Ascii(const ALE::Obj<PETSC_MESH_TYPE>& mesh, PetscViewer viewer)
 97: {
 98:   PetscViewerFormat format;
 99:   PetscErrorCode    ierr;

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

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

127:     PetscViewerFileGetName(viewer, (const char **) &filename);
128:     PetscStrlen(filename, &len);
129:     PetscStrcmp(&(filename[len-5]), ".lcon", &isConnect);
130:     if (!isConnect) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Invalid element connectivity filename: %s", filename);

132:     ALE::PCICE::Viewer::writeElements(mesh, viewer);
133:     PetscStrncpy(coordFilename, filename, len-5);

135:     coordFilename[len-5] = '\0';

137:     PetscStrcat(coordFilename, ".nodes");
138:     PetscViewerFileSetName(viewer, coordFilename);
139:     ALE::PCICE::Viewer::writeVertices(mesh, viewer);
140:   } else if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
141:     mesh->view("Mesh");
142:   } else {
143:     PetscInt dim      = mesh->getDimension();
144:     PetscInt size     = mesh->commSize();
145:     PetscInt locDepth = mesh->depth(), depth;
146:     PetscInt num      = 0;
147:     PetscInt *sizes;

149:     PetscMalloc(size * sizeof(PetscInt), &sizes);
150:     PetscViewerASCIIPrintf(viewer, "Mesh in %d dimensions:\n", dim);
151:     MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, mesh->comm());
152:     if (depth == 1) {
153:       num  = mesh->depthStratum(0)->size();
154:       MPI_Gather(&num, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, mesh->comm());
155:       PetscViewerASCIIPrintf(viewer, "  %d-cells:", 0);
156:       for (PetscInt p = 0; p < size; ++p) {PetscViewerASCIIPrintf(viewer, " %d", sizes[p]);}
157:       PetscViewerASCIIPrintf(viewer, "\n");
158:       num  = mesh->heightStratum(0)->size();
159:       MPI_Gather(&num, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, mesh->comm());
160:       PetscViewerASCIIPrintf(viewer, "  %d-cells:", dim);
161:       for (PetscInt p = 0; p < size; ++p) {PetscViewerASCIIPrintf(viewer, " %d", sizes[p]);}
162:       PetscViewerASCIIPrintf(viewer, "\n");
163:     } else {
164:       for (int d = 0; d <= dim; d++) {
165:         num  = mesh->depthStratum(d)->size();
166:         MPI_Gather(&num, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, mesh->comm());
167:         PetscViewerASCIIPrintf(viewer, "  %d-cells:", d);
168:         for (PetscInt p = 0; p < size; ++p) {PetscViewerASCIIPrintf(viewer, " %d", sizes[p]);}
169:         PetscViewerASCIIPrintf(viewer, "\n");
170:       }
171:     }
172:     PetscFree(sizes);
173:   }
174:   PetscViewerFlush(viewer);
175:   return(0);
176: }


181: PetscErrorCode DMMeshView_Sieve_Binary(const ALE::Obj<PETSC_MESH_TYPE>& mesh, PetscViewer viewer)
182: {
183:   char           *filename;

187:   PetscViewerFileGetName(viewer, (const char**) &filename);
188:   ALE::MeshSerializer::writeMesh(filename, *mesh);
189:   return(0);
190: }

194: PetscErrorCode DMMeshView_Sieve(const ALE::Obj<PETSC_MESH_TYPE>& mesh, PetscViewer viewer)
195: {
196:   PetscBool      iascii, isbinary, isdraw;

200:   PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);
201:   PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);
202:   PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);

204:   if (iascii) {
205:     DMMeshView_Sieve_Ascii(mesh, viewer);
206:   } else if (isbinary) {
207:     DMMeshView_Sieve_Binary(mesh, viewer);
208:   } else if (isdraw) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Draw viewer not implemented for DMMesh");
209:   else SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Viewer type %s not supported by this mesh object", ((PetscObject)viewer)->type_name);
210:   return(0);
211: }

215: PetscErrorCode DMMeshView_Mesh_Ascii(DM dm, PetscViewer viewer)
216: {
217:   DM_Mesh           *mesh = (DM_Mesh*) dm->data;
218:   PetscViewerFormat format;
219:   PetscErrorCode    ierr;

222:   PetscViewerGetFormat(viewer, &format);
223:   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
224:     const char  *name;
225:     PetscInt    maxConeSize, maxSupportSize;
226:     PetscInt    pStart, pEnd, p;
227:     PetscMPIInt rank;

229:     MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);
230:     PetscObjectGetName((PetscObject) dm, &name);
231:     DMMeshGetChart(dm, &pStart, &pEnd);
232:     DMMeshGetMaxSizes(dm, &maxConeSize, &maxSupportSize);
233:     PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);
234:     PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);
235:     PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %d support: %d\n", maxConeSize, maxSupportSize);
236:     PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);
237:     PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);
238:     for (p = pStart; p < pEnd; ++p) {
239:       PetscInt dof, off, s;

241:       PetscSectionGetDof(mesh->supportSection, p, &dof);
242:       PetscSectionGetOffset(mesh->supportSection, p, &off);
243:       for (s = off; s < off+dof; ++s) {
244:         PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %d ----> %d\n", rank, p, mesh->supports[s]);
245:       }
246:     }
247:     PetscViewerFlush(viewer);
248:     PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);
249:     for (p = pStart; p < pEnd; ++p) {
250:       PetscInt dof, off, c;

252:       PetscSectionGetDof(mesh->coneSection, p, &dof);
253:       PetscSectionGetOffset(mesh->coneSection, p, &off);
254:       for (c = off; c < off+dof; ++c) {
255:         PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %d <---- %d\n", rank, p, mesh->cones[c]);
256:         /* PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %d <---- %d: %d\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]); */
257:       }
258:     }
259:     PetscViewerFlush(viewer);
260:     PetscSectionVecView(mesh->coordSection, mesh->coordinates, viewer);
261:   } else {
262:     MPI_Comm    comm;
263:     PetscInt    *sizes;
264:     PetscInt    depth, dim, d;
265:     PetscInt    pStart, pEnd, p;
266:     PetscMPIInt size;

268:     PetscObjectGetComm((PetscObject)dm,&comm);
269:     MPI_Comm_size(comm, &size);
270:     DMMeshGetDimension(dm, &dim);
271:     PetscViewerASCIIPrintf(viewer, "Mesh in %d dimensions:\n", dim);
272:     MPI_Allreduce(&depth, &depth, 1, MPIU_INT, MPI_MAX, comm);
273:     PetscMalloc(size * sizeof(PetscInt), &sizes);
274:     DMMeshGetLabelSize(dm, "depth", &depth);
275:     if (depth == 2) {
276:       DMMeshGetDepthStratum(dm, 0, &pStart, &pEnd);
277:       pEnd = pEnd - pStart;
278:       MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);
279:       PetscViewerASCIIPrintf(viewer, "  %d-cells:", 0);
280:       for (p = 0; p < size; ++p) {PetscViewerASCIIPrintf(viewer, " %d", sizes[p]);}
281:       PetscViewerASCIIPrintf(viewer, "\n");
282:       DMMeshGetHeightStratum(dm, 0, &pStart, &pEnd);
283:       pEnd = pEnd - pStart;
284:       MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);
285:       PetscViewerASCIIPrintf(viewer, "  %d-cells:", dim);
286:       for (p = 0; p < size; ++p) {PetscViewerASCIIPrintf(viewer, " %d", sizes[p]);}
287:       PetscViewerASCIIPrintf(viewer, "\n");
288:     } else {
289:       for (d = 0; d <= dim; d++) {
290:         DMMeshGetDepthStratum(dm, d, &pStart, &pEnd);
291:         pEnd = pEnd - pStart;
292:         MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);
293:         PetscViewerASCIIPrintf(viewer, "  %d-cells:", d);
294:         for (p = 0; p < size; ++p) {PetscViewerASCIIPrintf(viewer, " %d", sizes[p]);}
295:         PetscViewerASCIIPrintf(viewer, "\n");
296:       }
297:     }
298:     PetscFree(sizes);
299:   }
300:   return(0);
301: }

305: PetscErrorCode DMView_Mesh(DM dm, PetscViewer viewer)
306: {
307:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

313:   if (mesh->useNewImpl) {
314:     PetscBool iascii, isbinary;

316:     PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);
317:     PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);

319:     if (iascii) {
320:       DMMeshView_Mesh_Ascii(dm, viewer);
321: #if 0
322:     } else if (isbinary) {
323:       DMMeshView_Mesh_Binary(dm, viewer);
324: #endif
325:     } else {
326:       DMMeshView_Sieve(mesh->m, viewer);
327:     }
328:   }
329:   return(0);
330: }

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

337:   Collective on Viewer

339:   Input Parameter:
340: . viewer - The viewer containing the data

342:   Output Parameters:
343: . mesh - the mesh object

345:   Level: advanced

347: .seealso DMView()
348: @*/
349: PetscErrorCode DMMeshLoad(PetscViewer viewer, DM dm)
350: {
351:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;
352:   char           *filename;

356:   if (!mesh->m) {
357:     MPI_Comm comm;

359:     PetscObjectGetComm((PetscObject) viewer, &comm);
360:     ALE::Obj<PETSC_MESH_TYPE> m = new PETSC_MESH_TYPE(comm, 1);
361:     DMMeshSetMesh(dm, m);
362:   }
363:   PetscViewerFileGetName(viewer, (const char**) &filename);
364:   ALE::MeshSerializer::loadMesh(filename, *mesh->m);
365:   return(0);
366: }

370: PetscErrorCode GetAdjacentDof_Private()
371: {
373:   return(0);
374: }

378: PetscErrorCode DMCreateMatrix_Mesh(DM dm, MatType mtype, Mat *J)
379: {
380:   DM_Mesh                *mesh = (DM_Mesh*) dm->data;
381:   ISLocalToGlobalMapping ltog;
382:   PetscErrorCode         ierr;

385: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
386:   MatInitializePackage();
387: #endif
388:   if (!mtype) mtype = MATAIJ;
389:   if (mesh->useNewImpl) {
390:     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not supported");
391:   } else {
392:     ALE::Obj<PETSC_MESH_TYPE>                    m;
393:     ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;
394:     SectionReal                                  section;
395:     PetscBool                                    flag;
396:     DMMeshHasSectionReal(dm, "default", &flag);
397:     if (!flag) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Must set default section");
398:     DMMeshGetSectionReal(dm, "default", &section);
399:     DMMeshGetMesh(dm, m);
400:     SectionRealGetSection(section, s);
401:     try {
402:       DMMeshCreateMatrix(m, s, mtype, J, -1, !dm->prealloc_only);
403:     } catch(ALE::Exception e) {
404:       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, e.message());
405:     }
406:     SectionRealDestroy(&section);
407:   }
408:   MatSetDM(*J, dm);
409:   DMGetLocalToGlobalMapping(dm, &ltog);
410:   MatSetLocalToGlobalMapping(*J, ltog, ltog);
411:   return(0);
412: }

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

420:   Collective on DMMesh

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

428:   Output Parameter:
429: . J  - matrix with the correct nonzero preallocation
430:        (obviously without the correct Jacobian values)

432:   Level: advanced

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

437: .seealso ISColoringView(), ISColoringGetIS(), MatFDColoringCreate(), DMDASetBlockFills()
438: @*/
439: PetscErrorCode DMMeshCreateMatrix(DM dm, SectionReal section, MatType mtype, Mat *J)
440: {
441:   ALE::Obj<PETSC_MESH_TYPE>                    m;
442:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;
443:   PetscErrorCode                               ierr;

446: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
447:   MatInitializePackage();
448: #endif
449:   if (!mtype) mtype = MATAIJ;
450:   DMMeshGetMesh(dm, m);
451:   SectionRealGetSection(section, s);
452:   try {
453:     DMMeshCreateMatrix(m, s, mtype, J, -1, !dm->prealloc_only);
454:   } catch(ALE::Exception e) {
455:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB, e.message());
456:   }
457:   MatSetDM(*J, dm);
458:   return(0);
459: }

463: /*@
464:   DMMeshCreateVector - Creates a global vector matching the input section

466:   Collective on DMMesh

468:   Input Parameters:
469: + mesh - the DMMesh
470: - section - the Section

472:   Output Parameter:
473: . vec - the global vector

475:   Level: advanced

477:   Notes: The vector can safely be destroyed using VecDestroy().
478: .seealso DMMeshCreate()
479: @*/
480: PetscErrorCode DMMeshCreateVector(DM mesh, SectionReal section, Vec *vec)
481: {
482:   ALE::Obj<PETSC_MESH_TYPE>                    m;
483:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;
484:   PetscErrorCode                               ierr;

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

491:   VecCreate(m->comm(), vec);
492:   VecSetSizes(*vec, order->getLocalSize(), order->getGlobalSize());
493:   VecSetFromOptions(*vec);
494:   return(0);
495: }

499: PetscErrorCode DMDestroy_Mesh(DM dm)
500: {
501:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;
502:   SieveLabel     next  = mesh->labels;

506:   mesh->m = NULL;
507:   PetscSectionDestroy(&mesh->defaultSection);
508:   VecScatterDestroy(&mesh->globalScatter);

510:   /* NEW_MESH_IMPL */
511:   PetscSFDestroy(&mesh->sf);
512:   PetscSectionDestroy(&mesh->coneSection);
513:   PetscFree(mesh->cones);
514:   PetscSectionDestroy(&mesh->supportSection);
515:   PetscFree(mesh->supports);
516:   PetscSectionDestroy(&mesh->coordSection);
517:   VecDestroy(&mesh->coordinates);
518:   PetscFree2(mesh->meetTmpA,mesh->meetTmpB);
519:   PetscFree2(mesh->joinTmpA,mesh->joinTmpB);
520:   PetscFree2(mesh->closureTmpA,mesh->closureTmpB);
521:   while (next) {
522:     SieveLabel tmp;

524:     PetscFree(next->name);
525:     PetscFree(next->stratumValues);
526:     PetscFree(next->stratumOffsets);
527:     PetscFree(next->stratumSizes);
528:     PetscFree(next->points);
529:     tmp  = next->next;
530:     PetscFree(next);
531:     next = tmp;
532:   }
533:   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
534:   PetscFree(mesh);
535:   return(0);
536: }

540: PetscErrorCode DMCreateGlobalVector_Mesh(DM dm, Vec *gvec)
541: {
542:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;
543:   PetscInt       localSize, globalSize;

547:   if (mesh->useNewImpl) {
548:     PetscSection s;

550:     /* DOES NOT WORK IN PARALLEL, CHANGE TO DMPLEX */
551:     DMMeshGetDefaultSection(dm, &s);
552:     PetscSectionGetStorageSize(s, &localSize);
553:     globalSize = PETSC_DETERMINE;
554:   } else {
555:     ALE::Obj<PETSC_MESH_TYPE> m;
556:     PetscBool                 flag;
557:     DMMeshGetMesh(dm, m);
558:     DMMeshHasSectionReal(dm, "default", &flag);
559:     if (!flag) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Must set default section");
560:     const ALE::Obj<PETSC_MESH_TYPE::order_type>& order = m->getFactory()->getGlobalOrder(m, "default", m->getRealSection("default"));

562:     localSize  = order->getLocalSize();
563:     globalSize = order->getGlobalSize();
564:   }
565:   VecCreate(PetscObjectComm((PetscObject)dm), gvec);
566:   VecSetSizes(*gvec, localSize, globalSize);
567:   VecSetFromOptions(*gvec);
568:   VecSetDM(*gvec, dm);
569:   return(0);
570: }

574: PetscErrorCode DMCreateLocalVector_Mesh(DM dm, Vec *lvec)
575: {
576:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;
577:   PetscInt       size;

581:   if (mesh->useNewImpl) {
582:     PetscSection s;

584:     DMMeshGetDefaultSection(dm, &s);
585:     PetscSectionGetStorageSize(s, &size);
586:   } else {
587:     ALE::Obj<PETSC_MESH_TYPE> m;
588:     DMMeshGetMesh(dm, m);
589:     PetscBool flag;
590:     DMMeshGetMesh(dm, m);
591:     DMMeshHasSectionReal(dm, "default", &flag);
592:     if (!flag) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Must set default section");
593:     size = m->getRealSection("default")->getStorageSize();
594:   }
595:   VecCreate(PETSC_COMM_SELF, lvec);
596:   VecSetSizes(*lvec, size, size);
597:   VecSetFromOptions(*lvec);
598:   VecSetDM(*lvec, dm);
599:   return(0);
600: }

604: PetscErrorCode DMGetLocalToGlobalMapping_Mesh(DM dm)
605: {
606:   ALE::Obj<PETSC_MESH_TYPE>                    m;
607:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;
608:   SectionReal                                  section;
609:   PetscBool                                    flag;
610:   PetscErrorCode                               ierr;
611:   PetscInt                                     *ltog;

614:   DMMeshHasSectionReal(dm, "default", &flag);
615:   if (!flag) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Must set default section");
616:   DMMeshGetSectionReal(dm,"default", &section);
617:   DMMeshGetMesh(dm, m);
618:   SectionRealGetSection(section, s);
619:   const ALE::Obj<PETSC_MESH_TYPE::order_type>& globalOrder = m->getFactory()->getGlobalOrder(m, s->getName(), s);

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

625:     for (PetscInt c = 0; c < s->getConstrainedFiberDimension(p); ++c, ++l) {
626:       ltog[l] = g+c;
627:     }
628:   }
629:   ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, s->size(), ltog, PETSC_OWN_POINTER, &dm->ltogmap);
630:   PetscLogObjectParent(dm, dm->ltogmap);
631:   SectionRealDestroy(&section);
632:   return(0);
633: }

637: /*@
638:   DMMeshCreateGlobalScatter - Create a VecScatter which maps from local, overlapping
639:   storage in the Section to a global Vec

641:   Collective on DMMesh

643:   Input Parameters:
644: + mesh - the mesh object
645: - section - The Scetion which determines data layout

647:   Output Parameter:
648: . scatter - the VecScatter

650:   Level: advanced

652: .seealso DMDestroy(), DMMeshCreateGlobalRealVector(), DMMeshCreate()
653: @*/
654: PetscErrorCode DMMeshCreateGlobalScatter(DM dm, SectionReal section, VecScatter *scatter)
655: {
656:   ALE::Obj<PETSC_MESH_TYPE>                    m;
657:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;
658:   PetscErrorCode                               ierr;

661:   DMMeshGetMesh(dm, m);
662:   SectionRealGetSection(section, s);
663:   if (m->hasLabel("marker")) {
664:     DMMeshCreateGlobalScatter(m, s, m->getLabel("marker"), scatter);
665:   } else {
666:     DMMeshCreateGlobalScatter(m, s, scatter);
667:   }
668:   return(0);
669: }

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

676:   Collective on DMMesh

678:   Input Parameters:
679: . mesh - the mesh object

681:   Output Parameter:
682: . scatter - the VecScatter

684:   Level: advanced

686: .seealso MeshDestroy(), DMMeshCreateGlobalrealVector(), DMMeshCreate()
687: @*/
688: PetscErrorCode DMMeshGetGlobalScatter(DM dm, VecScatter *scatter)
689: {
690:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

696:   if (!mesh->globalScatter) {
697:     SectionReal section;

699:     DMMeshGetSectionReal(dm, "default", &section);
700:     DMMeshCreateGlobalScatter(dm, section, &mesh->globalScatter);
701:     SectionRealDestroy(&section);
702:   }
703:   *scatter = mesh->globalScatter;
704:   return(0);
705: }

709: PetscErrorCode  DMGlobalToLocalBegin_Mesh(DM dm, Vec g, InsertMode mode, Vec l)
710: {
711:   VecScatter     injection;

715:   DMMeshGetGlobalScatter(dm, &injection);
716:   VecScatterBegin(injection, g, l, mode, SCATTER_REVERSE);
717:   return(0);
718: }

722: PetscErrorCode  DMGlobalToLocalEnd_Mesh(DM dm, Vec g, InsertMode mode, Vec l)
723: {
724:   VecScatter     injection;

728:   DMMeshGetGlobalScatter(dm, &injection);
729:   VecScatterEnd(injection, g, l, mode, SCATTER_REVERSE);
730:   return(0);
731: }

735: PetscErrorCode  DMLocalToGlobalBegin_Mesh(DM dm, Vec l, InsertMode mode, Vec g)
736: {
737:   VecScatter     injection;

741:   DMMeshGetGlobalScatter(dm, &injection);
742:   VecScatterBegin(injection, l, g, mode, SCATTER_FORWARD);
743:   return(0);
744: }

748: PetscErrorCode  DMLocalToGlobalEnd_Mesh(DM dm, Vec l, InsertMode mode, Vec g)
749: {
750:   VecScatter     injection;

754:   DMMeshGetGlobalScatter(dm, &injection);
755:   VecScatterEnd(injection, l, g, mode, SCATTER_FORWARD);
756:   return(0);
757: }

761: PetscErrorCode DMMeshGetLocalFunction(DM dm, PetscErrorCode (**lf)(DM, Vec, Vec, void*))
762: {
763:   DM_Mesh *mesh = (DM_Mesh*) dm->data;

767:   if (lf) *lf = mesh->lf;
768:   return(0);
769: }

773: PetscErrorCode DMMeshSetLocalFunction(DM dm, PetscErrorCode (*lf)(DM, Vec, Vec, void*))
774: {
775:   DM_Mesh *mesh = (DM_Mesh*) dm->data;

779:   mesh->lf = lf;
780:   return(0);
781: }

785: PetscErrorCode DMMeshGetLocalJacobian(DM dm, PetscErrorCode (**lj)(DM, Vec, Mat, void*))
786: {
787:   DM_Mesh *mesh = (DM_Mesh*) dm->data;

791:   if (lj) *lj = mesh->lj;
792:   return(0);
793: }

797: PetscErrorCode DMMeshSetLocalJacobian(DM dm, PetscErrorCode (*lj)(DM, Vec, Mat, void*))
798: {
799:   DM_Mesh *mesh = (DM_Mesh*) dm->data;

803:   mesh->lj = lj;
804:   return(0);
805: }

809: /*@
810:   DMMeshGetDimension - Return the topological mesh dimension

812:   Not collective

814:   Input Parameter:
815: . mesh - The DMMesh

817:   Output Parameter:
818: . dim - The topological mesh dimension

820:   Level: beginner

822: .seealso: DMMeshCreate()
823: @*/
824: PetscErrorCode DMMeshGetDimension(DM dm, PetscInt *dim)
825: {
826:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

832:   if (mesh->useNewImpl) *dim = mesh->dim;
833:   else {
834:     Obj<PETSC_MESH_TYPE> m;
835:     DMMeshGetMesh(dm, m);
836:     *dim = m->getDimension();
837:   }
838:   return(0);
839: }

843: /*@
844:   DMMeshSetDimension - Set the topological mesh dimension

846:   Collective on mesh

848:   Input Parameters:
849: + mesh - The DMMesh
850: - dim - The topological mesh dimension

852:   Level: beginner

854: .seealso: DMMeshCreate()
855: @*/
856: PetscErrorCode DMMeshSetDimension(DM dm, PetscInt dim)
857: {
858:   DM_Mesh *mesh = (DM_Mesh*) dm->data;

863:   if (mesh->useNewImpl) mesh->dim = dim;
864:   else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot reset dimension of C++ mesh");
865:   return(0);
866: }

870: /*@
871:   DMMeshGetChart - Return the interval for all mesh points [pStart, pEnd)

873:   Not collective

875:   Input Parameter:
876: . mesh - The DMMesh

878:   Output Parameters:
879: + pStart - The first mesh point
880: - pEnd   - The upper bound for mesh points

882:   Level: beginner

884: .seealso: DMMeshCreate(), DMMeshSetChart()
885: @*/
886: PetscErrorCode DMMeshGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
887: {
888:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

893:   if (mesh->useNewImpl) {
894:     PetscSectionGetChart(mesh->coneSection, pStart, pEnd);
895:   } else {
896:     Obj<PETSC_MESH_TYPE> m;
897:     DMMeshGetMesh(dm, m);
898:     if (pStart) *pStart = m->getSieve()->getChart().min();
899:     if (pEnd)   *pEnd   = m->getSieve()->getChart().max();
900:   }
901:   return(0);
902: }

906: /*@
907:   DMMeshSetChart - Set the interval for all mesh points [pStart, pEnd)

909:   Not collective

911:   Input Parameters:
912: + mesh - The DMMesh
913: . pStart - The first mesh point
914: - pEnd   - The upper bound for mesh points

916:   Output Parameters:

918:   Level: beginner

920: .seealso: DMMeshCreate(), DMMeshGetChart()
921: @*/
922: PetscErrorCode DMMeshSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
923: {
924:   DM_Mesh       *mesh = (DM_Mesh*) dm->data;

929:   if (mesh->useNewImpl) {
930:     PetscSectionSetChart(mesh->coneSection, pStart, pEnd);
931:   } else {
932:     Obj<PETSC_MESH_TYPE> m;
933:     DMMeshGetMesh(dm, m);
934:     m->getSieve()->setChart(PETSC_MESH_TYPE::sieve_type::chart_type(pStart, pEnd));
935:   }
936:   return(0);
937: }

941: /*@
942:   DMMeshGetConeSize - Return the number of in-edges for this point in the Sieve DAG

944:   Not collective

946:   Input Parameters:
947: + mesh - The DMMesh
948: - p - The Sieve point, which must lie in the chart set with DMMeshSetChart()

950:   Output Parameter:
951: . size - The cone size for point p

953:   Level: beginner

955: .seealso: DMMeshCreate(), DMMeshSetConeSize(), DMMeshSetChart()
956: @*/
957: PetscErrorCode DMMeshGetConeSize(DM dm, PetscInt p, PetscInt *size)
958: {
959:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

965:   if (mesh->useNewImpl) {
966:     PetscSectionGetDof(mesh->coneSection, p, size);
967:   } else {
968:     Obj<PETSC_MESH_TYPE> m;
969:     DMMeshGetMesh(dm, m);
970:     *size = m->getSieve()->getConeSize(p);
971:   }
972:   return(0);
973: }

977: /*@
978:   DMMeshSetConeSize - Set the number of in-edges for this point in the Sieve DAG

980:   Not collective

982:   Input Parameters:
983: + mesh - The DMMesh
984: . p - The Sieve point, which must lie in the chart set with DMMeshSetChart()
985: - size - The cone size for point p

987:   Output Parameter:

989:   Note:
990:   This should be called after DMMeshSetChart().

992:   Level: beginner

994: .seealso: DMMeshCreate(), DMMeshGetConeSize(), DMMeshSetChart()
995: @*/
996: PetscErrorCode DMMeshSetConeSize(DM dm, PetscInt p, PetscInt size)
997: {
998:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1003:   if (mesh->useNewImpl) {
1004:     PetscSectionSetDof(mesh->coneSection, p, size);
1005:     mesh->maxConeSize = PetscMax(mesh->maxConeSize, size);
1006:   } else {
1007:     Obj<PETSC_MESH_TYPE> m;
1008:     DMMeshGetMesh(dm, m);
1009:     m->getSieve()->setConeSize(p, size);
1010:   }
1011:   return(0);
1012: }

1016: /*@C
1017:   DMMeshGetCone - Return the points on the in-edges for this point in the Sieve DAG

1019:   Not collective

1021:   Input Parameters:
1022: + mesh - The DMMesh
1023: - p - The Sieve point, which must lie in the chart set with DMMeshSetChart()

1025:   Output Parameter:
1026: . cone - An array of points which are on the in-edges for point p

1028:   Level: beginner

1030:   Note:
1031:   This routine is not available in Fortran.

1033: .seealso: DMMeshCreate(), DMMeshSetCone(), DMMeshSetChart()
1034: @*/
1035: PetscErrorCode DMMeshGetCone(DM dm, PetscInt p, const PetscInt *cone[])
1036: {
1037:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1043:   if (mesh->useNewImpl) {
1044:     PetscInt off;

1046:     PetscSectionGetOffset(mesh->coneSection, p, &off);
1047:     *cone = &mesh->cones[off];
1048:   } else {
1049:     Obj<PETSC_MESH_TYPE> m;
1050:     DMMeshGetMesh(dm, m);
1051:     ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> v(m->getSieve()->getConeSize(p));

1053:     m->getSieve()->cone(p, v);
1054:     if (!mesh->meetTmpA) {PetscMalloc2(m->getSieve()->getMaxConeSize(),PetscInt,&mesh->meetTmpA,m->getSieve()->getMaxConeSize(),PetscInt,&mesh->meetTmpB);}
1055:     for (size_t c = 0; c < v.getSize(); ++c) {
1056:       mesh->meetTmpA[c] = v.getPoints()[c];
1057:     }
1058:     *cone = mesh->meetTmpA;
1059:   }
1060:   return(0);
1061: }

1065: /*@
1066:   DMMeshSetCone - Set the points on the in-edges for this point in the Sieve DAG

1068:   Not collective

1070:   Input Parameters:
1071: + mesh - The DMMesh
1072: . p - The Sieve point, which must lie in the chart set with DMMeshSetChart()
1073: - cone - An array of points which are on the in-edges for point p

1075:   Output Parameter:

1077:   Note:
1078:   This should be called after all calls to DMMeshSetConeSize() and DMMeshSetUp().

1080:   Level: beginner

1082: .seealso: DMMeshCreate(), DMMeshGetCone(), DMMeshSetChart(), DMMeshSetConeSize(), DMMeshSetUp()
1083: @*/
1084: PetscErrorCode DMMeshSetCone(DM dm, PetscInt p, const PetscInt cone[])
1085: {
1086:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1092:   if (mesh->useNewImpl) {
1093:     PetscInt pStart, pEnd;
1094:     PetscInt dof, off, c;

1096:     PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);
1097:     PetscSectionGetDof(mesh->coneSection, p, &dof);
1098:     PetscSectionGetOffset(mesh->coneSection, p, &off);
1099:     for (c = 0; c < dof; ++c) {
1100:       if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %d is not in the valid range [%d. %d)", cone[c], pStart, pEnd);
1101:       mesh->cones[off+c] = cone[c];
1102:     }
1103:   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This method does not make sense for the C++ Sieve implementation");
1104:   return(0);
1105: }

1109: /*@
1110:   DMMeshGetSupportSize - Return the number of out-edges for this point in the Sieve DAG

1112:   Not collective

1114:   Input Parameters:
1115: + mesh - The DMMesh
1116: - p - The Sieve point, which must lie in the chart set with DMMeshSetChart()

1118:   Output Parameter:
1119: . size - The support size for point p

1121:   Level: beginner

1123: .seealso: DMMeshCreate(), DMMeshSetConeSize(), DMMeshSetChart(), DMMeshGetConeSize()
1124: @*/
1125: PetscErrorCode DMMeshGetSupportSize(DM dm, PetscInt p, PetscInt *size)
1126: {
1127:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1133:   if (mesh->useNewImpl) {
1134:     PetscSectionGetDof(mesh->supportSection, p, size);
1135:   } else {
1136:     Obj<PETSC_MESH_TYPE> m;
1137:     DMMeshGetMesh(dm, m);
1138:     *size = m->getSieve()->getSupportSize(p);
1139:   }
1140:   return(0);
1141: }

1145: /*@C
1146:   DMMeshGetSupport - Return the points on the out-edges for this point in the Sieve DAG

1148:   Not collective

1150:   Input Parameters:
1151: + mesh - The DMMesh
1152: - p - The Sieve point, which must lie in the chart set with DMMeshSetChart()

1154:   Output Parameter:
1155: . support - An array of points which are on the out-edges for point p

1157:   Level: beginner

1159: .seealso: DMMeshCreate(), DMMeshSetCone(), DMMeshSetChart(), DMMeshGetCone()
1160: @*/
1161: PetscErrorCode DMMeshGetSupport(DM dm, PetscInt p, const PetscInt *support[])
1162: {
1163:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1169:   if (mesh->useNewImpl) {
1170:     PetscInt off;

1172:     PetscSectionGetOffset(mesh->supportSection, p, &off);
1173:     *support = &mesh->supports[off];
1174:   } else {
1175:     Obj<PETSC_MESH_TYPE> m;
1176:     DMMeshGetMesh(dm, m);
1177:     ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> v(m->getSieve()->getSupportSize(p));

1179:     m->getSieve()->support(p, v);
1180:     if (!mesh->joinTmpA) {PetscMalloc2(m->getSieve()->getMaxSupportSize(),PetscInt,&mesh->joinTmpA,m->getSieve()->getMaxSupportSize(),PetscInt,&mesh->joinTmpB);}
1181:     for (size_t s = 0; s < v.getSize(); ++s) {
1182:       mesh->joinTmpA[s] = v.getPoints()[s];
1183:     }
1184:     *support = mesh->joinTmpA;
1185:   }
1186:   return(0);
1187: }

1191: /*@C
1192:   DMMeshGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG

1194:   Not collective

1196:   Input Parameters:
1197: + mesh - The DMMesh
1198: . p - The Sieve point, which must lie in the chart set with DMMeshSetChart()
1199: - useCone - PETSC_TRUE for in-edges,  otherwise use out-edges

1201:   Output Parameters:
1202: + numPoints - The number of points in the closure
1203: - points - The points

1205:   Level: beginner

1207: .seealso: DMMeshCreate(), DMMeshSetCone(), DMMeshSetChart(), DMMeshGetCone()
1208: @*/
1209: PetscErrorCode DMMeshGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, const PetscInt *points[])
1210: {
1211:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1216:   if (!mesh->closureTmpA) {
1217:     PetscInt maxSize;
1218:     if (mesh->useNewImpl) {
1219:       maxSize = PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1;
1220:     } else {
1221:       Obj<PETSC_MESH_TYPE> m;
1222:       DMMeshGetMesh(dm, m);
1223:       maxSize = PetscMax(m->getSieve()->getMaxConeSize(), m->getSieve()->getMaxSupportSize())+1;
1224:     }
1225:     PetscMalloc2(maxSize,PetscInt,&mesh->closureTmpA,maxSize,PetscInt,&mesh->closureTmpB);
1226:   }
1227:   if (mesh->useNewImpl) {
1228:     const PetscInt *tmp;
1229:     PetscInt       tmpSize, t;
1230:     PetscInt       closureSize = 1;

1232:     mesh->closureTmpA[0] = p;
1233:     /* This is only 1-level */
1234:     if (useCone) {
1235:       DMMeshGetConeSize(dm, p, &tmpSize);
1236:       DMMeshGetCone(dm, p, &tmp);
1237:     } else {
1238:       DMMeshGetSupportSize(dm, p, &tmpSize);
1239:       DMMeshGetSupport(dm, p, &tmp);
1240:     }
1241:     for (t = 0; t < tmpSize; ++t) {
1242:       mesh->closureTmpA[closureSize++] = tmp[t];
1243:     }
1244:     if (numPoints) *numPoints = closureSize;
1245:     if (points) *points = mesh->closureTmpA;
1246:   } else {
1247:     Obj<PETSC_MESH_TYPE> m;
1248:     DMMeshGetMesh(dm, m);
1249:     typedef ALE::ISieveVisitor::TransitiveClosureVisitor<PETSC_MESH_TYPE::sieve_type> visitor_type;
1250:     visitor_type::visitor_type nV;
1251:     visitor_type               cV(*m->getSieve(), nV);

1253:     if (useCone) {
1254:       m->getSieve()->cone(p, cV);
1255:     } else {
1256:       cV.setIsCone(false);
1257:       m->getSieve()->support(p, cV);
1258:     }
1259:     int i = 0;

1261:     for (std::set<PETSC_MESH_TYPE::point_type>::const_iterator p_iter = cV.getPoints().begin(); p_iter != cV.getPoints().end(); ++p_iter, ++i) {
1262:       mesh->closureTmpA[i] = *p_iter;
1263:     }
1264:     if (numPoints) *numPoints = cV.getPoints().size();
1265:     if (points) *points = mesh->closureTmpA;
1266:   }
1267:   return(0);
1268: }

1272: /*@
1273:   DMMeshGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG

1275:   Not collective

1277:   Input Parameter:
1278: . mesh - The DMMesh

1280:   Output Parameters:
1281: + maxConeSize - The maximum number of in-edges
1282: - maxSupportSize - The maximum number of out-edges

1284:   Level: beginner

1286: .seealso: DMMeshCreate(), DMMeshSetConeSize(), DMMeshSetChart()
1287: @*/
1288: PetscErrorCode DMMeshGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
1289: {
1290:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1295:   if (mesh->useNewImpl) {
1296:     if (maxConeSize)    *maxConeSize    = mesh->maxConeSize;
1297:     if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize;
1298:   } else {
1299:     Obj<PETSC_MESH_TYPE> m;
1300:     DMMeshGetMesh(dm, m);
1301:     if (maxConeSize)    *maxConeSize    = m->getSieve()->getMaxConeSize();
1302:     if (maxSupportSize) *maxSupportSize = m->getSieve()->getMaxSupportSize();
1303:   }
1304:   return(0);
1305: }

1309: /*@
1310:   DMMeshSetUp - Allocate space for the Sieve DAG

1312:   Not collective

1314:   Input Parameter:
1315: . mesh - The DMMesh

1317:   Output Parameter:

1319:   Note:
1320:   This should be called after DMMeshSetChart() and all calls to DMMeshSetConeSize()

1322:   Level: beginner

1324: .seealso: DMMeshCreate(), DMMeshSetChart(), DMMeshSetConeSize()
1325: @*/
1326: PetscErrorCode DMMeshSetUp(DM dm)
1327: {
1328:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1333:   if (mesh->useNewImpl) {
1334:     PetscInt size;

1336:     PetscSectionSetUp(mesh->coneSection);
1337:     PetscSectionGetStorageSize(mesh->coneSection, &size);
1338:     PetscMalloc(size * sizeof(PetscInt), &mesh->cones);
1339:   }
1340:   return(0);
1341: }

1345: /*@
1346:   DMMeshSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation

1348:   Not collective

1350:   Input Parameter:
1351: . mesh - The DMMesh

1353:   Output Parameter:

1355:   Note:
1356:   This should be called after all calls to DMMeshSetCone()

1358:   Level: beginner

1360: .seealso: DMMeshCreate(), DMMeshSetChart(), DMMeshSetConeSize(), DMMeshSetCone()
1361: @*/
1362: PetscErrorCode DMMeshSymmetrize(DM dm)
1363: {
1364:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1369:   if (mesh->useNewImpl) {
1370:     PetscInt *offsets;
1371:     PetscInt supportSize;
1372:     PetscInt pStart, pEnd, p;

1374:     /* Calculate support sizes */
1375:     DMMeshGetChart(dm, &pStart, &pEnd);
1376:     PetscSectionSetChart(mesh->supportSection, pStart, pEnd);
1377:     for (p = pStart; p < pEnd; ++p) {
1378:       PetscInt dof, off, c;

1380:       PetscSectionGetDof(mesh->coneSection, p, &dof);
1381:       PetscSectionGetOffset(mesh->coneSection, p, &off);
1382:       for (c = off; c < off+dof; ++c) {
1383:         PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);
1384:       }
1385:     }
1386:     for (p = pStart; p < pEnd; ++p) {
1387:       PetscInt dof;

1389:       PetscSectionGetDof(mesh->supportSection, p, &dof);

1391:       mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof);
1392:     }
1393:     PetscSectionSetUp(mesh->supportSection);
1394:     /* Calculate supports */
1395:     PetscSectionGetStorageSize(mesh->supportSection, &supportSize);
1396:     PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);
1397:     PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);
1398:     PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));
1399:     for (p = pStart; p < pEnd; ++p) {
1400:       PetscInt dof, off, c;

1402:       PetscSectionGetDof(mesh->coneSection, p, &dof);
1403:       PetscSectionGetOffset(mesh->coneSection, p, &off);
1404:       for (c = off; c < off+dof; ++c) {
1405:         const PetscInt q = mesh->cones[c];
1406:         PetscInt       offS;

1408:         PetscSectionGetOffset(mesh->supportSection, q, &offS);

1410:         mesh->supports[offS+offsets[q]] = p;
1411:         ++offsets[q];
1412:       }
1413:     }
1414:     PetscFree(offsets);
1415:   } else {
1416:     Obj<PETSC_MESH_TYPE> m;
1417:     DMMeshGetMesh(dm, m);
1418:     m->getSieve()->symmetrize();
1419:   }
1420:   return(0);
1421: }

1425: /*@
1426:   DMMeshStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and
1427:   can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
1428:   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
1429:   the DAG.

1431:   Not collective

1433:   Input Parameter:
1434: . mesh - The DMMesh

1436:   Output Parameter:

1438:   Notes:
1439:   The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would
1440:   have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1.

1442:   This should be called after all calls to DMMeshSymmetrize()

1444:   Level: beginner

1446: .seealso: DMMeshCreate(), DMMeshSymmetrize()
1447: @*/
1448: PetscErrorCode DMMeshStratify(DM dm)
1449: {
1450:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1455:   if (mesh->useNewImpl) {
1456:     PetscInt pStart, pEnd, p;
1457:     PetscInt numRoots = 0, numLeaves = 0;

1459:     /* Calculate depth */
1460:     PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);
1461:     /* Initialize roots and count leaves */
1462:     for (p = pStart; p < pEnd; ++p) {
1463:       PetscInt coneSize, supportSize;

1465:       PetscSectionGetDof(mesh->coneSection, p, &coneSize);
1466:       PetscSectionGetDof(mesh->supportSection, p, &supportSize);
1467:       if (!coneSize && supportSize) {
1468:         ++numRoots;
1469:         DMMeshSetLabelValue(dm, "depth", p, 0);
1470:       } else if (!supportSize && coneSize) {
1471:         ++numLeaves;
1472:       }
1473:     }
1474:     if (numRoots + numLeaves == (pEnd - pStart)) {
1475:       for (p = pStart; p < pEnd; ++p) {
1476:         PetscInt coneSize, supportSize;

1478:         PetscSectionGetDof(mesh->coneSection, p, &coneSize);
1479:         PetscSectionGetDof(mesh->supportSection, p, &supportSize);
1480:         if (!supportSize && coneSize) {
1481:           DMMeshSetLabelValue(dm, "depth", p, 1);
1482:         }
1483:       }
1484:     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Have not yet coded general stratification");
1485:   } else {
1486:     Obj<PETSC_MESH_TYPE> m;
1487:     DMMeshGetMesh(dm, m);
1488:     m->stratify();
1489:   }
1490:   return(0);
1491: }

1495: /*@C
1496:   DMMeshGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default

1498:   Not Collective

1500:   Input Parameters:
1501: + dm   - The DMMesh object
1502: . name - The label name
1503: - point - The mesh point

1505:   Output Parameter:
1506: . value - The label value for this point, or 0 if the point is not in the label

1508:   Level: beginner

1510: .keywords: mesh
1511: .seealso: DMMeshSetLabelValue(), DMMeshGetLabelStratum()
1512: @*/
1513: PetscErrorCode DMMeshGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
1514: {
1515:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1521:   if (mesh->useNewImpl) {
1522:     SieveLabel next = mesh->labels;
1523:     PetscBool  flg  = PETSC_FALSE;
1524:     PetscInt   v, p;

1526:     *value = 0;
1527:     while (next) {
1528:       PetscStrcmp(name, next->name, &flg);
1529:       if (flg) break;
1530:       next = next->next;
1531:     }
1532:     if (!flg) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
1533:     /* Find, or add, label value */
1534:     for (v = 0; v < next->numStrata; ++v) {
1535:       for (p = next->stratumOffsets[v]; p < next->stratumOffsets[v]+next->stratumSizes[v]; ++p) {
1536:         if (next->points[p] == point) {
1537:           *value = next->stratumValues[v];
1538:           break;
1539:         }
1540:       }
1541:     }
1542:   } else {
1543:     ALE::Obj<PETSC_MESH_TYPE> m;
1544:     DMMeshGetMesh(dm, m);
1545:     *value = m->getValue(m->getLabel(name), point);
1546:   }
1547:   return(0);
1548: }

1552: /*@C
1553:   DMMeshSetLabelValue - Add a point to a Sieve Label with given value

1555:   Not Collective

1557:   Input Parameters:
1558: + dm   - The DMMesh object
1559: . name - The label name
1560: . point - The mesh point
1561: - value - The label value for this point

1563:   Output Parameter:

1565:   Level: beginner

1567: .keywords: mesh
1568: .seealso: DMMeshGetLabelStratum()
1569: @*/
1570: PetscErrorCode DMMeshSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
1571: {
1572:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1578:   if (mesh->useNewImpl) {
1579:     SieveLabel next = mesh->labels;
1580:     PetscBool  flg  = PETSC_FALSE;
1581:     PetscInt   v, p;

1583:     /* Find, or create, label */
1584:     while (next) {
1585:       PetscStrcmp(name, next->name, &flg);
1586:       if (flg) break;
1587:       next = next->next;
1588:     }
1589:     if (!flg) {
1590:       SieveLabel tmpLabel = mesh->labels;
1591:       PetscNew(struct Sieve_Label, &mesh->labels);
1592:       mesh->labels->next = tmpLabel;
1593:       next               = mesh->labels;
1594:       PetscStrallocpy(name, &next->name);
1595:     }
1596:     /* Find, or add, label value */
1597:     for (v = 0; v < next->numStrata; ++v) {
1598:       if (next->stratumValues[v] == value) break;
1599:     }
1600:     if (v >= next->numStrata) {
1601:       PetscInt *tmpV, *tmpO, *tmpS;
1602:       PetscMalloc3(next->numStrata+1,PetscInt,&tmpV,next->numStrata+2,PetscInt,&tmpO,next->numStrata+1,PetscInt,&tmpS);
1603:       for (v = 0; v < next->numStrata; ++v) {
1604:         tmpV[v] = next->stratumValues[v];
1605:         tmpO[v] = next->stratumOffsets[v];
1606:         tmpS[v] = next->stratumSizes[v];
1607:       }
1608:       tmpV[v]   = value;
1609:       tmpO[v]   = v == 0 ? 0 : next->stratumOffsets[v];
1610:       tmpS[v]   = 0;
1611:       tmpO[v+1] = tmpO[v];
1612:       ++next->numStrata;
1613:       PetscFree3(next->stratumValues,next->stratumOffsets,next->stratumSizes);

1615:       next->stratumValues  = tmpV;
1616:       next->stratumOffsets = tmpO;
1617:       next->stratumSizes   = tmpS;
1618:     }
1619:     /* Check whether point exists */
1620:     for (p = next->stratumOffsets[v]; p < next->stratumOffsets[v]+next->stratumSizes[v]; ++p) {
1621:       if (next->points[p] == point) break;
1622:     }
1623:     /* Add point: NEED TO OPTIMIZE */
1624:     if (p >= next->stratumOffsets[v]+next->stratumSizes[v]) {
1625:       /* Check for reallocation */
1626:       if (next->stratumSizes[v] >= next->stratumOffsets[v+1]-next->stratumOffsets[v]) {
1627:         PetscInt oldSize   = next->stratumOffsets[v+1]-next->stratumOffsets[v];
1628:         PetscInt newSize   = PetscMax(10, 2*oldSize);  /* Double the size, since 2 is the optimal base for this online algorithm */
1629:         PetscInt shift     = newSize - oldSize;
1630:         PetscInt allocSize = next->stratumOffsets[next->numStrata] + shift;
1631:         PetscInt *newPoints;
1632:         PetscInt w, q;

1634:         PetscMalloc(allocSize * sizeof(PetscInt), &newPoints);
1635:         for (q = 0; q < next->stratumOffsets[v]+next->stratumSizes[v]; ++q) {
1636:           newPoints[q] = next->points[q];
1637:         }
1638:         for (w = v+1; w < next->numStrata; ++w) {
1639:           for (q = next->stratumOffsets[w]; q < next->stratumOffsets[w]+next->stratumSizes[w]; ++q) {
1640:             newPoints[q+shift] = next->points[q];
1641:           }
1642:           next->stratumOffsets[w] += shift;
1643:         }
1644:         next->stratumOffsets[next->numStrata] += shift;

1646:         PetscFree(next->points);

1648:         next->points = newPoints;
1649:       }
1650:       /* Insert point and resort */
1651:       next->points[next->stratumOffsets[v]+next->stratumSizes[v]] = point;
1652:       ++next->stratumSizes[v];
1653:       PetscSortInt(next->stratumSizes[v], &next->points[next->stratumOffsets[v]]);
1654:     }
1655:   } else {
1656:     ALE::Obj<PETSC_MESH_TYPE> m;
1657:     DMMeshGetMesh(dm, m);
1658:     m->setValue(m->getLabel(name), point, value);
1659:   }
1660:   return(0);
1661: }

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

1668:   Not Collective

1670:   Input Parameters:
1671: + dm   - The DMMesh object
1672: - name - The label name

1674:   Output Parameter:
1675: . size - The label size (number of different integer ids)

1677:   Level: beginner

1679: .keywords: mesh
1680: .seealso: DMMeshSetLabelValue()
1681: @*/
1682: PetscErrorCode DMMeshGetLabelSize(DM dm, const char name[], PetscInt *size)
1683: {
1684:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1691:   if (mesh->useNewImpl) {
1692:     SieveLabel next = mesh->labels;
1693:     PetscBool  flg;

1695:     *size = 0;
1696:     while (next) {
1697:       PetscStrcmp(name, next->name, &flg);
1698:       if (flg) {
1699:         *size = next->numStrata;
1700:         break;
1701:       }
1702:       next = next->next;
1703:     }
1704:   } else {
1705:     ALE::Obj<PETSC_MESH_TYPE> m;
1706:     DMMeshGetMesh(dm, m);
1707:     *size = m->getLabel(name)->getCapSize();
1708:   }
1709:   return(0);
1710: }

1714: /*@C
1715:   DMMeshGetLabelIdIS - Get the integer ids in a label

1717:   Not Collective

1719:   Input Parameters:
1720: + mesh - The DMMesh object
1721: - name - The label name

1723:   Output Parameter:
1724: . ids - The integer ids

1726:   Level: beginner

1728: .keywords: mesh
1729: .seealso: DMMeshGetLabelSize()
1730: @*/
1731: PetscErrorCode DMMeshGetLabelIdIS(DM dm, const char name[], IS *ids)
1732: {
1733:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;
1734:   PetscInt       *values;
1735:   PetscInt       size, i = 0;

1742:   if (mesh->useNewImpl) {
1743:     SieveLabel next = mesh->labels;
1744:     PetscBool  flg;

1746:     while (next) {
1747:       PetscStrcmp(name, next->name, &flg);
1748:       if (flg) {
1749:         size = next->numStrata;
1750:         PetscMalloc(size * sizeof(PetscInt), &values);
1751:         for (i = 0; i < next->numStrata; ++i) {
1752:           values[i] = next->stratumValues[i];
1753:         }
1754:         break;
1755:       }
1756:       next = next->next;
1757:     }
1758:   } else {
1759:     ALE::Obj<PETSC_MESH_TYPE> m;
1760:     DMMeshGetMesh(dm, m);
1761:     const ALE::Obj<PETSC_MESH_TYPE::label_type::capSequence>&      labelIds = m->getLabel(name)->cap();
1762:     const PETSC_MESH_TYPE::label_type::capSequence::const_iterator iEnd     = labelIds->end();

1764:     size = labelIds->size();
1765:     PetscMalloc(size * sizeof(PetscInt), &values);
1766:     for (PETSC_MESH_TYPE::label_type::capSequence::const_iterator i_iter = labelIds->begin(); i_iter != iEnd; ++i_iter, ++i) {
1767:       values[i] = *i_iter;
1768:     }
1769:   }
1770:   ISCreateGeneral(PetscObjectComm((PetscObject)dm), size, values, PETSC_OWN_POINTER, ids);
1771:   return(0);
1772: }

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

1779:   Not Collective

1781:   Input Parameters:
1782: + dm - The DMMesh object
1783: . name - The label name
1784: - value - The stratum value

1786:   Output Parameter:
1787: . size - The stratum size

1789:   Level: beginner

1791: .keywords: mesh
1792: .seealso: DMMeshGetLabelSize(), DMMeshGetLabelIds()
1793: @*/
1794: PetscErrorCode DMMeshGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
1795: {
1796:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1803:   if (mesh->useNewImpl) {
1804:     SieveLabel next = mesh->labels;
1805:     PetscBool  flg;

1807:     *size = 0;
1808:     while (next) {
1809:       PetscStrcmp(name, next->name, &flg);
1810:       if (flg) {
1811:         PetscInt v;

1813:         for (v = 0; v < next->numStrata; ++v) {
1814:           if (next->stratumValues[v] == value) {
1815:             *size = next->stratumSizes[v];
1816:             break;
1817:           }
1818:         }
1819:         break;
1820:       }
1821:       next = next->next;
1822:     }
1823:   } else {
1824:     ALE::Obj<PETSC_MESH_TYPE> m;
1825:     DMMeshGetMesh(dm, m);
1826:     *size = m->getLabelStratum(name, value)->size();
1827:   }
1828:   return(0);
1829: }

1833: /*@C
1834:   DMMeshGetStratumIS - Get the points in a label stratum

1836:   Not Collective

1838:   Input Parameters:
1839: + dm - The DMMesh object
1840: . name - The label name
1841: - value - The stratum value

1843:   Output Parameter:
1844: . is - The stratum points

1846:   Level: beginner

1848: .keywords: mesh
1849: .seealso: DMMeshGetStratumSize()
1850: @*/
1851: PetscErrorCode DMMeshGetStratumIS(DM dm, const char name[], PetscInt value, IS *is)
1852: {
1853:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1860:   *is = NULL;
1861:   if (mesh->useNewImpl) {
1862:     SieveLabel next = mesh->labels;
1863:     PetscBool  flg;

1865:     while (next) {
1866:       PetscStrcmp(name, next->name, &flg);
1867:       if (flg) {
1868:         PetscInt v;

1870:         for (v = 0; v < next->numStrata; ++v) {
1871:           if (next->stratumValues[v] == value) {
1872:             ISCreateGeneral(PETSC_COMM_SELF, next->stratumSizes[v], &next->points[next->stratumOffsets[v]], PETSC_COPY_VALUES, is);
1873:             break;
1874:           }
1875:         }
1876:         break;
1877:       }
1878:       next = next->next;
1879:     }
1880:   } else {
1881:     ALE::Obj<PETSC_MESH_TYPE> mesh;
1882:     DMMeshGetMesh(dm, mesh);
1883:     if (mesh->hasLabel(name)) {
1884:       const Obj<PETSC_MESH_TYPE::label_sequence>& stratum = mesh->getLabelStratum(name, value);
1885:       PetscInt                                    *idx, i = 0;

1887:       PetscMalloc(stratum->size() * sizeof(PetscInt), &idx);
1888:       for (PETSC_MESH_TYPE::label_sequence::iterator e_iter = stratum->begin(); e_iter != stratum->end(); ++e_iter, ++i) {
1889:         idx[i] = *e_iter;
1890:       }
1891:       ISCreateGeneral(PETSC_COMM_SELF, stratum->size(), idx, PETSC_OWN_POINTER, is);
1892:     }
1893:   }
1894:   return(0);
1895: }

1899: /* This is a 1-level join */
1900: PetscErrorCode DMMeshJoinPoints(DM dm, const PetscInt points[], PetscInt *coveredPoint)
1901: {
1902:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

1909:   if (mesh->useNewImpl) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not yet supported");
1910:   else {
1911:     ALE::Obj<PETSC_MESH_TYPE> m;
1912:     DMMeshGetMesh(dm, m);
1913:     /* const Obj<typename Mesh::sieve_type::supportSet> edge = m->getSieve()->nJoin(points[0], points[1], 1); */
1914:     *coveredPoint = -1;
1915:   }
1916:   return(0);
1917: }

1921: /* This is a 1-level meet */
1922: PetscErrorCode DMMeshMeetPoints(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
1923: {
1924:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;
1925:   PetscInt       *meet[2];
1926:   PetscInt       meetSize, i = 0;
1927:   PetscInt       dof, off, p, c, m;

1935:   if (mesh->useNewImpl) {
1936:     if (!mesh->meetTmpA) {PetscMalloc2(mesh->maxConeSize,PetscInt,&mesh->meetTmpA,mesh->maxConeSize,PetscInt,&mesh->meetTmpB);}
1937:     meet[0] = mesh->meetTmpA; meet[1] = mesh->meetTmpB;
1938:     /* Copy in cone of first point */
1939:     PetscSectionGetDof(mesh->coneSection, points[0], &dof);
1940:     PetscSectionGetOffset(mesh->coneSection, points[0], &off);
1941:     for (meetSize = 0; meetSize < dof; ++meetSize) {
1942:       meet[i][meetSize] = mesh->cones[off+meetSize];
1943:     }
1944:     /* Check each successive cone */
1945:     for (p = 1; p < numPoints; ++p) {
1946:       PetscInt newMeetSize = 0;

1948:       PetscSectionGetDof(mesh->coneSection, points[p], &dof);
1949:       PetscSectionGetOffset(mesh->coneSection, points[p], &off);
1950:       for (c = 0; c < dof; ++c) {
1951:         const PetscInt point = mesh->cones[off+c];

1953:         for (m = 0; m < meetSize; ++m) {
1954:           if (point == meet[i][m]) {
1955:             meet[1-i][newMeetSize++] = point;
1956:             break;
1957:           }
1958:         }
1959:       }
1960:       meetSize = newMeetSize;
1961:       i        = 1-i;
1962:     }
1963:     *numCoveringPoints = meetSize;
1964:     *coveringPoints    = meet[1-i];
1965:   } else {
1966:     ALE::Obj<PETSC_MESH_TYPE> m;
1967:     DMMeshGetMesh(dm, m);
1968:     /* const Obj<typename Mesh::sieve_type::supportSet> edge = m->getSieve()->nJoin(points[0], points[1], 1); */
1969:     *numCoveringPoints = 0;
1970:     *coveringPoints    = NULL;
1971:   }
1972:   return(0);
1973: }

1977: /*@C
1978:   DMMeshGetMaximumDegree - Return the maximum degree of any mesh vertex

1980:   Collective on mesh

1982:   Input Parameter:
1983: . mesh - The DMMesh

1985:   Output Parameter:
1986: . maxDegree - The maximum number of edges at any vertex

1988:    Level: beginner

1990: .seealso: DMMeshCreate()
1991: @*/
1992: PetscErrorCode DMMeshGetMaximumDegree(DM dm, PetscInt *maxDegree)
1993: {
1994:   Obj<PETSC_MESH_TYPE> m;
1995:   PetscErrorCode       ierr;

1998:   DMMeshGetMesh(dm, m);
1999:   const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& vertices = m->depthStratum(0);
2000:   const ALE::Obj<PETSC_MESH_TYPE::sieve_type>&     sieve    = m->getSieve();
2001:   PetscInt                                         maxDeg   = -1;

2003:   for (PETSC_MESH_TYPE::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
2004:     maxDeg = PetscMax(maxDeg, (PetscInt) sieve->getSupportSize(*v_iter));
2005:   }
2006:   *maxDegree = maxDeg;
2007:   return(0);
2008: }

2010: extern PetscErrorCode assembleFullField(VecScatter, Vec, Vec, InsertMode);

2014: /*@
2015:   DMMeshRestrictVector - Insert values from a global vector into a local ghosted vector

2017:   Collective on g

2019:   Input Parameters:
2020: + g - The global vector
2021: . l - The local vector
2022: - mode - either ADD_VALUES or INSERT_VALUES, where
2023:    ADD_VALUES adds values to any existing entries, and
2024:    INSERT_VALUES replaces existing entries with new values

2026:    Level: beginner

2028: .seealso: MatSetOption()
2029: @*/
2030: PetscErrorCode DMMeshRestrictVector(Vec g, Vec l, InsertMode mode)
2031: {
2032:   VecScatter     injection;

2036:   PetscLogEventBegin(DMMesh_restrictVector,0,0,0,0);
2037:   PetscObjectQuery((PetscObject) g, "injection", (PetscObject*) &injection);
2038:   if (injection) {
2039:     VecScatterBegin(injection, g, l, mode, SCATTER_REVERSE);
2040:     VecScatterEnd(injection, g, l, mode, SCATTER_REVERSE);
2041:   } else {
2042:     if (mode == INSERT_VALUES) {
2043:       VecCopy(g, l);
2044:     } else {
2045:       VecAXPY(l, 1.0, g);
2046:     }
2047:   }
2048:   PetscLogEventEnd(DMMesh_restrictVector,0,0,0,0);
2049:   return(0);
2050: }

2054: /*@
2055:   DMMeshAssembleVectorComplete - Insert values from a local ghosted vector into a global vector

2057:   Collective on g

2059:   Input Parameters:
2060: + g - The global vector
2061: . l - The local vector
2062: - mode - either ADD_VALUES or INSERT_VALUES, where
2063:    ADD_VALUES adds values to any existing entries, and
2064:    INSERT_VALUES replaces existing entries with new values

2066:    Level: beginner

2068: .seealso: MatSetOption()
2069: @*/
2070: PetscErrorCode DMMeshAssembleVectorComplete(Vec g, Vec l, InsertMode mode)
2071: {
2072:   VecScatter     injection;

2076:   PetscLogEventBegin(DMMesh_assembleVectorComplete,0,0,0,0);
2077:   PetscObjectQuery((PetscObject) g, "injection", (PetscObject*) &injection);
2078:   if (injection) {
2079:     VecScatterBegin(injection, l, g, mode, SCATTER_FORWARD);
2080:     VecScatterEnd(injection, l, g, mode, SCATTER_FORWARD);
2081:   } else {
2082:     if (mode == INSERT_VALUES) {
2083:       VecCopy(l, g);
2084:     } else {
2085:       VecAXPY(g, 1.0, l);
2086:     }
2087:   }
2088:   PetscLogEventEnd(DMMesh_assembleVectorComplete,0,0,0,0);
2089:   return(0);
2090: }

2094: /*@
2095:   DMMeshAssembleVector - Insert values into a vector

2097:   Collective on A

2099:   Input Parameters:
2100: + b - the vector
2101: . e - The element number
2102: . v - The values
2103: - mode - either ADD_VALUES or INSERT_VALUES, where
2104:    ADD_VALUES adds values to any existing entries, and
2105:    INSERT_VALUES replaces existing entries with new values

2107:    Level: beginner

2109: .seealso: VecSetOption()
2110: @*/
2111: PetscErrorCode DMMeshAssembleVector(Vec b, PetscInt e, PetscScalar v[], InsertMode mode)
2112: {
2113:   DM             dm;
2114:   SectionReal    section;

2118:   VecGetDM(b, &dm);
2119:   DMMeshGetSectionReal(dm, "x", &section);
2120:   DMMeshAssembleVectorDM(b, dm, section, e, v, mode);
2121:   SectionRealDestroy(&section);
2122:   return(0);
2123: }

2125: PetscErrorCode DMMeshAssembleVectorDM(Vec b, DM dm, SectionReal section, PetscInt e, PetscScalar v[], InsertMode mode)
2126: {
2127:   ALE::Obj<PETSC_MESH_TYPE>                    m;
2128:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;
2129:   PetscInt                                     firstElement;
2130:   PetscErrorCode                               ierr;

2133:   PetscLogEventBegin(DMMesh_assembleVector,0,0,0,0);
2134:   DMMeshGetMesh(dm, m);
2135:   SectionRealGetSection(section, s);
2136:   //firstElement = elementBundle->getLocalSizes()[bundle->getCommRank()];
2137:   firstElement = 0;
2138: #if defined(PETSC_USE_COMPLEX)
2139:   SETERRQ(PetscObjectComm((PetscObject)mesh),PETSC_ERR_SUP, "SectionReal does not support complex update");
2140: #else
2141:   if (mode == INSERT_VALUES) {
2142:     m->update(s, PETSC_MESH_TYPE::point_type(e + firstElement), v);
2143:   } else {
2144:     m->updateAdd(s, PETSC_MESH_TYPE::point_type(e + firstElement), v);
2145:   }
2146: #endif
2147:   PetscLogEventEnd(DMMesh_assembleVector,0,0,0,0);
2148:   return(0);
2149: }

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

2156:   Not Collective

2158:   Input Parameters:
2159: + mat - the matrix
2160: . dmr - The row DM
2161: . nrow, rowPoints - number of rows and their local Sieve points
2162: . dmc - The column DM
2163: . ncol, colPoints - number of columns and their local Sieve points
2164: . v -  a logically two-dimensional array of values
2165: - mode - either ADD_VALUES or INSERT_VALUES, where
2166:    ADD_VALUES adds values to any existing entries, and
2167:    INSERT_VALUES replaces existing entries with new values

2169:    Level: intermediate

2171: .seealso: DMMeshCreate(), MatSetValuesStencil()
2172: @*/
2173: PetscErrorCode MatSetValuesTopology(Mat mat, DM dmr, PetscInt nrow, const PetscInt rowPoints[], DM dmc, PetscInt ncol, const PetscInt colPoints[], const PetscScalar v[], InsertMode mode)
2174: {
2175:   ALE::Obj<PETSC_MESH_TYPE> mr;
2176:   ALE::Obj<PETSC_MESH_TYPE> mc;
2177:   PetscErrorCode            ierr;

2182:   if (!nrow || !ncol) return(0); /* no values to insert */
2188:   DMMeshGetMesh(dmr, mr);
2189:   DMMeshGetMesh(dmc, mc);
2190:   typedef ALE::ISieveVisitor::IndicesVisitor<PETSC_MESH_TYPE::real_section_type,PETSC_MESH_TYPE::order_type,PetscInt> visitor_type;
2191:   visitor_type rV(*mr->getRealSection("default"), *mr->getFactory()->getLocalOrder(mr, "default", mr->getRealSection("default")),(int) pow((double) mr->getSieve()->getMaxConeSize(), mr->depth())*mr->getMaxDof() *nrow, mr->depth() > 1);
2192:   visitor_type cV(*mc->getRealSection("default"), *mc->getFactory()->getLocalOrder(mc, "default", mc->getRealSection("default")),(int) pow((double) mc->getSieve()->getMaxConeSize(), mc->depth())*mc->getMaxDof() *ncol, mc->depth() > 1);

2194:   try {
2195:     for (PetscInt r = 0; r < nrow; ++r) {
2196:       ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*mr->getSieve(), rowPoints[r], rV);
2197:     }
2198:   } catch(ALE::Exception e) {
2199:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB, e.message());
2200:   }
2201:   const PetscInt *rowIndices   = rV.getValues();
2202:   const int      numRowIndices = rV.getSize();
2203:   try {
2204:     for (PetscInt c = 0; c < ncol; ++c) {
2205:       ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*mc->getSieve(), colPoints[c], cV);
2206:     }
2207:   } catch(ALE::Exception e) {
2208:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB, e.message());
2209:   }
2210:   const PetscInt *colIndices   = cV.getValues();
2211:   const int      numColIndices = cV.getSize();

2213:   MatSetValuesLocal(mat, numRowIndices, rowIndices, numColIndices, colIndices, v, mode);
2214:   return(0);
2215: }

2219: 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)
2220: {

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

2227:   updateOperator(A, *m->getSieve(), iV, e, array, mode);
2228:   return(0);
2229: }

2233: 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)
2234: {
2235:   typedef ALE::ISieveVisitor::IndicesVisitor<PETSC_MESH_TYPE::real_section_type,PETSC_MESH_TYPE::order_type,PetscInt> visitor_type;
2236:   visitor_type iVr(*rowSection, *rowGlobalOrder, (int) pow((double) rowM->getSieve()->getMaxConeSize(), rowM->depth())*rowM->getMaxDof(), rowM->depth() > 1);
2237:   visitor_type iVc(*colSection, *colGlobalOrder, (int) pow((double) colM->getSieve()->getMaxConeSize(), colM->depth())*colM->getMaxDof(), colM->depth() > 1);

2239:   PetscErrorCode updateOperator(A, *rowM->getSieve(), iVr, rowE, *colM->getSieve(), iVc, colE, array, mode);
2240:   return(0);
2241: }

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

2248:   Logically Collective on A

2250:   Input Parameters:
2251: + A - the matrix
2252: . mesh - DMMesh needed for orderings
2253: . section - A Section which describes the layout
2254: . e - The element number
2255: . v - The values
2256: - mode - either ADD_VALUES or INSERT_VALUES, where
2257:    ADD_VALUES adds values to any existing entries, and
2258:    INSERT_VALUES replaces existing entries with new values

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

2262:    Level: developer

2264: .seealso: DMMeshUpdateOperator(), DMMeshAssembleMatrixDM()
2265: @*/
2266: PetscErrorCode DMMeshSetMaxDof(DM dm, PetscInt maxDof)
2267: {
2268:   Obj<PETSC_MESH_TYPE> m;
2269:   PetscErrorCode       ierr;

2272:   DMMeshGetMesh(dm, m);
2273:   m->setMaxDof(maxDof);
2274:   return(0);
2275: }

2279: /*@
2280:   DMMeshAssembleMatrixDM - Insert values into a matrix

2282:   Collective on A

2284:   Input Parameters:
2285: + A - the matrix
2286: . dm - DMMesh needed for orderings
2287: . section - A Section which describes the layout
2288: . e - The element
2289: . v - The values
2290: - mode - either ADD_VALUES or INSERT_VALUES, where
2291:    ADD_VALUES adds values to any existing entries, and
2292:    INSERT_VALUES replaces existing entries with new values

2294:    Level: beginner

2296: .seealso: MatSetOption()
2297: @*/
2298: PetscErrorCode DMMeshAssembleMatrixDM(Mat A, DM dm, SectionReal section, PetscInt e, PetscScalar v[], InsertMode mode)
2299: {

2303:   PetscLogEventBegin(DMMesh_assembleMatrix,0,0,0,0);
2304:   try {
2305:     Obj<PETSC_MESH_TYPE>                    m;
2306:     Obj<PETSC_MESH_TYPE::real_section_type> s;

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

2312:     if (m->debug()) {
2313:       std::cout << "Assembling matrix for element number " << e << " --> point " << e << std::endl;
2314:     }
2315:     DMMeshUpdateOperator(A, m, s, globalOrder, e, v, mode);
2316:   } catch (ALE::Exception e) {
2317:     std::cout << e.msg() << std::endl;
2318:   }
2319:   PetscLogEventEnd(DMMesh_assembleMatrix,0,0,0,0);
2320:   return(0);
2321: }

2323: /******************************** C Wrappers **********************************/

2327: PetscErrorCode WriteVTKHeader(DM dm, PetscViewer viewer)
2328: {
2329:   ALE::Obj<PETSC_MESH_TYPE> m;
2330:   PetscErrorCode            ierr;

2332:   DMMeshGetMesh(dm, m);
2333:   return VTKViewer::writeHeader(m, viewer);
2334: }

2338: PetscErrorCode WriteVTKVertices(DM dm, PetscViewer viewer)
2339: {
2340:   ALE::Obj<PETSC_MESH_TYPE> m;
2341:   PetscErrorCode            ierr;

2343:   DMMeshGetMesh(dm, m);
2344:   return VTKViewer::writeVertices(m, viewer);
2345: }

2349: PetscErrorCode WriteVTKElements(DM dm, PetscViewer viewer)
2350: {
2351:   ALE::Obj<PETSC_MESH_TYPE> m;
2352:   PetscErrorCode            ierr;

2354:   DMMeshGetMesh(dm, m);
2355:   return VTKViewer::writeElements(m, viewer);
2356: }

2360: /*@C
2361:   DMMeshGetCoordinates - Creates an array holding the coordinates.

2363:   Not Collective

2365:   Input Parameter:
2366: + dm - The DMMesh object
2367: - columnMajor - Flag for column major order

2369:   Output Parameter:
2370: + numVertices - The number of vertices
2371: . dim - The embedding dimension
2372: - coords - The array holding local coordinates

2374:   Level: intermediate

2376: .keywords: mesh, coordinates
2377: .seealso: DMMeshCreate()
2378: @*/
2379: PetscErrorCode DMMeshGetCoordinates(DM dm, PetscBool columnMajor, PetscInt *numVertices, PetscInt *dim, PetscReal *coords[])
2380: {
2381:   ALE::Obj<PETSC_MESH_TYPE> m;
2382:   PetscErrorCode            ierr;

2385:   DMMeshGetMesh(dm, m);
2386:   ALE::PCICE::Builder::outputVerticesLocal(m, numVertices, dim, coords, columnMajor);
2387:   return(0);
2388: }

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

2395:   Not Collective

2397:   Input Parameters:
2398: + dm - The DMMesh object
2399: - columnMajor - Flag for column major order

2401:   Output Parameters:
2402: + numElements - The number of elements
2403: . numCorners - The number of vertices per element
2404: - vertices - The array holding vertices on each local element

2406:   Level: intermediate

2408: .keywords: mesh, elements
2409: .seealso: DMMeshCreate()
2410: @*/
2411: PetscErrorCode DMMeshGetElements(DM dm, PetscBool columnMajor, PetscInt *numElements, PetscInt *numCorners, PetscInt *vertices[])
2412: {
2413:   ALE::Obj<PETSC_MESH_TYPE> m;
2414:   PetscErrorCode            ierr;

2417:   DMMeshGetMesh(dm, m);
2418:   ALE::PCICE::Builder::outputElementsLocal(m, numElements, numCorners, vertices, columnMajor);
2419:   return(0);
2420: }

2424: PetscErrorCode DMMeshCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency)
2425: {
2426:   const PetscInt maxFaceCases = 30;
2427:   PetscInt       numFaceCases = 0;
2428:   PetscInt       numFaceVertices[maxFaceCases];
2429:   PetscInt       *off, *adj;
2430:   PetscInt       dim, depth, cStart, cEnd, c, numCells, cell;

2434:   /* For parallel partitioning, I think you have to communicate supports */
2435:   DMMeshGetDimension(dm, &dim);
2436:   DMMeshGetLabelSize(dm, "depth", &depth);
2437:   --depth;
2438:   DMMeshGetHeightStratum(dm, 0, &cStart, &cEnd);
2439:   if (cEnd - cStart == 0) {
2440:     *numVertices = 0;
2441:     *offsets     = NULL;
2442:     *adjacency   = NULL;
2443:     return(0);
2444:   }
2445:   numCells = cEnd - cStart;
2446:   /* Setup face recognition */
2447:   {
2448:     PetscInt cornersSeen[30] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Could use PetscBT */

2450:     for (c = cStart; c < cEnd; ++c) {
2451:       PetscInt corners;

2453:       DMMeshGetConeSize(dm, c, &corners);
2454:       if (!cornersSeen[corners]) {
2455:         if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases");
2456:         cornersSeen[corners] = 1;
2457:         if (corners == dim+1) {
2458:           numFaceVertices[numFaceCases] = dim;
2459:           PetscInfo(dm, "Recognizing simplices\n");
2460:         } else if ((dim == 1) && (corners == 3)) {
2461:           numFaceVertices[numFaceCases] = 3;
2462:           PetscInfo(dm, "Recognizing quadratic edges\n");
2463:         } else if ((dim == 2) && (corners == 4)) {
2464:           numFaceVertices[numFaceCases] = 2;
2465:           PetscInfo(dm, "Recognizing quads\n");
2466:         } else if ((dim == 2) && (corners == 6)) {
2467:           numFaceVertices[numFaceCases] = 3;
2468:           PetscInfo(dm, "Recognizing tri and quad cohesive Lagrange cells\n");
2469:         } else if ((dim == 2) && (corners == 9)) {
2470:           numFaceVertices[numFaceCases] = 3;
2471:           PetscInfo(dm, "Recognizing quadratic quads and quadratic quad cohesive Lagrange cells\n");
2472:         } else if ((dim == 3) && (corners == 6)) {
2473:           numFaceVertices[numFaceCases] = 4;
2474:           PetscInfo(dm, "Recognizing tet cohesive cells\n");
2475:         } else if ((dim == 3) && (corners == 8)) {
2476:           numFaceVertices[numFaceCases] = 4;
2477:           PetscInfo(dm, "Recognizing hexes\n");
2478:         } else if ((dim == 3) && (corners == 9)) {
2479:           numFaceVertices[numFaceCases] = 6;
2480:           PetscInfo(dm, "Recognizing tet cohesive Lagrange cells\n");
2481:         } else if ((dim == 3) && (corners == 10)) {
2482:           numFaceVertices[numFaceCases] = 6;
2483:           PetscInfo(dm, "Recognizing quadratic tets\n");
2484:         } else if ((dim == 3) && (corners == 12)) {
2485:           numFaceVertices[numFaceCases] = 6;
2486:           PetscInfo(dm, "Recognizing hex cohesive Lagrange cells\n");
2487:         } else if ((dim == 3) && (corners == 18)) {
2488:           numFaceVertices[numFaceCases] = 6;
2489:           PetscInfo(dm, "Recognizing quadratic tet cohesive Lagrange cells\n");
2490:         } else if ((dim == 3) && (corners == 27)) {
2491:           numFaceVertices[numFaceCases] = 9;
2492:           PetscInfo(dm, "Recognizing quadratic hexes and quadratic hex cohesive Lagrange cells\n");
2493:         } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Could not recognize number of face vertices for %d corners", corners);
2494:         ++numFaceCases;
2495:       }
2496:     }
2497:   }
2498:   /* Check for optimized depth 1 construction */
2499:   PetscMalloc((numCells+1) * sizeof(PetscInt), &off);
2500:   PetscMemzero(off, (numCells+1) * sizeof(PetscInt));
2501:   if (depth == 1) {
2502:     PetscInt *neighborCells;
2503:     PetscInt n;
2504:     PetscInt maxConeSize, maxSupportSize;

2506:     /* Temp space for point adj <= maxConeSize*maxSupportSize */
2507:     DMMeshGetMaxSizes(dm, &maxConeSize, &maxSupportSize);
2508:     PetscMalloc(maxConeSize*maxSupportSize * sizeof(PetscInt), &neighborCells);
2509:     /* Count neighboring cells */
2510:     for (cell = cStart; cell < cEnd; ++cell) {
2511:       const PetscInt *cone;
2512:       PetscInt       numNeighbors = 0;
2513:       PetscInt       coneSize, c;

2515:       /* Get support of the cone, and make a set of the cells */
2516:       DMMeshGetConeSize(dm, cell, &coneSize);
2517:       DMMeshGetCone(dm, cell, &cone);
2518:       for (c = 0; c < coneSize; ++c) {
2519:         const PetscInt *support;
2520:         PetscInt       supportSize, s;

2522:         DMMeshGetSupportSize(dm, cone[c], &supportSize);
2523:         DMMeshGetSupport(dm, cone[c], &support);
2524:         for (s = 0; s < supportSize; ++s) {
2525:           const PetscInt point = support[s];

2527:           if (point == cell) continue;
2528:           for (n = 0; n < numNeighbors; ++n) {
2529:             if (neighborCells[n] == point) break;
2530:           }
2531:           if (n == numNeighbors) {
2532:             neighborCells[n] = point;
2533:             ++numNeighbors;
2534:           }
2535:         }
2536:       }
2537:       /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */
2538:       for (n = 0; n < numNeighbors; ++n) {
2539:         PetscInt       cellPair[2] = {cell, neighborCells[n]};
2540:         PetscInt       meetSize;
2541:         const PetscInt *meet;

2543:         DMMeshMeetPoints(dm, 2, cellPair, &meetSize, &meet);
2544:         if (meetSize) {
2545:           PetscInt f;

2547:           for (f = 0; f < numFaceCases; ++f) {
2548:             if (numFaceVertices[f] == meetSize) {
2549:               ++off[cell-cStart+1];
2550:               break;
2551:             }
2552:           }
2553:         }
2554:       }
2555:     }
2556:     /* Prefix sum */
2557:     for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1];
2558:     PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);
2559:     /* Get neighboring cells */
2560:     for (cell = cStart; cell < cEnd; ++cell) {
2561:       const PetscInt *cone;
2562:       PetscInt       numNeighbors = 0;
2563:       PetscInt       cellOffset   = 0;
2564:       PetscInt       coneSize, c;

2566:       /* Get support of the cone, and make a set of the cells */
2567:       DMMeshGetConeSize(dm, cell, &coneSize);
2568:       DMMeshGetCone(dm, cell, &cone);
2569:       for (c = 0; c < coneSize; ++c) {
2570:         const PetscInt *support;
2571:         PetscInt       supportSize, s;

2573:         DMMeshGetSupportSize(dm, cone[c], &supportSize);
2574:         DMMeshGetSupport(dm, cone[c], &support);
2575:         for (s = 0; s < supportSize; ++s) {
2576:           const PetscInt point = support[s];

2578:           if (point == cell) continue;
2579:           for (n = 0; n < numNeighbors; ++n) {
2580:             if (neighborCells[n] == point) break;
2581:           }
2582:           if (n == numNeighbors) {
2583:             neighborCells[n] = point;
2584:             ++numNeighbors;
2585:           }
2586:         }
2587:       }
2588:       /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */
2589:       for (n = 0; n < numNeighbors; ++n) {
2590:         PetscInt       cellPair[2] = {cell, neighborCells[n]};
2591:         PetscInt       meetSize;
2592:         const PetscInt *meet;

2594:         DMMeshMeetPoints(dm, 2, cellPair, &meetSize, &meet);
2595:         if (meetSize) {
2596:           PetscInt f;

2598:           for (f = 0; f < numFaceCases; ++f) {
2599:             if (numFaceVertices[f] == meetSize) {
2600:               adj[off[cell-cStart]+cellOffset] = neighborCells[n];
2601:               ++cellOffset;
2602:               break;
2603:             }
2604:           }
2605:         }
2606:       }
2607:     }
2608:     PetscFree(neighborCells);
2609:   } else if (depth == dim) {
2610:     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Neighbor graph creation not implemented for interpolated meshes");
2611: #if 0
2612:     OffsetVisitor<typename Mesh::sieve_type> oV(*sieve, *overlapSieve, off);
2613:     PetscInt p;

2615:     for (typename Mesh::label_sequence::iterator c_iter = cells->begin(); c_iter != cEnd; ++c_iter) {
2616:       sieve->cone(*c_iter, oV);
2617:     }
2618:     for (p = 1; p <= numCells; ++p) off[p] = off[p] + off[p-1];
2619:     PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);
2620:     AdjVisitor<typename Mesh::sieve_type> aV(adj, zeroBase);
2621:     ISieveVisitor::SupportVisitor<typename Mesh::sieve_type, AdjVisitor<typename Mesh::sieve_type> > sV(*sieve, aV);
2622:     ISieveVisitor::SupportVisitor<typename Mesh::sieve_type, AdjVisitor<typename Mesh::sieve_type> > ovSV(*overlapSieve, aV);

2624:     for (typename Mesh::label_sequence::iterator c_iter = cells->begin(); c_iter != cEnd; ++c_iter) {
2625:       aV.setCell(*c_iter);
2626:       sieve->cone(*c_iter, sV);
2627:       sieve->cone(*c_iter, ovSV);
2628:     }
2629:     offset = aV.getOffset();
2630: #endif
2631:   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Neighbor graph creation not defined for partially interpolated meshes");

2633:   *numVertices = numCells;
2634:   *offsets     = off;
2635:   *adjacency   = adj;
2636:   return(0);
2637: }

2639: #if defined(PETSC_HAVE_CHACO)
2640: #if defined(PETSC_HAVE_UNISTD_H)
2641: #include <unistd.h>
2642: #endif
2643: /* Chaco does not have an include file */
2644: extern "C" {
2645:   extern int interface(int nvtxs, int *start, int *adjacency, int *vwgts,
2646:                        float *ewgts, float *x, float *y, float *z, char *outassignname,
2647:                        char *outfilename, short *assignment, int architecture, int ndims_tot,
2648:                        int mesh_dims[3], double *goal, int global_method, int local_method,
2649:                        int rqi_flag, int vmax, int ndims, double eigtol, long seed);

2651:   extern int FREE_GRAPH;
2652: }

2656: PetscErrorCode DMMeshPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition)
2657: {
2658:   enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3};
2659:   MPI_Comm       comm           = ((PetscObject) dm)->comm;
2660:   int            nvtxs          = numVertices;                /* number of vertices in full graph */
2661:   int            *vwgts         = NULL;                       /* weights for all vertices */
2662:   float          *ewgts         = NULL;                       /* weights for all edges */
2663:   float          *x             = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */
2664:   char           *outassignname = NULL;                       /*  name of assignment output file */
2665:   char           *outfilename   = NULL;                       /* output file name */
2666:   int            architecture   = 1;                          /* 0 => hypercube, d => d-dimensional mesh */
2667:   int            ndims_tot      = 0;                          /* total number of cube dimensions to divide */
2668:   int            mesh_dims[3];                                /* dimensions of mesh of processors */
2669:   double         *goal         = NULL;                        /* desired set sizes for each set */
2670:   int            global_method = 1;                           /* global partitioning algorithm */
2671:   int            local_method  = 1;                           /* local partitioning algorithm */
2672:   int            rqi_flag      = 0;                           /* should I use RQI/Symmlq eigensolver? */
2673:   int            vmax          = 200;                         /* how many vertices to coarsen down to? */
2674:   int            ndims         = 1;                           /* number of eigenvectors (2^d sets) */
2675:   double         eigtol        = 0.001;                       /* tolerance on eigenvectors */
2676:   long           seed          = 123636512;                   /* for random graph mutations */
2677:   short int      *assignment;                                 /* Output partition */
2678:   int            fd_stdout, fd_pipe[2];
2679:   PetscInt       *points;
2680:   PetscMPIInt    commSize;
2681:   int            i, v, p;

2685:   MPI_Comm_size(comm, &commSize);
2686:   if (!numVertices) {
2687:     PetscSectionCreate(comm, partSection);
2688:     PetscSectionSetChart(*partSection, 0, commSize);
2689:     PetscSectionSetUp(*partSection);
2690:     ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);
2691:     return(0);
2692:   }
2693:   FREE_GRAPH = 0;                         /* Do not let Chaco free my memory */
2694:   for (i = 0; i < start[numVertices]; ++i) ++adjacency[i];

2696:   if (global_method == INERTIAL_METHOD) SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported");

2698:   mesh_dims[0] = commSize;
2699:   mesh_dims[1] = 1;
2700:   mesh_dims[2] = 1;
2701:   PetscMalloc(nvtxs * sizeof(short int), &assignment);
2702:   /* Chaco outputs to stdout. We redirect this to a buffer. */
2703:   /* TODO: check error codes for UNIX calls */
2704: #if defined(PETSC_HAVE_UNISTD_H)
2705:   {
2706:     fd_stdout = dup(1);
2707:     pipe(fd_pipe);
2708:     close(1);
2709:     dup2(fd_pipe[1], 1);
2710:   }
2711: #endif
2712:   interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename,
2713:                    assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag,
2714:                    vmax, ndims, eigtol, seed);
2715: #if defined(PETSC_HAVE_UNISTD_H)
2716:   {
2717:     char msgLog[10000];
2718:     int  count;

2720:     fflush(stdout);
2721:     count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char));
2722:     if (count < 0) count = 0;
2723:     msgLog[count] = 0;
2724:     close(1);
2725:     dup2(fd_stdout, 1);
2726:     close(fd_stdout);
2727:     close(fd_pipe[0]);
2728:     close(fd_pipe[1]);
2729:     if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog);
2730:   }
2731: #endif
2732:   /* Convert to PetscSection+IS */
2733:   PetscSectionCreate(comm, partSection);
2734:   PetscSectionSetChart(*partSection, 0, commSize);
2735:   for (v = 0; v < nvtxs; ++v) {
2736:     PetscSectionAddDof(*partSection, assignment[v], 1);
2737:   }
2738:   PetscSectionSetUp(*partSection);
2739:   PetscMalloc(nvtxs * sizeof(PetscInt), &points);
2740:   for (p = 0, i = 0; p < commSize; ++p) {
2741:     for (v = 0; v < nvtxs; ++v) {
2742:       if (assignment[v] == p) points[i++] = v;
2743:     }
2744:   }
2745:   if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %d should be %d", i, nvtxs);
2746:   ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);
2747:   if (global_method == INERTIAL_METHOD) {
2748:     /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */
2749:   }
2750:   PetscFree(assignment);
2751:   for (i = 0; i < start[numVertices]; ++i) --adjacency[i];
2752:   return(0);
2753: }
2754: #endif

2756: #if defined(PETSC_HAVE_PARMETIS)
2759: PetscErrorCode DMMeshPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition)
2760: {
2762:   return(0);
2763: }
2764: #endif

2768: PetscErrorCode DMMeshCreatePartition(DM dm, PetscSection *partSection, IS *partition, PetscInt height)
2769: {
2770:   PetscMPIInt    size;

2774:   MPI_Comm_size(((PetscObject) dm)->comm, &size);
2775:   if (size == 1) {
2776:     PetscInt *points;
2777:     PetscInt cStart, cEnd, c;

2779:     DMMeshGetHeightStratum(dm, 0, &cStart, &cEnd);
2780:     PetscSectionCreate(((PetscObject) dm)->comm, partSection);
2781:     PetscSectionSetChart(*partSection, 0, size);
2782:     PetscSectionSetDof(*partSection, 0, cEnd-cStart);
2783:     PetscSectionSetUp(*partSection);
2784:     PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);
2785:     for (c = cStart; c < cEnd; ++c) points[c] = c;
2786:     ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);
2787:     return(0);
2788:   }
2789:   if (height == 0) {
2790:     PetscInt numVertices;
2791:     PetscInt *start     = NULL;
2792:     PetscInt *adjacency = NULL;

2794:     if (1) {
2795:       DMMeshCreateNeighborCSR(dm, &numVertices, &start, &adjacency);
2796: #if defined(PETSC_HAVE_CHACO)
2797:       DMMeshPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);
2798: #endif
2799:     } else {
2800:       DMMeshCreateNeighborCSR(dm, &numVertices, &start, &adjacency);
2801: #if defined(PETSC_HAVE_PARMETIS)
2802:       DMMeshPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);
2803: #endif
2804:     }
2805:     PetscFree(start);
2806:     PetscFree(adjacency);
2807: # if 0
2808:   } else if (height == 1) {
2809:     /* Build the dual graph for faces and partition the hypergraph */
2810:     PetscInt numEdges;

2812:     buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase());
2813:     GraphPartitioner().partition(numEdges, start, adjacency, partition, manager);
2814:     destroyCSR(numEdges, start, adjacency);
2815: #endif
2816:   } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %d", height);
2817:   return(0);
2818: }

2822: PetscErrorCode DMMeshCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition)
2823: {
2824:   const PetscInt *partArray;
2825:   PetscInt       *allPoints, *partPoints = NULL;
2826:   PetscInt       rStart, rEnd, rank, maxPartSize = 0, newSize;

2830:   PetscSectionGetChart(pointSection, &rStart, &rEnd);
2831:   ISGetIndices(pointPartition, &partArray);
2832:   PetscSectionCreate(((PetscObject) dm)->comm, section);
2833:   PetscSectionSetChart(*section, rStart, rEnd);
2834:   for (rank = rStart; rank < rEnd; ++rank) {
2835:     PetscInt partSize = 0;
2836:     PetscInt numPoints, offset, p;

2838:     PetscSectionGetDof(pointSection, rank, &numPoints);
2839:     PetscSectionGetOffset(pointSection, rank, &offset);
2840:     for (p = 0; p < numPoints; ++p) {
2841:       PetscInt       point = partArray[offset+p], closureSize;
2842:       const PetscInt *closure;

2844:       /* TODO Include support for height > 0 case */
2845:       DMMeshGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);
2846:       /* Merge into existing points */
2847:       if (partSize+closureSize > maxPartSize) {
2848:         PetscInt *tmpPoints;

2850:         maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize);
2851:         PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);
2852:         PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));
2853:         PetscFree(partPoints);
2854:         partPoints  = tmpPoints;
2855:       }
2856:       PetscMemcpy(&partPoints[partSize], closure, closureSize * sizeof(PetscInt));
2857:       partSize += closureSize;
2858:       PetscSortRemoveDupsInt(&partSize, partPoints);
2859:     }
2860:     PetscSectionSetDof(*section, rank, partSize);
2861:   }
2862:   PetscSectionSetUp(*section);
2863:   PetscSectionGetStorageSize(*section, &newSize);
2864:   PetscMalloc(newSize * sizeof(PetscInt), &allPoints);

2866:   for (rank = rStart; rank < rEnd; ++rank) {
2867:     PetscInt partSize = 0, newOffset;
2868:     PetscInt numPoints, offset, p;

2870:     PetscSectionGetDof(pointSection, rank, &numPoints);
2871:     PetscSectionGetOffset(pointSection, rank, &offset);
2872:     for (p = 0; p < numPoints; ++p) {
2873:       PetscInt       point = partArray[offset+p], closureSize;
2874:       const PetscInt *closure;

2876:       /* TODO Include support for height > 0 case */
2877:       DMMeshGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);
2878:       /* Merge into existing points */
2879:       PetscMemcpy(&partPoints[partSize], closure, closureSize * sizeof(PetscInt));
2880:       partSize += closureSize;
2881:       PetscSortRemoveDupsInt(&partSize, partPoints);
2882:     }
2883:     PetscSectionGetOffset(*section, rank, &newOffset);
2884:     PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));
2885:   }
2886:   ISRestoreIndices(pointPartition, &partArray);
2887:   PetscFree(partPoints);
2888:   ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);
2889:   return(0);
2890: }

2894: /*
2895:   Input Parameters:
2896: . originalSection
2897: , originalVec

2899:   Output Parameters:
2900: . newSection
2901: . newVec
2902: */
2903: PetscErrorCode DMMeshDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec)
2904: {
2905:   PetscSF        fieldSF;
2906:   PetscInt       *remoteOffsets, fieldSize;
2907:   PetscScalar    *originalValues, *newValues;

2911:   PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);

2913:   PetscSectionGetStorageSize(newSection, &fieldSize);
2914:   VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);
2915:   VecSetFromOptions(newVec);

2917:   VecGetArray(originalVec, &originalValues);
2918:   VecGetArray(newVec, &newValues);
2919:   PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);
2920:   PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);
2921:   PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);
2922:   PetscSFDestroy(&fieldSF);
2923:   VecRestoreArray(newVec, &newValues);
2924:   VecRestoreArray(originalVec, &originalValues);
2925:   return(0);
2926: }

2930: /*@C
2931:   DMMeshDistribute - Distributes the mesh and any associated sections.

2933:   Not Collective

2935:   Input Parameter:
2936: + dm  - The original DMMesh object
2937: - partitioner - The partitioning package, or NULL for the default

2939:   Output Parameter:
2940: . parallelMesh - The distributed DMMesh object

2942:   Level: intermediate

2944: .keywords: mesh, elements

2946: .seealso: DMMeshCreate(), DMMeshDistributeByFace()
2947: @*/
2948: PetscErrorCode DMMeshDistribute(DM dm, const char partitioner[], DM *dmParallel)
2949: {
2950:   DM_Mesh        *mesh = (DM_Mesh*) dm->data, *pmesh;
2951:   MPI_Comm       comm  = ((PetscObject) dm)->comm;
2952:   PetscMPIInt    rank, numProcs, p;

2958:   MPI_Comm_rank(comm, &rank);
2959:   MPI_Comm_size(comm, &numProcs);
2960:   if (numProcs == 1) return(0);
2961:   if (mesh->useNewImpl) {
2962:     const PetscInt         height = 0;
2963:     PetscInt               dim, numRemoteRanks;
2964:     IS                     cellPart,        part;
2965:     PetscSection           cellPartSection, partSection;
2966:     PetscSFNode            *remoteRanks;
2967:     PetscSF                partSF, pointSF, coneSF;
2968:     ISLocalToGlobalMapping renumbering;
2969:     PetscSection           originalConeSection, newConeSection;
2970:     PetscInt               *remoteOffsets;
2971:     PetscInt               *cones, *newCones, newConesSize;
2972:     PetscBool              flg;

2974:     DMMeshGetDimension(dm, &dim);
2975:     /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */
2976:     DMMeshCreatePartition(dm, &cellPartSection, &cellPart, height);
2977:     /* Create SF assuming a serial partition for all processes: Could check for IS length here */
2978:     if (!rank) numRemoteRanks = numProcs;
2979:     else numRemoteRanks = 0;
2980:     PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);
2981:     for (p = 0; p < numRemoteRanks; ++p) {
2982:       remoteRanks[p].rank  = p;
2983:       remoteRanks[p].index = 0;
2984:     }
2985:     PetscSFCreate(comm, &partSF);
2986:     PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);
2987:     PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);
2988:     if (flg) {
2989:       PetscPrintf(comm, "Cell Partition:\n");
2990:       PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);
2991:       ISView(cellPart, NULL);
2992:       PetscSFView(partSF, NULL);
2993:     }
2994:     /* Close the partition over the mesh */
2995:     DMMeshCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);
2996:     ISDestroy(&cellPart);
2997:     PetscSectionDestroy(&cellPartSection);
2998:     /* Create new mesh */
2999:     DMMeshCreate(comm, dmParallel);
3000:     DMMeshSetDimension(*dmParallel, dim);
3001:     PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");
3002:     pmesh = (DM_Mesh*) (*dmParallel)->data;
3003:     /* Distribute sieve points and the global point numbering (replaces creating remote bases) */
3004:     PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);
3005:     if (flg) {
3006:       PetscPrintf(comm, "Point Partition:\n");
3007:       PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);
3008:       ISView(part, NULL);
3009:       PetscSFView(pointSF, NULL);
3010:       PetscPrintf(comm, "Point Renumbering after partition:\n");
3011:       ISLocalToGlobalMappingView(renumbering, NULL);
3012:     }
3013:     /* Distribute cone section */
3014:     DMMeshGetConeSection(dm, &originalConeSection);
3015:     DMMeshGetConeSection(*dmParallel, &newConeSection);
3016:     PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);
3017:     DMMeshSetUp(*dmParallel);
3018:     {
3019:       PetscInt pStart, pEnd, p;

3021:       PetscSectionGetChart(newConeSection, &pStart, &pEnd);
3022:       for (p = pStart; p < pEnd; ++p) {
3023:         PetscInt coneSize;
3024:         PetscSectionGetDof(newConeSection, p, &coneSize);
3025:         pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize);
3026:       }
3027:     }
3028:     /* Communicate and renumber cones */
3029:     PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);
3030:     DMMeshGetCones(dm, &cones);
3031:     DMMeshGetCones(*dmParallel, &newCones);
3032:     PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);
3033:     PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);
3034:     PetscSectionGetStorageSize(newConeSection, &newConesSize);
3035:     ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);
3036:     PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);
3037:     if (flg) {
3038:       PetscPrintf(comm, "Serial Cone Section:\n");
3039:       PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);
3040:       PetscPrintf(comm, "Parallel Cone Section:\n");
3041:       PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);
3042:       PetscSFView(coneSF, NULL);
3043:     }
3044:     PetscSFDestroy(&coneSF);
3045:     /* Create supports and stratify sieve */
3046:     DMMeshSymmetrize(*dmParallel);
3047:     DMMeshStratify(*dmParallel);
3048:     /* Distribute Coordinates */
3049:     {
3050:       PetscSection originalCoordSection, newCoordSection;
3051:       Vec          originalCoordinates, newCoordinates;

3053:       DMMeshGetCoordinateSection(dm, &originalCoordSection);
3054:       DMMeshGetCoordinateSection(*dmParallel, &newCoordSection);
3055:       DMMeshGetCoordinateVec(dm, &originalCoordinates);
3056:       DMMeshGetCoordinateVec(*dmParallel, &newCoordinates);

3058:       DMMeshDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);
3059:     }
3060:     /* Distribute labels */
3061:     {
3062:       SieveLabel next      = mesh->labels, newNext = NULL;
3063:       PetscInt   numLabels = 0, l;

3065:       /* Bcast number of labels */
3066:       while (next) {
3067:         ++numLabels; next = next->next;
3068:       }
3069:       MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);
3070:       next = mesh->labels;
3071:       for (l = 0; l < numLabels; ++l) {
3072:         SieveLabel     newLabel;
3073:         const PetscInt *partArray;
3074:         PetscInt       *stratumSizes = NULL, *points = NULL;
3075:         PetscMPIInt    *sendcnts     = NULL, *offsets = NULL, *displs = NULL;
3076:         PetscInt       nameSize, s, p;
3077:         size_t         len = 0;

3079:         PetscNew(struct Sieve_Label, &newLabel);
3080:         /* Bcast name (could filter for no points) */
3081:         if (!rank) {PetscStrlen(next->name, &len);}
3082:         nameSize = len;
3083:         MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);
3084:         PetscMalloc(nameSize+1, &newLabel->name);
3085:         if (!rank) {PetscMemcpy(newLabel->name, next->name, nameSize+1);}
3086:         MPI_Bcast(newLabel->name, nameSize+1, MPI_CHAR, 0, comm);
3087:         /* Bcast numStrata (could filter for no points in stratum) */
3088:         if (!rank) newLabel->numStrata = next->numStrata;
3089:         MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);
3090:         PetscMalloc(newLabel->numStrata * sizeof(PetscInt), &newLabel->stratumValues);
3091:         PetscMalloc(newLabel->numStrata * sizeof(PetscInt), &newLabel->stratumSizes);
3092:         PetscMalloc((newLabel->numStrata+1) * sizeof(PetscInt), &newLabel->stratumOffsets);
3093:         /* Bcast stratumValues (could filter for no points in stratum) */
3094:         if (!rank) {PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));}
3095:         MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);
3096:         /* Find size on each process and Scatter */
3097:         if (!rank) {
3098:           ISGetIndices(part, &partArray);
3099:           PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);
3100:           PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));
3101:           for (s = 0; s < next->numStrata; ++s) {
3102:             for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) {
3103:               const PetscInt point = next->points[p];
3104:               PetscInt       proc;

3106:               for (proc = 0; proc < numProcs; ++proc) {
3107:                 PetscInt dof, off, pPart;

3109:                 PetscSectionGetDof(partSection, proc, &dof);
3110:                 PetscSectionGetOffset(partSection, proc, &off);
3111:                 for (pPart = off; pPart < off+dof; ++pPart) {
3112:                   if (partArray[pPart] == point) {
3113:                     ++stratumSizes[proc*next->numStrata+s];
3114:                     break;
3115:                   }
3116:                 }
3117:               }
3118:             }
3119:           }
3120:           ISRestoreIndices(part, &partArray);
3121:         }
3122:         MPI_Scatter(stratumSizes, newLabel->numStrata, MPI_INT, newLabel->stratumSizes, newLabel->numStrata, MPI_INT, 0, comm);
3123:         /* Calculate stratumOffsets */
3124:         newLabel->stratumOffsets[0] = 0;
3125:         for (s = 0; s < newLabel->numStrata; ++s) {
3126:           newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s];
3127:         }
3128:         /* Pack points and Scatter */
3129:         if (!rank) {
3130:           PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);
3131:           displs[0] = 0;
3132:           for (p = 0; p < numProcs; ++p) {
3133:             sendcnts[p] = 0;
3134:             for (s = 0; s < next->numStrata; ++s) {
3135:               sendcnts[p] += stratumSizes[p*next->numStrata+s];
3136:             }
3137:             offsets[p]  = displs[p];
3138:             displs[p+1] = displs[p] + sendcnts[p];
3139:           }
3140:           PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);
3141:           for (s = 0; s < next->numStrata; ++s) {
3142:             for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) {
3143:               const PetscInt point = next->points[p];
3144:               PetscInt       proc;

3146:               for (proc = 0; proc < numProcs; ++proc) {
3147:                 PetscInt dof, off, pPart;

3149:                 PetscSectionGetDof(partSection, proc, &dof);
3150:                 PetscSectionGetOffset(partSection, proc, &off);
3151:                 for (pPart = off; pPart < off+dof; ++pPart) {
3152:                   if (partArray[pPart] == point) {
3153:                     points[offsets[proc]++] = point;
3154:                     break;
3155:                   }
3156:                 }
3157:               }
3158:             }
3159:           }
3160:         }
3161:         PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);
3162:         MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);
3163:         PetscFree(points);
3164:         PetscFree3(sendcnts,offsets,displs);
3165:         PetscFree(stratumSizes);
3166:         /* Renumber points */
3167:         ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, NULL, newLabel->points);
3168:         /* Sort points */
3169:         for (s = 0; s < newLabel->numStrata; ++s) {
3170:           PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);
3171:         }
3172:         /* Insert into list */
3173:         if (newNext) newNext->next = newLabel;
3174:         else pmesh->labels = newLabel;
3175:         newNext = newLabel;
3176:         if (!rank) next = next->next;
3177:       }
3178:     }
3179:     /* Cleanup Partition */
3180:     ISLocalToGlobalMappingDestroy(&renumbering);
3181:     PetscSFDestroy(&partSF);
3182:     PetscSectionDestroy(&partSection);
3183:     ISDestroy(&part);
3184:     /* Create point SF for parallel mesh */
3185:     {
3186:       const PetscInt *leaves;
3187:       PetscSFNode    *remotePoints;
3188:       PetscMPIInt    *rowners, *lowners;
3189:       PetscInt       *ghostPoints, numRoots, numLeaves, numGhostPoints = 0, p, gp;

3191:       PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);
3192:       PetscMalloc2(numRoots*2,PetscInt,&rowners,numLeaves*2,PetscInt,&lowners);
3193:       for (p = 0; p < numRoots*2; ++p) rowners[p] = 0;
3194:       for (p = 0; p < numLeaves; ++p) {
3195:         lowners[p*2+0] = rank;
3196:         PetscMPIIntCast(leaves ? leaves[p] : p,lowners + 2*p + 1);
3197:       }
3198:       PetscSFReduceBegin(pointSF, MPI_2INT, lowners, rowners, MPI_MAXLOC);
3199:       PetscSFReduceEnd(pointSF, MPI_2INT, lowners, rowners, MPI_MAXLOC);
3200:       PetscSFBcastBegin(pointSF, MPI_2INT, rowners, lowners);
3201:       PetscSFBcastEnd(pointSF, MPI_2INT, rowners, lowners);
3202:       for (p = 0; p < numLeaves; ++p) {
3203:         if (lowners[p*2+0] != rank) ++numGhostPoints;
3204:       }
3205:       PetscMalloc(numGhostPoints * sizeof(PetscInt),    &ghostPoints);
3206:       PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);
3207:       for (p = 0, gp = 0; p < numLeaves; ++p) {
3208:         if (lowners[p*2+0] != rank) {
3209:           ghostPoints[gp]        = leaves ? leaves[p] : p;
3210:           remotePoints[gp].rank  = lowners[p*2+0];
3211:           remotePoints[gp].index = lowners[p*2+1];
3212:           ++gp;
3213:         }
3214:       }
3215:       PetscFree2(rowners,lowners);
3216:       PetscSFCreate(comm, &pmesh->sf);
3217:       PetscSFSetGraph(pmesh->sf, PETSC_DETERMINE, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);
3218:       PetscSFSetFromOptions(pmesh->sf);
3219:     }
3220:     /* Cleanup */
3221:     PetscSFDestroy(&pointSF);
3222:     DMSetFromOptions(*dmParallel);
3223:   } else {
3224:     ALE::Obj<PETSC_MESH_TYPE> oldMesh;
3225:     DMMeshGetMesh(dm, oldMesh);
3226:     DMMeshCreate(comm, dmParallel);
3227:     const Obj<PETSC_MESH_TYPE>             newMesh  = new PETSC_MESH_TYPE(comm, oldMesh->getDimension(), oldMesh->debug());
3228:     const Obj<PETSC_MESH_TYPE::sieve_type> newSieve = new PETSC_MESH_TYPE::sieve_type(comm, oldMesh->debug());

3230:     newMesh->setSieve(newSieve);
3231:     ALE::DistributionNew<PETSC_MESH_TYPE>::distributeMeshAndSectionsV(oldMesh, newMesh);
3232:     DMMeshSetMesh(*dmParallel, newMesh);
3233:   }
3234:   return(0);
3235: }

3239: /*@C
3240:   DMMeshDistribute - Distributes the mesh and any associated sections.

3242:   Not Collective

3244:   Input Parameter:
3245: + serialMesh  - The original DMMesh object
3246: - partitioner - The partitioning package, or NULL for the default

3248:   Output Parameter:
3249: . parallelMesh - The distributed DMMesh object

3251:   Level: intermediate

3253: .keywords: mesh, elements

3255: .seealso: DMMeshCreate(), DMMeshDistribute()
3256: @*/
3257: PetscErrorCode DMMeshDistributeByFace(DM serialMesh, const char partitioner[], DM *parallelMesh)
3258: {
3259:   ALE::Obj<PETSC_MESH_TYPE> oldMesh;
3260:   PetscErrorCode            ierr;

3263:   DMMeshGetMesh(serialMesh, oldMesh);
3264:   DMMeshCreate(oldMesh->comm(), parallelMesh);
3265:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "I am being lazy, bug me.");
3266: #if 0
3267:   ALE::DistributionNew<PETSC_MESH_TYPE>::distributeMeshAndSectionsV(oldMesh, newMesh, height = 1);
3268: #endif
3269:   return(0);
3270: }

3272: #if defined(PETSC_HAVE_TRIANGLE)
3273: /* Already included since C++ is turned on #include <triangle.h> */

3277: PetscErrorCode TriangleInitInput(struct triangulateio *inputCtx)
3278: {
3280:   inputCtx->numberofpoints             = 0;
3281:   inputCtx->numberofpointattributes    = 0;
3282:   inputCtx->pointlist                  = NULL;
3283:   inputCtx->pointattributelist         = NULL;
3284:   inputCtx->pointmarkerlist            = NULL;
3285:   inputCtx->numberofsegments           = 0;
3286:   inputCtx->segmentlist                = NULL;
3287:   inputCtx->segmentmarkerlist          = NULL;
3288:   inputCtx->numberoftriangleattributes = 0;
3289:   inputCtx->trianglelist               = NULL;
3290:   inputCtx->numberofholes              = 0;
3291:   inputCtx->holelist                   = NULL;
3292:   inputCtx->numberofregions            = 0;
3293:   inputCtx->regionlist                 = NULL;
3294:   return(0);
3295: }

3299: PetscErrorCode TriangleInitOutput(struct triangulateio *outputCtx)
3300: {
3302:   outputCtx->numberofpoints        = 0;
3303:   outputCtx->pointlist             = NULL;
3304:   outputCtx->pointattributelist    = NULL;
3305:   outputCtx->pointmarkerlist       = NULL;
3306:   outputCtx->numberoftriangles     = 0;
3307:   outputCtx->trianglelist          = NULL;
3308:   outputCtx->triangleattributelist = NULL;
3309:   outputCtx->neighborlist          = NULL;
3310:   outputCtx->segmentlist           = NULL;
3311:   outputCtx->segmentmarkerlist     = NULL;
3312:   outputCtx->edgelist              = NULL;
3313:   outputCtx->edgemarkerlist        = NULL;
3314:   return(0);
3315: }

3319: PetscErrorCode TriangleFiniOutput(struct triangulateio *outputCtx)
3320: {
3322:   free(outputCtx->pointmarkerlist);
3323:   free(outputCtx->edgelist);
3324:   free(outputCtx->edgemarkerlist);
3325:   free(outputCtx->trianglelist);
3326:   free(outputCtx->neighborlist);
3327:   return(0);
3328: }

3332: PetscErrorCode DMMeshGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm)
3333: {
3334:   MPI_Comm             comm             = ((PetscObject) boundary)->comm;
3335:   DM_Mesh              *bd              = (DM_Mesh*) boundary->data;
3336:   PetscInt             dim              = 2;
3337:   const PetscBool      createConvexHull = PETSC_FALSE;
3338:   const PetscBool      constrained      = PETSC_FALSE;
3339:   struct triangulateio in;
3340:   struct triangulateio out;
3341:   PetscInt             vStart, vEnd, v, eStart, eEnd, e;
3342:   PetscMPIInt          rank;
3343:   PetscErrorCode       ierr;

3346:   MPI_Comm_rank(comm, &rank);
3347:   TriangleInitInput(&in);
3348:   TriangleInitOutput(&out);
3349:   DMMeshGetDepthStratum(boundary, 0, &vStart, &vEnd);

3351:   in.numberofpoints = vEnd - vStart;
3352:   if (in.numberofpoints > 0) {
3353:     PetscScalar *array;

3355:     PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);
3356:     PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);
3357:     VecGetArray(bd->coordinates, &array);
3358:     for (v = vStart; v < vEnd; ++v) {
3359:       const PetscInt idx = v - vStart;
3360:       PetscInt       off, d;

3362:       PetscSectionGetOffset(bd->coordSection, v, &off);
3363:       for (d = 0; d < dim; ++d) {
3364:         in.pointlist[idx*dim + d] = array[off+d];
3365:       }
3366:       DMMeshGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);
3367:     }
3368:     VecRestoreArray(bd->coordinates, &array);
3369:   }
3370:   DMMeshGetHeightStratum(boundary, 0, &eStart, &eEnd);

3372:   in.numberofsegments = eEnd - eStart;
3373:   if (in.numberofsegments > 0) {
3374:     PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);
3375:     PetscMalloc(in.numberofsegments   * sizeof(int), &in.segmentmarkerlist);
3376:     for (e = eStart; e < eEnd; ++e) {
3377:       const PetscInt idx = e - eStart;
3378:       const PetscInt *cone;

3380:       DMMeshGetCone(boundary, e, &cone);

3382:       in.segmentlist[idx*2+0] = cone[0] - vStart;
3383:       in.segmentlist[idx*2+1] = cone[1] - vStart;

3385:       DMMeshGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);
3386:     }
3387:   }
3388: #if 0 /* Do not currently support holes */
3389:   PetscReal *holeCoords;
3390:   PetscInt  h, d;

3392:   DMMeshGetHoles(boundary, &in.numberofholes, &holeCords);
3393:   if (in.numberofholes > 0) {
3394:     PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRXX(ierr);
3395:     for (h = 0; h < in.numberofholes; ++h) {
3396:       for (d = 0; d < dim; ++d) {
3397:         in.holelist[h*dim+d] = holeCoords[h*dim+d];
3398:       }
3399:     }
3400:   }
3401: #endif
3402:   if (!rank) {
3403:     char args[32];

3405:     /* Take away 'Q' for verbose output */
3406:     PetscStrcpy(args, "pqezQ");
3407:     if (createConvexHull) {
3408:       PetscStrcat(args, "c");
3409:     }
3410:     if (constrained) {
3411:       PetscStrcpy(args, "zepDQ");
3412:     }
3413:     triangulate(args, &in, &out, NULL);
3414:   }
3415:   PetscFree(in.pointlist);
3416:   PetscFree(in.pointmarkerlist);
3417:   PetscFree(in.segmentlist);
3418:   PetscFree(in.segmentmarkerlist);
3419:   PetscFree(in.holelist);

3421:   DMCreate(comm, dm);
3422:   DMSetType(*dm, DMMESH);
3423:   DMMeshSetDimension(*dm, dim);
3424:   {
3425:     DM_Mesh        *mesh       = (DM_Mesh*) (*dm)->data;
3426:     const PetscInt numCorners  = 3;
3427:     const PetscInt numCells    = out.numberoftriangles;
3428:     const PetscInt numVertices = out.numberofpoints;
3429:     int            *cells      = out.trianglelist;
3430:     double         *meshCoords = out.pointlist;
3431:     PetscInt       coordSize, c;
3432:     PetscScalar    *coords;

3434:     DMMeshSetChart(*dm, 0, numCells+numVertices);
3435:     for (c = 0; c < numCells; ++c) {
3436:       DMMeshSetConeSize(*dm, c, numCorners);
3437:     }
3438:     DMMeshSetUp(*dm);
3439:     for (c = 0; c < numCells; ++c) {
3440:       PetscInt cone[numCorners] = {cells[c*numCorners+0]+numCells, cells[c*numCorners+1]+numCells, cells[c*numCorners+2]+numCells};

3442:       DMMeshSetCone(*dm, c, cone);
3443:     }
3444:     DMMeshSymmetrize(*dm);
3445:     DMMeshStratify(*dm);
3446:     PetscSectionSetChart(mesh->coordSection, numCells, numCells + numVertices);
3447:     for (v = numCells; v < numCells+numVertices; ++v) {
3448:       PetscSectionSetDof(mesh->coordSection, v, dim);
3449:     }
3450:     PetscSectionSetUp(mesh->coordSection);
3451:     PetscSectionGetStorageSize(mesh->coordSection, &coordSize);
3452:     VecSetSizes(mesh->coordinates, coordSize, PETSC_DETERMINE);
3453:     VecSetFromOptions(mesh->coordinates);
3454:     VecGetArray(mesh->coordinates, &coords);
3455:     for (v = 0; v < numVertices; ++v) {
3456:       coords[v*dim+0] = meshCoords[v*dim+0];
3457:       coords[v*dim+1] = meshCoords[v*dim+1];
3458:     }
3459:     VecRestoreArray(mesh->coordinates, &coords);
3460:     for (v = 0; v < numVertices; ++v) {
3461:       if (out.pointmarkerlist[v]) {
3462:         DMMeshSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);
3463:       }
3464:     }
3465:     if (interpolate) {
3466:       for (e = 0; e < out.numberofedges; e++) {
3467:         if (out.edgemarkerlist[e]) {
3468:           const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
3469:           PetscInt       edge;

3471:           DMMeshJoinPoints(*dm, vertices, &edge); /* 1-level join */
3472:           DMMeshSetLabelValue(*dm, "marker", edge, out.edgemarkerlist[e]);
3473:         }
3474:       }
3475:     }
3476:   }
3477: #if 0 /* Do not currently support holes */
3478:   DMMeshCopyHoles(*dm, boundary);
3479: #endif
3480:   TriangleFiniOutput(&out);
3481:   return(0);
3482: }
3483: #endif

3487: /*@C
3488:   DMMeshGenerate - Generates a mesh.

3490:   Not Collective

3492:   Input Parameters:
3493: + boundary - The DMMesh boundary object
3494: - interpolate - Flag to create intermediate mesh elements

3496:   Output Parameter:
3497: . mesh - The DMMesh object

3499:   Level: intermediate

3501: .keywords: mesh, elements
3502: .seealso: DMMeshCreate(), DMMeshRefine()
3503: @*/
3504: PetscErrorCode DMMeshGenerate(DM boundary, PetscBool interpolate, DM *mesh)
3505: {
3506:   DM_Mesh        *bd = (DM_Mesh*) boundary->data;

3512:   if (bd->useNewImpl) {
3513:     if (interpolate) SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Interpolation (creation of faces and edges) is not yet supported.");
3514: #if defined(PETSC_HAVE_TRIANGLE)
3515:     DMMeshGenerate_Triangle(boundary, interpolate, mesh);
3516: #endif
3517:   } else {
3518:     ALE::Obj<PETSC_MESH_TYPE> mB;

3520:     DMMeshGetMesh(boundary, mB);
3521:     DMMeshCreate(mB->comm(), mesh);
3522:     ALE::Obj<PETSC_MESH_TYPE> m = ALE::Generator<PETSC_MESH_TYPE>::generateMeshV(mB, interpolate, false, true);
3523:     DMMeshSetMesh(*mesh, m);
3524:   }
3525:   return(0);
3526: }

3530: /*@C
3531:   DMMeshRefine - Refines the mesh.

3533:   Not Collective

3535:   Input Parameters:
3536: + mesh - The original DMMesh object
3537: . refinementLimit - The maximum size of any cell
3538: - interpolate - Flag to create intermediate mesh elements

3540:   Output Parameter:
3541: . refinedMesh - The refined DMMesh object

3543:   Level: intermediate

3545: .keywords: mesh, elements
3546: .seealso: DMMeshCreate(), DMMeshGenerate()
3547: @*/
3548: PetscErrorCode DMMeshRefine(DM mesh, double refinementLimit, PetscBool interpolate, DM *refinedMesh)
3549: {
3550:   ALE::Obj<PETSC_MESH_TYPE> oldMesh;
3551:   PetscErrorCode            ierr;

3554:   if (refinementLimit == 0.0) return(0);
3555:   DMMeshGetMesh(mesh, oldMesh);
3556:   DMMeshCreate(oldMesh->comm(), refinedMesh);
3557:   ALE::Obj<PETSC_MESH_TYPE> newMesh = ALE::Generator<PETSC_MESH_TYPE>::refineMeshV(oldMesh, refinementLimit, interpolate, false, true);
3558:   DMMeshSetMesh(*refinedMesh, newMesh);
3559:   return(0);
3560: }

3564: PetscErrorCode DMRefine_Mesh(DM dm, MPI_Comm comm, DM *dmRefined)
3565: {
3566:   ALE::Obj<PETSC_MESH_TYPE> oldMesh;
3567:   double                    refinementLimit;
3568:   PetscErrorCode            ierr;

3571:   DMMeshGetMesh(dm, oldMesh);
3572:   DMMeshCreate(comm, dmRefined);

3574:   refinementLimit = oldMesh->getMaxVolume()/2.0;
3575:   ALE::Obj<PETSC_MESH_TYPE> newMesh = ALE::Generator<PETSC_MESH_TYPE>::refineMeshV(oldMesh, refinementLimit, true);
3576:   DMMeshSetMesh(*dmRefined, newMesh);
3577:   return(0);
3578: }

3582: PetscErrorCode DMCoarsenHierarchy_Mesh(DM mesh, int numLevels, DM *coarseHierarchy)
3583: {
3584:   PetscReal      cfactor = 1.5;

3588:   PetscOptionsReal("-mesh_coarsen_factor", "The coarsening factor", NULL, cfactor, &cfactor, NULL);
3589:   SETERRQ(((PetscObject) mesh)->comm, PETSC_ERR_SUP, "Peter needs to incorporate his code.");
3590:   return(0);
3591: }

3595: PetscErrorCode DMCreateInterpolation_Mesh(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
3596: {
3597:   SETERRQ(((PetscObject) dmCoarse)->comm, PETSC_ERR_SUP, "Peter needs to incorporate his code.");
3598: }

3602: PetscErrorCode DMMeshMarkBoundaryCells(DM dm, const char labelName[], PetscInt marker, PetscInt newMarker)
3603: {
3604:   ALE::Obj<PETSC_MESH_TYPE> mesh;
3605:   PetscErrorCode            ierr;

3608:   DMMeshGetMesh(dm, mesh);
3609:   mesh->markBoundaryCells(labelName, marker, newMarker);
3610:   return(0);
3611: }

3615: PetscErrorCode DMMeshGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end)
3616: {
3617:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

3622:   if (mesh->useNewImpl) {
3623:     SieveLabel next = mesh->labels;
3624:     PetscBool  flg  = PETSC_FALSE;
3625:     PetscInt   depth;

3627:     if (stratumValue < 0) {
3628:       DMMeshGetChart(dm, start, end);
3629:       return(0);
3630:     } else {
3631:       PetscInt pStart, pEnd;

3633:       if (start) *start = 0;
3634:       if (end)   *end   = 0;
3635:       DMMeshGetChart(dm, &pStart, &pEnd);
3636:       if (pStart == pEnd) return(0);
3637:     }
3638:     while (next) {
3639:       PetscStrcmp("depth", next->name, &flg);
3640:       if (flg) break;
3641:       next = next->next;
3642:     }
3643:     if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");
3644:     /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */
3645:     depth = stratumValue;
3646:     if ((depth < 0) || (depth >= next->numStrata)) {
3647:       if (start) *start = 0;
3648:       if (end)   *end   = 0;
3649:     } else {
3650:       if (start) *start = next->points[next->stratumOffsets[depth]];
3651:       if (end)   *end   = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;
3652:     }
3653:   } else {
3654:     ALE::Obj<PETSC_MESH_TYPE> mesh;
3655:     DMMeshGetMesh(dm, mesh);
3656:     if (stratumValue < 0) {
3657:       if (start) *start = mesh->getSieve()->getChart().min();
3658:       if (end)   *end   = mesh->getSieve()->getChart().max();
3659:     } else {
3660:       const Obj<PETSC_MESH_TYPE::label_sequence>& stratum = mesh->depthStratum(stratumValue);
3661:       if (start) *start = *stratum->begin();
3662:       if (end)   *end   = *stratum->rbegin()+1;
3663:     }
3664:   }
3665:   return(0);
3666: }

3670: PetscErrorCode DMMeshGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end)
3671: {
3672:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

3677:   if (mesh->useNewImpl) {
3678:     SieveLabel next = mesh->labels;
3679:     PetscBool  flg  = PETSC_FALSE;
3680:     PetscInt   depth;

3682:     if (stratumValue < 0) {
3683:       DMMeshGetChart(dm, start, end);
3684:     } else {
3685:       PetscInt pStart, pEnd;

3687:       if (start) *start = 0;
3688:       if (end)   *end   = 0;
3689:       DMMeshGetChart(dm, &pStart, &pEnd);
3690:       if (pStart == pEnd) return(0);
3691:     }
3692:     while (next) {
3693:       PetscStrcmp("depth", next->name, &flg);
3694:       if (flg) break;
3695:       next = next->next;
3696:     }
3697:     if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");
3698:     /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */
3699:     depth = next->stratumValues[next->numStrata-1] - stratumValue;
3700:     if ((depth < 0) || (depth >= next->numStrata)) {
3701:       if (start) *start = 0;
3702:       if (end)   *end   = 0;
3703:     } else {
3704:       if (start) *start = next->points[next->stratumOffsets[depth]];
3705:       if (end)   *end   = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;
3706:     }
3707:   } else {
3708:     ALE::Obj<PETSC_MESH_TYPE> mesh;
3709:     DMMeshGetMesh(dm, mesh);
3710:     if (mesh->getLabel("height")->size()) {
3711:       const Obj<PETSC_MESH_TYPE::label_sequence>& stratum = mesh->heightStratum(stratumValue);
3712:       if (start) *start = *stratum->begin();
3713:       if (end)   *end   = *stratum->rbegin()+1;
3714:     } else {
3715:       if (start) *start = 0;
3716:       if (end)   *end   = 0;
3717:     }
3718:   }
3719:   return(0);
3720: }

3724: PetscErrorCode DMMeshCreateSection(DM dm, PetscInt dim, PetscInt numFields, PetscInt numComp[], PetscInt numDof[], PetscInt numBC, PetscInt bcField[], IS bcPoints[], PetscSection *section)
3725: {
3726:   PetscInt       *numDofTot, *maxConstraints;
3727:   PetscInt       pStart = 0, pEnd = 0;

3731:   PetscMalloc2(dim+1,PetscInt,&numDofTot,numFields+1,PetscInt,&maxConstraints);
3732:   for (PetscInt d = 0; d <= dim; ++d) {
3733:     numDofTot[d] = 0;
3734:     for (PetscInt f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d];
3735:   }
3736:   PetscSectionCreate(((PetscObject) dm)->comm, section);
3737:   if (numFields > 1) {
3738:     PetscSectionSetNumFields(*section, numFields);
3739:     if (numComp) {
3740:       for (PetscInt f = 0; f < numFields; ++f) {
3741:         PetscSectionSetFieldComponents(*section, f, numComp[f]);
3742:       }
3743:     }
3744:   } else {
3745:     numFields = 0;
3746:   }
3747:   DMMeshGetChart(dm, &pStart, &pEnd);
3748:   PetscSectionSetChart(*section, pStart, pEnd);
3749:   for (PetscInt d = 0; d <= dim; ++d) {
3750:     DMMeshGetDepthStratum(dm, d, &pStart, &pEnd);
3751:     for (PetscInt p = pStart; p < pEnd; ++p) {
3752:       for (PetscInt f = 0; f < numFields; ++f) {
3753:         PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);
3754:       }
3755:       PetscSectionSetDof(*section, p, numDofTot[d]);
3756:     }
3757:   }
3758:   if (numBC) {
3759:     for (PetscInt f = 0; f <= numFields; ++f) maxConstraints[f] = 0;
3760:     for (PetscInt bc = 0; bc < numBC; ++bc) {
3761:       PetscInt       field = 0;
3762:       const PetscInt *idx;
3763:       PetscInt       n;

3765:       if (numFields) field = bcField[bc];
3766:       ISGetLocalSize(bcPoints[bc], &n);
3767:       ISGetIndices(bcPoints[bc], &idx);
3768:       for (PetscInt i = 0; i < n; ++i) {
3769:         const PetscInt p = idx[i];
3770:         PetscInt       depth, numConst;

3772:         DMMeshGetLabelValue(dm, "depth", p, &depth);
3773:         numConst              = numDof[field*(dim+1)+depth];
3774:         maxConstraints[field] = PetscMax(maxConstraints[field], numConst);
3775:         if (numFields) {
3776:           PetscSectionSetFieldConstraintDof(*section, p, field, numConst);
3777:         }
3778:         PetscSectionAddConstraintDof(*section, p, numConst);
3779:       }
3780:       ISRestoreIndices(bcPoints[bc], &idx);
3781:     }
3782:     for (PetscInt f = 0; f < numFields; ++f) {
3783:       maxConstraints[numFields] += maxConstraints[f];
3784:     }
3785:   }
3786:   PetscSectionSetUp(*section);
3787:   if (maxConstraints[numFields]) {
3788:     PetscInt *indices;

3790:     PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);
3791:     PetscSectionGetChart(*section, &pStart, &pEnd);
3792:     for (PetscInt p = pStart; p < pEnd; ++p) {
3793:       PetscInt cDof;

3795:       PetscSectionGetConstraintDof(*section, p, &cDof);
3796:       if (cDof) {
3797:         if (cDof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %d cDof %d > maxConstraints %d", p, cDof, maxConstraints);
3798:         if (numFields) {
3799:           PetscInt numConst = 0, fOff = 0;

3801:           for (PetscInt f = 0; f < numFields; ++f) {
3802:             PetscInt cfDof, fDof;

3804:             PetscSectionGetFieldDof(*section, p, f, &fDof);
3805:             PetscSectionGetFieldConstraintDof(*section, p, f, &cfDof);
3806:             for (PetscInt d = 0; d < cfDof; ++d) {
3807:               indices[numConst+d] = fOff+d;
3808:             }
3809:             PetscSectionSetFieldConstraintIndices(*section, p, f, &indices[numConst]);
3810:             numConst += cfDof;
3811:             fOff     += fDof;
3812:           }
3813:           if (cDof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %d should be %d", numConst, cDof);
3814:         } else {
3815:           for (PetscInt d = 0; d < cDof; ++d) indices[d] = d;
3816:         }
3817:         PetscSectionSetConstraintIndices(*section, p, indices);
3818:       }
3819:     }
3820:     PetscFree(indices);
3821:   }
3822:   PetscFree2(numDofTot,maxConstraints);
3823:   {
3824:     PetscBool view = PETSC_FALSE;

3826:     PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);
3827:     if (view) {
3828:       PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);
3829:     }
3830:   }
3831:   return(0);
3832: }

3836: PetscErrorCode DMMeshConvertSection(const ALE::Obj<PETSC_MESH_TYPE>& mesh, const Obj<PETSC_MESH_TYPE::real_section_type>& s, PetscSection *section)
3837: {
3838:   const PetscInt pStart    = s->getChart().min();
3839:   const PetscInt pEnd      = s->getChart().max();
3840:   PetscInt       numFields = s->getNumSpaces();

3844:   PetscSectionCreate(mesh->comm(), section);
3845:   if (numFields) {
3846:     PetscSectionSetNumFields(*section, numFields);
3847:     for (PetscInt f = 0; f < numFields; ++f) {
3848:       PetscSectionSetFieldComponents(*section, f, s->getSpaceComponents(f));
3849:     }
3850:   }
3851:   PetscSectionSetChart(*section, pStart, pEnd);
3852:   for (PetscInt p = pStart; p < pEnd; ++p) {
3853:     PetscSectionSetDof(*section, p, s->getFiberDimension(p));
3854:     for (PetscInt f = 0; f < numFields; ++f) {
3855:       PetscSectionSetFieldDof(*section, p, f, s->getFiberDimension(p, f));
3856:     }
3857:     PetscSectionSetConstraintDof(*section, p, s->getConstraintDimension(p));
3858:     for (PetscInt f = 0; f < numFields; ++f) {
3859:       PetscSectionSetFieldConstraintDof(*section, p, f, s->getConstraintDimension(p, f));
3860:     }
3861:   }
3862:   PetscSectionSetUp(*section);
3863:   for (PetscInt p = pStart; p < pEnd; ++p) {
3864:     PetscSectionSetConstraintIndices(*section, p, (PetscInt*) s->getConstraintDof(p));
3865:     for (PetscInt f = 0; f < numFields; ++f) {
3866:       PetscSectionSetFieldConstraintIndices(*section, p, f, (PetscInt*) s->getConstraintDof(p, f));
3867:     }
3868:   }
3869:   return(0);
3870: }

3874: PetscErrorCode DMMeshGetSection(DM dm, const char name[], PetscSection *section)
3875: {
3876:   ALE::Obj<PETSC_MESH_TYPE> mesh;
3877:   PetscErrorCode            ierr;

3880:   DMMeshGetMesh(dm, mesh);
3881:   DMMeshConvertSection(mesh, mesh->getRealSection(name), section);
3882:   return(0);
3883: }

3887: PetscErrorCode DMMeshSetSection(DM dm, const char name[], PetscSection section)
3888: {
3889:   ALE::Obj<PETSC_MESH_TYPE> mesh;
3890:   PetscErrorCode            ierr;

3893:   DMMeshGetMesh(dm, mesh);
3894:   {
3895:     const Obj<PETSC_MESH_TYPE::real_section_type>& s = mesh->getRealSection(name);
3896:     PetscInt                                       pStart, pEnd, numFields;

3898:     PetscSectionGetChart(section, &pStart, &pEnd);
3899:     s->setChart(PETSC_MESH_TYPE::real_section_type::chart_type(pStart, pEnd));
3900:     PetscSectionGetNumFields(section, &numFields);
3901:     for (PetscInt f = 0; f < numFields; ++f) {
3902:       PetscInt comp;
3903:       PetscSectionGetFieldComponents(section, f, &comp);
3904:       s->addSpace(comp);
3905:     }
3906:     for (PetscInt p = pStart; p < pEnd; ++p) {
3907:       PetscInt fDim, cDim;

3909:       PetscSectionGetDof(section, p, &fDim);
3910:       s->setFiberDimension(p, fDim);
3911:       for (PetscInt f = 0; f < numFields; ++f) {
3912:         PetscSectionGetFieldDof(section, p, f, &fDim);
3913:         s->setFiberDimension(p, fDim, f);
3914:       }
3915:       PetscSectionGetConstraintDof(section, p, &cDim);
3916:       if (cDim) {
3917:         s->setConstraintDimension(p, cDim);
3918:         for (PetscInt f = 0; f < numFields; ++f) {
3919:           PetscSectionGetFieldConstraintDof(section, p, f, &cDim);
3920:           s->setConstraintDimension(p, cDim, f);
3921:         }
3922:       }
3923:     }
3924:     s->allocatePoint();
3925:     for (PetscInt p = pStart; p < pEnd; ++p) {
3926:       const PetscInt *indices;

3928:       PetscSectionGetConstraintIndices(section, p, &indices);
3929:       s->setConstraintDof(p, indices);
3930:       for (PetscInt f = 0; f < numFields; ++f) {
3931:         PetscSectionGetFieldConstraintIndices(section, p, f, &indices);
3932:         s->setConstraintDof(p, indices, f);
3933:       }
3934:     }
3935:     {
3936:       PetscBool isDefault;

3938:       PetscStrcmp(name, "default", &isDefault);
3939:       if (isDefault) {
3940:         PetscInt maxDof = 0;

3942:         for (PetscInt p = pStart; p < pEnd; ++p) {
3943:           PetscInt fDim;

3945:           PetscSectionGetDof(section, p, &fDim);
3946:           maxDof = PetscMax(maxDof, fDim);
3947:         }
3948:         mesh->setMaxDof(maxDof);
3949:       }
3950:     }
3951:   }
3952:   return(0);
3953: }

3957: /*
3958:   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3959: */
3960: PetscErrorCode DMMeshGetDefaultSection(DM dm, PetscSection *section)
3961: {
3962:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

3966:   if (!mesh->defaultSection && !mesh->useNewImpl) {
3967:     DMMeshGetSection(dm, "default", &mesh->defaultSection);
3968:   }
3969:   *section = mesh->defaultSection;
3970:   return(0);
3971: }

3975: /*
3976:   Note: This reference will be stolen, so the user should not destroy this PetscSection.
3977: */
3978: PetscErrorCode DMMeshSetDefaultSection(DM dm, PetscSection section)
3979: {
3980:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

3984:   mesh->defaultSection = section;
3985:   if (!mesh->useNewImpl) {
3986:     DMMeshSetSection(dm, "default", mesh->defaultSection);
3987:   }
3988:   return(0);
3989: }

3993: PetscErrorCode DMMeshGetCoordinateSection(DM dm, PetscSection *section)
3994: {
3995:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

4001:   if (mesh->useNewImpl) *section = mesh->coordSection;
4002:   else {
4003:     DMMeshGetSection(dm, "coordinates", section);
4004:   }
4005:   return(0);
4006: }

4010: PetscErrorCode DMMeshSetCoordinateSection(DM dm, PetscSection section)
4011: {

4015:   DMMeshSetSection(dm, "coordinates", section);
4016:   return(0);
4017: }

4021: PetscErrorCode DMMeshGetConeSection(DM dm, PetscSection *section)
4022: {
4023:   DM_Mesh *mesh = (DM_Mesh*) dm->data;

4027:   if (!mesh->useNewImpl) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This method is only valid for C implementation meshes.");
4028:   if (section) *section = mesh->coneSection;
4029:   return(0);
4030: }

4034: PetscErrorCode DMMeshGetCones(DM dm, PetscInt *cones[])
4035: {
4036:   DM_Mesh *mesh = (DM_Mesh*) dm->data;

4040:   if (!mesh->useNewImpl) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This method is only valid for C implementation meshes.");
4041:   if (cones) *cones = mesh->cones;
4042:   return(0);
4043: }

4047: PetscErrorCode DMMeshCreateConeSection(DM dm, PetscSection *section)
4048: {
4049:   ALE::Obj<PETSC_MESH_TYPE> mesh;
4050:   PetscInt                  p;
4051:   PetscErrorCode            ierr;

4054:   DMMeshGetMesh(dm, mesh);
4055:   PetscSectionCreate(((PetscObject) dm)->comm, section);
4056:   PetscSectionSetChart(*section, mesh->getSieve()->getChart().min(), mesh->getSieve()->getChart().max());
4057:   for (p = mesh->getSieve()->getChart().min(); p < mesh->getSieve()->getChart().max(); ++p) {
4058:     PetscSectionSetDof(*section, p, mesh->getSieve()->getConeSize(p));
4059:   }
4060:   PetscSectionSetUp(*section);
4061:   return(0);
4062: }

4066: PetscErrorCode DMMeshGetCoordinateVec(DM dm, Vec *coordinates)
4067: {
4068:   DM_Mesh        *mesh = (DM_Mesh*) dm->data;

4074:   if (mesh->useNewImpl) *coordinates = mesh->coordinates;
4075:   else {
4076:     ALE::Obj<PETSC_MESH_TYPE> mesh;
4077:     DMMeshGetMesh(dm, mesh);
4078:     const Obj<PETSC_MESH_TYPE::real_section_type>& coords = mesh->getRealSection("coordinates");
4079:     VecCreateSeqWithArray(PETSC_COMM_SELF,1, coords->getStorageSize(), coords->restrictSpace(), coordinates);
4080:   }
4081:   return(0);
4082: }

4086: PetscErrorCode DMMeshComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ)
4087: {
4088:   ALE::Obj<PETSC_MESH_TYPE> mesh;
4089:   PetscErrorCode            ierr;

4092:   DMMeshGetMesh(dm, mesh);
4093:   {
4094:     ALE::Obj<PETSC_MESH_TYPE::real_section_type> coordinates = mesh->getRealSection("coordinates");

4096:     mesh->computeElementGeometry(coordinates, cell, v0, J, invJ, *detJ);
4097:   }
4098:   return(0);
4099: }

4103: PetscErrorCode DMMeshVecGetClosure(DM dm, Vec v, PetscInt point, const PetscScalar *values[])
4104: {
4105:   ALE::Obj<PETSC_MESH_TYPE> mesh;
4106:   PetscErrorCode            ierr;

4109: #if defined(PETSC_USE_COMPLEX)
4110:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "DMMesh does not support complex closure");
4111: #else
4112:   DMMeshGetMesh(dm, mesh);
4113:   /* Peeling back IMesh::restrictClosure() */
4114:   try {
4115:     typedef ALE::ISieveVisitor::RestrictVecVisitor<PetscScalar> visitor_type;
4116:     PetscSection section;
4117:     PetscScalar  *array;
4118:     PetscInt     numFields;

4120:     DMMeshGetDefaultSection(dm, &section);
4121:     PetscSectionGetNumFields(section, &numFields);
4122:     const PetscInt size = mesh->sizeWithBC(section, point); /* OPT: This can be precomputed */
4123:     DMGetWorkArray(dm, 2*size+numFields+1, PETSC_SCALAR, &array);
4124:     visitor_type rV(v, section, size, array, (PetscInt*) &array[2*size], (PetscInt*) &array[size]);
4125:     if (mesh->depth() == 1) {
4126:       rV.visitPoint(point, 0);
4127:       // Cone is guarateed to be ordered correctly
4128:       mesh->getSieve()->orientedCone(point, rV);
4129:     } else {
4130:       ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type,visitor_type> pV((int) pow((double) mesh->getSieve()->getMaxConeSize(), mesh->depth())+1, rV, true);

4132:       ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*mesh->getSieve(), point, pV);
4133:     }
4134:     *values = rV.getValues();
4135:   } catch(ALE::Exception e) {
4136:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid argument: %s", e.message());
4137:   } catch(PETSc::Exception e) {
4138:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid argument: %s", e.message());
4139:   }
4140: #endif
4141:   return(0);
4142: }

4146: PetscErrorCode DMMeshVecRestoreClosure(DM dm, Vec v, PetscInt point, const PetscScalar *values[])
4147: {

4151:   DMRestoreWorkArray(dm, 0, PETSC_SCALAR, values);
4152:   return(0);
4153: }

4157: PetscErrorCode DMMeshVecSetClosure(DM dm, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
4158: {
4159:   ALE::Obj<PETSC_MESH_TYPE> mesh;
4160:   PetscErrorCode            ierr;

4163: #if defined(PETSC_USE_COMPLEX)
4164:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "DMMesh does not support complex closure");
4165: #else
4166:   DMMeshGetMesh(dm, mesh);
4167:   /* Peeling back IMesh::update() and IMesh::updateAdd() */
4168:   try {
4169:     typedef ALE::ISieveVisitor::UpdateVecVisitor<PetscScalar> visitor_type;
4170:     PetscSection section;
4171:     PetscInt     *fieldSize;
4172:     PetscInt     numFields;

4174:     DMMeshGetDefaultSection(dm, &section);
4175:     PetscSectionGetNumFields(section, &numFields);
4176:     DMGetWorkArray(dm, numFields, PETSC_INT, &fieldSize);
4177:     mesh->sizeWithBC(section, point, fieldSize); /* OPT: This can be precomputed */
4178:     visitor_type uV(v, section, values, mode, numFields, fieldSize);
4179:     if (mesh->depth() == 1) {
4180:       uV.visitPoint(point, 0);
4181:       // Cone is guarateed to be ordered correctly
4182:       mesh->getSieve()->orientedCone(point, uV);
4183:     } else {
4184:       ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type,visitor_type> pV((int) pow((double) mesh->getSieve()->getMaxConeSize(), mesh->depth())+1, uV, true);

4186:       ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*mesh->getSieve(), point, pV);
4187:     }
4188:     DMRestoreWorkArray(dm, numFields, PETSC_INT, &fieldSize);
4189:   } catch(ALE::Exception e) {
4190:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid argument: %s", e.message());
4191:   }
4192: #endif
4193:   return(0);
4194: }

4198: PetscErrorCode DMMeshMatSetClosure(DM dm, Mat A, PetscInt point, PetscScalar values[], InsertMode mode)
4199: {
4200:   ALE::Obj<PETSC_MESH_TYPE> mesh;
4201:   PetscErrorCode            ierr;

4204: #if defined(PETSC_USE_COMPLEX)
4205:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "DMMesh does not support complex closure");
4206: #else
4207:   DMMeshGetMesh(dm, mesh);
4208:   /* Copying from updateOperator() */
4209:   try {
4210:     typedef ALE::ISieveVisitor::IndicesVisitor<PetscSection,PETSC_MESH_TYPE::order_type,PetscInt> visitor_type;
4211:     ALE::Obj<PETSC_MESH_TYPE::real_section_type> s           = mesh->getRealSection("default");
4212:     const ALE::Obj<PETSC_MESH_TYPE::order_type>& globalOrder = mesh->getFactory()->getGlobalOrder(mesh, s->getName(), s);
4213:     PetscSection                                 section;
4214:     PetscInt                                     numFields;
4215:     PetscInt                                     *fieldSize = NULL;

4217:     DMMeshGetDefaultSection(dm, &section);
4218:     PetscSectionGetNumFields(section, &numFields);
4219:     if (numFields) {
4220:       DMGetWorkArray(dm, numFields, PETSC_INT, &fieldSize);
4221:       mesh->sizeWithBC(section, point, fieldSize); /* OPT: This can be precomputed */
4222:     }
4223:     visitor_type iV(section, *globalOrder, (int) pow((double) mesh->getSieve()->getMaxConeSize(), mesh->depth())*mesh->getMaxDof(), mesh->depth() > 1, fieldSize);

4225:     updateOperator(A, *mesh->getSieve(), iV, point, values, mode);
4226:     if (numFields) {
4227:       DMRestoreWorkArray(dm, numFields, PETSC_INT, &fieldSize);
4228:     }
4229:   } catch(ALE::Exception e) {
4230:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid argument: %s", e.message());
4231:   }
4232: #endif
4233:   return(0);
4234: }

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

4241:   Not Collective

4243:   Input Parameters:
4244: + mesh - The DMMesh object
4245: - name - The section name

4247:   Output Parameter:
4248: . flag - True if the SectionReal is present in the DMMesh

4250:   Level: intermediate

4252: .keywords: mesh, elements
4253: .seealso: DMMeshCreate()
4254: @*/
4255: PetscErrorCode DMMeshHasSectionReal(DM dm, const char name[], PetscBool  *flag)
4256: {
4257:   ALE::Obj<PETSC_MESH_TYPE> m;
4258:   PetscErrorCode            ierr;

4261:   DMMeshGetMesh(dm, m);
4262:   *flag = (PetscBool) m->hasRealSection(std::string(name));
4263:   return(0);
4264: }

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

4271:   Collective on DMMesh

4273:   Input Parameters:
4274: + mesh - The DMMesh object
4275: - name - The section name

4277:   Output Parameter:
4278: . section - The SectionReal

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

4282:   Level: intermediate

4284: .keywords: mesh, elements

4286: .seealso: DMMeshCreate(), SectionRealDestroy()
4287: @*/
4288: PetscErrorCode DMMeshGetSectionReal(DM dm, const char name[], SectionReal *section)
4289: {
4290:   ALE::Obj<PETSC_MESH_TYPE> m;
4291:   bool                      has;
4292:   PetscErrorCode            ierr;

4295:   DMMeshGetMesh(dm, m);
4296:   SectionRealCreate(m->comm(), section);
4297:   PetscObjectSetName((PetscObject) *section, name);
4298:   has  = m->hasRealSection(std::string(name));
4299:   SectionRealSetSection(*section, m->getRealSection(std::string(name)));
4300:   SectionRealSetBundle(*section, m);
4301:   if (!has) {
4302:     m->getRealSection(std::string(name))->setChart(m->getSieve()->getChart());
4303:   }
4304:   return(0);
4305: }

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

4312:   Collective on DMMesh

4314:   Input Parameters:
4315: + mesh - The DMMesh object
4316: - section - The SectionReal

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

4320:   Level: intermediate

4322: .keywords: mesh, elements
4323: .seealso: DMMeshCreate()
4324: @*/
4325: PetscErrorCode DMMeshSetSectionReal(DM dm, const char name[], SectionReal section)
4326: {
4327:   ALE::Obj<PETSC_MESH_TYPE>                    m;
4328:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;
4329:   PetscErrorCode                               ierr;

4332:   DMMeshGetMesh(dm, m);
4333:   PetscObjectGetName((PetscObject) section, &name);
4334:   SectionRealGetSection(section, s);
4335:   m->setRealSection(std::string(name), s);
4336:   return(0);
4337: }

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

4344:   Not Collective

4346:   Input Parameters:
4347: + mesh - The DMMesh object
4348: - name - The section name

4350:   Output Parameter:
4351: . flag - True if the SectionInt is present in the DMMesh

4353:   Level: intermediate

4355: .keywords: mesh, elements
4356: .seealso: DMMeshCreate()
4357: @*/
4358: PetscErrorCode DMMeshHasSectionInt(DM dm, const char name[], PetscBool  *flag)
4359: {
4360:   ALE::Obj<PETSC_MESH_TYPE> m;
4361:   PetscErrorCode            ierr;

4364:   DMMeshGetMesh(dm, m);
4365:   *flag = (PetscBool) m->hasIntSection(std::string(name));
4366:   return(0);
4367: }

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

4374:   Collective on DMMesh

4376:   Input Parameters:
4377: + mesh - The DMMesh object
4378: - name - The section name

4380:   Output Parameter:
4381: . section - The SectionInt

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

4385:   Level: intermediate

4387: .keywords: mesh, elements
4388: .seealso: DMMeshCreate()
4389: @*/
4390: PetscErrorCode DMMeshGetSectionInt(DM dm, const char name[], SectionInt *section)
4391: {
4392:   ALE::Obj<PETSC_MESH_TYPE> m;
4393:   bool                      has;
4394:   PetscErrorCode            ierr;

4397:   DMMeshGetMesh(dm, m);
4398:   SectionIntCreate(m->comm(), section);
4399:   PetscObjectSetName((PetscObject) *section, name);
4400:   has  = m->hasIntSection(std::string(name));
4401:   SectionIntSetSection(*section, m->getIntSection(std::string(name)));
4402:   SectionIntSetBundle(*section, m);
4403:   if (!has) m->getIntSection(std::string(name))->setChart(m->getSieve()->getChart());
4404:   return(0);
4405: }

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

4412:   Collective on DMMesh

4414:   Input Parameters:
4415: + mesh - The DMMesh object
4416: - section - The SectionInt

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

4420:   Level: intermediate

4422: .keywords: mesh, elements
4423: .seealso: DMMeshCreate()
4424: @*/
4425: PetscErrorCode DMMeshSetSectionInt(DM dm, SectionInt section)
4426: {
4427:   ALE::Obj<PETSC_MESH_TYPE>                   m;
4428:   ALE::Obj<PETSC_MESH_TYPE::int_section_type> s;
4429:   const char                                  *name;
4430:   PetscErrorCode                              ierr;

4433:   DMMeshGetMesh(dm, m);
4434:   PetscObjectGetName((PetscObject) section, &name);
4435:   SectionIntGetSection(section, s);
4436:   m->setIntSection(std::string(name), s);
4437:   return(0);
4438: }

4442: /*@C
4443:   SectionGetArray - Returns the array underlying the Section.

4445:   Not Collective

4447:   Input Parameters:
4448: + mesh - The DMMesh object
4449: - name - The section name

4451:   Output Parameters:
4452: + numElements - The number of mesh element with values
4453: . fiberDim - The number of values per element
4454: - array - The array

4456:   Level: intermediate

4458: .keywords: mesh, elements
4459: .seealso: DMMeshCreate()
4460: @*/
4461: PetscErrorCode SectionGetArray(DM dm, const char name[], PetscInt *numElements, PetscInt *fiberDim, PetscScalar *array[])
4462: {
4463:   ALE::Obj<PETSC_MESH_TYPE> m;
4464:   PetscErrorCode            ierr;

4467:   DMMeshGetMesh(dm, m);
4468:   const Obj<PETSC_MESH_TYPE::real_section_type>& section = m->getRealSection(std::string(name));
4469:   if (section->size() == 0) {
4470:     *numElements = 0;
4471:     *fiberDim    = 0;
4472:     *array       = NULL;
4473:     return(0);
4474:   }
4475:   const PETSC_MESH_TYPE::real_section_type::chart_type& chart = section->getChart();
4476: /*   const int                                  depth   = m->depth(*chart.begin()); */
4477: /*   *numElements = m->depthStratum(depth)->size(); */
4478: /*   *fiberDim    = section->getFiberDimension(*chart.begin()); */
4479: /*   *array       = (PetscScalar*) m->restrict(section); */
4480:   int fiberDimMin = section->getFiberDimension(*chart.begin());
4481:   int numElem     = 0;

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

4486:     if (fiberDim < fiberDimMin) fiberDimMin = fiberDim;
4487:   }
4488:   for (PETSC_MESH_TYPE::real_section_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
4489:     const int fiberDim = section->getFiberDimension(*c_iter);

4491:     numElem += fiberDim/fiberDimMin;
4492:   }
4493:   *numElements = numElem;
4494:   *fiberDim    = fiberDimMin;
4495:   *array       = (PetscScalar*) section->restrictSpace();
4496:   return(0);
4497: }

4501: inline void ExpandInterval(const ALE::Point& interval, int indices[], int& indx)
4502: {
4503:   const int end = interval.prefix + interval.index;
4504:   for (int i = interval.index; i < end; i++) indices[indx++] = i;
4505: }

4509: inline void ExpandInterval_New(ALE::Point interval, PetscInt indices[], PetscInt *indx)
4510: {
4511:   for (int i = 0; i < interval.prefix; i++) indices[(*indx)++] = interval.index + i;
4512:   for (int i = 0; i < -interval.prefix; i++) indices[(*indx)++] = -1;
4513: }

4517: /*@
4518:   DMMeshClone - Creates a DMMesh object with the same mesh as the original.

4520:   Collective on MPI_Comm

4522:   Input Parameter:
4523: . dm - The original DMMesh object

4525:   Output Parameter:
4526: . newdm  - The new DMMesh object

4528:   Level: beginner

4530: .keywords: DMMesh, create
4531: @*/
4532: PetscErrorCode DMMeshClone(DM dm, DM *newdm)
4533: {
4534:   ALE::Obj<PETSC_MESH_TYPE> m;
4535:   void                      *ctx;
4536:   PetscErrorCode            ierr;

4541:   DMCreate(((PetscObject) dm)->comm, newdm);
4542:   DMSetType(*newdm, DMMESH);
4543:   DMMeshGetMesh(dm, m);
4544:   ALE::Obj<PETSC_MESH_TYPE> newm = new PETSC_MESH_TYPE(m->comm(), m->getDimension(), m->debug());
4545:   newm->copy(m);
4546:   DMMeshSetMesh(*newdm, newm);
4547:   DMGetApplicationContext(dm, &ctx);
4548:   DMSetApplicationContext(*newdm, ctx);
4549:   return(0);
4550: }