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