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