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