Actual source code: network.c
petsc-3.9.2 2018-05-20
1: #include <petsc/private/dmnetworkimpl.h>
2: #include <petscdmplex.h>
3: #include <petscsf.h>
5: /*@
6: DMNetworkGetPlex - Gets the Plex DM associated with this network DM
8: Not collective
10: Input Parameters:
11: + netdm - the dm object
12: - plexmdm - the plex dm object
14: Level: Advanced
16: .seealso: DMNetworkCreate()
17: @*/
18: PetscErrorCode DMNetworkGetPlex(DM netdm, DM *plexdm)
19: {
20: DM_Network *network = (DM_Network*) netdm->data;
23: *plexdm = network->plex;
24: return(0);
25: }
27: /*@
28: DMNetworkSetSizes - Sets the number of subnetworks, local and global vertices and edges for each subnetwork.
30: Collective on DM
32: Input Parameters:
33: + dm - the dm object
34: . Nsubnet - number of subnetworks
35: . NsubnetCouple - number of coupling subnetworks
36: . nV - number of local vertices for each subnetwork and coupling subnetwork
37: . nE - number of local edges for each subnetwork and coupling subnetwork
38: . NV - number of global vertices (or PETSC_DETERMINE) for each subnetwork and coupling subnetwork
39: - NE - number of global edges (or PETSC_DETERMINE) for each subnetwork and coupling subnetwork
41: Notes
42: If one processor calls this with NV (NE) of PETSC_DECIDE then all processors must, otherwise the prgram will hang.
44: You cannot change the sizes once they have been set. nV, nE, NV and NE are arrays of length Nsubnet+NsubnetCouple.
46: Level: intermediate
48: .seealso: DMNetworkCreate()
49: @*/
50: PetscErrorCode DMNetworkSetSizes(DM dm,PetscInt Nsubnet,PetscInt NsubnetCouple,PetscInt nV[], PetscInt nE[], PetscInt NV[], PetscInt NE[])
51: {
53: DM_Network *network = (DM_Network*) dm->data;
54: PetscInt a[2],b[2],i;
58: if (Nsubnet <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of subnetworks %D cannot be less than 1",Nsubnet);
59: if (NsubnetCouple < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of coupling subnetworks %D cannot be less than 0",NsubnetCouple);
62: if (network->nsubnet != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Network sizes alread set, cannot resize the network");
64: network->nsubnet = Nsubnet + NsubnetCouple;
65: Nsubnet += NsubnetCouple;
66: network->ncsubnet = NsubnetCouple;
67: PetscCalloc1(Nsubnet,&network->subnet);
68: for(i=0; i < Nsubnet; i++) {
69: if (NV) {
71: if (NV[i] > 0 && nV[i] > NV[i]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Subnetwork %D: Local vertex size %D cannot be larger than global vertex size %D",i,nV[i],NV[i]);
72: }
73: if (NE) {
75: if (NE[i] > 0 && nE[i] > NE[i]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Subnetwork %D: Local edge size %D cannot be larger than global edge size %D",i,nE[i],NE[i]);
76: }
78: a[0] = nV[i]; a[1] = nE[i];
79: MPIU_Allreduce(a,b,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));
80: network->subnet[i].Nvtx = b[0]; network->subnet[i].Nedge = b[1];
82: network->subnet[i].id = i;
84: network->subnet[i].nvtx = nV[i];
85: network->subnet[i].vStart = network->nVertices;
86: network->subnet[i].vEnd = network->subnet[i].vStart + network->subnet[i].Nvtx;
87: network->nVertices += network->subnet[i].nvtx;
88: network->NVertices += network->subnet[i].Nvtx;
90: network->subnet[i].nedge = nE[i];
91: network->subnet[i].eStart = network->nEdges;
92: network->subnet[i].eEnd = network->subnet[i].eStart + network->subnet[i].Nedge;
93: network->nEdges += network->subnet[i].nedge;
94: network->NEdges += network->subnet[i].Nedge;
95: }
96: return(0);
97: }
99: /*@
100: DMNetworkSetEdgeList - Sets the list of local edges (vertex connectivity) for the network
102: Logically collective on DM
104: Input Parameters:
105: + dm - the dm object
106: . edgelist - list of edges for each subnetwork
107: - edgelistCouple - list of edges for each coupling subnetwork
109: Notes:
110: There is no copy involved in this operation, only the pointer is referenced. The edgelist should
111: not be destroyed before the call to DMNetworkLayoutSetUp
113: Level: intermediate
115: Example usage:
116: Consider the following 2 separate networks and a coupling network:
118: .vb
119: network 0: v0 -> v1 -> v2 -> v3
120: network 1: v1 -> v2 -> v0
121: coupling network: network 1: v2 -> network 0: v0
122: .ve
124: The resulting input
125: edgelist[0] = [0 1 | 1 2 | 2 3];
126: edgelist[1] = [1 2 | 2 0]
127: edgelistCouple[0] = [(network)1 (v)2 (network)0 (v)0].
129: .seealso: DMNetworkCreate, DMNetworkSetSizes
130: @*/
131: PetscErrorCode DMNetworkSetEdgeList(DM dm,PetscInt *edgelist[],PetscInt *edgelistCouple[])
132: {
133: DM_Network *network = (DM_Network*) dm->data;
134: PetscInt i,nsubnet,ncsubnet=network->ncsubnet;
137: nsubnet = network->nsubnet - ncsubnet;
138: for(i=0; i < nsubnet; i++) {
139: network->subnet[i].edgelist = edgelist[i];
140: }
141: if (edgelistCouple) {
142: PetscInt j;
143: j = 0;
144: nsubnet = network->nsubnet;
145: while (i < nsubnet) network->subnet[i++].edgelist = edgelistCouple[j++];
146: }
147: return(0);
148: }
150: /*@
151: DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network
153: Collective on DM
155: Input Parameters
156: . DM - the dmnetwork object
158: Notes:
159: This routine should be called after the network sizes and edgelists have been provided. It creates
160: the bare layout of the network and sets up the network to begin insertion of components.
162: All the components should be registered before calling this routine.
164: Level: intermediate
166: .seealso: DMNetworkSetSizes, DMNetworkSetEdgeList
167: @*/
168: PetscErrorCode DMNetworkLayoutSetUp(DM dm)
169: {
171: DM_Network *network = (DM_Network*)dm->data;
172: PetscInt dim = 1; /* One dimensional network */
173: PetscInt numCorners=2,spacedim=2;
174: double *vertexcoords=NULL;
175: PetscInt i,j,ndata,ctr=0,nsubnet;
176: PetscInt k,netid,vid;
177: PetscInt *edgelist_couple=NULL;
180: if (network->nVertices) {
181: PetscCalloc1(numCorners*network->nVertices,&vertexcoords);
182: }
184: /* Create the edgelist for the network by concatenating edgelists of the subnetworks */
185: nsubnet = network->nsubnet - network->ncsubnet;
186: PetscCalloc1(2*network->nEdges,&network->edges);
187: for (i=0; i < nsubnet; i++) {
188: for (j = 0; j < network->subnet[i].nedge; j++) {
189: network->edges[2*ctr] = network->subnet[i].vStart + network->subnet[i].edgelist[2*j];
190: network->edges[2*ctr+1] = network->subnet[i].vStart + network->subnet[i].edgelist[2*j+1];
191: ctr++;
192: }
193: }
195: i = nsubnet; /* netid of coupling subnet */
196: nsubnet = network->nsubnet;
197: while (i < nsubnet) {
198: edgelist_couple = network->subnet[i].edgelist;
199: k = 0;
200: for (j = 0; j < network->subnet[i].nedge; j++) {
201: netid = edgelist_couple[k]; vid = edgelist_couple[k+1];
202: network->edges[2*ctr] = network->subnet[netid].vStart + vid; k += 2;
204: netid = edgelist_couple[k]; vid = edgelist_couple[k+1];
205: network->edges[2*ctr+1] = network->subnet[netid].vStart + vid; k+=2;
206: ctr++;
207: }
208: i++;
209: }
211: #if 0
212: for(i=0; i < network->nEdges; i++) {
213: PetscPrintf(PETSC_COMM_SELF,"[%D %D]",network->edges[2*i],network->edges[2*i+1]);
214: printf("\n");
215: }
216: #endif
218: #if defined(PETSC_USE_64BIT_INDICES)
219: {
220: int *edges;
221: PetscInt ii;
222: PetscMalloc1(network->nEdges*numCorners,&edges);
223: for (ii=0; ii<network->nEdges*numCorners; ii++) {
224: edges[ii] = (int) network->edges[ii];
225: }
226: DMPlexCreateFromCellList(PetscObjectComm((PetscObject)dm),dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,edges,spacedim,vertexcoords,&network->plex);
227: PetscFree(edges);
228: }
229: #else
230: DMPlexCreateFromCellList(PetscObjectComm((PetscObject)dm),dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,network->edges,spacedim,vertexcoords,&network->plex);
231: #endif
233: if (network->nVertices) {
234: PetscFree(vertexcoords);
235: }
236: PetscFree(network->edges);
238: DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);
239: DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);
240: DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);
242: PetscSectionCreate(PetscObjectComm((PetscObject)dm),&network->DataSection);
243: PetscSectionCreate(PetscObjectComm((PetscObject)dm),&network->DofSection);
244: PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);
245: PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);
247: /* Create vertices and edges array for the subnetworks */
248: for (j=0; j < network->nsubnet; j++) {
249: PetscCalloc1(network->subnet[j].nedge,&network->subnet[j].edges);
250: PetscCalloc1(network->subnet[j].nvtx,&network->subnet[j].vertices);
251: /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop.
252: These get updated when the vertices and edges are added. */
253: network->subnet[j].nvtx = network->subnet[j].nedge = 0;
254: }
256: network->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
257: PetscCalloc1(network->pEnd-network->pStart,&network->header);
258: for (i=network->eStart; i < network->eEnd; i++) {
259: network->header[i].index = i; /* Global edge number */
260: for (j=0; j < network->nsubnet; j++) {
261: if((network->subnet[j].eStart <= i) && (i < network->subnet[j].eEnd)) {
262: network->header[i].subnetid = j; /* Subnetwork id */
263: network->subnet[j].edges[network->subnet[j].nedge++] = i;
264: break;
265: }
266: }
267: network->header[i].ndata = 0;
268: ndata = network->header[i].ndata;
269: PetscSectionAddDof(network->DataSection,i,network->dataheadersize);
270: network->header[i].offset[ndata] = 0;
271: }
273: for(i=network->vStart; i < network->vEnd; i++) {
274: network->header[i].index = i - network->vStart;
275: for (j=0; j < network->nsubnet; j++) {
276: if ((network->subnet[j].vStart <= i-network->vStart) && (i-network->vStart < network->subnet[j].vEnd)) {
277: network->header[i].subnetid = j;
278: network->subnet[j].vertices[network->subnet[j].nvtx++] = i;
279: break;
280: }
281: }
282: network->header[i].ndata = 0;
283: ndata = network->header[i].ndata;
284: PetscSectionAddDof(network->DataSection,i,network->dataheadersize);
285: network->header[i].offset[ndata] = 0;
286: }
288: PetscMalloc1(network->pEnd-network->pStart,&network->cvalue);
289: return(0);
290: }
292: /*@C
293: DMNetworkGetSubnetworkInfo - Returns the info for the subnetwork
295: Input Parameters
296: + dm - the number object
297: - id - the ID (integer) of the subnetwork
299: Output Parameters
300: + nv - number of vertices (local)
301: . ne - number of edges (local)
302: . vtx - local vertices for this subnetwork
303: . edge - local edges for this subnetwork
305: Notes:
306: Cannot call this routine before DMNetworkLayoutSetup()
308: .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
309: @*/
310: PetscErrorCode DMNetworkGetSubnetworkInfo(DM netdm,PetscInt id,PetscInt *nv, PetscInt *ne,const PetscInt **vtx, const PetscInt **edge)
311: {
312: DM_Network *network = (DM_Network*) netdm->data;
315: *nv = network->subnet[id].nvtx;
316: *ne = network->subnet[id].nedge;
317: *vtx = network->subnet[id].vertices;
318: *edge = network->subnet[id].edges;
319: return(0);
320: }
322: /*@C
323: DMNetworkRegisterComponent - Registers the network component
325: Logically collective on DM
327: Input Parameters
328: + dm - the network object
329: . name - the component name
330: - size - the storage size in bytes for this component data
332: Output Parameters
333: . key - an integer key that defines the component
335: Notes
336: This routine should be called by all processors before calling DMNetworkLayoutSetup().
338: Level: intermediate
340: .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
341: @*/
342: PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,PetscInt size,PetscInt *key)
343: {
344: PetscErrorCode ierr;
345: DM_Network *network = (DM_Network*) dm->data;
346: DMNetworkComponent *component=&network->component[network->ncomponent];
347: PetscBool flg=PETSC_FALSE;
348: PetscInt i;
351: for (i=0; i < network->ncomponent; i++) {
352: PetscStrcmp(component->name,name,&flg);
353: if (flg) {
354: *key = i;
355: return(0);
356: }
357: }
358: if(network->ncomponent == MAX_COMPONENTS) {
359: SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Number of components registered exceeds the max %D",MAX_COMPONENTS);
360: }
362: PetscStrcpy(component->name,name);
363: component->size = size/sizeof(DMNetworkComponentGenericDataType);
364: *key = network->ncomponent;
365: network->ncomponent++;
366: return(0);
367: }
369: /*@
370: DMNetworkGetVertexRange - Get the bounds [start, end) for the vertices.
372: Not Collective
374: Input Parameters:
375: + dm - The DMNetwork object
377: Output Paramters:
378: + vStart - The first vertex point
379: - vEnd - One beyond the last vertex point
381: Level: intermediate
383: .seealso: DMNetworkGetEdgeRange
384: @*/
385: PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd)
386: {
387: DM_Network *network = (DM_Network*)dm->data;
390: if (vStart) *vStart = network->vStart;
391: if (vEnd) *vEnd = network->vEnd;
392: return(0);
393: }
395: /*@
396: DMNetworkGetEdgeRange - Get the bounds [start, end) for the edges.
398: Not Collective
400: Input Parameters:
401: + dm - The DMNetwork object
403: Output Paramters:
404: + eStart - The first edge point
405: - eEnd - One beyond the last edge point
407: Level: intermediate
409: .seealso: DMNetworkGetVertexRange
410: @*/
411: PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd)
412: {
413: DM_Network *network = (DM_Network*)dm->data;
416: if (eStart) *eStart = network->eStart;
417: if (eEnd) *eEnd = network->eEnd;
418: return(0);
419: }
421: /*@
422: DMNetworkGetGlobalEdgeIndex - Get the user global numbering for the edge.
424: Not Collective
426: Input Parameters:
427: + dm - DMNetwork object
428: - p - edge point
430: Output Paramters:
431: . index - user global numbering for the edge
433: Level: intermediate
435: .seealso: DMNetworkGetGlobalVertexIndex
436: @*/
437: PetscErrorCode DMNetworkGetGlobalEdgeIndex(DM dm,PetscInt p,PetscInt *index)
438: {
439: PetscErrorCode ierr;
440: DM_Network *network = (DM_Network*)dm->data;
441: PetscInt offsetp;
442: DMNetworkComponentHeader header;
445: PetscSectionGetOffset(network->DataSection,p,&offsetp);
446: header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
447: *index = header->index;
448: return(0);
449: }
451: /*@
452: DMNetworkGetGlobalVertexIndex - Get the user global numbering for the vertex.
454: Not Collective
456: Input Parameters:
457: + dm - DMNetwork object
458: - p - vertex point
460: Output Paramters:
461: . index - user global numbering for the vertex
463: Level: intermediate
465: .seealso: DMNetworkGetGlobalEdgeIndex
466: @*/
467: PetscErrorCode DMNetworkGetGlobalVertexIndex(DM dm,PetscInt p,PetscInt *index)
468: {
469: PetscErrorCode ierr;
470: DM_Network *network = (DM_Network*)dm->data;
471: PetscInt offsetp;
472: DMNetworkComponentHeader header;
475: PetscSectionGetOffset(network->DataSection,p,&offsetp);
476: header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
477: *index = header->index;
478: return(0);
479: }
481: /*
482: DMNetworkGetComponentKeyOffset - Gets the type along with the offset for indexing the
483: component value from the component data array
485: Not Collective
487: Input Parameters:
488: + dm - The DMNetwork object
489: . p - vertex/edge point
490: - compnum - component number
492: Output Parameters:
493: + compkey - the key obtained when registering the component
494: - offset - offset into the component data array associated with the vertex/edge point
496: Notes:
497: Typical usage:
499: DMNetworkGetComponentDataArray(dm, &arr);
500: DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
501: Loop over vertices or edges
502: DMNetworkGetNumComponents(dm,v,&numcomps);
503: Loop over numcomps
504: DMNetworkGetComponentKeyOffset(dm,v,compnum,&key,&offset);
505: compdata = (UserCompDataType)(arr+offset);
507: Level: intermediate
509: .seealso: DMNetworkGetNumComponents, DMNetworkGetComponentDataArray,
510: */
511: PetscErrorCode DMNetworkGetComponentKeyOffset(DM dm,PetscInt p, PetscInt compnum, PetscInt *compkey, PetscInt *offset)
512: {
513: PetscErrorCode ierr;
514: PetscInt offsetp;
515: DMNetworkComponentHeader header;
516: DM_Network *network = (DM_Network*)dm->data;
519: PetscSectionGetOffset(network->DataSection,p,&offsetp);
520: header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
521: if (compkey) *compkey = header->key[compnum];
522: if (offset) *offset = offsetp+network->dataheadersize+header->offset[compnum];
523: return(0);
524: }
526: /*@
527: DMNetworkGetComponent - Returns the network component and its key
529: Not Collective
531: Input Parameters
532: + dm - DMNetwork object
533: . p - edge or vertex point
534: - compnum - component number
536: Output Parameters:
537: + compkey - the key set for this computing during registration
538: - component - the component data
540: Notes:
541: Typical usage:
543: DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
544: Loop over vertices or edges
545: DMNetworkGetNumComponents(dm,v,&numcomps);
546: Loop over numcomps
547: DMNetworkGetComponent(dm,v,compnum,&key,&component);
549: Level: intermediate
551: .seealso: DMNetworkGetNumComponents, DMNetworkGetVariableOffset
552: @*/
553: PetscErrorCode DMNetworkGetComponent(DM dm, PetscInt p, PetscInt compnum, PetscInt *key, void **component)
554: {
556: DM_Network *network = (DM_Network*)dm->data;
557: PetscInt offsetd;
561: DMNetworkGetComponentKeyOffset(dm,p,compnum,key,&offsetd);
562: *component = network->componentdataarray+offsetd;
564: return(0);
565: }
567: /*@
568: DMNetworkAddComponent - Adds a network component at the given point (vertex/edge)
570: Not Collective
572: Input Parameters:
573: + dm - The DMNetwork object
574: . p - vertex/edge point
575: . componentkey - component key returned while registering the component
576: - compvalue - pointer to the data structure for the component
578: Level: intermediate
580: .seealso: DMNetworkGetVertexRange, DMNetworkGetEdgeRange, DMNetworkRegisterComponent
581: @*/
582: PetscErrorCode DMNetworkAddComponent(DM dm, PetscInt p,PetscInt componentkey,void* compvalue)
583: {
584: DM_Network *network = (DM_Network*)dm->data;
585: DMNetworkComponent *component = &network->component[componentkey];
586: DMNetworkComponentHeader header = &network->header[p];
587: DMNetworkComponentValue cvalue = &network->cvalue[p];
588: PetscErrorCode ierr;
591: 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);
593: header->size[header->ndata] = component->size;
594: PetscSectionAddDof(network->DataSection,p,component->size);
595: header->key[header->ndata] = componentkey;
596: if (header->ndata != 0) header->offset[header->ndata] = header->offset[header->ndata-1] + header->size[header->ndata-1];
598: cvalue->data[header->ndata] = (void*)compvalue;
599: header->ndata++;
600: return(0);
601: }
603: /*@
604: DMNetworkGetNumComponents - Get the number of components at a vertex/edge
606: Not Collective
608: Input Parameters:
609: + dm - The DMNetwork object
610: . p - vertex/edge point
612: Output Parameters:
613: . numcomponents - Number of components at the vertex/edge
615: Level: intermediate
617: .seealso: DMNetworkRegisterComponent, DMNetworkAddComponent
618: @*/
619: PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents)
620: {
622: PetscInt offset;
623: DM_Network *network = (DM_Network*)dm->data;
626: PetscSectionGetOffset(network->DataSection,p,&offset);
627: *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
628: return(0);
629: }
631: /*@
632: DMNetworkGetVariableOffset - Get the offset for accessing the variable associated with the given vertex/edge from the local vector.
634: Not Collective
636: Input Parameters:
637: + dm - The DMNetwork object
638: - p - the edge/vertex point
640: Output Parameters:
641: . offset - the offset
643: Level: intermediate
645: .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
646: @*/
647: PetscErrorCode DMNetworkGetVariableOffset(DM dm,PetscInt p,PetscInt *offset)
648: {
650: DM_Network *network = (DM_Network*)dm->data;
653: PetscSectionGetOffset(network->plex->defaultSection,p,offset);
654: return(0);
655: }
657: /*@
658: DMNetworkGetVariableGlobalOffset - Get the global offset for the variable associated with the given vertex/edge from the global vector.
660: Not Collective
662: Input Parameters:
663: + dm - The DMNetwork object
664: - p - the edge/vertex point
666: Output Parameters:
667: . offsetg - the offset
669: Level: intermediate
671: .seealso: DMNetworkGetVariableOffset, DMGetLocalVector
672: @*/
673: PetscErrorCode DMNetworkGetVariableGlobalOffset(DM dm,PetscInt p,PetscInt *offsetg)
674: {
676: DM_Network *network = (DM_Network*)dm->data;
679: PetscSectionGetOffset(network->plex->defaultGlobalSection,p,offsetg);
680: if (*offsetg < 0) *offsetg = -(*offsetg + 1); /* Convert to actual global offset for ghost vertex */
681: return(0);
682: }
684: /*@
685: DMNetworkGetEdgeOffset - Get the offset for accessing the variable associated with the given edge from the local subvector.
687: Not Collective
689: Input Parameters:
690: + dm - The DMNetwork object
691: - p - the edge point
693: Output Parameters:
694: . offset - the offset
696: Level: intermediate
698: .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
699: @*/
700: PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset)
701: {
703: DM_Network *network = (DM_Network*)dm->data;
707: PetscSectionGetOffset(network->edge.DofSection,p,offset);
708: return(0);
709: }
711: /*@
712: DMNetworkGetVertexOffset - Get the offset for accessing the variable associated with the given vertex from the local subvector.
714: Not Collective
716: Input Parameters:
717: + dm - The DMNetwork object
718: - p - the vertex point
720: Output Parameters:
721: . offset - the offset
723: Level: intermediate
725: .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
726: @*/
727: PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset)
728: {
730: DM_Network *network = (DM_Network*)dm->data;
734: p -= network->vStart;
736: PetscSectionGetOffset(network->vertex.DofSection,p,offset);
737: return(0);
738: }
739: /*@
740: DMNetworkAddNumVariables - Add number of variables associated with a given point.
742: Not Collective
744: Input Parameters:
745: + dm - The DMNetworkObject
746: . p - the vertex/edge point
747: - nvar - number of additional variables
749: Level: intermediate
751: .seealso: DMNetworkSetNumVariables
752: @*/
753: PetscErrorCode DMNetworkAddNumVariables(DM dm,PetscInt p,PetscInt nvar)
754: {
756: DM_Network *network = (DM_Network*)dm->data;
759: PetscSectionAddDof(network->DofSection,p,nvar);
760: return(0);
761: }
763: /*@
764: DMNetworkGetNumVariables - Gets number of variables for a vertex/edge point.
766: Not Collective
768: Input Parameters:
769: + dm - The DMNetworkObject
770: - p - the vertex/edge point
772: Output Parameters:
773: . nvar - number of variables
775: Level: intermediate
777: .seealso: DMNetworkAddNumVariables, DMNetworkSddNumVariables
778: @*/
779: PetscErrorCode DMNetworkGetNumVariables(DM dm,PetscInt p,PetscInt *nvar)
780: {
782: DM_Network *network = (DM_Network*)dm->data;
785: PetscSectionGetDof(network->DofSection,p,nvar);
786: return(0);
787: }
789: /*@
790: DMNetworkSetNumVariables - Sets number of variables for a vertex/edge point.
792: Not Collective
794: Input Parameters:
795: + dm - The DMNetworkObject
796: . p - the vertex/edge point
797: - nvar - number of variables
799: Level: intermediate
801: .seealso: DMNetworkAddNumVariables
802: @*/
803: PetscErrorCode DMNetworkSetNumVariables(DM dm,PetscInt p,PetscInt nvar)
804: {
806: DM_Network *network = (DM_Network*)dm->data;
809: PetscSectionSetDof(network->DofSection,p,nvar);
810: return(0);
811: }
813: /* Sets up the array that holds the data for all components and its associated section. This
814: function is called during DMSetUp() */
815: PetscErrorCode DMNetworkComponentSetUp(DM dm)
816: {
817: PetscErrorCode ierr;
818: DM_Network *network = (DM_Network*)dm->data;
819: PetscInt arr_size,p,offset,offsetp,ncomp,i;
820: DMNetworkComponentHeader header;
821: DMNetworkComponentValue cvalue;
822: DMNetworkComponentGenericDataType *componentdataarray;
825: PetscSectionSetUp(network->DataSection);
826: PetscSectionGetStorageSize(network->DataSection,&arr_size);
827: PetscMalloc1(arr_size,&network->componentdataarray);
828: componentdataarray = network->componentdataarray;
829: for (p = network->pStart; p < network->pEnd; p++) {
830: PetscSectionGetOffset(network->DataSection,p,&offsetp);
831: /* Copy header */
832: header = &network->header[p];
833: PetscMemcpy(componentdataarray+offsetp,header,network->dataheadersize*sizeof(DMNetworkComponentGenericDataType));
834: /* Copy data */
835: cvalue = &network->cvalue[p];
836: ncomp = header->ndata;
837: for (i = 0; i < ncomp; i++) {
838: offset = offsetp + network->dataheadersize + header->offset[i];
839: PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));
840: }
841: }
842: return(0);
843: }
845: /* Sets up the section for dofs. This routine is called during DMSetUp() */
846: PetscErrorCode DMNetworkVariablesSetUp(DM dm)
847: {
849: DM_Network *network = (DM_Network*)dm->data;
852: PetscSectionSetUp(network->DofSection);
853: return(0);
854: }
856: /*@C
857: DMNetworkGetComponentDataArray - Returns the component data array
859: Not Collective
861: Input Parameters:
862: . dm - The DMNetwork Object
864: Output Parameters:
865: . componentdataarray - array that holds data for all components
867: Level: intermediate
869: .seealso: DMNetworkGetComponentKeyOffset, DMNetworkGetNumComponents
870: @*/
871: PetscErrorCode DMNetworkGetComponentDataArray(DM dm,DMNetworkComponentGenericDataType **componentdataarray)
872: {
873: DM_Network *network = (DM_Network*)dm->data;
876: *componentdataarray = network->componentdataarray;
877: return(0);
878: }
880: /* Get a subsection from a range of points */
881: PetscErrorCode DMNetworkGetSubSection_private(PetscSection master, PetscInt pstart, PetscInt pend,PetscSection *subsection)
882: {
884: PetscInt i, nvar;
887: PetscSectionCreate(PetscObjectComm((PetscObject)master), subsection);
888: PetscSectionSetChart(*subsection, 0, pend - pstart);
889: for (i = pstart; i < pend; i++) {
890: PetscSectionGetDof(master,i,&nvar);
891: PetscSectionSetDof(*subsection, i - pstart, nvar);
892: }
894: PetscSectionSetUp(*subsection);
895: return(0);
896: }
898: /* Create a submap of points with a GlobalToLocal structure */
899: PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
900: {
902: PetscInt i, *subpoints;
905: /* Create index sets to map from "points" to "subpoints" */
906: PetscMalloc1(pend - pstart, &subpoints);
907: for (i = pstart; i < pend; i++) {
908: subpoints[i - pstart] = i;
909: }
910: ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);
911: PetscFree(subpoints);
912: return(0);
913: }
915: /*@
916: DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute.
918: Collective
920: Input Parameters:
921: . dm - The DMNetworkObject
923: Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
925: points = [0 1 2 3 4 5 6]
927: where edges = [0, 3] and vertices = [4, 6]. The new orderings will be specific to the subset (i.e vertices = [0, 2]).
929: With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
931: Level: intermediate
933: @*/
934: PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
935: {
937: MPI_Comm comm;
938: PetscMPIInt rank, size;
939: DM_Network *network = (DM_Network*)dm->data;
942: PetscObjectGetComm((PetscObject)dm,&comm);
943: MPI_Comm_rank(comm, &rank);
944: MPI_Comm_size(comm, &size);
946: /* Create maps for vertices and edges */
947: DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);
948: DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);
950: /* Create local sub-sections */
951: DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);
952: DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);
954: if (size > 1) {
955: PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);
956: PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);
957: PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);
958: PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);
959: } else {
960: /* create structures for vertex */
961: PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);
962: /* create structures for edge */
963: PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);
964: }
967: /* Add viewers */
968: PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");
969: PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");
970: PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");
971: PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");
973: return(0);
974: }
976: /*@
977: DMNetworkDistribute - Distributes the network and moves associated component data.
979: Collective
981: Input Parameter:
982: + DM - the DMNetwork object
983: - overlap - The overlap of partitions, 0 is the default
985: Notes:
986: Distributes the network with <overlap>-overlapping partitioning of the edges.
988: Level: intermediate
990: .seealso: DMNetworkCreate
991: @*/
992: PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap)
993: {
994: MPI_Comm comm;
996: PetscMPIInt size;
997: DM_Network *oldDMnetwork = (DM_Network*)((*dm)->data);
998: DM_Network *newDMnetwork;
999: PetscSF pointsf;
1000: DM newDM;
1001: PetscPartitioner part;
1002: PetscInt j,e,v,offset;
1003: DMNetworkComponentHeader header;
1007: PetscObjectGetComm((PetscObject)*dm,&comm);
1008: MPI_Comm_size(comm, &size);
1009: if (size == 1) return(0);
1011: DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);
1012: newDMnetwork = (DM_Network*)newDM->data;
1013: newDMnetwork->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
1015: /* Enable runtime options for petscpartitioner */
1016: DMPlexGetPartitioner(oldDMnetwork->plex,&part);
1017: PetscPartitionerSetFromOptions(part);
1019: /* Distribute plex dm and dof section */
1020: DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);
1022: /* Distribute dof section */
1023: PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DofSection);
1024: PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);
1025: PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DataSection);
1027: /* Distribute data and associated section */
1028: DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);
1030: PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);
1031: DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);
1032: DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);
1033: newDMnetwork->nEdges = newDMnetwork->eEnd - newDMnetwork->eStart;
1034: newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart;
1035: newDMnetwork->NVertices = oldDMnetwork->NVertices;
1036: newDMnetwork->NEdges = oldDMnetwork->NEdges;
1038: /* Set Dof section as the default section for dm */
1039: DMSetDefaultSection(newDMnetwork->plex,newDMnetwork->DofSection);
1040: DMGetDefaultGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);
1042: /* Set up subnetwork info in the newDM */
1043: newDMnetwork->nsubnet = oldDMnetwork->nsubnet;
1044: PetscCalloc1(newDMnetwork->nsubnet,&newDMnetwork->subnet);
1045: /* Copy over the global number of vertices and edges in each subnetwork. Note that these are already
1046: calculated in DMNetworkLayoutSetUp()
1047: */
1048: for(j=0; j < newDMnetwork->nsubnet; j++) {
1049: newDMnetwork->subnet[j].Nvtx = oldDMnetwork->subnet[j].Nvtx;
1050: newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge;
1051: }
1053: for(e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) {
1054: PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);
1055: header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);
1056: newDMnetwork->subnet[header->subnetid].nedge++;
1057: }
1059: for(v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) {
1060: PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);
1061: header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);
1062: newDMnetwork->subnet[header->subnetid].nvtx++;
1063: }
1065: /* Now create the vertices and edge arrays for the subnetworks */
1066: for(j=0; j < newDMnetwork->nsubnet; j++) {
1067: PetscCalloc1(newDMnetwork->subnet[j].nedge,&newDMnetwork->subnet[j].edges);
1068: PetscCalloc1(newDMnetwork->subnet[j].nvtx,&newDMnetwork->subnet[j].vertices);
1069: /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop.
1070: These get updated when the vertices and edges are added. */
1071: newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0;
1072: }
1074: /* Set the vertices and edges in each subnetwork */
1075: for(e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) {
1076: PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);
1077: header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);
1078: newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e;
1079: }
1081: for(v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) {
1082: PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);
1083: header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);
1084: newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v;
1085: }
1087: /* Destroy point SF */
1088: PetscSFDestroy(&pointsf);
1090: DMDestroy(dm);
1091: *dm = newDM;
1092: return(0);
1093: }
1095: /*@C
1096: PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering.
1098: Input Parameters:
1099: + masterSF - the original SF structure
1100: - map - a ISLocalToGlobal mapping that contains the subset of points
1102: Output Parameters:
1103: . subSF - a subset of the masterSF for the desired subset.
1104: */
1106: PetscErrorCode PetscSFGetSubSF(PetscSF mastersf, ISLocalToGlobalMapping map, PetscSF *subSF) {
1108: PetscErrorCode ierr;
1109: PetscInt nroots, nleaves, *ilocal_sub;
1110: PetscInt i, *ilocal_map, nroots_sub, nleaves_sub = 0;
1111: PetscInt *local_points, *remote_points;
1112: PetscSFNode *iremote_sub;
1113: const PetscInt *ilocal;
1114: const PetscSFNode *iremote;
1117: PetscSFGetGraph(mastersf,&nroots,&nleaves,&ilocal,&iremote);
1119: /* Look for leaves that pertain to the subset of points. Get the local ordering */
1120: PetscMalloc1(nleaves,&ilocal_map);
1121: ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);
1122: for (i = 0; i < nleaves; i++) {
1123: if (ilocal_map[i] != -1) nleaves_sub += 1;
1124: }
1125: /* Re-number ilocal with subset numbering. Need information from roots */
1126: PetscMalloc2(nroots,&local_points,nroots,&remote_points);
1127: for (i = 0; i < nroots; i++) local_points[i] = i;
1128: ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);
1129: PetscSFBcastBegin(mastersf, MPIU_INT, local_points, remote_points);
1130: PetscSFBcastEnd(mastersf, MPIU_INT, local_points, remote_points);
1131: /* Fill up graph using local (that is, local to the subset) numbering. */
1132: PetscMalloc1(nleaves_sub,&ilocal_sub);
1133: PetscMalloc1(nleaves_sub,&iremote_sub);
1134: nleaves_sub = 0;
1135: for (i = 0; i < nleaves; i++) {
1136: if (ilocal_map[i] != -1) {
1137: ilocal_sub[nleaves_sub] = ilocal_map[i];
1138: iremote_sub[nleaves_sub].rank = iremote[i].rank;
1139: iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
1140: nleaves_sub += 1;
1141: }
1142: }
1143: PetscFree2(local_points,remote_points);
1144: ISLocalToGlobalMappingGetSize(map,&nroots_sub);
1146: /* Create new subSF */
1147: PetscSFCreate(PETSC_COMM_WORLD,subSF);
1148: PetscSFSetFromOptions(*subSF);
1149: PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);
1150: PetscFree(ilocal_map);
1151: PetscFree(iremote_sub);
1152: return(0);
1153: }
1155: /*@C
1156: DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
1158: Not Collective
1160: Input Parameters:
1161: + dm - The DMNetwork object
1162: - p - the vertex point
1164: Output Paramters:
1165: + nedges - number of edges connected to this vertex point
1166: - edges - List of edge points
1168: Level: intermediate
1170: Fortran Notes:
1171: Since it returns an array, this routine is only available in Fortran 90, and you must
1172: include petsc.h90 in your code.
1174: .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices
1175: @*/
1176: PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
1177: {
1179: DM_Network *network = (DM_Network*)dm->data;
1182: DMPlexGetSupportSize(network->plex,vertex,nedges);
1183: DMPlexGetSupport(network->plex,vertex,edges);
1184: return(0);
1185: }
1187: /*@C
1188: DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
1190: Not Collective
1192: Input Parameters:
1193: + dm - The DMNetwork object
1194: - p - the edge point
1196: Output Paramters:
1197: . vertices - vertices connected to this edge
1199: Level: intermediate
1201: Fortran Notes:
1202: Since it returns an array, this routine is only available in Fortran 90, and you must
1203: include petsc.h90 in your code.
1205: .seealso: DMNetworkCreate, DMNetworkGetSupportingEdges
1206: @*/
1207: PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
1208: {
1210: DM_Network *network = (DM_Network*)dm->data;
1213: DMPlexGetCone(network->plex,edge,vertices);
1214: return(0);
1215: }
1217: /*@
1218: DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
1220: Not Collective
1222: Input Parameters:
1223: + dm - The DMNetwork object
1224: . p - the vertex point
1226: Output Parameter:
1227: . isghost - TRUE if the vertex is a ghost point
1229: Level: intermediate
1231: .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices, DMNetworkGetVertexRange
1232: @*/
1233: PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
1234: {
1236: DM_Network *network = (DM_Network*)dm->data;
1237: PetscInt offsetg;
1238: PetscSection sectiong;
1241: *isghost = PETSC_FALSE;
1242: DMGetDefaultGlobalSection(network->plex,§iong);
1243: PetscSectionGetOffset(sectiong,p,&offsetg);
1244: if (offsetg < 0) *isghost = PETSC_TRUE;
1245: return(0);
1246: }
1248: PetscErrorCode DMSetUp_Network(DM dm)
1249: {
1251: DM_Network *network=(DM_Network*)dm->data;
1254: DMNetworkComponentSetUp(dm);
1255: DMNetworkVariablesSetUp(dm);
1257: DMSetDefaultSection(network->plex,network->DofSection);
1258: DMGetDefaultGlobalSection(network->plex,&network->GlobalDofSection);
1259: return(0);
1260: }
1262: /*@
1263: DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
1264: -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
1266: Collective
1268: Input Parameters:
1269: + dm - The DMNetwork object
1270: . eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
1271: - vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
1273: Level: intermediate
1275: @*/
1276: PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
1277: {
1278: DM_Network *network=(DM_Network*)dm->data;
1282: network->userEdgeJacobian = eflg;
1283: network->userVertexJacobian = vflg;
1285: if (eflg && !network->Je) {
1286: PetscCalloc1(3*network->nEdges,&network->Je);
1287: }
1289: if (vflg && !network->Jv) {
1290: PetscInt i,*vptr,nedges,vStart=network->vStart;
1291: PetscInt nVertices = network->nVertices,nedges_total;
1292: const PetscInt *edges;
1294: /* count nvertex_total */
1295: nedges_total = 0;
1296: PetscMalloc1(nVertices+1,&vptr);
1298: vptr[0] = 0;
1299: for (i=0; i<nVertices; i++) {
1300: DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);
1301: nedges_total += nedges;
1302: vptr[i+1] = vptr[i] + 2*nedges + 1;
1303: }
1305: PetscCalloc1(2*nedges_total+nVertices,&network->Jv);
1306: network->Jvptr = vptr;
1307: }
1308: return(0);
1309: }
1311: /*@
1312: DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
1314: Not Collective
1316: Input Parameters:
1317: + dm - The DMNetwork object
1318: . p - the edge point
1319: - J - array (size = 3) of Jacobian submatrices for this edge point:
1320: J[0]: this edge
1321: J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
1323: Level: intermediate
1325: .seealso: DMNetworkVertexSetMatrix
1326: @*/
1327: PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
1328: {
1329: DM_Network *network=(DM_Network*)dm->data;
1332: if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
1334: if (J) {
1335: network->Je[3*p] = J[0];
1336: network->Je[3*p+1] = J[1];
1337: network->Je[3*p+2] = J[2];
1338: }
1339: return(0);
1340: }
1342: /*@
1343: DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
1345: Not Collective
1347: Input Parameters:
1348: + dm - The DMNetwork object
1349: . p - the vertex point
1350: - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
1351: J[0]: this vertex
1352: J[1+2*i]: i-th supporting edge
1353: J[1+2*i+1]: i-th connected vertex
1355: Level: intermediate
1357: .seealso: DMNetworkEdgeSetMatrix
1358: @*/
1359: PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
1360: {
1362: DM_Network *network=(DM_Network*)dm->data;
1363: PetscInt i,*vptr,nedges,vStart=network->vStart;
1364: const PetscInt *edges;
1367: if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
1369: if (J) {
1370: vptr = network->Jvptr;
1371: network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
1373: /* Set Jacobian for each supporting edge and connected vertex */
1374: DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);
1375: for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
1376: }
1377: return(0);
1378: }
1380: PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
1381: {
1383: PetscInt j;
1384: PetscScalar val=(PetscScalar)ncols;
1387: if (!ghost) {
1388: for (j=0; j<nrows; j++) {
1389: VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);
1390: }
1391: } else {
1392: for (j=0; j<nrows; j++) {
1393: VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);
1394: }
1395: }
1396: return(0);
1397: }
1399: PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
1400: {
1402: PetscInt j,ncols_u;
1403: PetscScalar val;
1406: if (!ghost) {
1407: for (j=0; j<nrows; j++) {
1408: MatGetRow(Ju,j,&ncols_u,NULL,NULL);
1409: val = (PetscScalar)ncols_u;
1410: VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);
1411: MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);
1412: }
1413: } else {
1414: for (j=0; j<nrows; j++) {
1415: MatGetRow(Ju,j,&ncols_u,NULL,NULL);
1416: val = (PetscScalar)ncols_u;
1417: VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);
1418: MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);
1419: }
1420: }
1421: return(0);
1422: }
1424: PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
1425: {
1429: if (Ju) {
1430: MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);
1431: } else {
1432: MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);
1433: }
1434: return(0);
1435: }
1437: PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1438: {
1440: PetscInt j,*cols;
1441: PetscScalar *zeros;
1444: PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);
1445: for (j=0; j<ncols; j++) cols[j] = j+ cstart;
1446: MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);
1447: PetscFree2(cols,zeros);
1448: return(0);
1449: }
1451: PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1452: {
1454: PetscInt j,M,N,row,col,ncols_u;
1455: const PetscInt *cols;
1456: PetscScalar zero=0.0;
1459: MatGetSize(Ju,&M,&N);
1460: if (nrows != M || ncols != N) SETERRQ4(PetscObjectComm((PetscObject)Ju),PETSC_ERR_USER,"%D by %D must equal %D by %D",nrows,ncols,M,N);
1462: for (row=0; row<nrows; row++) {
1463: MatGetRow(Ju,row,&ncols_u,&cols,NULL);
1464: for (j=0; j<ncols_u; j++) {
1465: col = cols[j] + cstart;
1466: MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);
1467: }
1468: MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);
1469: }
1470: return(0);
1471: }
1473: PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1474: {
1478: if (Ju) {
1479: MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);
1480: } else {
1481: MatSetDenseblock_private(nrows,rows,ncols,cstart,J);
1482: }
1483: return(0);
1484: }
1486: /* 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.
1487: */
1488: PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
1489: {
1491: PetscInt i, size, dof;
1492: PetscInt *glob2loc;
1495: PetscSectionGetStorageSize(localsec,&size);
1496: PetscMalloc1(size,&glob2loc);
1498: for (i = 0; i < size; i++) {
1499: PetscSectionGetOffset(globalsec,i,&dof);
1500: dof = (dof >= 0) ? dof : -(dof + 1);
1501: glob2loc[i] = dof;
1502: }
1504: ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);
1505: #if 0
1506: PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);
1507: #endif
1508: return(0);
1509: }
1511: #include <petsc/private/matimpl.h>
1512: PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
1513: {
1515: PetscMPIInt rank, size;
1516: DM_Network *network = (DM_Network*)dm->data;
1517: PetscInt eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
1518: PetscInt cstart,ncols,j,e,v;
1519: PetscBool ghost,ghost_vc,ghost2,isNest;
1520: Mat Juser;
1521: PetscSection sectionGlobal;
1522: PetscInt nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
1523: const PetscInt *edges,*cone;
1524: MPI_Comm comm;
1525: MatType mtype;
1526: Vec vd_nz,vo_nz;
1527: PetscInt *dnnz,*onnz;
1528: PetscScalar *vdnz,*vonz;
1531: mtype = dm->mattype;
1532: PetscStrcmp(mtype, MATNEST, &isNest);
1534: if (isNest) {
1535: /* DMCreateMatrix_Network_Nest(); */
1536: PetscInt eDof, vDof;
1537: Mat j11, j12, j21, j22, bA[2][2];
1538: ISLocalToGlobalMapping eISMap, vISMap;
1540: PetscObjectGetComm((PetscObject)dm,&comm);
1541: MPI_Comm_rank(comm,&rank);
1542: MPI_Comm_size(comm,&size);
1544: PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);
1545: PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);
1547: MatCreate(comm, &j11);
1548: MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);
1549: MatSetType(j11, MATMPIAIJ);
1551: MatCreate(comm, &j12);
1552: MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);
1553: MatSetType(j12, MATMPIAIJ);
1555: MatCreate(comm, &j21);
1556: MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);
1557: MatSetType(j21, MATMPIAIJ);
1559: MatCreate(comm, &j22);
1560: MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);
1561: MatSetType(j22, MATMPIAIJ);
1563: bA[0][0] = j11;
1564: bA[0][1] = j12;
1565: bA[1][0] = j21;
1566: bA[1][1] = j22;
1568: CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);
1569: CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);
1571: MatSetLocalToGlobalMapping(j11,eISMap,eISMap);
1572: MatSetLocalToGlobalMapping(j12,eISMap,vISMap);
1573: MatSetLocalToGlobalMapping(j21,vISMap,eISMap);
1574: MatSetLocalToGlobalMapping(j22,vISMap,vISMap);
1576: MatSetUp(j11);
1577: MatSetUp(j12);
1578: MatSetUp(j21);
1579: MatSetUp(j22);
1581: MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);
1582: MatSetUp(*J);
1583: MatNestSetVecType(*J,VECNEST);
1584: MatDestroy(&j11);
1585: MatDestroy(&j12);
1586: MatDestroy(&j21);
1587: MatDestroy(&j22);
1589: MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
1590: MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
1592: /* Free structures */
1593: ISLocalToGlobalMappingDestroy(&eISMap);
1594: ISLocalToGlobalMappingDestroy(&vISMap);
1596: return(0);
1597: } else if (!network->userEdgeJacobian && !network->userVertexJacobian) {
1598: /* user does not provide Jacobian blocks */
1599: DMCreateMatrix(network->plex,J);
1600: MatSetDM(*J,dm);
1601: return(0);
1602: }
1604: MatCreate(PetscObjectComm((PetscObject)dm),J);
1605: DMGetDefaultGlobalSection(network->plex,§ionGlobal);
1606: PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);
1607: MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);
1609: MatSetType(*J,MATAIJ);
1610: MatSetFromOptions(*J);
1612: /* (1) Set matrix preallocation */
1613: /*------------------------------*/
1614: PetscObjectGetComm((PetscObject)dm,&comm);
1615: VecCreate(comm,&vd_nz);
1616: VecSetSizes(vd_nz,localSize,PETSC_DECIDE);
1617: VecSetFromOptions(vd_nz);
1618: VecSet(vd_nz,0.0);
1619: VecDuplicate(vd_nz,&vo_nz);
1621: /* Set preallocation for edges */
1622: /*-----------------------------*/
1623: DMNetworkGetEdgeRange(dm,&eStart,&eEnd);
1625: PetscMalloc1(localSize,&rows);
1626: for (e=eStart; e<eEnd; e++) {
1627: /* Get row indices */
1628: DMNetworkGetVariableGlobalOffset(dm,e,&rstart);
1629: DMNetworkGetNumVariables(dm,e,&nrows);
1630: if (nrows) {
1631: for (j=0; j<nrows; j++) rows[j] = j + rstart;
1633: /* Set preallocation for conntected vertices */
1634: DMNetworkGetConnectedVertices(dm,e,&cone);
1635: for (v=0; v<2; v++) {
1636: DMNetworkGetNumVariables(dm,cone[v],&ncols);
1638: if (network->Je) {
1639: Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
1640: } else Juser = NULL;
1641: DMNetworkIsGhostVertex(dm,cone[v],&ghost);
1642: MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);
1643: }
1645: /* Set preallocation for edge self */
1646: cstart = rstart;
1647: if (network->Je) {
1648: Juser = network->Je[3*e]; /* Jacobian(e,e) */
1649: } else Juser = NULL;
1650: MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);
1651: }
1652: }
1654: /* Set preallocation for vertices */
1655: /*--------------------------------*/
1656: DMNetworkGetVertexRange(dm,&vStart,&vEnd);
1657: if (vEnd - vStart) vptr = network->Jvptr;
1659: for (v=vStart; v<vEnd; v++) {
1660: /* Get row indices */
1661: DMNetworkGetVariableGlobalOffset(dm,v,&rstart);
1662: DMNetworkGetNumVariables(dm,v,&nrows);
1663: if (!nrows) continue;
1665: DMNetworkIsGhostVertex(dm,v,&ghost);
1666: if (ghost) {
1667: PetscMalloc1(nrows,&rows_v);
1668: } else {
1669: rows_v = rows;
1670: }
1672: for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1674: /* Get supporting edges and connected vertices */
1675: DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);
1677: for (e=0; e<nedges; e++) {
1678: /* Supporting edges */
1679: DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);
1680: DMNetworkGetNumVariables(dm,edges[e],&ncols);
1682: if (network->Jv) {
1683: Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
1684: } else Juser = NULL;
1685: MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);
1687: /* Connected vertices */
1688: DMNetworkGetConnectedVertices(dm,edges[e],&cone);
1689: vc = (v == cone[0]) ? cone[1]:cone[0];
1690: DMNetworkIsGhostVertex(dm,vc,&ghost_vc);
1692: DMNetworkGetNumVariables(dm,vc,&ncols);
1694: if (network->Jv) {
1695: Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
1696: } else Juser = NULL;
1697: if (ghost_vc||ghost) {
1698: ghost2 = PETSC_TRUE;
1699: } else {
1700: ghost2 = PETSC_FALSE;
1701: }
1702: MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);
1703: }
1705: /* Set preallocation for vertex self */
1706: DMNetworkIsGhostVertex(dm,v,&ghost);
1707: if (!ghost) {
1708: DMNetworkGetVariableGlobalOffset(dm,v,&cstart);
1709: if (network->Jv) {
1710: Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
1711: } else Juser = NULL;
1712: MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);
1713: }
1714: if (ghost) {
1715: PetscFree(rows_v);
1716: }
1717: }
1719: VecAssemblyBegin(vd_nz);
1720: VecAssemblyBegin(vo_nz);
1722: PetscMalloc2(localSize,&dnnz,localSize,&onnz);
1724: VecAssemblyEnd(vd_nz);
1725: VecAssemblyEnd(vo_nz);
1727: VecGetArray(vd_nz,&vdnz);
1728: VecGetArray(vo_nz,&vonz);
1729: for (j=0; j<localSize; j++) {
1730: dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
1731: onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
1732: }
1733: VecRestoreArray(vd_nz,&vdnz);
1734: VecRestoreArray(vo_nz,&vonz);
1735: VecDestroy(&vd_nz);
1736: VecDestroy(&vo_nz);
1738: MatSeqAIJSetPreallocation(*J,0,dnnz);
1739: MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);
1740: MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);
1742: PetscFree2(dnnz,onnz);
1744: /* (2) Set matrix entries for edges */
1745: /*----------------------------------*/
1746: for (e=eStart; e<eEnd; e++) {
1747: /* Get row indices */
1748: DMNetworkGetVariableGlobalOffset(dm,e,&rstart);
1749: DMNetworkGetNumVariables(dm,e,&nrows);
1750: if (nrows) {
1751: for (j=0; j<nrows; j++) rows[j] = j + rstart;
1753: /* Set matrix entries for conntected vertices */
1754: DMNetworkGetConnectedVertices(dm,e,&cone);
1755: for (v=0; v<2; v++) {
1756: DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);
1757: DMNetworkGetNumVariables(dm,cone[v],&ncols);
1759: if (network->Je) {
1760: Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
1761: } else Juser = NULL;
1762: MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);
1763: }
1765: /* Set matrix entries for edge self */
1766: cstart = rstart;
1767: if (network->Je) {
1768: Juser = network->Je[3*e]; /* Jacobian(e,e) */
1769: } else Juser = NULL;
1770: MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);
1771: }
1772: }
1774: /* Set matrix entries for vertices */
1775: /*---------------------------------*/
1776: for (v=vStart; v<vEnd; v++) {
1777: /* Get row indices */
1778: DMNetworkGetVariableGlobalOffset(dm,v,&rstart);
1779: DMNetworkGetNumVariables(dm,v,&nrows);
1780: if (!nrows) continue;
1782: DMNetworkIsGhostVertex(dm,v,&ghost);
1783: if (ghost) {
1784: PetscMalloc1(nrows,&rows_v);
1785: } else {
1786: rows_v = rows;
1787: }
1788: for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1790: /* Get supporting edges and connected vertices */
1791: DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);
1793: for (e=0; e<nedges; e++) {
1794: /* Supporting edges */
1795: DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);
1796: DMNetworkGetNumVariables(dm,edges[e],&ncols);
1798: if (network->Jv) {
1799: Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
1800: } else Juser = NULL;
1801: MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);
1803: /* Connected vertices */
1804: DMNetworkGetConnectedVertices(dm,edges[e],&cone);
1805: vc = (v == cone[0]) ? cone[1]:cone[0];
1807: DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);
1808: DMNetworkGetNumVariables(dm,vc,&ncols);
1810: if (network->Jv) {
1811: Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
1812: } else Juser = NULL;
1813: MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);
1814: }
1816: /* Set matrix entries for vertex self */
1817: if (!ghost) {
1818: DMNetworkGetVariableGlobalOffset(dm,v,&cstart);
1819: if (network->Jv) {
1820: Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
1821: } else Juser = NULL;
1822: MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);
1823: }
1824: if (ghost) {
1825: PetscFree(rows_v);
1826: }
1827: }
1828: PetscFree(rows);
1830: MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
1831: MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
1833: MatSetDM(*J,dm);
1834: return(0);
1835: }
1837: PetscErrorCode DMDestroy_Network(DM dm)
1838: {
1840: DM_Network *network = (DM_Network*)dm->data;
1841: PetscInt j;
1844: if (--network->refct > 0) return(0);
1845: if (network->Je) {
1846: PetscFree(network->Je);
1847: }
1848: if (network->Jv) {
1849: PetscFree(network->Jvptr);
1850: PetscFree(network->Jv);
1851: }
1853: ISLocalToGlobalMappingDestroy(&network->vertex.mapping);
1854: PetscSectionDestroy(&network->vertex.DofSection);
1855: PetscSectionDestroy(&network->vertex.GlobalDofSection);
1856: if (network->vertex.sf) {
1857: PetscSFDestroy(&network->vertex.sf);
1858: }
1859: /* edge */
1860: ISLocalToGlobalMappingDestroy(&network->edge.mapping);
1861: PetscSectionDestroy(&network->edge.DofSection);
1862: PetscSectionDestroy(&network->edge.GlobalDofSection);
1863: if (network->edge.sf) {
1864: PetscSFDestroy(&network->edge.sf);
1865: }
1866: DMDestroy(&network->plex);
1867: network->edges = NULL;
1868: PetscSectionDestroy(&network->DataSection);
1869: PetscSectionDestroy(&network->DofSection);
1871: for(j=0; j < network->nsubnet; j++) {
1872: PetscFree(network->subnet[j].edges);
1873: PetscFree(network->subnet[j].vertices);
1874: }
1875: PetscFree(network->subnet);
1876: PetscFree(network->componentdataarray);
1877: PetscFree(network->cvalue);
1878: PetscFree(network->header);
1879: PetscFree(network);
1880: return(0);
1881: }
1883: PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
1884: {
1886: DM_Network *network = (DM_Network*)dm->data;
1889: DMView(network->plex,viewer);
1890: return(0);
1891: }
1893: PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
1894: {
1896: DM_Network *network = (DM_Network*)dm->data;
1899: DMGlobalToLocalBegin(network->plex,g,mode,l);
1900: return(0);
1901: }
1903: PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
1904: {
1906: DM_Network *network = (DM_Network*)dm->data;
1909: DMGlobalToLocalEnd(network->plex,g,mode,l);
1910: return(0);
1911: }
1913: PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
1914: {
1916: DM_Network *network = (DM_Network*)dm->data;
1919: DMLocalToGlobalBegin(network->plex,l,mode,g);
1920: return(0);
1921: }
1923: PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
1924: {
1926: DM_Network *network = (DM_Network*)dm->data;
1929: DMLocalToGlobalEnd(network->plex,l,mode,g);
1930: return(0);
1931: }