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