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