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