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