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