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