1 2 /* 3 This file contains routines for basic map object implementation. 4 */ 5 6 #include <petscvec.h> 7 #include <petscsf.h> 8 #include <petsc-private/threadcommimpl.h> 9 #undef __FUNCT__ 10 #define __FUNCT__ "PetscLayoutCreate" 11 /*@C 12 PetscLayoutCreate - Allocates PetscLayout space and sets the map contents to the default. 13 14 Collective on MPI_Comm 15 16 Input Parameters: 17 + comm - the MPI communicator 18 - map - pointer to the map 19 20 Level: advanced 21 22 Notes: 23 Typical calling sequence 24 .vb 25 PetscLayoutCreate(MPI_Comm,PetscLayout *); 26 PetscLayoutSetBlockSize(PetscLayout,1); 27 PetscLayoutSetSize(PetscLayout,N) // or PetscLayoutSetLocalSize(PetscLayout,n); 28 PetscLayoutSetUp(PetscLayout); 29 .ve 30 Optionally use any of the following: 31 32 + PetscLayoutGetSize(PetscLayout,PetscInt *); 33 . PetscLayoutGetLocalSize(PetscLayout,PetscInt *); 34 . PetscLayoutGetRange(PetscLayout,PetscInt *rstart,PetscInt *rend); 35 . PetscLayoutGetRanges(PetscLayout,const PetscInt *range[]); 36 - PetscLayoutDestroy(PetscLayout*); 37 38 The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is often not needed in 39 user codes unless you really gain something in their use. 40 41 Fortran Notes: 42 Not available from Fortran 43 44 .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(), 45 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp() 46 47 @*/ 48 PetscErrorCode PetscLayoutCreate(MPI_Comm comm,PetscLayout *map) 49 { 50 PetscErrorCode ierr; 51 52 PetscFunctionBegin; 53 ierr = PetscNew(map);CHKERRQ(ierr); 54 55 (*map)->comm = comm; 56 (*map)->bs = -1; 57 (*map)->n = -1; 58 (*map)->N = -1; 59 (*map)->range = 0; 60 (*map)->rstart = 0; 61 (*map)->rend = 0; 62 (*map)->trstarts = 0; 63 PetscFunctionReturn(0); 64 } 65 66 /*@C 67 PetscLayoutDestroy - Frees a map object and frees its range if that exists. 68 69 Collective on MPI_Comm 70 71 Input Parameters: 72 . map - the PetscLayout 73 74 Level: developer 75 76 The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is 77 recommended they not be used in user codes unless you really gain something in their use. 78 79 Fortran Notes: 80 Not available from Fortran 81 82 .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutCreate(), 83 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp() 84 85 @*/ 86 #undef __FUNCT__ 87 #define __FUNCT__ "PetscLayoutDestroy" 88 PetscErrorCode PetscLayoutDestroy(PetscLayout *map) 89 { 90 PetscErrorCode ierr; 91 92 PetscFunctionBegin; 93 if (!*map) PetscFunctionReturn(0); 94 if (!(*map)->refcnt--) { 95 ierr = PetscFree((*map)->range);CHKERRQ(ierr); 96 ierr = ISLocalToGlobalMappingDestroy(&(*map)->mapping);CHKERRQ(ierr); 97 #if defined(PETSC_THREADCOMM_ACTIVE) 98 ierr = PetscFree((*map)->trstarts);CHKERRQ(ierr); 99 #endif 100 101 ierr = PetscFree((*map));CHKERRQ(ierr); 102 } 103 *map = NULL; 104 PetscFunctionReturn(0); 105 } 106 107 /*@C 108 PetscLayoutSetUp - given a map where you have set either the global or local 109 size sets up the map so that it may be used. 110 111 Collective on MPI_Comm 112 113 Input Parameters: 114 . map - pointer to the map 115 116 Level: developer 117 118 Notes: Typical calling sequence 119 PetscLayoutCreate(MPI_Comm,PetscLayout *); 120 PetscLayoutSetBlockSize(PetscLayout,1); 121 PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both 122 PetscLayoutSetUp(PetscLayout); 123 PetscLayoutGetSize(PetscLayout,PetscInt *); 124 125 126 If the local size, global size are already set and range exists then this does nothing. 127 128 Fortran Notes: 129 Not available from Fortran 130 131 .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(), 132 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutCreate() 133 134 @*/ 135 #undef __FUNCT__ 136 #define __FUNCT__ "PetscLayoutSetUp" 137 PetscErrorCode PetscLayoutSetUp(PetscLayout map) 138 { 139 PetscMPIInt rank,size; 140 PetscInt p; 141 PetscErrorCode ierr; 142 143 PetscFunctionBegin; 144 if ((map->n >= 0) && (map->N >= 0) && (map->range)) PetscFunctionReturn(0); 145 146 ierr = MPI_Comm_size(map->comm, &size);CHKERRQ(ierr); 147 ierr = MPI_Comm_rank(map->comm, &rank);CHKERRQ(ierr); 148 if (map->n > 0) map->n = map->n/PetscAbs(map->bs); 149 if (map->N > 0) map->N = map->N/PetscAbs(map->bs); 150 ierr = PetscSplitOwnership(map->comm,&map->n,&map->N);CHKERRQ(ierr); 151 map->n = map->n*PetscAbs(map->bs); 152 map->N = map->N*PetscAbs(map->bs); 153 if (!map->range) { 154 ierr = PetscMalloc1(size+1, &map->range);CHKERRQ(ierr); 155 } 156 ierr = MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);CHKERRQ(ierr); 157 158 map->range[0] = 0; 159 for (p = 2; p <= size; p++) map->range[p] += map->range[p-1]; 160 161 map->rstart = map->range[rank]; 162 map->rend = map->range[rank+1]; 163 #if defined(PETSC_THREADCOMM_ACTIVE) 164 /* Set the thread ownership ranges */ 165 ierr = PetscThreadCommGetOwnershipRanges(map->comm,map->n,&map->trstarts);CHKERRQ(ierr); 166 #endif 167 PetscFunctionReturn(0); 168 } 169 170 #undef __FUNCT__ 171 #define __FUNCT__ "PetscLayoutDuplicate" 172 /*@C 173 174 PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first. 175 176 Collective on PetscLayout 177 178 Input Parameter: 179 . in - input PetscLayout to be duplicated 180 181 Output Parameter: 182 . out - the copy 183 184 Level: developer 185 186 Notes: PetscLayoutSetUp() does not need to be called on the resulting PetscLayout 187 188 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference() 189 190 @*/ 191 PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out) 192 { 193 PetscMPIInt size; 194 PetscErrorCode ierr; 195 MPI_Comm comm = in->comm; 196 197 PetscFunctionBegin; 198 ierr = PetscLayoutDestroy(out);CHKERRQ(ierr); 199 ierr = PetscLayoutCreate(comm,out);CHKERRQ(ierr); 200 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 201 ierr = PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));CHKERRQ(ierr); 202 ierr = PetscMalloc1(size+1,&(*out)->range);CHKERRQ(ierr); 203 ierr = PetscMemcpy((*out)->range,in->range,(size+1)*sizeof(PetscInt));CHKERRQ(ierr); 204 205 (*out)->refcnt = 0; 206 PetscFunctionReturn(0); 207 } 208 209 #undef __FUNCT__ 210 #define __FUNCT__ "PetscLayoutReference" 211 /*@C 212 213 PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX() 214 215 Collective on PetscLayout 216 217 Input Parameter: 218 . in - input PetscLayout to be copied 219 220 Output Parameter: 221 . out - the reference location 222 223 Level: developer 224 225 Notes: PetscLayoutSetUp() does not need to be called on the resulting PetscLayout 226 227 If the out location already contains a PetscLayout it is destroyed 228 229 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate() 230 231 @*/ 232 PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out) 233 { 234 PetscErrorCode ierr; 235 236 PetscFunctionBegin; 237 in->refcnt++; 238 ierr = PetscLayoutDestroy(out);CHKERRQ(ierr); 239 *out = in; 240 PetscFunctionReturn(0); 241 } 242 243 #undef __FUNCT__ 244 #define __FUNCT__ "PetscLayoutSetISLocalToGlobalMapping" 245 /*@C 246 247 PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout 248 249 Collective on PetscLayout 250 251 Input Parameter: 252 + in - input PetscLayout 253 - ltog - the local to global mapping 254 255 256 Level: developer 257 258 Notes: PetscLayoutSetUp() does not need to be called on the resulting PetscLayout 259 260 If the ltog location already contains a PetscLayout it is destroyed 261 262 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate() 263 264 @*/ 265 PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog) 266 { 267 PetscErrorCode ierr; 268 PetscInt bs; 269 270 PetscFunctionBegin; 271 ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&bs);CHKERRQ(ierr); 272 if (in->bs > 0 && in->bs != bs) SETERRQ2(in->comm,PETSC_ERR_PLIB,"Blocksize of layout %D must match that of mapping %D",in->bs,bs); 273 ierr = PetscObjectReference((PetscObject)ltog);CHKERRQ(ierr); 274 ierr = ISLocalToGlobalMappingDestroy(&in->mapping);CHKERRQ(ierr); 275 in->mapping = ltog; 276 PetscFunctionReturn(0); 277 } 278 279 /*@C 280 PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object. 281 282 Collective on PetscLayout 283 284 Input Parameters: 285 + map - pointer to the map 286 - n - the local size 287 288 Level: developer 289 290 Notes: 291 Call this after the call to PetscLayoutCreate() 292 293 Fortran Notes: 294 Not available from Fortran 295 296 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp() 297 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize() 298 299 @*/ 300 #undef __FUNCT__ 301 #define __FUNCT__ "PetscLayoutSetLocalSize" 302 PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n) 303 { 304 PetscFunctionBegin; 305 if (map->bs > 1 && n % map->bs) SETERRQ2(map->comm,PETSC_ERR_ARG_INCOMP,"Local size %D not compatible with block size %D",n,map->bs); 306 map->n = n; 307 PetscFunctionReturn(0); 308 } 309 310 /*@C 311 PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object. 312 313 Not Collective 314 315 Input Parameters: 316 . map - pointer to the map 317 318 Output Parameters: 319 . n - the local size 320 321 Level: developer 322 323 Notes: 324 Call this after the call to PetscLayoutSetUp() 325 326 Fortran Notes: 327 Not available from Fortran 328 329 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp() 330 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize() 331 332 @*/ 333 #undef __FUNCT__ 334 #define __FUNCT__ "PetscLayoutGetLocalSize" 335 PetscErrorCode PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n) 336 { 337 PetscFunctionBegin; 338 *n = map->n; 339 PetscFunctionReturn(0); 340 } 341 342 /*@C 343 PetscLayoutSetSize - Sets the global size for a PetscLayout object. 344 345 Logically Collective on PetscLayout 346 347 Input Parameters: 348 + map - pointer to the map 349 - n - the global size 350 351 Level: developer 352 353 Notes: 354 Call this after the call to PetscLayoutCreate() 355 356 Fortran Notes: 357 Not available from Fortran 358 359 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp() 360 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize() 361 362 @*/ 363 #undef __FUNCT__ 364 #define __FUNCT__ "PetscLayoutSetSize" 365 PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n) 366 { 367 PetscFunctionBegin; 368 map->N = n; 369 PetscFunctionReturn(0); 370 } 371 372 /*@C 373 PetscLayoutGetSize - Gets the global size for a PetscLayout object. 374 375 Not Collective 376 377 Input Parameters: 378 . map - pointer to the map 379 380 Output Parameters: 381 . n - the global size 382 383 Level: developer 384 385 Notes: 386 Call this after the call to PetscLayoutSetUp() 387 388 Fortran Notes: 389 Not available from Fortran 390 391 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp() 392 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize() 393 394 @*/ 395 #undef __FUNCT__ 396 #define __FUNCT__ "PetscLayoutGetSize" 397 PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n) 398 { 399 PetscFunctionBegin; 400 *n = map->N; 401 PetscFunctionReturn(0); 402 } 403 404 /*@C 405 PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object. 406 407 Logically Collective on PetscLayout 408 409 Input Parameters: 410 + map - pointer to the map 411 - bs - the size 412 413 Level: developer 414 415 Notes: 416 Call this after the call to PetscLayoutCreate() 417 418 Fortran Notes: 419 Not available from Fortran 420 421 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(), 422 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp() 423 424 @*/ 425 #undef __FUNCT__ 426 #define __FUNCT__ "PetscLayoutSetBlockSize" 427 PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs) 428 { 429 PetscFunctionBegin; 430 if (bs < 0) PetscFunctionReturn(0); 431 if (map->n > 0 && map->n % bs) SETERRQ2(map->comm,PETSC_ERR_ARG_INCOMP,"Local size %D not compatible with block size %D",map->n,bs); 432 if (map->range && map->bs > 0 && map->bs != bs) SETERRQ2(map->comm,PETSC_ERR_ARG_INCOMP,"Cannot change block size %D to %D",map->bs,bs); 433 if (map->mapping) { 434 PetscInt lbs; 435 PetscErrorCode ierr; 436 437 ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&lbs);CHKERRQ(ierr); 438 if (lbs != bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Blocksize of localtoglobalmapping %D must match that of layout %D",lbs,bs); 439 } 440 map->bs = bs; 441 PetscFunctionReturn(0); 442 } 443 444 /*@C 445 PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object. 446 447 Not Collective 448 449 Input Parameters: 450 . map - pointer to the map 451 452 Output Parameters: 453 . bs - the size 454 455 Level: developer 456 457 Notes: 458 Call this after the call to PetscLayoutSetUp() 459 460 Fortran Notes: 461 Not available from Fortran 462 463 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp() 464 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize() 465 466 @*/ 467 #undef __FUNCT__ 468 #define __FUNCT__ "PetscLayoutGetBlockSize" 469 PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs) 470 { 471 PetscFunctionBegin; 472 *bs = PetscAbs(map->bs); 473 PetscFunctionReturn(0); 474 } 475 476 477 /*@C 478 PetscLayoutGetRange - gets the range of values owned by this process 479 480 Not Collective 481 482 Input Parameters: 483 . map - pointer to the map 484 485 Output Parameters: 486 + rstart - first index owned by this process 487 - rend - one more than the last index owned by this process 488 489 Level: developer 490 491 Notes: 492 Call this after the call to PetscLayoutSetUp() 493 494 Fortran Notes: 495 Not available from Fortran 496 497 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), 498 PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp() 499 500 @*/ 501 #undef __FUNCT__ 502 #define __FUNCT__ "PetscLayoutGetRange" 503 PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend) 504 { 505 PetscFunctionBegin; 506 if (rstart) *rstart = map->rstart; 507 if (rend) *rend = map->rend; 508 PetscFunctionReturn(0); 509 } 510 511 /*@C 512 PetscLayoutGetRanges - gets the range of values owned by all processes 513 514 Not Collective 515 516 Input Parameters: 517 . map - pointer to the map 518 519 Output Parameters: 520 . range - start of each processors range of indices (the final entry is one more then the 521 last index on the last process) 522 523 Level: developer 524 525 Notes: 526 Call this after the call to PetscLayoutSetUp() 527 528 Fortran Notes: 529 Not available from Fortran 530 531 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), 532 PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp() 533 534 @*/ 535 #undef __FUNCT__ 536 #define __FUNCT__ "PetscLayoutGetRanges" 537 PetscErrorCode PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[]) 538 { 539 PetscFunctionBegin; 540 *range = map->range; 541 PetscFunctionReturn(0); 542 } 543 544 #undef __FUNCT__ 545 #define __FUNCT__ "PetscSFSetGraphLayout" 546 /*@C 547 PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout 548 549 Collective 550 551 Input Arguments: 552 + sf - star forest 553 . layout - PetscLayout defining the global space 554 . nleaves - number of leaf vertices on the current process, each of these references a root on any process 555 . ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage 556 - iremote - remote locations of root vertices for each leaf on the current process 557 558 Level: intermediate 559 560 .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph() 561 @*/ 562 PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote) 563 { 564 PetscErrorCode ierr; 565 PetscInt i,nroots; 566 PetscSFNode *remote; 567 568 PetscFunctionBegin; 569 ierr = PetscLayoutGetLocalSize(layout,&nroots);CHKERRQ(ierr); 570 ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr); 571 for (i=0; i<nleaves; i++) { 572 PetscInt owner = -1; 573 ierr = PetscLayoutFindOwner(layout,iremote[i],&owner);CHKERRQ(ierr); 574 remote[i].rank = owner; 575 remote[i].index = iremote[i] - layout->range[owner]; 576 } 577 ierr = PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);CHKERRQ(ierr); 578 PetscFunctionReturn(0); 579 } 580 581