xref: /petsc/src/dm/impls/network/network.c (revision e6e75211d226c622f451867f53ce5d558649ff4f)
1 #include <petsc/private/dmnetworkimpl.h>  /*I  "petscdmnetwork.h"  I*/
2 #include <petscdmplex.h>
3 #include <petscsf.h>
4 
5 #undef __FUNCT__
6 #define __FUNCT__ "DMNetworkSetSizes"
7 /*@
8   DMNetworkSetSizes - Sets the local and global vertices and edges.
9 
10   Collective on DM
11 
12   Input Parameters:
13 + dm - the dm object
14 . nV - number of local vertices
15 . nE - number of local edges
16 . NV - number of global vertices (or PETSC_DETERMINE)
17 - NE - number of global edges (or PETSC_DETERMINE)
18 
19    Notes
20    If one processor calls this with NV (NE) of PETSC_DECIDE then all processors must, otherwise the prgram will hang.
21 
22    You cannot change the sizes once they have been set
23 
24    Level: intermediate
25 
26 .seealso: DMNetworkCreate
27 @*/
28 PetscErrorCode DMNetworkSetSizes(DM dm, PetscInt nV, PetscInt nE, PetscInt NV, PetscInt NE)
29 {
30   PetscErrorCode ierr;
31   DM_Network     *network = (DM_Network*) dm->data;
32   PetscInt       a[2],b[2];
33 
34   PetscFunctionBegin;
35   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
36   if (NV > 0) PetscValidLogicalCollectiveInt(dm,NV,4);
37   if (NE > 0) PetscValidLogicalCollectiveInt(dm,NE,5);
38   if (NV > 0 && nV > NV) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local vertex size %D cannot be larger than global vertex size %D",nV,NV);
39   if (NE > 0 && nE > NE) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local edge size %D cannot be larger than global edge size %D",nE,NE);
40   if ((network->nNodes >= 0 || network->NNodes >= 0) && (network->nNodes != nV || network->NNodes != NV)) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot change/reset vertex sizes to %D local %D global after previously setting them to %D local %D global",nV,NV,network->nNodes,network->NNodes);
41   if ((network->nEdges >= 0 || network->NEdges >= 0) && (network->nEdges != nE || network->NEdges != NE)) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot change/reset edge sizes to %D local %D global after previously setting them to %D local %D global",nE,NE,network->nEdges,network->NEdges);
42   if (NE < 0 || NV < 0) {
43     a[0] = nV; a[1] = nE;
44     ierr = MPI_Allreduce(a,b,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
45     NV = b[0]; NE = b[1];
46   }
47   network->nNodes = nV;
48   network->NNodes = NV;
49   network->nEdges = nE;
50   network->NEdges = NE;
51   PetscFunctionReturn(0);
52 }
53 
54 #undef __FUNCT__
55 #define __FUNCT__ "DMNetworkSetEdgeList"
56 /*@
57   DMNetworkSetEdgeList - Sets the list of local edges (vertex connectivity) for the network
58 
59   Logically collective on DM
60 
61   Input Parameters:
62 . edges - list of edges
63 
64   Notes:
65   There is no copy involved in this operation, only the pointer is referenced. The edgelist should
66   not be destroyed before the call to DMNetworkLayoutSetUp
67 
68   Level: intermediate
69 
70 .seealso: DMNetworkCreate, DMNetworkSetSizes
71 @*/
72 PetscErrorCode DMNetworkSetEdgeList(DM dm, int edgelist[])
73 {
74   DM_Network *network = (DM_Network*) dm->data;
75 
76   PetscFunctionBegin;
77   network->edges = edgelist;
78   PetscFunctionReturn(0);
79 }
80 
81 #undef __FUNCT__
82 #define __FUNCT__ "DMNetworkLayoutSetUp"
83 /*@
84   DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network
85 
86   Collective on DM
87 
88   Input Parameters
89 . DM - the dmnetwork object
90 
91   Notes:
92   This routine should be called after the network sizes and edgelists have been provided. It creates
93   the bare layout of the network and sets up the network to begin insertion of components.
94 
95   All the components should be registered before calling this routine.
96 
97   Level: intermediate
98 
99 .seealso: DMNetworkSetSizes, DMNetworkSetEdgeList
100 @*/
101 PetscErrorCode DMNetworkLayoutSetUp(DM dm)
102 {
103   PetscErrorCode ierr;
104   DM_Network     *network = (DM_Network*) dm->data;
105   PetscInt       dim = 1; /* One dimensional network */
106   PetscInt       numCorners=2;
107   PetscInt       spacedim=2;
108   double         *vertexcoords=NULL;
109   PetscInt       i;
110   PetscInt       ndata;
111 
112   PetscFunctionBegin;
113   if (network->nNodes) {
114     ierr = PetscMalloc1(numCorners*network->nNodes,&vertexcoords);CHKERRQ(ierr);
115   }
116   ierr = DMPlexCreateFromCellList(PetscObjectComm((PetscObject)dm),dim,network->nEdges,network->nNodes,numCorners,PETSC_FALSE,network->edges,spacedim,vertexcoords,&network->plex);CHKERRQ(ierr);
117   if (network->nNodes) {
118     ierr = PetscFree(vertexcoords);CHKERRQ(ierr);
119   }
120   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
121   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
122   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
123 
124   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&network->DataSection);CHKERRQ(ierr);
125   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&network->DofSection);CHKERRQ(ierr);
126   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
127   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
128 
129   network->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
130   ierr = PetscMalloc1(network->pEnd-network->pStart,&network->header);CHKERRQ(ierr);
131   for (i = network->pStart; i < network->pEnd; i++) {
132     network->header[i].ndata = 0;
133     ndata = network->header[i].ndata;
134     ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr);
135     network->header[i].offset[ndata] = 0;
136   }
137   ierr = PetscMalloc1(network->pEnd-network->pStart,&network->cvalue);CHKERRQ(ierr);
138   PetscFunctionReturn(0);
139 }
140 
141 #undef __FUNCT__
142 #define __FUNCT__ "DMNetworkRegisterComponent"
143 /*@
144   DMNetworkRegisterComponent - Registers the network component
145 
146   Logically collective on DM
147 
148   Input Parameters
149 + dm   - the network object
150 . name - the component name
151 - size - the storage size in bytes for this component data
152 
153    Output Parameters
154 .   key - an integer key that defines the component
155 
156    Notes
157    This routine should be called by all processors before calling DMNetworkLayoutSetup().
158 
159    Level: intermediate
160 
161 .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
162 @*/
163 PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,PetscInt size,PetscInt *key)
164 {
165   PetscErrorCode        ierr;
166   DM_Network            *network = (DM_Network*) dm->data;
167   DMNetworkComponent    *component=&network->component[network->ncomponent];
168   PetscBool             flg=PETSC_FALSE;
169   PetscInt              i;
170 
171   PetscFunctionBegin;
172 
173   for (i=0; i < network->ncomponent; i++) {
174     ierr = PetscStrcmp(component->name,name,&flg);CHKERRQ(ierr);
175     if (flg) {
176       *key = i;
177       PetscFunctionReturn(0);
178     }
179   }
180 
181   ierr = PetscStrcpy(component->name,name);CHKERRQ(ierr);
182   component->size = size/sizeof(DMNetworkComponentGenericDataType);
183   *key = network->ncomponent;
184   network->ncomponent++;
185   PetscFunctionReturn(0);
186 }
187 
188 #undef __FUNCT__
189 #define __FUNCT__ "DMNetworkGetVertexRange"
190 /*@
191   DMNetworkGetVertexRange - Get the bounds [start, end) for the vertices.
192 
193   Not Collective
194 
195   Input Parameters:
196 + dm - The DMNetwork object
197 
198   Output Paramters:
199 + vStart - The first vertex point
200 - vEnd   - One beyond the last vertex point
201 
202   Level: intermediate
203 
204 .seealso: DMNetworkGetEdgeRange
205 @*/
206 PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd)
207 {
208   DM_Network     *network = (DM_Network*)dm->data;
209 
210   PetscFunctionBegin;
211   if (vStart) *vStart = network->vStart;
212   if (vEnd) *vEnd = network->vEnd;
213   PetscFunctionReturn(0);
214 }
215 
216 #undef __FUNCT__
217 #define __FUNCT__ "DMNetworkGetEdgeRange"
218 /*@
219   DMNetworkGetEdgeRange - Get the bounds [start, end) for the edges.
220 
221   Not Collective
222 
223   Input Parameters:
224 + dm - The DMNetwork object
225 
226   Output Paramters:
227 + eStart - The first edge point
228 - eEnd   - One beyond the last edge point
229 
230   Level: intermediate
231 
232 .seealso: DMNetworkGetVertexRange
233 @*/
234 PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd)
235 {
236   DM_Network     *network = (DM_Network*)dm->data;
237 
238   PetscFunctionBegin;
239   if (eStart) *eStart = network->eStart;
240   if (eEnd) *eEnd = network->eEnd;
241   PetscFunctionReturn(0);
242 }
243 
244 #undef __FUNCT__
245 #define __FUNCT__ "DMNetworkAddComponent"
246 /*@
247   DMNetworkAddComponent - Adds a network component at the given point (vertex/edge)
248 
249   Not Collective
250 
251   Input Parameters:
252 + dm           - The DMNetwork object
253 . p            - vertex/edge point
254 . componentkey - component key returned while registering the component
255 - compvalue    - pointer to the data structure for the component
256 
257   Level: intermediate
258 
259 .seealso: DMNetworkGetVertexRange, DMNetworkGetEdgeRange, DMNetworkRegisterComponent
260 @*/
261 PetscErrorCode DMNetworkAddComponent(DM dm, PetscInt p,PetscInt componentkey,void* compvalue)
262 {
263   DM_Network     *network = (DM_Network*)dm->data;
264   DMNetworkComponent component=network->component[componentkey];
265   DMNetworkComponentHeader header=&network->header[p];
266   DMNetworkComponentValue  cvalue=&network->cvalue[p];
267   PetscErrorCode         ierr;
268 
269   PetscFunctionBegin;
270   header->size[header->ndata] = component.size;
271   ierr = PetscSectionAddDof(network->DataSection,p,component.size);CHKERRQ(ierr);
272   header->key[header->ndata] = componentkey;
273   if (header->ndata != 0) header->offset[header->ndata] = header->offset[header->ndata-1] + header->size[header->ndata-1];
274 
275   cvalue->data[header->ndata] = (void*)compvalue;
276   header->ndata++;
277   PetscFunctionReturn(0);
278 }
279 
280 #undef __FUNCT__
281 #define __FUNCT__ "DMNetworkGetNumComponents"
282 /*@
283   DMNetworkGetNumComponents - Get the number of components at a vertex/edge
284 
285   Not Collective
286 
287   Input Parameters:
288 + dm - The DMNetwork object
289 . p  - vertex/edge point
290 
291   Output Parameters:
292 . numcomponents - Number of components at the vertex/edge
293 
294   Level: intermediate
295 
296 .seealso: DMNetworkRegisterComponent, DMNetworkAddComponent
297 @*/
298 PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents)
299 {
300   PetscErrorCode ierr;
301   PetscInt       offset;
302   DM_Network     *network = (DM_Network*)dm->data;
303 
304   PetscFunctionBegin;
305   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
306   *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
307   PetscFunctionReturn(0);
308 }
309 
310 #undef __FUNCT__
311 #define __FUNCT__ "DMNetworkGetComponentTypeOffset"
312 /*@
313   DMNetworkGetComponentTypeOffset - Gets the type along with the offset for indexing the
314                                     component value from the component data array
315 
316   Not Collective
317 
318   Input Parameters:
319 + dm      - The DMNetwork object
320 . p       - vertex/edge point
321 - compnum - component number
322 
323   Output Parameters:
324 + compkey - the key obtained when registering the component
325 - offset  - offset into the component data array associated with the vertex/edge point
326 
327   Notes:
328   Typical usage:
329 
330   DMNetworkGetComponentDataArray(dm, &arr);
331   DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
332   Loop over vertices or edges
333     DMNetworkGetNumComponents(dm,v,&numcomps);
334     Loop over numcomps
335       DMNetworkGetComponentTypeOffset(dm,v,compnum,&key,&offset);
336       compdata = (UserCompDataType)(arr+offset);
337 
338   Level: intermediate
339 
340 .seealso: DMNetworkGetNumComponents, DMNetworkGetComponentDataArray,
341 @*/
342 PetscErrorCode DMNetworkGetComponentTypeOffset(DM dm,PetscInt p, PetscInt compnum, PetscInt *compkey, PetscInt *offset)
343 {
344   PetscErrorCode ierr;
345   PetscInt       offsetp;
346   DMNetworkComponentHeader header;
347   DM_Network     *network = (DM_Network*)dm->data;
348 
349   PetscFunctionBegin;
350   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
351   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
352   *compkey = header->key[compnum];
353   *offset  = offsetp+network->dataheadersize+header->offset[compnum];
354   PetscFunctionReturn(0);
355 }
356 
357 #undef __FUNCT__
358 #define __FUNCT__ "DMNetworkGetVariableOffset"
359 /*@
360   DMNetworkGetVariableOffset - Get the offset for accessing the variable associated with the given vertex/edge from the local vector.
361 
362   Not Collective
363 
364   Input Parameters:
365 + dm     - The DMNetwork object
366 - p      - the edge/vertex point
367 
368   Output Parameters:
369 . offset - the offset
370 
371   Level: intermediate
372 
373 .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
374 @*/
375 PetscErrorCode DMNetworkGetVariableOffset(DM dm,PetscInt p,PetscInt *offset)
376 {
377   PetscErrorCode ierr;
378   DM_Network     *network = (DM_Network*)dm->data;
379 
380   PetscFunctionBegin;
381   ierr = PetscSectionGetOffset(network->DofSection,p,offset);CHKERRQ(ierr);
382   PetscFunctionReturn(0);
383 }
384 
385 #undef __FUNCT__
386 #define __FUNCT__ "DMNetworkGetVariableGlobalOffset"
387 /*@
388   DMNetworkGetVariableGlobalOffset - Get the global offset for the variable associated with the given vertex/edge from the global vector.
389 
390   Not Collective
391 
392   Input Parameters:
393 + dm      - The DMNetwork object
394 - p       - the edge/vertex point
395 
396   Output Parameters:
397 . offsetg - the offset
398 
399   Level: intermediate
400 
401 .seealso: DMNetworkGetVariableOffset, DMGetLocalVector
402 @*/
403 PetscErrorCode DMNetworkGetVariableGlobalOffset(DM dm,PetscInt p,PetscInt *offsetg)
404 {
405   PetscErrorCode ierr;
406   DM_Network     *network = (DM_Network*)dm->data;
407 
408   PetscFunctionBegin;
409   ierr = PetscSectionGetOffset(network->GlobalDofSection,p,offsetg);CHKERRQ(ierr);
410   PetscFunctionReturn(0);
411 }
412 
413 #undef __FUNCT__
414 #define __FUNCT__ "DMNetworkAddNumVariables"
415 /*@
416   DMNetworkAddNumVariables - Add number of variables associated with a given point.
417 
418   Not Collective
419 
420   Input Parameters:
421 + dm   - The DMNetworkObject
422 . p    - the vertex/edge point
423 - nvar - number of additional variables
424 
425   Level: intermediate
426 
427 .seealso: DMNetworkSetNumVariables
428 @*/
429 PetscErrorCode DMNetworkAddNumVariables(DM dm,PetscInt p,PetscInt nvar)
430 {
431   PetscErrorCode ierr;
432   DM_Network     *network = (DM_Network*)dm->data;
433 
434   PetscFunctionBegin;
435   ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr);
436   PetscFunctionReturn(0);
437 }
438 
439 #undef __FUNCT__
440 #define __FUNCT__ "DMNetworkAddNumVariables"
441 /*@
442   DMNetworkSetNumVariables - Sets number of variables for a vertex/edge point.
443 
444   Not Collective
445 
446   Input Parameters:
447 + dm   - The DMNetworkObject
448 . p    - the vertex/edge point
449 - nvar - number of variables
450 
451   Level: intermediate
452 
453 .seealso: DMNetworkAddNumVariables
454 @*/
455 PetscErrorCode DMNetworkSetNumVariables(DM dm,PetscInt p,PetscInt nvar)
456 {
457   PetscErrorCode ierr;
458   DM_Network     *network = (DM_Network*)dm->data;
459 
460   PetscFunctionBegin;
461   ierr = PetscSectionSetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
462   PetscFunctionReturn(0);
463 }
464 
465 /* Sets up the array that holds the data for all components and its associated section. This
466    function is called during DMSetUp() */
467 #undef __FUNCT__
468 #define __FUNCT__ "DMNetworkComponentSetUp"
469 PetscErrorCode DMNetworkComponentSetUp(DM dm)
470 {
471   PetscErrorCode              ierr;
472   DM_Network     *network = (DM_Network*)dm->data;
473   PetscInt                    arr_size;
474   PetscInt                    p,offset,offsetp;
475   DMNetworkComponentHeader header;
476   DMNetworkComponentValue  cvalue;
477   DMNetworkComponentGenericDataType      *componentdataarray;
478   PetscInt ncomp, i;
479 
480   PetscFunctionBegin;
481   ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr);
482   ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr);
483   ierr = PetscMalloc1(arr_size,&network->componentdataarray);CHKERRQ(ierr);
484   componentdataarray = network->componentdataarray;
485   for (p = network->pStart; p < network->pEnd; p++) {
486     ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
487     /* Copy header */
488     header = &network->header[p];
489     ierr = PetscMemcpy(componentdataarray+offsetp,header,network->dataheadersize*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
490     /* Copy data */
491     cvalue = &network->cvalue[p];
492     ncomp = header->ndata;
493     for (i = 0; i < ncomp; i++) {
494       offset = offsetp + network->dataheadersize + header->offset[i];
495       ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
496     }
497   }
498   PetscFunctionReturn(0);
499 }
500 
501 /* Sets up the section for dofs. This routine is called during DMSetUp() */
502 #undef __FUNCT__
503 #define __FUNCT__ "DMNetworkVariablesSetUp"
504 PetscErrorCode DMNetworkVariablesSetUp(DM dm)
505 {
506   PetscErrorCode ierr;
507   DM_Network     *network = (DM_Network*)dm->data;
508 
509   PetscFunctionBegin;
510   ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr);
511   PetscFunctionReturn(0);
512 }
513 
514 #undef __FUNCT__
515 #define __FUNCT__ "DMNetworkGetComponentDataArray"
516 /*@C
517   DMNetworkGetComponentDataArray - Returns the component data array
518 
519   Not Collective
520 
521   Input Parameters:
522 . dm - The DMNetwork Object
523 
524   Output Parameters:
525 . componentdataarray - array that holds data for all components
526 
527   Level: intermediate
528 
529 .seealso: DMNetworkGetComponentTypeOffset, DMNetworkGetNumComponents
530 @*/
531 PetscErrorCode DMNetworkGetComponentDataArray(DM dm,DMNetworkComponentGenericDataType **componentdataarray)
532 {
533   DM_Network     *network = (DM_Network*)dm->data;
534 
535   PetscFunctionBegin;
536   *componentdataarray = network->componentdataarray;
537   PetscFunctionReturn(0);
538 }
539 
540 #undef __FUNCT__
541 #define __FUNCT__ "DMNetworkDistribute"
542 /*@
543   DMNetworkDistribute - Distributes the network and moves associated component data.
544 
545   Collective
546 
547   Input Parameter:
548 + oldDM - the original DMNetwork object
549 - overlap - The overlap of partitions, 0 is the default
550 
551   Output Parameter:
552 . distDM - the distributed DMNetwork object
553 
554   Notes:
555   This routine should be called only when using multiple processors.
556 
557   Distributes the network with a non-overlapping partitioning of the edges.
558 
559   Level: intermediate
560 
561 .seealso: DMNetworkCreate
562 @*/
563 PetscErrorCode DMNetworkDistribute(DM oldDM, PetscInt overlap,DM *distDM)
564 {
565   PetscErrorCode ierr;
566   DM_Network     *oldDMnetwork = (DM_Network*)oldDM->data;
567   PetscSF        pointsf;
568   DM             newDM;
569   DM_Network     *newDMnetwork;
570 
571   PetscFunctionBegin;
572   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)oldDM),&newDM);CHKERRQ(ierr);
573   newDMnetwork = (DM_Network*)newDM->data;
574   newDMnetwork->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
575   /* Distribute plex dm and dof section */
576   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
577   /* Distribute dof section */
578   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)oldDM),&newDMnetwork->DofSection);CHKERRQ(ierr);
579   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
580   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)oldDM),&newDMnetwork->DataSection);CHKERRQ(ierr);
581   /* Distribute data and associated section */
582   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPI_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
583   /* Destroy point SF */
584   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
585 
586   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
587   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
588   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
589   newDMnetwork->nEdges = newDMnetwork->eEnd - newDMnetwork->eStart;
590   newDMnetwork->nNodes = newDMnetwork->vEnd - newDMnetwork->vStart;
591   newDMnetwork->NNodes = oldDMnetwork->NNodes;
592   newDMnetwork->NEdges = oldDMnetwork->NEdges;
593   /* Set Dof section as the default section for dm */
594   ierr = DMSetDefaultSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
595   ierr = DMGetDefaultGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
596 
597   *distDM = newDM;
598   PetscFunctionReturn(0);
599 }
600 
601 #undef __FUNCT__
602 #define __FUNCT__ "DMNetworkGetSupportingEdges"
603 /*@C
604   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
605 
606   Not Collective
607 
608   Input Parameters:
609 + dm - The DMNetwork object
610 - p  - the vertex point
611 
612   Output Paramters:
613 + nedges - number of edges connected to this vertex point
614 - edges  - List of edge points
615 
616   Level: intermediate
617 
618   Fortran Notes:
619   Since it returns an array, this routine is only available in Fortran 90, and you must
620   include petsc.h90 in your code.
621 
622 .seealso: DMNetworkCreate, DMNetworkGetConnectedNodes
623 @*/
624 PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
625 {
626   PetscErrorCode ierr;
627   DM_Network     *network = (DM_Network*)dm->data;
628 
629   PetscFunctionBegin;
630   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
631   ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);
632   PetscFunctionReturn(0);
633 }
634 
635 #undef __FUNCT__
636 #define __FUNCT__ "DMNetworkGetConnectedNodes"
637 /*@C
638   DMNetworkGetConnectedNodes - Return the connected edges for this edge point
639 
640   Not Collective
641 
642   Input Parameters:
643 + dm - The DMNetwork object
644 - p  - the edge point
645 
646   Output Paramters:
647 . vertices  - vertices connected to this edge
648 
649   Level: intermediate
650 
651   Fortran Notes:
652   Since it returns an array, this routine is only available in Fortran 90, and you must
653   include petsc.h90 in your code.
654 
655 .seealso: DMNetworkCreate, DMNetworkGetSupportingEdges
656 @*/
657 PetscErrorCode DMNetworkGetConnectedNodes(DM dm,PetscInt edge,const PetscInt *vertices[])
658 {
659   PetscErrorCode ierr;
660   DM_Network     *network = (DM_Network*)dm->data;
661 
662   PetscFunctionBegin;
663   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
664   PetscFunctionReturn(0);
665 }
666 
667 #undef __FUNCT__
668 #define __FUNCT__ "DMNetworkIsGhostVertex"
669 /*@
670   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
671 
672   Not Collective
673 
674   Input Parameters:
675 + dm - The DMNetwork object
676 . p  - the vertex point
677 
678   Output Parameter:
679 . isghost - TRUE if the vertex is a ghost point
680 
681   Level: intermediate
682 
683 .seealso: DMNetworkCreate, DMNetworkGetConnectedNodes, DMNetworkGetVertexRange
684 @*/
685 PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
686 {
687   PetscErrorCode ierr;
688   DM_Network     *network = (DM_Network*)dm->data;
689   PetscInt       offsetg;
690   PetscSection   sectiong;
691 
692   PetscFunctionBegin;
693   *isghost = PETSC_FALSE;
694   ierr = DMGetDefaultGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
695   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
696   if (offsetg < 0) *isghost = PETSC_TRUE;
697   PetscFunctionReturn(0);
698 }
699 
700 #undef __FUNCT__
701 #define __FUNCT__ "DMSetUp_Network"
702 PetscErrorCode DMSetUp_Network(DM dm)
703 {
704   PetscErrorCode ierr;
705   DM_Network     *network=(DM_Network*)dm->data;
706 
707   PetscFunctionBegin;
708   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
709   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
710 
711   ierr = DMSetDefaultSection(network->plex,network->DofSection);CHKERRQ(ierr);
712   ierr = DMGetDefaultGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
713   PetscFunctionReturn(0);
714 }
715 
716 #undef __FUNCT__
717 #define __FUNCT__ "DMCreateMatrix_Network"
718 PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
719 {
720   PetscErrorCode ierr;
721   DM_Network     *network = (DM_Network*) dm->data;
722 
723   PetscFunctionBegin;
724   ierr = DMCreateMatrix(network->plex,J);CHKERRQ(ierr);
725   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
726   PetscFunctionReturn(0);
727 }
728 
729 #undef __FUNCT__
730 #define __FUNCT__ "DMDestroy_Network"
731 PetscErrorCode DMDestroy_Network(DM dm)
732 {
733   PetscErrorCode ierr;
734   DM_Network     *network = (DM_Network*) dm->data;
735 
736   PetscFunctionBegin;
737   if (--network->refct > 0) PetscFunctionReturn(0);
738   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
739   network->edges = NULL;
740   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
741   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
742   /*  ierr = PetscSectionDestroy(&network->GlobalDofSection);CHKERRQ(ierr); */
743   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
744   ierr = PetscFree(network->cvalue);CHKERRQ(ierr);
745   ierr = PetscFree(network->header);CHKERRQ(ierr);
746   ierr = PetscFree(network);CHKERRQ(ierr);
747   PetscFunctionReturn(0);
748 }
749 
750 #undef __FUNCT__
751 #define __FUNCT__ "DMView_Network"
752 PetscErrorCode DMView_Network(DM dm, PetscViewer viewer)
753 {
754   PetscErrorCode ierr;
755   DM_Network     *network = (DM_Network*) dm->data;
756 
757   PetscFunctionBegin;
758   ierr = DMView(network->plex,viewer);CHKERRQ(ierr);
759   PetscFunctionReturn(0);
760 }
761 
762 #undef __FUNCT__
763 #define __FUNCT__ "DMGlobalToLocalBegin_Network"
764 PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
765 {
766   PetscErrorCode ierr;
767   DM_Network     *network = (DM_Network*) dm->data;
768 
769   PetscFunctionBegin;
770   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
771   PetscFunctionReturn(0);
772 }
773 
774 #undef __FUNCT__
775 #define __FUNCT__ "DMGlobalToLocalEnd_Network"
776 PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
777 {
778   PetscErrorCode ierr;
779   DM_Network     *network = (DM_Network*) dm->data;
780 
781   PetscFunctionBegin;
782   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
783   PetscFunctionReturn(0);
784 }
785 
786 #undef __FUNCT__
787 #define __FUNCT__ "DMLocalToGlobalBegin_Network"
788 PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
789 {
790   PetscErrorCode ierr;
791   DM_Network     *network = (DM_Network*) dm->data;
792 
793   PetscFunctionBegin;
794   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
795   PetscFunctionReturn(0);
796 }
797 
798 #undef __FUNCT__
799 #define __FUNCT__ "DMLocalToGlobalEnd_Network"
800 PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
801 {
802   PetscErrorCode ierr;
803   DM_Network     *network = (DM_Network*) dm->data;
804 
805   PetscFunctionBegin;
806   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
807   PetscFunctionReturn(0);
808 }
809