xref: /petsc/src/dm/impls/network/network.c (revision fbfcfee5110779e3d6a9465ca0a2e0f9a1a6e5e3) !
1 #include <petsc/private/dmnetworkimpl.h>  /*I  "petscdmnetwork.h"  I*/
2 #include <petscdmplex.h>
3 #include <petscsf.h>
4 
5 /*@
6   DMNetworkSetSizes - Sets the local and global vertices and edges.
7 
8   Collective on DM
9 
10   Input Parameters:
11 + dm - the dm object
12 . nV - number of local vertices
13 . nE - number of local edges
14 . NV - number of global vertices (or PETSC_DETERMINE)
15 - NE - number of global edges (or PETSC_DETERMINE)
16 
17    Notes
18    If one processor calls this with NV (NE) of PETSC_DECIDE then all processors must, otherwise the prgram will hang.
19 
20    You cannot change the sizes once they have been set
21 
22    Level: intermediate
23 
24 .seealso: DMNetworkCreate()
25 @*/
26 PetscErrorCode DMNetworkSetSizes(DM dm, PetscInt nV, PetscInt nE, PetscInt NV, PetscInt NE)
27 {
28   PetscErrorCode ierr;
29   DM_Network     *network = (DM_Network*) dm->data;
30   PetscInt       a[2],b[2];
31 
32   PetscFunctionBegin;
33   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
34   if (NV > 0) PetscValidLogicalCollectiveInt(dm,NV,4);
35   if (NE > 0) PetscValidLogicalCollectiveInt(dm,NE,5);
36   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);
37   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);
38   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);
39   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);
40   if (NE < 0 || NV < 0) {
41     a[0] = nV; a[1] = nE;
42     ierr = MPIU_Allreduce(a,b,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
43     NV = b[0]; NE = b[1];
44   }
45   network->nNodes = nV;
46   network->NNodes = NV;
47   network->nEdges = nE;
48   network->NEdges = NE;
49   PetscFunctionReturn(0);
50 }
51 
52 /*@
53   DMNetworkSetEdgeList - Sets the list of local edges (vertex connectivity) for the network
54 
55   Logically collective on DM
56 
57   Input Parameters:
58 . edges - list of edges
59 
60   Notes:
61   There is no copy involved in this operation, only the pointer is referenced. The edgelist should
62   not be destroyed before the call to DMNetworkLayoutSetUp
63 
64   Level: intermediate
65 
66 .seealso: DMNetworkCreate, DMNetworkSetSizes
67 @*/
68 PetscErrorCode DMNetworkSetEdgeList(DM dm, int edgelist[])
69 {
70   DM_Network *network = (DM_Network*) dm->data;
71 
72   PetscFunctionBegin;
73   network->edges = edgelist;
74   PetscFunctionReturn(0);
75 }
76 
77 /*@
78   DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network
79 
80   Collective on DM
81 
82   Input Parameters
83 . DM - the dmnetwork object
84 
85   Notes:
86   This routine should be called after the network sizes and edgelists have been provided. It creates
87   the bare layout of the network and sets up the network to begin insertion of components.
88 
89   All the components should be registered before calling this routine.
90 
91   Level: intermediate
92 
93 .seealso: DMNetworkSetSizes, DMNetworkSetEdgeList
94 @*/
95 PetscErrorCode DMNetworkLayoutSetUp(DM dm)
96 {
97   PetscErrorCode ierr;
98   DM_Network     *network = (DM_Network*) dm->data;
99   PetscInt       dim = 1; /* One dimensional network */
100   PetscInt       numCorners=2;
101   PetscInt       spacedim=2;
102   double         *vertexcoords=NULL;
103   PetscInt       i;
104   PetscInt       ndata;
105 
106   PetscFunctionBegin;
107   if (network->nNodes) {
108     ierr = PetscCalloc1(numCorners*network->nNodes,&vertexcoords);CHKERRQ(ierr);
109   }
110   ierr = DMPlexCreateFromCellList(PetscObjectComm((PetscObject)dm),dim,network->nEdges,network->nNodes,numCorners,PETSC_FALSE,network->edges,spacedim,vertexcoords,&network->plex);CHKERRQ(ierr);
111   if (network->nNodes) {
112     ierr = PetscFree(vertexcoords);CHKERRQ(ierr);
113   }
114   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
115   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
116   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
117 
118   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&network->DataSection);CHKERRQ(ierr);
119   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&network->DofSection);CHKERRQ(ierr);
120   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
121   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
122 
123 
124 
125   network->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
126   ierr = PetscCalloc1(network->pEnd-network->pStart,&network->header);CHKERRQ(ierr);
127   for (i = network->pStart; i < network->pEnd; i++) {
128     network->header[i].ndata = 0;
129     ndata = network->header[i].ndata;
130     ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr);
131     network->header[i].offset[ndata] = 0;
132   }
133   ierr = PetscMalloc1(network->pEnd-network->pStart,&network->cvalue);CHKERRQ(ierr);
134   PetscFunctionReturn(0);
135 }
136 
137 /*@
138   DMNetworkRegisterComponent - Registers the network component
139 
140   Logically collective on DM
141 
142   Input Parameters
143 + dm   - the network object
144 . name - the component name
145 - size - the storage size in bytes for this component data
146 
147    Output Parameters
148 .   key - an integer key that defines the component
149 
150    Notes
151    This routine should be called by all processors before calling DMNetworkLayoutSetup().
152 
153    Level: intermediate
154 
155 .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
156 @*/
157 PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,PetscInt size,PetscInt *key)
158 {
159   PetscErrorCode        ierr;
160   DM_Network            *network = (DM_Network*) dm->data;
161   DMNetworkComponent    *component=&network->component[network->ncomponent];
162   PetscBool             flg=PETSC_FALSE;
163   PetscInt              i;
164 
165   PetscFunctionBegin;
166 
167   for (i=0; i < network->ncomponent; i++) {
168     ierr = PetscStrcmp(component->name,name,&flg);CHKERRQ(ierr);
169     if (flg) {
170       *key = i;
171       PetscFunctionReturn(0);
172     }
173   }
174 
175   ierr = PetscStrcpy(component->name,name);CHKERRQ(ierr);
176   component->size = size/sizeof(DMNetworkComponentGenericDataType);
177   *key = network->ncomponent;
178   network->ncomponent++;
179   PetscFunctionReturn(0);
180 }
181 
182 /*@
183   DMNetworkGetVertexRange - Get the bounds [start, end) for the vertices.
184 
185   Not Collective
186 
187   Input Parameters:
188 + dm - The DMNetwork object
189 
190   Output Paramters:
191 + vStart - The first vertex point
192 - vEnd   - One beyond the last vertex point
193 
194   Level: intermediate
195 
196 .seealso: DMNetworkGetEdgeRange
197 @*/
198 PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd)
199 {
200   DM_Network     *network = (DM_Network*)dm->data;
201 
202   PetscFunctionBegin;
203   if (vStart) *vStart = network->vStart;
204   if (vEnd) *vEnd = network->vEnd;
205   PetscFunctionReturn(0);
206 }
207 
208 /*@
209   DMNetworkGetEdgeRange - Get the bounds [start, end) for the edges.
210 
211   Not Collective
212 
213   Input Parameters:
214 + dm - The DMNetwork object
215 
216   Output Paramters:
217 + eStart - The first edge point
218 - eEnd   - One beyond the last edge point
219 
220   Level: intermediate
221 
222 .seealso: DMNetworkGetVertexRange
223 @*/
224 PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd)
225 {
226   DM_Network     *network = (DM_Network*)dm->data;
227 
228   PetscFunctionBegin;
229   if (eStart) *eStart = network->eStart;
230   if (eEnd) *eEnd = network->eEnd;
231   PetscFunctionReturn(0);
232 }
233 
234 /*@
235   DMNetworkAddComponent - Adds a network component at the given point (vertex/edge)
236 
237   Not Collective
238 
239   Input Parameters:
240 + dm           - The DMNetwork object
241 . p            - vertex/edge point
242 . componentkey - component key returned while registering the component
243 - compvalue    - pointer to the data structure for the component
244 
245   Level: intermediate
246 
247 .seealso: DMNetworkGetVertexRange, DMNetworkGetEdgeRange, DMNetworkRegisterComponent
248 @*/
249 PetscErrorCode DMNetworkAddComponent(DM dm, PetscInt p,PetscInt componentkey,void* compvalue)
250 {
251   DM_Network               *network = (DM_Network*)dm->data;
252   DMNetworkComponent       *component = &network->component[componentkey];
253   DMNetworkComponentHeader header = &network->header[p];
254   DMNetworkComponentValue  cvalue = &network->cvalue[p];
255   PetscErrorCode           ierr;
256 
257   PetscFunctionBegin;
258   if (header->ndata == MAX_DATA_AT_POINT) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Number of components at a point exceeds the max %D",MAX_DATA_AT_POINT);
259 
260   header->size[header->ndata] = component->size;
261   ierr = PetscSectionAddDof(network->DataSection,p,component->size);CHKERRQ(ierr);
262   header->key[header->ndata] = componentkey;
263   if (header->ndata != 0) header->offset[header->ndata] = header->offset[header->ndata-1] + header->size[header->ndata-1];
264 
265   cvalue->data[header->ndata] = (void*)compvalue;
266   header->ndata++;
267   PetscFunctionReturn(0);
268 }
269 
270 /*@
271   DMNetworkGetNumComponents - Get the number of components at a vertex/edge
272 
273   Not Collective
274 
275   Input Parameters:
276 + dm - The DMNetwork object
277 . p  - vertex/edge point
278 
279   Output Parameters:
280 . numcomponents - Number of components at the vertex/edge
281 
282   Level: intermediate
283 
284 .seealso: DMNetworkRegisterComponent, DMNetworkAddComponent
285 @*/
286 PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents)
287 {
288   PetscErrorCode ierr;
289   PetscInt       offset;
290   DM_Network     *network = (DM_Network*)dm->data;
291 
292   PetscFunctionBegin;
293   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
294   *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
295   PetscFunctionReturn(0);
296 }
297 
298 /*@
299   DMNetworkGetComponentTypeOffset - Gets the type along with the offset for indexing the
300                                     component value from the component data array
301 
302   Not Collective
303 
304   Input Parameters:
305 + dm      - The DMNetwork object
306 . p       - vertex/edge point
307 - compnum - component number
308 
309   Output Parameters:
310 + compkey - the key obtained when registering the component
311 - offset  - offset into the component data array associated with the vertex/edge point
312 
313   Notes:
314   Typical usage:
315 
316   DMNetworkGetComponentDataArray(dm, &arr);
317   DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
318   Loop over vertices or edges
319     DMNetworkGetNumComponents(dm,v,&numcomps);
320     Loop over numcomps
321       DMNetworkGetComponentTypeOffset(dm,v,compnum,&key,&offset);
322       compdata = (UserCompDataType)(arr+offset);
323 
324   Level: intermediate
325 
326 .seealso: DMNetworkGetNumComponents, DMNetworkGetComponentDataArray,
327 @*/
328 PetscErrorCode DMNetworkGetComponentTypeOffset(DM dm,PetscInt p, PetscInt compnum, PetscInt *compkey, PetscInt *offset)
329 {
330   PetscErrorCode           ierr;
331   PetscInt                 offsetp;
332   DMNetworkComponentHeader header;
333   DM_Network               *network = (DM_Network*)dm->data;
334 
335   PetscFunctionBegin;
336   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
337   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
338   if (compkey) *compkey = header->key[compnum];
339   if (offset) *offset  = offsetp+network->dataheadersize+header->offset[compnum];
340   PetscFunctionReturn(0);
341 }
342 
343 /*@
344   DMNetworkGetVariableOffset - Get the offset for accessing the variable associated with the given vertex/edge from the local vector.
345 
346   Not Collective
347 
348   Input Parameters:
349 + dm     - The DMNetwork object
350 - p      - the edge/vertex point
351 
352   Output Parameters:
353 . offset - the offset
354 
355   Level: intermediate
356 
357 .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
358 @*/
359 PetscErrorCode DMNetworkGetVariableOffset(DM dm,PetscInt p,PetscInt *offset)
360 {
361   PetscErrorCode ierr;
362   DM_Network     *network = (DM_Network*)dm->data;
363 
364   PetscFunctionBegin;
365   ierr = PetscSectionGetOffset(network->DofSection,p,offset);CHKERRQ(ierr);
366   PetscFunctionReturn(0);
367 }
368 
369 /*@
370   DMNetworkGetVariableGlobalOffset - Get the global offset for the variable associated with the given vertex/edge from the global vector.
371 
372   Not Collective
373 
374   Input Parameters:
375 + dm      - The DMNetwork object
376 - p       - the edge/vertex point
377 
378   Output Parameters:
379 . offsetg - the offset
380 
381   Level: intermediate
382 
383 .seealso: DMNetworkGetVariableOffset, DMGetLocalVector
384 @*/
385 PetscErrorCode DMNetworkGetVariableGlobalOffset(DM dm,PetscInt p,PetscInt *offsetg)
386 {
387   PetscErrorCode ierr;
388   DM_Network     *network = (DM_Network*)dm->data;
389 
390   PetscFunctionBegin;
391   ierr = PetscSectionGetOffset(network->GlobalDofSection,p,offsetg);CHKERRQ(ierr);
392   if (*offsetg < 0) *offsetg = -(*offsetg + 1); /* Convert to actual global offset for ghost node */
393   PetscFunctionReturn(0);
394 }
395 
396 /*@
397   DMNetworkGetEdgeOffset - Get the offset for accessing the variable associated with the given edge from the local subvector.
398 
399   Not Collective
400 
401   Input Parameters:
402 + dm     - The DMNetwork object
403 - p      - the edge point
404 
405   Output Parameters:
406 . offset - the offset
407 
408   Level: intermediate
409 
410 .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
411 @*/
412 PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset)
413 {
414   PetscErrorCode ierr;
415   DM_Network     *network = (DM_Network*)dm->data;
416 
417   PetscFunctionBegin;
418 
419   ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr);
420   PetscFunctionReturn(0);
421 }
422 
423 /*@
424   DMNetworkGetVertexOffset - Get the offset for accessing the variable associated with the given vertex from the local subvector.
425 
426   Not Collective
427 
428   Input Parameters:
429 + dm     - The DMNetwork object
430 - p      - the vertex point
431 
432   Output Parameters:
433 . offset - the offset
434 
435   Level: intermediate
436 
437 .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
438 @*/
439 PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset)
440 {
441   PetscErrorCode ierr;
442   DM_Network     *network = (DM_Network*)dm->data;
443 
444   PetscFunctionBegin;
445 
446   p -= network->vStart;
447 
448   ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr);
449   PetscFunctionReturn(0);
450 }
451 /*@
452   DMNetworkAddNumVariables - Add number of variables associated with a given point.
453 
454   Not Collective
455 
456   Input Parameters:
457 + dm   - The DMNetworkObject
458 . p    - the vertex/edge point
459 - nvar - number of additional variables
460 
461   Level: intermediate
462 
463 .seealso: DMNetworkSetNumVariables
464 @*/
465 PetscErrorCode DMNetworkAddNumVariables(DM dm,PetscInt p,PetscInt nvar)
466 {
467   PetscErrorCode ierr;
468   DM_Network     *network = (DM_Network*)dm->data;
469 
470   PetscFunctionBegin;
471   ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr);
472   PetscFunctionReturn(0);
473 }
474 
475 /*@
476   DMNetworkGetNumVariables - Gets number of variables for a vertex/edge point.
477 
478   Not Collective
479 
480   Input Parameters:
481 + dm   - The DMNetworkObject
482 - p    - the vertex/edge point
483 
484   Output Parameters:
485 . nvar - number of variables
486 
487   Level: intermediate
488 
489 .seealso: DMNetworkAddNumVariables, DMNetworkSddNumVariables
490 @*/
491 PetscErrorCode DMNetworkGetNumVariables(DM dm,PetscInt p,PetscInt *nvar)
492 {
493   PetscErrorCode ierr;
494   DM_Network     *network = (DM_Network*)dm->data;
495 
496   PetscFunctionBegin;
497   ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
498   PetscFunctionReturn(0);
499 }
500 
501 /*@
502   DMNetworkSetNumVariables - Sets number of variables for a vertex/edge point.
503 
504   Not Collective
505 
506   Input Parameters:
507 + dm   - The DMNetworkObject
508 . p    - the vertex/edge point
509 - nvar - number of variables
510 
511   Level: intermediate
512 
513 .seealso: DMNetworkAddNumVariables
514 @*/
515 PetscErrorCode DMNetworkSetNumVariables(DM dm,PetscInt p,PetscInt nvar)
516 {
517   PetscErrorCode ierr;
518   DM_Network     *network = (DM_Network*)dm->data;
519 
520   PetscFunctionBegin;
521   ierr = PetscSectionSetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
522   PetscFunctionReturn(0);
523 }
524 
525 /* Sets up the array that holds the data for all components and its associated section. This
526    function is called during DMSetUp() */
527 PetscErrorCode DMNetworkComponentSetUp(DM dm)
528 {
529   PetscErrorCode              ierr;
530   DM_Network     *network = (DM_Network*)dm->data;
531   PetscInt                    arr_size;
532   PetscInt                    p,offset,offsetp;
533   DMNetworkComponentHeader header;
534   DMNetworkComponentValue  cvalue;
535   DMNetworkComponentGenericDataType      *componentdataarray;
536   PetscInt ncomp, i;
537 
538   PetscFunctionBegin;
539   ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr);
540   ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr);
541   ierr = PetscMalloc1(arr_size,&network->componentdataarray);CHKERRQ(ierr);
542   componentdataarray = network->componentdataarray;
543   for (p = network->pStart; p < network->pEnd; p++) {
544     ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
545     /* Copy header */
546     header = &network->header[p];
547     ierr = PetscMemcpy(componentdataarray+offsetp,header,network->dataheadersize*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
548     /* Copy data */
549     cvalue = &network->cvalue[p];
550     ncomp = header->ndata;
551     for (i = 0; i < ncomp; i++) {
552       offset = offsetp + network->dataheadersize + header->offset[i];
553       ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
554     }
555   }
556   PetscFunctionReturn(0);
557 }
558 
559 /* Sets up the section for dofs. This routine is called during DMSetUp() */
560 PetscErrorCode DMNetworkVariablesSetUp(DM dm)
561 {
562   PetscErrorCode ierr;
563   DM_Network     *network = (DM_Network*)dm->data;
564 
565   PetscFunctionBegin;
566   ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr);
567   PetscFunctionReturn(0);
568 }
569 
570 /*@C
571   DMNetworkGetComponentDataArray - Returns the component data array
572 
573   Not Collective
574 
575   Input Parameters:
576 . dm - The DMNetwork Object
577 
578   Output Parameters:
579 . componentdataarray - array that holds data for all components
580 
581   Level: intermediate
582 
583 .seealso: DMNetworkGetComponentTypeOffset, DMNetworkGetNumComponents
584 @*/
585 PetscErrorCode DMNetworkGetComponentDataArray(DM dm,DMNetworkComponentGenericDataType **componentdataarray)
586 {
587   DM_Network     *network = (DM_Network*)dm->data;
588 
589   PetscFunctionBegin;
590   *componentdataarray = network->componentdataarray;
591   PetscFunctionReturn(0);
592 }
593 
594 /* Get a subsection from a range of points */
595 PetscErrorCode DMNetworkGetSubSection_private(PetscSection master, PetscInt pstart, PetscInt pend,PetscSection *subsection)
596 {
597   PetscErrorCode ierr;
598   PetscInt       i, nvar;
599 
600   PetscFunctionBegin;
601   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)master), subsection);CHKERRQ(ierr);
602   ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr);
603   for (i = pstart; i < pend; i++) {
604     ierr = PetscSectionGetDof(master,i,&nvar);CHKERRQ(ierr);
605     ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr);
606   }
607 
608   ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr);
609   PetscFunctionReturn(0);
610 }
611 
612 /* Create a submap of points with a GlobalToLocal structure */
613 PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
614 {
615   PetscErrorCode ierr;
616   PetscInt       i, *subpoints;
617 
618   PetscFunctionBegin;
619   /* Create index sets to map from "points" to "subpoints" */
620   ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr);
621   for (i = pstart; i < pend; i++) {
622     subpoints[i - pstart] = i;
623   }
624   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr);
625   ierr = PetscFree(subpoints);CHKERRQ(ierr);
626   PetscFunctionReturn(0);
627 }
628 
629 /*@
630   DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute.
631 
632   Collective
633 
634   Input Parameters:
635 . dm   - The DMNetworkObject
636 
637   Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
638 
639   points = [0 1 2 3 4 5 6]
640 
641   where edges = [0, 3] and vertices = [4, 6]. The new orderings will be specific to the subset (i.e vertices = [0, 2]).
642 
643   With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
644 
645   Level: intermediate
646 
647 @*/
648 PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
649 {
650   PetscErrorCode ierr;
651   MPI_Comm       comm;
652   PetscMPIInt    rank, numProcs;
653   DM_Network     *network = (DM_Network*)dm->data;
654 
655   PetscFunctionBegin;
656   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
657   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
658   ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr);
659 
660   /* Create maps for vertices and edges */
661   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
662   ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr);
663 
664   /* Create local sub-sections */
665   ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr);
666   ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr);
667 
668   if (numProcs > 1) {
669     ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
670     ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr);
671   ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr);
672   ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr);
673   } else {
674   /* create structures for vertex */
675   ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr);
676   /* create structures for edge */
677   ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr);
678   }
679 
680 
681   /* Add viewers */
682   ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr);
683   ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr);
684   ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr);
685   ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr);
686 
687   PetscFunctionReturn(0);
688 }
689 /*@
690   DMNetworkDistribute - Distributes the network and moves associated component data.
691 
692   Collective
693 
694   Input Parameter:
695 + oldDM - the original DMNetwork object
696 - overlap - The overlap of partitions, 0 is the default
697 
698   Output Parameter:
699 . distDM - the distributed DMNetwork object
700 
701   Notes:
702   This routine should be called only when using multiple processors.
703 
704   Distributes the network with <overlap>-overlapping partitioning of the edges.
705 
706   Level: intermediate
707 
708 .seealso: DMNetworkCreate
709 @*/
710 PetscErrorCode DMNetworkDistribute(DM oldDM, PetscInt overlap,DM *distDM)
711 {
712   PetscErrorCode ierr;
713   DM_Network     *oldDMnetwork = (DM_Network*)oldDM->data;
714   PetscSF        pointsf;
715   DM             newDM;
716   DM_Network     *newDMnetwork;
717 
718   PetscFunctionBegin;
719   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)oldDM),&newDM);CHKERRQ(ierr);
720   newDMnetwork = (DM_Network*)newDM->data;
721   newDMnetwork->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
722   /* Distribute plex dm and dof section */
723   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
724   /* Distribute dof section */
725   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)oldDM),&newDMnetwork->DofSection);CHKERRQ(ierr);
726   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
727   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)oldDM),&newDMnetwork->DataSection);CHKERRQ(ierr);
728   /* Distribute data and associated section */
729   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
730 
731 
732   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
733   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
734   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
735   newDMnetwork->nEdges = newDMnetwork->eEnd - newDMnetwork->eStart;
736   newDMnetwork->nNodes = newDMnetwork->vEnd - newDMnetwork->vStart;
737   newDMnetwork->NNodes = oldDMnetwork->NNodes;
738   newDMnetwork->NEdges = oldDMnetwork->NEdges;
739 
740   /* Set Dof section as the default section for dm */
741   ierr = DMSetDefaultSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
742   ierr = DMGetDefaultGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
743 
744   /* Destroy point SF */
745   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
746 
747   *distDM = newDM;
748   PetscFunctionReturn(0);
749 }
750 
751 /*@C
752   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering.
753 
754   Input Parameters:
755 + masterSF - the original SF structure
756 - map      - a ISLocalToGlobal mapping that contains the subset of points
757 
758   Output Parameters:
759 . subSF    - a subset of the masterSF for the desired subset.
760 */
761 
762 PetscErrorCode PetscSFGetSubSF(PetscSF mastersf, ISLocalToGlobalMapping map, PetscSF *subSF) {
763 
764   PetscErrorCode        ierr;
765   PetscInt              nroots, nleaves, *ilocal_sub;
766   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
767   PetscInt              *local_points, *remote_points;
768   PetscSFNode           *iremote_sub;
769   const PetscInt        *ilocal;
770   const PetscSFNode     *iremote;
771 
772   PetscFunctionBegin;
773   ierr = PetscSFGetGraph(mastersf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
774 
775   /* Look for leaves that pertain to the subset of points. Get the local ordering */
776   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
777   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
778   for (i = 0; i < nleaves; i++) {
779     if (ilocal_map[i] != -1) nleaves_sub += 1;
780   }
781   /* Re-number ilocal with subset numbering. Need information from roots */
782   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
783   for (i = 0; i < nroots; i++) local_points[i] = i;
784   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
785   ierr = PetscSFBcastBegin(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
786   ierr = PetscSFBcastEnd(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
787   /* Fill up graph using local (that is, local to the subset) numbering. */
788   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
789   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
790   nleaves_sub = 0;
791   for (i = 0; i < nleaves; i++) {
792     if (ilocal_map[i] != -1) {
793       ilocal_sub[nleaves_sub] = ilocal_map[i];
794       iremote_sub[nleaves_sub].rank = iremote[i].rank;
795       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
796       nleaves_sub += 1;
797     }
798   }
799   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
800   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
801 
802   /* Create new subSF */
803   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
804   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
805   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
806   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
807   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
808 
809   PetscFunctionReturn(0);
810 }
811 
812 
813 /*@C
814   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
815 
816   Not Collective
817 
818   Input Parameters:
819 + dm - The DMNetwork object
820 - p  - the vertex point
821 
822   Output Paramters:
823 + nedges - number of edges connected to this vertex point
824 - edges  - List of edge points
825 
826   Level: intermediate
827 
828   Fortran Notes:
829   Since it returns an array, this routine is only available in Fortran 90, and you must
830   include petsc.h90 in your code.
831 
832 .seealso: DMNetworkCreate, DMNetworkGetConnectedNodes
833 @*/
834 PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
835 {
836   PetscErrorCode ierr;
837   DM_Network     *network = (DM_Network*)dm->data;
838 
839   PetscFunctionBegin;
840   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
841   ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);
842   PetscFunctionReturn(0);
843 }
844 
845 /*@C
846   DMNetworkGetConnectedNodes - Return the connected vertices for this edge point
847 
848   Not Collective
849 
850   Input Parameters:
851 + dm - The DMNetwork object
852 - p  - the edge point
853 
854   Output Paramters:
855 . vertices  - vertices connected to this edge
856 
857   Level: intermediate
858 
859   Fortran Notes:
860   Since it returns an array, this routine is only available in Fortran 90, and you must
861   include petsc.h90 in your code.
862 
863 .seealso: DMNetworkCreate, DMNetworkGetSupportingEdges
864 @*/
865 PetscErrorCode DMNetworkGetConnectedNodes(DM dm,PetscInt edge,const PetscInt *vertices[])
866 {
867   PetscErrorCode ierr;
868   DM_Network     *network = (DM_Network*)dm->data;
869 
870   PetscFunctionBegin;
871   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
872   PetscFunctionReturn(0);
873 }
874 
875 /*@
876   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
877 
878   Not Collective
879 
880   Input Parameters:
881 + dm - The DMNetwork object
882 . p  - the vertex point
883 
884   Output Parameter:
885 . isghost - TRUE if the vertex is a ghost point
886 
887   Level: intermediate
888 
889 .seealso: DMNetworkCreate, DMNetworkGetConnectedNodes, DMNetworkGetVertexRange
890 @*/
891 PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
892 {
893   PetscErrorCode ierr;
894   DM_Network     *network = (DM_Network*)dm->data;
895   PetscInt       offsetg;
896   PetscSection   sectiong;
897 
898   PetscFunctionBegin;
899   *isghost = PETSC_FALSE;
900   ierr = DMGetDefaultGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
901   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
902   if (offsetg < 0) *isghost = PETSC_TRUE;
903   PetscFunctionReturn(0);
904 }
905 
906 PetscErrorCode DMSetUp_Network(DM dm)
907 {
908   PetscErrorCode ierr;
909   DM_Network     *network=(DM_Network*)dm->data;
910 
911   PetscFunctionBegin;
912   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
913   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
914 
915   ierr = DMSetDefaultSection(network->plex,network->DofSection);CHKERRQ(ierr);
916   ierr = DMGetDefaultGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
917   PetscFunctionReturn(0);
918 }
919 
920 /*@
921     DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
922                             -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
923 
924     Collective
925 
926     Input Parameters:
927 +   dm - The DMNetwork object
928 .   eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
929 -   vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
930 
931     Level: intermediate
932 
933 @*/
934 PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
935 {
936   DM_Network     *network=(DM_Network*)dm->data;
937 
938   PetscFunctionBegin;
939   network->userEdgeJacobian   = eflg;
940   network->userVertexJacobian = vflg;
941   PetscFunctionReturn(0);
942 }
943 
944 /*@
945     DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
946 
947     Not Collective
948 
949     Input Parameters:
950 +   dm - The DMNetwork object
951 .   p  - the edge point
952 -   J - array (size = 3) of Jacobian submatrices for this edge point:
953         J[0]: this edge
954         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedNodes()
955 
956     Level: intermediate
957 
958 .seealso: DMNetworkVertexSetMatrix
959 @*/
960 PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
961 {
962   PetscErrorCode ierr;
963   DM_Network     *network=(DM_Network*)dm->data;
964 
965   PetscFunctionBegin;
966   if (!network->userEdgeJacobian) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
967   if (!network->Je) {
968     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
969   }
970   network->Je[3*p]   = J[0];
971   network->Je[3*p+1] = J[1];
972   network->Je[3*p+2] = J[2];
973   PetscFunctionReturn(0);
974 }
975 
976 /*@
977     DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
978 
979     Not Collective
980 
981     Input Parameters:
982 +   dm - The DMNetwork object
983 .   p  - the vertex point
984 -   J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
985         J[0]:       this vertex
986         J[1+2*i]:   i-th supporting edge
987         J[1+2*i+1]: i-th connected vertex
988 
989     Level: intermediate
990 
991 .seealso: DMNetworkEdgeSetMatrix
992 @*/
993 PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
994 {
995   PetscErrorCode ierr;
996   DM_Network     *network=(DM_Network*)dm->data;
997   PetscInt       i,*vptr,nedges,vStart,vEnd;
998   const PetscInt *edges;
999 
1000   PetscFunctionBegin;
1001   if (!network->userVertexJacobian) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
1002 
1003   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
1004 
1005   if (!network->Jv) {
1006     PetscInt nNodes = network->nNodes,nedges_total;
1007     /* count nvertex_total */
1008     nedges_total = 0;
1009     ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
1010     ierr = PetscMalloc1(nNodes+1,&vptr);CHKERRQ(ierr);
1011 
1012     vptr[0] = 0;
1013     for (i=0; i<nNodes; i++) {
1014       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
1015       nedges_total += nedges;
1016       vptr[i+1] = vptr[i] + 2*nedges + 1;
1017     }
1018 
1019     ierr = PetscCalloc1(2*nedges_total+nNodes,&network->Jv);CHKERRQ(ierr);
1020     network->Jvptr = vptr;
1021   }
1022 
1023   vptr = network->Jvptr;
1024   network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
1025 
1026   /* Set Jacobian for each supporting edge and connected vertex */
1027   ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
1028   for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
1029   PetscFunctionReturn(0);
1030 }
1031 
1032 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
1033 {
1034   PetscErrorCode ierr;
1035   PetscInt       j;
1036   PetscScalar    val=(PetscScalar)ncols;
1037 
1038   PetscFunctionBegin;
1039   if (!ghost) {
1040     for (j=0; j<nrows; j++) {
1041       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
1042     }
1043   } else {
1044     for (j=0; j<nrows; j++) {
1045       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
1046     }
1047   }
1048   PetscFunctionReturn(0);
1049 }
1050 
1051 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
1052 {
1053   PetscErrorCode ierr;
1054   PetscInt       j,ncols_u;
1055   PetscScalar    val;
1056 
1057   PetscFunctionBegin;
1058   if (!ghost) {
1059     for (j=0; j<nrows; j++) {
1060       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
1061       val = (PetscScalar)ncols_u;
1062       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
1063       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
1064     }
1065   } else {
1066     for (j=0; j<nrows; j++) {
1067       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
1068       val = (PetscScalar)ncols_u;
1069       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
1070       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
1071     }
1072   }
1073   PetscFunctionReturn(0);
1074 }
1075 
1076 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
1077 {
1078   PetscErrorCode ierr;
1079 
1080   PetscFunctionBegin;
1081   if (Ju) {
1082     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
1083   } else {
1084     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
1085   }
1086   PetscFunctionReturn(0);
1087 }
1088 
1089 PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1090 {
1091   PetscErrorCode ierr;
1092   PetscInt       j,*cols;
1093   PetscScalar    *zeros;
1094 
1095   PetscFunctionBegin;
1096   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
1097   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
1098   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
1099   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
1100   PetscFunctionReturn(0);
1101 }
1102 
1103 PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1104 {
1105   PetscErrorCode ierr;
1106   PetscInt       j,M,N,row,col,ncols_u;
1107   const PetscInt *cols;
1108   PetscScalar    zero=0.0;
1109 
1110   PetscFunctionBegin;
1111   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
1112   if (nrows != M || ncols != N) SETERRQ4(PetscObjectComm((PetscObject)Ju),PETSC_ERR_USER,"%D by %D must equal %D by %D",nrows,ncols,M,N);
1113 
1114   for (row=0; row<nrows; row++) {
1115     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
1116     for (j=0; j<ncols_u; j++) {
1117       col = cols[j] + cstart;
1118       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
1119     }
1120     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
1121   }
1122   PetscFunctionReturn(0);
1123 }
1124 
1125 PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1126 {
1127   PetscErrorCode ierr;
1128 
1129   PetscFunctionBegin;
1130   if (Ju) {
1131     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1132   } else {
1133     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1134   }
1135   PetscFunctionReturn(0);
1136 }
1137 
1138 
1139 /* Creates a GlobalToLocal mapping with a Local and Global section. This is akin to the routine DMGetLocalToGlobalMapping but without the need of providing a dm.
1140 */
1141 PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
1142 {
1143   PetscErrorCode ierr;
1144   PetscInt       i, size, dof;
1145   PetscInt       *glob2loc;
1146 
1147   PetscFunctionBegin;
1148   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
1149   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
1150 
1151   for (i = 0; i < size; i++) {
1152     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
1153     dof = (dof >= 0) ? dof : -(dof + 1);
1154     glob2loc[i] = dof;
1155   }
1156 
1157   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
1158 #if 0
1159   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
1160 #endif
1161   PetscFunctionReturn(0);
1162 }
1163 
1164 PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
1165 {
1166   PetscErrorCode ierr;
1167   PetscMPIInt    rank, size;
1168   DM_Network     *network = (DM_Network*) dm->data;
1169   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
1170   PetscInt       cstart,ncols,j,e,v;
1171   PetscBool      ghost,ghost_vc,ghost2,isNest;
1172   Mat            Juser;
1173   PetscSection   sectionGlobal;
1174   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
1175   const PetscInt *edges,*cone;
1176   MPI_Comm       comm;
1177   MatType        mtype;
1178   Vec            vd_nz,vo_nz;
1179   PetscInt       *dnnz,*onnz;
1180   PetscScalar    *vdnz,*vonz;
1181 
1182   PetscFunctionBegin;
1183   mtype = dm->mattype;
1184   ierr = PetscStrcmp(mtype, MATNEST, &isNest);CHKERRQ(ierr);
1185 
1186   if (isNest) {
1187     /* ierr = DMCreateMatrix_Network_Nest(); */
1188     PetscInt   eDof, vDof;
1189     Mat        j11, j12, j21, j22, bA[2][2];
1190     ISLocalToGlobalMapping eISMap, vISMap;
1191 
1192     ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1193     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1194     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1195 
1196     ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
1197     ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
1198 
1199 #if 0
1200     printf("rank[%d] vdof = %d. edof = %d\n", rank, vDof, eDof);
1201 #endif
1202 
1203     ierr = MatCreate(PETSC_COMM_WORLD, &j11);CHKERRQ(ierr);
1204     ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
1205     ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
1206 
1207     ierr = MatCreate(PETSC_COMM_WORLD, &j12);CHKERRQ(ierr);
1208     ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
1209     ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
1210 
1211     ierr = MatCreate(PETSC_COMM_WORLD, &j21);CHKERRQ(ierr);
1212     ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
1213     ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
1214 
1215     ierr = MatCreate(PETSC_COMM_WORLD, &j22);CHKERRQ(ierr);
1216     ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
1217     ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
1218 
1219     bA[0][0] = j11;
1220     bA[0][1] = j12;
1221     bA[1][0] = j21;
1222     bA[1][1] = j22;
1223 
1224     ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
1225     ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
1226 
1227     ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
1228     ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
1229     ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
1230     ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
1231 
1232     ierr = MatSetUp(j11);CHKERRQ(ierr);
1233     ierr = MatSetUp(j12);CHKERRQ(ierr);
1234     ierr = MatSetUp(j21);CHKERRQ(ierr);
1235     ierr = MatSetUp(j22);CHKERRQ(ierr);
1236 
1237     ierr = MatCreateNest(PETSC_COMM_WORLD,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
1238     ierr = MatSetUp(*J);CHKERRQ(ierr);
1239     ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
1240     ierr = MatDestroy(&j11);CHKERRQ(ierr);
1241     ierr = MatDestroy(&j12);CHKERRQ(ierr);
1242     ierr = MatDestroy(&j21);CHKERRQ(ierr);
1243     ierr = MatDestroy(&j22);CHKERRQ(ierr);
1244 
1245     ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1246     ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1247 
1248     /* Free structures */
1249     ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
1250     ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
1251 
1252     PetscFunctionReturn(0);
1253   } else if (!network->userEdgeJacobian && !network->userVertexJacobian) {
1254     /* user does not provide Jacobian blocks */
1255     ierr = DMCreateMatrix(network->plex,J);CHKERRQ(ierr);
1256     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
1257     PetscFunctionReturn(0);
1258   }
1259 
1260   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
1261   ierr = DMGetDefaultGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
1262   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
1263   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
1264 
1265   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
1266   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
1267 
1268   /* (1) Set matrix preallocation */
1269   /*------------------------------*/
1270   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1271   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
1272   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
1273   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
1274   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
1275   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
1276 
1277   /* Set preallocation for edges */
1278   /*-----------------------------*/
1279   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
1280 
1281   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
1282   for (e=eStart; e<eEnd; e++) {
1283     /* Get row indices */
1284     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
1285     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
1286     if (nrows) {
1287       if (!network->Je) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide Je");
1288       for (j=0; j<nrows; j++) rows[j] = j + rstart;
1289 
1290       /* Set preallocation for conntected vertices */
1291       ierr = DMNetworkGetConnectedNodes(dm,e,&cone);CHKERRQ(ierr);
1292       for (v=0; v<2; v++) {
1293         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
1294 
1295         Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
1296         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
1297         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1298       }
1299 
1300       /* Set preallocation for edge self */
1301       cstart = rstart;
1302       Juser = network->Je[3*e]; /* Jacobian(e,e) */
1303       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1304     }
1305   }
1306 
1307   /* Set preallocation for vertices */
1308   /*--------------------------------*/
1309   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
1310   if (vEnd - vStart) {
1311     if (!network->Jv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide Jv");
1312     vptr = network->Jvptr;
1313     if (!vptr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide vptr");
1314   }
1315 
1316   for (v=vStart; v<vEnd; v++) {
1317     /* Get row indices */
1318     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
1319     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
1320     if (!nrows) continue;
1321 
1322     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1323     if (ghost) {
1324       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
1325     } else {
1326       rows_v = rows;
1327     }
1328 
1329     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1330 
1331     /* Get supporting edges and connected vertices */
1332     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1333 
1334     for (e=0; e<nedges; e++) {
1335       /* Supporting edges */
1336       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
1337       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
1338 
1339       Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
1340       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1341 
1342       /* Connected vertices */
1343       ierr = DMNetworkGetConnectedNodes(dm,edges[e],&cone);CHKERRQ(ierr);
1344       vc = (v == cone[0]) ? cone[1]:cone[0];
1345       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
1346 
1347       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
1348 
1349       Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
1350       if (ghost_vc||ghost) {
1351         ghost2 = PETSC_TRUE;
1352       } else {
1353         ghost2 = PETSC_FALSE;
1354       }
1355       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
1356     }
1357 
1358     /* Set preallocation for vertex self */
1359     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1360     if (!ghost) {
1361       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
1362       Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
1363       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1364     }
1365     if (ghost) {
1366       ierr = PetscFree(rows_v);CHKERRQ(ierr);
1367     }
1368   }
1369 
1370   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
1371   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
1372 
1373   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
1374 
1375   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
1376   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
1377 
1378   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
1379   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
1380   for (j=0; j<localSize; j++) {
1381     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
1382     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
1383   }
1384   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
1385   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
1386   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
1387   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
1388 
1389   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
1390   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
1391   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
1392 
1393   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
1394 
1395   /* (2) Set matrix entries for edges */
1396   /*----------------------------------*/
1397   for (e=eStart; e<eEnd; e++) {
1398     /* Get row indices */
1399     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
1400     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
1401     if (nrows) {
1402       if (!network->Je) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide Je");
1403 
1404       for (j=0; j<nrows; j++) rows[j] = j + rstart;
1405 
1406       /* Set matrix entries for conntected vertices */
1407       ierr = DMNetworkGetConnectedNodes(dm,e,&cone);CHKERRQ(ierr);
1408       for (v=0; v<2; v++) {
1409         ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr);
1410         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
1411 
1412         Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
1413         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1414       }
1415 
1416       /* Set matrix entries for edge self */
1417       cstart = rstart;
1418       Juser = network->Je[3*e]; /* Jacobian(e,e) */
1419       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
1420     }
1421   }
1422 
1423   /* Set matrix entries for vertices */
1424   /*---------------------------------*/
1425   for (v=vStart; v<vEnd; v++) {
1426     /* Get row indices */
1427     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
1428     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
1429     if (!nrows) continue;
1430 
1431     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1432     if (ghost) {
1433       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
1434     } else {
1435       rows_v = rows;
1436     }
1437     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1438 
1439     /* Get supporting edges and connected vertices */
1440     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1441 
1442     for (e=0; e<nedges; e++) {
1443       /* Supporting edges */
1444       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
1445       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
1446 
1447       Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
1448       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
1449 
1450       /* Connected vertices */
1451       ierr = DMNetworkGetConnectedNodes(dm,edges[e],&cone);CHKERRQ(ierr);
1452       vc = (v == cone[0]) ? cone[1]:cone[0];
1453 
1454       ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr);
1455       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
1456 
1457       Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
1458       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
1459     }
1460 
1461     /* Set matrix entries for vertex self */
1462     if (!ghost) {
1463       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
1464       Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
1465       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
1466     }
1467     if (ghost) {
1468       ierr = PetscFree(rows_v);CHKERRQ(ierr);
1469     }
1470   }
1471   ierr = PetscFree(rows);CHKERRQ(ierr);
1472 
1473   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1474   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1475 
1476   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
1477   PetscFunctionReturn(0);
1478 }
1479 
1480 PetscErrorCode DMDestroy_Network(DM dm)
1481 {
1482   PetscErrorCode ierr;
1483   DM_Network     *network = (DM_Network*) dm->data;
1484 
1485   PetscFunctionBegin;
1486   if (--network->refct > 0) PetscFunctionReturn(0);
1487   if (network->Je) {
1488     ierr = PetscFree(network->Je);CHKERRQ(ierr);
1489   }
1490   if (network->Jv) {
1491     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
1492     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
1493   }
1494 
1495   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
1496   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
1497   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
1498   if (network->vertex.sf) {
1499     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
1500   }
1501   /* edge */
1502   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
1503   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
1504   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
1505   if (network->edge.sf) {
1506     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
1507   }
1508   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
1509   network->edges = NULL;
1510   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
1511   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
1512 
1513   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
1514   ierr = PetscFree(network->cvalue);CHKERRQ(ierr);
1515   ierr = PetscFree(network->header);CHKERRQ(ierr);
1516   ierr = PetscFree(network);CHKERRQ(ierr);
1517   PetscFunctionReturn(0);
1518 }
1519 
1520 PetscErrorCode DMView_Network(DM dm, PetscViewer viewer)
1521 {
1522   PetscErrorCode ierr;
1523   DM_Network     *network = (DM_Network*) dm->data;
1524 
1525   PetscFunctionBegin;
1526   ierr = DMView(network->plex,viewer);CHKERRQ(ierr);
1527   PetscFunctionReturn(0);
1528 }
1529 
1530 PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
1531 {
1532   PetscErrorCode ierr;
1533   DM_Network     *network = (DM_Network*) dm->data;
1534 
1535   PetscFunctionBegin;
1536   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
1537   PetscFunctionReturn(0);
1538 }
1539 
1540 PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
1541 {
1542   PetscErrorCode ierr;
1543   DM_Network     *network = (DM_Network*) dm->data;
1544 
1545   PetscFunctionBegin;
1546   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
1547   PetscFunctionReturn(0);
1548 }
1549 
1550 PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
1551 {
1552   PetscErrorCode ierr;
1553   DM_Network     *network = (DM_Network*) dm->data;
1554 
1555   PetscFunctionBegin;
1556   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
1557   PetscFunctionReturn(0);
1558 }
1559 
1560 PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
1561 {
1562   PetscErrorCode ierr;
1563   DM_Network     *network = (DM_Network*) dm->data;
1564 
1565   PetscFunctionBegin;
1566   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
1567   PetscFunctionReturn(0);
1568 }
1569