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