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 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->range && map->bs > 0 && map->bs != bs) SETERRQ2(map->comm,PETSC_ERR_ARG_INCOMP,"Cannot change block size %D to %D",map->bs,bs); 400 if (map->mapping) { 401 PetscInt lbs; 402 PetscErrorCode ierr; 403 404 ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&lbs);CHKERRQ(ierr); 405 if (lbs != bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Blocksize of localtoglobalmapping %D must match that of layout %D",lbs,bs); 406 } 407 map->bs = bs; 408 PetscFunctionReturn(0); 409 } 410 411 #undef __FUNCT__ 412 #define __FUNCT__ "PetscLayoutGetBlockSize" 413 /*@ 414 PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object. 415 416 Not Collective 417 418 Input Parameters: 419 . map - pointer to the map 420 421 Output Parameters: 422 . bs - the size 423 424 Level: developer 425 426 Notes: 427 Call this after the call to PetscLayoutSetUp() 428 429 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp() 430 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize() 431 @*/ 432 PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs) 433 { 434 PetscFunctionBegin; 435 *bs = PetscAbs(map->bs); 436 PetscFunctionReturn(0); 437 } 438 439 #undef __FUNCT__ 440 #define __FUNCT__ "PetscLayoutGetRange" 441 /*@ 442 PetscLayoutGetRange - gets the range of values owned by this process 443 444 Not Collective 445 446 Input Parameters: 447 . map - pointer to the map 448 449 Output Parameters: 450 + rstart - first index owned by this process 451 - rend - one more than the last index owned by this process 452 453 Level: developer 454 455 Notes: 456 Call this after the call to PetscLayoutSetUp() 457 458 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), 459 PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp() 460 @*/ 461 PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend) 462 { 463 PetscFunctionBegin; 464 if (rstart) *rstart = map->rstart; 465 if (rend) *rend = map->rend; 466 PetscFunctionReturn(0); 467 } 468 469 /*@C 470 PetscLayoutGetRanges - gets the range of values owned by all processes 471 472 Not Collective 473 474 Input Parameters: 475 . map - pointer to the map 476 477 Output Parameters: 478 . range - start of each processors range of indices (the final entry is one more then the 479 last index on the last process) 480 481 Level: developer 482 483 Notes: 484 Call this after the call to PetscLayoutSetUp() 485 486 Fortran Notes: 487 Not available from Fortran 488 489 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), 490 PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp() 491 492 @*/ 493 #undef __FUNCT__ 494 #define __FUNCT__ "PetscLayoutGetRanges" 495 PetscErrorCode PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[]) 496 { 497 PetscFunctionBegin; 498 *range = map->range; 499 PetscFunctionReturn(0); 500 } 501 502 #undef __FUNCT__ 503 #define __FUNCT__ "PetscSFSetGraphLayout" 504 /*@C 505 PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout 506 507 Collective 508 509 Input Arguments: 510 + sf - star forest 511 . layout - PetscLayout defining the global space 512 . nleaves - number of leaf vertices on the current process, each of these references a root on any process 513 . ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage 514 - iremote - remote locations of root vertices for each leaf on the current process 515 516 Level: intermediate 517 518 .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph() 519 @*/ 520 PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote) 521 { 522 PetscErrorCode ierr; 523 PetscInt i,nroots; 524 PetscSFNode *remote; 525 526 PetscFunctionBegin; 527 ierr = PetscLayoutGetLocalSize(layout,&nroots);CHKERRQ(ierr); 528 ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr); 529 for (i=0; i<nleaves; i++) { 530 PetscInt owner = -1; 531 ierr = PetscLayoutFindOwner(layout,iremote[i],&owner);CHKERRQ(ierr); 532 remote[i].rank = owner; 533 remote[i].index = iremote[i] - layout->range[owner]; 534 } 535 ierr = PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);CHKERRQ(ierr); 536 PetscFunctionReturn(0); 537 } 538 539