xref: /petsc/src/dm/impls/network/networkcreate.c (revision 62aa33baec912248a234e90eff09bca4b3b58035)
1 #define PETSCDM_DLL
2 #include <petsc/private/dmnetworkimpl.h>    /*I   "petscdmnetwork.h"   I*/
3 #include <petscdmda.h>
4 
5 PetscErrorCode  DMSetFromOptions_Network(PetscOptionItems *PetscOptionsObject,DM dm)
6 {
7   PetscErrorCode ierr;
8 
9   PetscFunctionBegin;
10   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11   ierr = PetscOptionsHead(PetscOptionsObject,"DMNetwork Options");CHKERRQ(ierr);
12   ierr = PetscOptionsTail();CHKERRQ(ierr);
13   PetscFunctionReturn(0);
14 }
15 
16 /* External function declarations here */
17 extern PetscErrorCode DMCreateMatrix_Network(DM, Mat*);
18 extern PetscErrorCode DMDestroy_Network(DM);
19 extern PetscErrorCode DMView_Network(DM, PetscViewer);
20 extern PetscErrorCode DMGlobalToLocalBegin_Network(DM, Vec, InsertMode, Vec);
21 extern PetscErrorCode DMGlobalToLocalEnd_Network(DM, Vec, InsertMode, Vec);
22 extern PetscErrorCode DMLocalToGlobalBegin_Network(DM, Vec, InsertMode, Vec);
23 extern PetscErrorCode DMLocalToGlobalEnd_Network(DM, Vec, InsertMode, Vec);
24 extern PetscErrorCode DMSetUp_Network(DM);
25 extern PetscErrorCode DMClone_Network(DM, DM*);
26 
27 static PetscErrorCode VecArrayPrint_private(PetscViewer viewer,PetscInt n,const PetscScalar *xv)
28 {
29   PetscErrorCode ierr;
30   PetscInt       i;
31 
32   PetscFunctionBegin;
33   for (i=0; i<n; i++) {
34 #if defined(PETSC_USE_COMPLEX)
35     if (PetscImaginaryPart(xv[i]) > 0.0) {
36       ierr = PetscViewerASCIIPrintf(viewer,"    %g + %g i\n",(double)PetscRealPart(xv[i]),(double)PetscImaginaryPart(xv[i]));CHKERRQ(ierr);
37     } else if (PetscImaginaryPart(xv[i]) < 0.0) {
38       ierr = PetscViewerASCIIPrintf(viewer,"    %g - %g i\n",(double)PetscRealPart(xv[i]),-(double)PetscImaginaryPart(xv[i]));CHKERRQ(ierr);
39     } else {
40       ierr = PetscViewerASCIIPrintf(viewer,"    %g\n",(double)PetscRealPart(xv[i]));CHKERRQ(ierr);
41     }
42 #else
43     ierr = PetscViewerASCIIPrintf(viewer,"    %g\n",(double)xv[i]);CHKERRQ(ierr);
44 #endif
45   }
46   PetscFunctionReturn(0);
47 }
48 
49 static PetscErrorCode VecView_Network_Seq(DM networkdm,Vec X,PetscViewer viewer)
50 {
51   PetscErrorCode    ierr;
52   PetscInt          e,v,Start,End,offset,nvar;
53   const PetscScalar *xv;
54   DM_Network        *network = (DM_Network*)networkdm->data;
55 
56   PetscFunctionBegin;
57   ierr = VecGetArrayRead(X,&xv);CHKERRQ(ierr);
58 
59   /* iterate over edges */
60   ierr = DMNetworkGetEdgeRange(networkdm,&Start,&End);CHKERRQ(ierr);
61   for (e=Start; e<End; e++) {
62     ierr = DMNetworkGetVariableOffset(networkdm,e,&offset);CHKERRQ(ierr);
63     ierr = DMNetworkGetNumVariables(networkdm,e,&nvar);CHKERRQ(ierr);
64     if (!nvar) continue;
65 
66     ierr = PetscViewerASCIIPrintf(viewer,"  Edge %D:\n",e-Start);CHKERRQ(ierr);
67     ierr = VecArrayPrint_private(viewer,nvar,xv+offset);CHKERRQ(ierr);
68   }
69 
70   /* iterate over vertices */
71   ierr = DMNetworkGetVertexRange(networkdm,&Start,&End);CHKERRQ(ierr);
72   for (v=Start; v<End; v++) {
73     ierr = DMNetworkGetVariableOffset(networkdm,v,&offset);CHKERRQ(ierr);
74     ierr = DMNetworkGetNumVariables(networkdm,v,&nvar);CHKERRQ(ierr);
75     if (!nvar) continue;
76 
77     printf("network->header[%d].id = %d\n",v,network->header[v].id);
78 
79     ierr = PetscViewerASCIIPrintf(viewer,"  Vertex %D:\n",v-Start);CHKERRQ(ierr);
80     ierr = VecArrayPrint_private(viewer,nvar,xv+offset);CHKERRQ(ierr);
81   }
82   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
83   ierr = VecRestoreArrayRead(X,&xv);CHKERRQ(ierr);
84   PetscFunctionReturn(0);
85 }
86 
87 static PetscErrorCode VecView_Network_MPI(DM networkdm,Vec X,PetscViewer viewer)
88 {
89   PetscErrorCode    ierr;
90   PetscInt          i,e,v,eStart,eEnd,vStart,vEnd,offset,nvar,len_loc,len,k;
91   const PetscScalar *xv;
92   MPI_Comm          comm;
93   PetscMPIInt       size,rank,tag = ((PetscObject)viewer)->tag;
94   Vec               localX;
95   PetscBool         ghostvtex;
96   PetscScalar       *values;
97   PetscInt          j,n,ne,nv;
98   MPI_Status        status;
99   DM_Network        *network = (DM_Network*)networkdm->data;
100 
101   PetscFunctionBegin;
102   ierr = PetscObjectGetComm((PetscObject)networkdm,&comm);CHKERRQ(ierr);
103   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
104   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
105 
106   ierr = DMGetLocalVector(networkdm,&localX);CHKERRQ(ierr);
107   ierr = DMGlobalToLocalBegin(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr);
108   ierr = DMGlobalToLocalEnd(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr);
109   ierr = VecGetArrayRead(localX,&xv);CHKERRQ(ierr);
110 
111   ierr = VecGetLocalSize(localX,&len_loc);CHKERRQ(ierr);
112 
113   ierr = DMNetworkGetEdgeRange(networkdm,&eStart,&eEnd);CHKERRQ(ierr);
114   ierr = DMNetworkGetVertexRange(networkdm,&vStart,&vEnd);CHKERRQ(ierr);
115   len_loc += 2*(1 + eEnd-eStart + vEnd-vStart);
116 
117   /* values = [nedges, offset, nvar, xe; nvertices, offsets, nvars, xv] */
118   ierr = MPI_Allreduce(&len_loc,&len,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
119   ierr = PetscCalloc1(len,&values);CHKERRQ(ierr);
120 
121   if (!rank) {
122     ierr = PetscViewerASCIIPrintf(viewer,"Process [%d]\n",rank);CHKERRQ(ierr);
123   }
124 
125   /* iterate over edges */
126   k = 2;
127   for (e=eStart; e<eEnd; e++) {
128     ierr = DMNetworkGetVariableOffset(networkdm,e,&offset);CHKERRQ(ierr);
129     ierr = DMNetworkGetNumVariables(networkdm,e,&nvar);CHKERRQ(ierr);
130     if (!nvar) continue;
131 
132     values[0]  += 1; /* nedges */
133     values[k++] = offset;
134     values[k++] = nvar;
135 
136     //printf("network->header[%d].id = %p\n",e,&network->header[e]);
137     printf("network->header[%d].id = %d\n",e,network->header[e].id);
138 
139     if (!rank) { /* print its own entries */
140       ierr = PetscViewerASCIIPrintf(viewer,"  Edge %D:\n",e-eStart);CHKERRQ(ierr);
141       ierr = VecArrayPrint_private(viewer,nvar,xv+offset);CHKERRQ(ierr);
142     } else {
143       for (i=offset; i< offset+nvar; i++) {
144         values[k++] = xv[i];
145       }
146     }
147   }
148 
149   /* iterate over vertices */
150   for (v=vStart; v<vEnd; v++) {
151     ierr = DMNetworkIsGhostVertex(networkdm,v,&ghostvtex);CHKERRQ(ierr);
152     if (ghostvtex) continue;
153     ierr = DMNetworkGetVariableOffset(networkdm,v,&offset);CHKERRQ(ierr);
154     ierr = DMNetworkGetNumVariables(networkdm,v,&nvar);CHKERRQ(ierr);
155     if (!nvar) continue;
156 
157     values[1]  += 1; /* nvertices */
158     values[k++] = offset;
159     values[k++] = nvar;
160 
161     if (!rank) {
162       ierr = PetscViewerASCIIPrintf(viewer,"  Vertex %D:\n",v-vStart);CHKERRQ(ierr);
163       printf("network->header[%d].id = %d\n",v,network->header[v].id);
164     }
165 
166     if (!rank) {
167       ierr = VecArrayPrint_private(viewer,nvar,xv+offset);CHKERRQ(ierr);
168     } else {
169       for (i=offset; i< offset+nvar; i++) {
170         values[k++] = xv[i];
171       }
172     }
173   }
174 
175   if (!rank) {
176     /* proc[0] receives and prints messages */
177     for (j=1; j<size; j++) {
178       ierr = PetscViewerASCIIPrintf(viewer,"Process [%d]\n",j);CHKERRQ(ierr);
179 
180       ierr = MPI_Recv(values,(PetscMPIInt)len,MPIU_SCALAR,j,tag,comm,&status);CHKERRQ(ierr);
181       ierr = MPI_Get_count(&status,MPIU_SCALAR,&n);CHKERRQ(ierr);
182 
183       ne = (PetscInt)values[0];
184       nv = (PetscInt)values[1];
185 
186       /* print received edges */
187       k  = 2;
188       for (i=0; i<ne; i++) {
189         offset = (PetscInt)values[k++];
190         nvar   = (PetscInt)values[k++];
191         ierr = PetscViewerASCIIPrintf(viewer,"  Edge %D:\n",i);CHKERRQ(ierr);
192         ierr = VecArrayPrint_private(viewer,nvar,values+k);CHKERRQ(ierr);
193         k   += nvar;
194       }
195 
196       /* print received vertices */
197       for (i=0; i<nv; i++) {
198         offset = (PetscInt)values[k++];
199         nvar   = (PetscInt)values[k++];
200         ierr = PetscViewerASCIIPrintf(viewer,"  Vertex %D:\n",i);CHKERRQ(ierr);
201         ierr = VecArrayPrint_private(viewer,nvar,values+k);CHKERRQ(ierr);
202         k   += nvar;
203       }
204     }
205   } else {
206     /* sends values to proc[0] */
207     ierr = MPI_Send((void*)values,k,MPIU_SCALAR,0,tag,comm);CHKERRQ(ierr);
208   }
209 
210   ierr = PetscFree(values);CHKERRQ(ierr);
211   ierr = VecRestoreArrayRead(localX,&xv);CHKERRQ(ierr);
212   ierr = DMRestoreLocalVector(networkdm,&localX);CHKERRQ(ierr);
213   PetscFunctionReturn(0);
214 }
215 
216 PetscErrorCode VecView_Network(Vec v,PetscViewer viewer)
217 {
218   DM             dm;
219   PetscErrorCode ierr;
220   PetscBool      isseq;
221 
222   PetscFunctionBegin;
223   ierr = VecGetDM(v,&dm);CHKERRQ(ierr);
224   if (!dm) SETERRQ(PetscObjectComm((PetscObject)v),PETSC_ERR_ARG_WRONG,"Vector not generated from a DM");
225   ierr = PetscObjectTypeCompare((PetscObject)v,VECSEQ,&isseq);CHKERRQ(ierr);
226   if (isseq) {
227     ierr = VecView_Network_Seq(dm,v,viewer);CHKERRQ(ierr);
228   } else {
229     ierr = VecView_Network_MPI(dm,v,viewer);CHKERRQ(ierr);
230   }
231   PetscFunctionReturn(0);
232 }
233 
234 static PetscErrorCode DMCreateGlobalVector_Network(DM dm,Vec *vec)
235 {
236   PetscErrorCode ierr;
237   DM_Network     *network = (DM_Network*) dm->data;
238 
239   PetscFunctionBegin;
240   ierr = DMCreateGlobalVector(network->plex,vec);CHKERRQ(ierr);
241   ierr = VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Network);CHKERRQ(ierr);
242   ierr = VecSetDM(*vec,dm);CHKERRQ(ierr);
243   PetscFunctionReturn(0);
244 }
245 
246 static PetscErrorCode DMCreateLocalVector_Network(DM dm,Vec *vec)
247 {
248   PetscErrorCode ierr;
249   DM_Network     *network = (DM_Network*) dm->data;
250 
251   PetscFunctionBegin;
252   ierr = DMCreateLocalVector(network->plex,vec);CHKERRQ(ierr);
253   ierr = VecSetDM(*vec,dm);CHKERRQ(ierr);
254   PetscFunctionReturn(0);
255 }
256 
257 PetscErrorCode DMInitialize_Network(DM dm)
258 {
259 
260   PetscFunctionBegin;
261 
262   dm->ops->view                            = NULL;
263   dm->ops->setfromoptions                  = DMSetFromOptions_Network;
264   dm->ops->clone                           = DMClone_Network;
265   dm->ops->setup                           = DMSetUp_Network;
266   dm->ops->createglobalvector              = DMCreateGlobalVector_Network;
267   dm->ops->createlocalvector               = DMCreateLocalVector_Network;
268   dm->ops->getlocaltoglobalmapping         = NULL;
269   dm->ops->createfieldis                   = NULL;
270   dm->ops->createcoordinatedm              = NULL;
271   dm->ops->getcoloring                     = 0;
272   dm->ops->creatematrix                    = DMCreateMatrix_Network;
273   dm->ops->createinterpolation             = 0;
274   dm->ops->getaggregates                   = 0;
275   dm->ops->getinjection                    = 0;
276   dm->ops->refine                          = 0;
277   dm->ops->coarsen                         = 0;
278   dm->ops->refinehierarchy                 = 0;
279   dm->ops->coarsenhierarchy                = 0;
280   dm->ops->globaltolocalbegin              = DMGlobalToLocalBegin_Network;
281   dm->ops->globaltolocalend                = DMGlobalToLocalEnd_Network;
282   dm->ops->localtoglobalbegin              = DMLocalToGlobalBegin_Network;
283   dm->ops->localtoglobalend                = DMLocalToGlobalEnd_Network;
284   dm->ops->destroy                         = DMDestroy_Network;
285   dm->ops->createsubdm                     = NULL;
286   dm->ops->locatepoints                    = NULL;
287   PetscFunctionReturn(0);
288 }
289 
290 PetscErrorCode DMClone_Network(DM dm, DM *newdm)
291 {
292   DM_Network     *network = (DM_Network *) dm->data;
293   PetscErrorCode ierr;
294 
295   PetscFunctionBegin;
296   network->refct++;
297   (*newdm)->data = network;
298   ierr = PetscObjectChangeTypeName((PetscObject) *newdm, DMNETWORK);CHKERRQ(ierr);
299   ierr = DMInitialize_Network(*newdm);CHKERRQ(ierr);
300   PetscFunctionReturn(0);
301 }
302 
303 /*MC
304   DMNETWORK = "network" - A DM object that encapsulates an unstructured network. The implementation is based on the DM object
305                           DMPlex that manages unstructured grids. Distributed networks use a non-overlapping partitioning of
306                           the edges. In the local representation, Vecs contain all unknowns in the interior and shared boundary.
307                           This is specified by a PetscSection object. Ownership in the global representation is determined by
308                           ownership of the underlying DMPlex points. This is specified by another PetscSection object.
309 
310   Level: intermediate
311 
312 .seealso: DMType, DMNetworkCreate(), DMCreate(), DMSetType()
313 M*/
314 
315 PETSC_EXTERN PetscErrorCode DMCreate_Network(DM dm)
316 {
317   DM_Network     *network;
318   PetscErrorCode ierr;
319 
320   PetscFunctionBegin;
321   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
322   ierr     = PetscNewLog(dm,&network);CHKERRQ(ierr);
323   dm->data = network;
324 
325   network->refct          = 1;
326   network->NNodes         = -1;
327   network->NEdges         = -1;
328   network->nNodes         = -1;
329   network->nEdges         = -1;
330 
331 
332   ierr = DMInitialize_Network(dm);CHKERRQ(ierr);
333   PetscFunctionReturn(0);
334 }
335 
336 /*@
337   DMNetworkCreate - Creates a DMNetwork object, which encapsulates an unstructured network.
338 
339   Collective on MPI_Comm
340 
341   Input Parameter:
342 . comm - The communicator for the DMNetwork object
343 
344   Output Parameter:
345 . network  - The DMNetwork object
346 
347   Level: beginner
348 
349 .keywords: DMNetwork, create
350 @*/
351 PetscErrorCode DMNetworkCreate(MPI_Comm comm, DM *network)
352 {
353   PetscErrorCode ierr;
354 
355   PetscFunctionBegin;
356   PetscValidPointer(network,2);
357   ierr = DMCreate(comm, network);CHKERRQ(ierr);
358   ierr = DMSetType(*network, DMNETWORK);CHKERRQ(ierr);
359   PetscFunctionReturn(0);
360 }
361