1 /*$Id: isltog.c,v 1.44 2000/06/25 03:53:23 bsmith Exp bsmith $*/ 2 3 #include "petscsys.h" /*I "petscsys.h" I*/ 4 #include "src/vec/is/isimpl.h" /*I "petscis.h" I*/ 5 6 #undef __FUNC__ 7 #define __FUNC__ /*<a name="ISLocalToGlobalMappingGetSize"></a>*/"ISLocalToGlobalMappingGetSize" 8 /*@C 9 ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping. 10 11 Not Collective 12 13 Input Parameter: 14 . ltog - local to global mapping 15 16 Output Parameter: 17 . n - the number of entries in the local mapping 18 19 Level: advanced 20 21 .keywords: IS, local-to-global mapping, create 22 23 .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate() 24 @*/ 25 int ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,int *n) 26 { 27 PetscFunctionBegin; 28 PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE); 29 *n = mapping->n; 30 PetscFunctionReturn(0); 31 } 32 33 #undef __FUNC__ 34 #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingView" 35 /*@C 36 ISLocalToGlobalMappingView - View a local to global mapping 37 38 Not Collective 39 40 Input Parameters: 41 + ltog - local to global mapping 42 - viewer - viewer 43 44 Level: advanced 45 46 .keywords: IS, local-to-global mapping, create 47 48 .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate() 49 @*/ 50 int ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,Viewer viewer) 51 { 52 int i,ierr,rank; 53 PetscTruth isascii; 54 55 PetscFunctionBegin; 56 PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE); 57 if (!viewer) viewer = VIEWER_STDOUT_(mapping->comm); 58 PetscValidHeaderSpecific(viewer,VIEWER_COOKIE); 59 PetscCheckSameComm(mapping,viewer); 60 61 ierr = MPI_Comm_rank(mapping->comm,&rank);CHKERRQ(ierr); 62 ierr = PetscTypeCompare((PetscObject)viewer,ASCII_VIEWER,&isascii);CHKERRQ(ierr); 63 if (isascii) { 64 for (i=0; i<mapping->n; i++) { 65 ierr = ViewerASCIISynchronizedPrintf(viewer,"[%d] %d %d\n",rank,i,mapping->indices[i]);CHKERRQ(ierr); 66 } 67 ierr = ViewerFlush(viewer);CHKERRQ(ierr); 68 } else { 69 SETERRQ1(1,1,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name); 70 } 71 72 PetscFunctionReturn(0); 73 } 74 75 #undef __FUNC__ 76 #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingCreateIS" 77 /*@C 78 ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n) 79 ordering and a global parallel ordering. 80 81 Not collective 82 83 Input Parameter: 84 . is - index set containing the global numbers for each local 85 86 Output Parameter: 87 . mapping - new mapping data structure 88 89 Level: advanced 90 91 .keywords: IS, local-to-global mapping, create 92 93 .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate() 94 @*/ 95 int ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping) 96 { 97 int n,*indices,ierr; 98 MPI_Comm comm; 99 100 PetscFunctionBegin; 101 PetscValidHeaderSpecific(is,IS_COOKIE); 102 103 ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr); 104 ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr); 105 ierr = ISGetIndices(is,&indices);CHKERRQ(ierr); 106 ierr = ISLocalToGlobalMappingCreate(comm,n,indices,mapping);CHKERRQ(ierr); 107 ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr); 108 109 PetscFunctionReturn(0); 110 } 111 112 #undef __FUNC__ 113 #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingCreate" 114 /*@C 115 ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n) 116 ordering and a global parallel ordering. 117 118 Not Collective, but communicator may have more than one process 119 120 Input Parameters: 121 + comm - MPI communicator 122 . n - the number of local elements 123 - indices - the global index for each local element 124 125 Output Parameter: 126 . mapping - new mapping data structure 127 128 Level: advanced 129 130 .keywords: IS, local-to-global mapping, create 131 132 .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS() 133 @*/ 134 int ISLocalToGlobalMappingCreate(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping) 135 { 136 int ierr; 137 138 PetscFunctionBegin; 139 PetscValidIntPointer(indices); 140 PetscValidPointer(mapping); 141 142 PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_COOKIE,0,"ISLocalToGlobalMapping", 143 cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView); 144 PLogObjectCreate(*mapping); 145 PLogObjectMemory(*mapping,sizeof(struct _p_ISLocalToGlobalMapping)+n*sizeof(int)); 146 147 (*mapping)->n = n; 148 (*mapping)->indices = (int*)PetscMalloc((n+1)*sizeof(int));CHKPTRQ((*mapping)->indices); 149 ierr = PetscMemcpy((*mapping)->indices,indices,n*sizeof(int));CHKERRQ(ierr); 150 151 /* 152 Do not create the global to local mapping. This is only created if 153 ISGlobalToLocalMapping() is called 154 */ 155 (*mapping)->globals = 0; 156 PetscFunctionReturn(0); 157 } 158 159 #undef __FUNC__ 160 #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingDestroy" 161 /*@ 162 ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n) 163 ordering and a global parallel ordering. 164 165 Note Collective 166 167 Input Parameters: 168 . mapping - mapping data structure 169 170 Level: advanced 171 172 .keywords: IS, local-to-global mapping, destroy 173 174 .seealso: ISLocalToGlobalMappingCreate() 175 @*/ 176 int ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping) 177 { 178 int ierr; 179 PetscFunctionBegin; 180 PetscValidPointer(mapping); 181 if (--mapping->refct > 0) PetscFunctionReturn(0); 182 if (mapping->refct < 0) { 183 SETERRQ(1,1,"Mapping already destroyed"); 184 } 185 186 ierr = PetscFree(mapping->indices);CHKERRQ(ierr); 187 if (mapping->globals) {ierr = PetscFree(mapping->globals);CHKERRQ(ierr);} 188 PLogObjectDestroy(mapping); 189 PetscHeaderDestroy(mapping); 190 PetscFunctionReturn(0); 191 } 192 193 #undef __FUNC__ 194 #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingApplyIS" 195 /*@ 196 ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering 197 a new index set using the global numbering defined in an ISLocalToGlobalMapping 198 context. 199 200 Not collective 201 202 Input Parameters: 203 + mapping - mapping between local and global numbering 204 - is - index set in local numbering 205 206 Output Parameters: 207 . newis - index set in global numbering 208 209 Level: advanced 210 211 .keywords: IS, local-to-global mapping, apply 212 213 .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(), 214 ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply() 215 @*/ 216 int ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis) 217 { 218 int ierr,n,i,*idxin,*idxmap,*idxout,Nmax = mapping->n; 219 220 PetscFunctionBegin; 221 PetscValidPointer(mapping); 222 PetscValidHeaderSpecific(is,IS_COOKIE); 223 PetscValidPointer(newis); 224 225 ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr); 226 ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr); 227 idxmap = mapping->indices; 228 229 idxout = (int*)PetscMalloc((n+1)*sizeof(int));CHKPTRQ(idxout); 230 for (i=0; i<n; i++) { 231 if (idxin[i] >= Nmax) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,1,"Local index %d too large %d (max) at %d",idxin[i],Nmax,i); 232 idxout[i] = idxmap[idxin[i]]; 233 } 234 ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr); 235 ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,newis);CHKERRQ(ierr); 236 ierr = PetscFree(idxout);CHKERRQ(ierr); 237 PetscFunctionReturn(0); 238 } 239 240 /*MC 241 ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering 242 and converts them to the global numbering. 243 244 Not collective 245 246 Input Parameters: 247 + mapping - the local to global mapping context 248 . N - number of integers 249 - in - input indices in local numbering 250 251 Output Parameter: 252 . out - indices in global numbering 253 254 Synopsis: 255 ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,int in[],int out[]) 256 257 Notes: 258 The in and out array parameters may be identical. 259 260 Level: advanced 261 262 .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(), 263 ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(), 264 AOPetscToApplication(), ISGlobalToLocalMappingApply() 265 266 .keywords: local-to-global, mapping, apply 267 268 M*/ 269 270 /* -----------------------------------------------------------------------------------------*/ 271 272 #undef __FUNC__ 273 #define __FUNC__ /*<a name=""></a>*/"ISGlobalToLocalMappingSetUp_Private" 274 /* 275 Creates the global fields in the ISLocalToGlobalMapping structure 276 */ 277 static int ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping) 278 { 279 int i,*idx = mapping->indices,n = mapping->n,end,start,*globals; 280 281 PetscFunctionBegin; 282 end = 0; 283 start = 100000000; 284 285 for (i=0; i<n; i++) { 286 if (idx[i] < 0) continue; 287 if (idx[i] < start) start = idx[i]; 288 if (idx[i] > end) end = idx[i]; 289 } 290 if (start > end) {start = 0; end = -1;} 291 mapping->globalstart = start; 292 mapping->globalend = end; 293 294 globals = mapping->globals = (int*)PetscMalloc((end-start+2)*sizeof(int));CHKPTRQ(mapping->globals); 295 for (i=0; i<end-start+1; i++) { 296 globals[i] = -1; 297 } 298 for (i=0; i<n; i++) { 299 if (idx[i] < 0) continue; 300 globals[idx[i] - start] = i; 301 } 302 303 PLogObjectMemory(mapping,(end-start+1)*sizeof(int)); 304 PetscFunctionReturn(0); 305 } 306 307 #undef __FUNC__ 308 #define __FUNC__ /*<a name=""></a>*/"ISGlobalToLocalMappingApply" 309 /*@ 310 ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers 311 specified with a global numbering. 312 313 Not collective 314 315 Input Parameters: 316 + mapping - mapping between local and global numbering 317 . type - IS_GTOLM_MASK - replaces global indices with no local value with -1 318 IS_GTOLM_DROP - drops the indices with no local value from the output list 319 . n - number of global indices to map 320 - idx - global indices to map 321 322 Output Parameters: 323 + nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n) 324 - idxout - local index of each global index, one must pass in an array long enough 325 to hold all the indices. You can call ISGlobalToLocalMappingApply() with 326 idxout == PETSC_NULL to determine the required length (returned in nout) 327 and then allocate the required space and call ISGlobalToLocalMappingApply() 328 a second time to set the values. 329 330 Notes: 331 Either nout or idxout may be PETSC_NULL. idx and idxout may be identical. 332 333 This is not scalable in memory usage. Each processor requires O(Nglobal) size 334 array to compute these. 335 336 Level: advanced 337 338 .keywords: IS, global-to-local mapping, apply 339 340 .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(), 341 ISLocalToGlobalMappingDestroy() 342 @*/ 343 int ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, 344 int n,const int idx[],int *nout,int idxout[]) 345 { 346 int i,ierr,*globals,nf = 0,tmp,start,end; 347 348 PetscFunctionBegin; 349 if (!mapping->globals) { 350 ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr); 351 } 352 globals = mapping->globals; 353 start = mapping->globalstart; 354 end = mapping->globalend; 355 356 if (type == IS_GTOLM_MASK) { 357 if (idxout) { 358 for (i=0; i<n; i++) { 359 if (idx[i] < 0) idxout[i] = idx[i]; 360 else if (idx[i] < start) idxout[i] = -1; 361 else if (idx[i] > end) idxout[i] = -1; 362 else idxout[i] = globals[idx[i] - start]; 363 } 364 } 365 if (nout) *nout = n; 366 } else { 367 if (idxout) { 368 for (i=0; i<n; i++) { 369 if (idx[i] < 0) continue; 370 if (idx[i] < start) continue; 371 if (idx[i] > end) continue; 372 tmp = globals[idx[i] - start]; 373 if (tmp < 0) continue; 374 idxout[nf++] = tmp; 375 } 376 } else { 377 for (i=0; i<n; i++) { 378 if (idx[i] < 0) continue; 379 if (idx[i] < start) continue; 380 if (idx[i] > end) continue; 381 tmp = globals[idx[i] - start]; 382 if (tmp < 0) continue; 383 nf++; 384 } 385 } 386 if (nout) *nout = nf; 387 } 388 389 PetscFunctionReturn(0); 390 } 391 392 #undef __FUNC__ 393 #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingGetInfo" 394 /*@C 395 ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and 396 each index shared by more than one processor 397 398 Collective on ISLocalToGlobalMapping 399 400 Input Parameters: 401 . mapping - the mapping from local to global indexing 402 403 Output Parameter: 404 + nproc - number of processors that are connected to this one 405 . proc - neighboring processors 406 . indices - indices of local nodes shared with neighbor (sorted by global numbering) 407 408 Level: advanced 409 410 .keywords: IS, local-to-global mapping, neighbors 411 412 .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate() 413 @*/ 414 int ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int ***indices) 415 { 416 int i,n = mapping->n,ierr,Ng,ng = PETSC_DECIDE,max = 0,*lindices = mapping->indices; 417 int size,rank,*nprocs,*owner,nsends,*sends,j,*starts,*work,nmax,nrecvs,*recvs,proc; 418 int tag,cnt,*len,*source,imdex,scale,*ownedsenders,*nownedsenders,rstart,nowned; 419 int node,nownedm; 420 MPI_Request *recv_waits,*send_waits; 421 MPI_Status recv_status,*send_status; 422 MPI_Comm comm = mapping->comm; 423 424 PetscFunctionBegin; 425 ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag);CHKERRQ(ierr); 426 427 for (i=0; i<n; i++) { 428 if (lindices[i] > max) max = lindices[i]; 429 } 430 ierr = MPI_Allreduce(&max,&Ng,1,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr); 431 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 432 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 433 scale = Ng/size + 1; 434 ng = scale; if (rank == size-1) ng = Ng - scale*(size-1); 435 rstart = scale*rank; 436 437 /* determine ownership ranges of global indices */ 438 nprocs = (int*)PetscMalloc((2*size+1)*sizeof(int));CHKPTRQ(nprocs); 439 ierr = PetscMemzero(nprocs,size*sizeof(int));CHKERRQ(ierr); 440 441 /* determine owners of each local node */ 442 owner = (int*)PetscMalloc((n+1)*sizeof(int));CHKPTRQ(owner); 443 for (i=0; i<n; i++) { 444 proc = lindices[i]/scale; 445 nprocs[proc]++; nprocs[size+proc] = 1; owner[i] = proc; 446 } 447 nsends = 0; for (i=0; i<size; i++) nsends += nprocs[size + i]; 448 PLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of global owners for my local data %d\n",nsends); 449 450 /* inform other processors of number of messages and max length*/ 451 work = (int*)PetscMalloc(2*size*sizeof(int));CHKPTRQ(work); 452 ierr = MPI_Allreduce(nprocs,work,2*size,MPI_INT,PetscMaxSum_Op,comm);CHKERRQ(ierr); 453 nmax = work[rank]; 454 nrecvs = work[size+rank]; 455 ierr = PetscFree(work);CHKERRQ(ierr); 456 PLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of local owners for my global data %d\n",nrecvs); 457 458 /* post receives for owned rows */ 459 recvs = (int*)PetscMalloc((nrecvs+1)*(nmax+1)*sizeof(int));CHKPTRQ(recvs); 460 recv_waits = (MPI_Request*)PetscMalloc((nrecvs+1)*sizeof(MPI_Request));CHKPTRQ(recv_waits); 461 for (i=0; i<nrecvs; i++) { 462 ierr = MPI_Irecv(recvs+nmax*i,nmax,MPI_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);CHKERRQ(ierr); 463 } 464 465 /* pack messages containing lists of local nodes to owners */ 466 sends = (int*)PetscMalloc((n+1)*sizeof(int));CHKPTRQ(sends); 467 starts = (int*)PetscMalloc((size+1)*sizeof(int));CHKPTRQ(starts); 468 starts[0] = 0; 469 for (i=1; i<size; i++) { starts[i] = starts[i-1] + nprocs[i-1];} 470 for (i=0; i<n; i++) { 471 sends[starts[owner[i]]++] = lindices[i]; 472 } 473 ierr = PetscFree(owner);CHKERRQ(ierr); 474 starts[0] = 0; 475 for (i=1; i<size; i++) { starts[i] = starts[i-1] + nprocs[i-1];} 476 477 /* send the messages */ 478 send_waits = (MPI_Request*)PetscMalloc((nsends+1)*sizeof(MPI_Request));CHKPTRQ(send_waits); 479 cnt = 0; 480 for (i=0; i<size; i++) { 481 if (nprocs[i]) { 482 ierr = MPI_Isend(sends+starts[i],nprocs[i],MPI_INT,i,tag,comm,send_waits+cnt);CHKERRQ(ierr); 483 cnt++; 484 } 485 } 486 ierr = PetscFree(starts);CHKERRQ(ierr); 487 488 /* wait on receives */ 489 source = (int*)PetscMalloc((2*nrecvs+1)*sizeof(int));CHKPTRQ(source); 490 len = source + nrecvs; 491 cnt = nrecvs; 492 nownedsenders = (int*)PetscMalloc((ng+1)*sizeof(int));CHKPTRQ(nownedsenders); 493 ierr = PetscMemzero(nownedsenders,ng*sizeof(int));CHKERRQ(ierr); 494 while (cnt) { 495 ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr); 496 /* unpack receives into our local space */ 497 ierr = MPI_Get_count(&recv_status,MPI_INT,&len[imdex]);CHKERRQ(ierr); 498 source[imdex] = recv_status.MPI_SOURCE; 499 /* count how many local owners for each of my global owned indices */ 500 for (i=0; i<len[imdex]; i++) nownedsenders[recvs[imdex*nmax+i]-rstart]++; 501 cnt--; 502 } 503 ierr = PetscFree(recv_waits);CHKERRQ(ierr); 504 505 /* count how many globally owned indices are on an edge multiplied by how many processors 506 own them. */ 507 nowned = 0; 508 nownedm = 0; 509 for (i=0; i<ng; i++) { 510 if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;} 511 } 512 513 /* create single array to contain rank of all local owners of each globally owned index */ 514 ownedsenders = (int*)PetscMalloc((nownedm+1)*sizeof(int));CHKERRQ(ierr); 515 starts = (int*)PetscMalloc((nowned+1)*sizeof(int));CHKPTRQ(starts); 516 starts[0] = 0; 517 for (i=1; i<ng; i++) { 518 if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1]; 519 else starts[i] = starts[i-1]; 520 } 521 522 /* for each globally owned node list all ariving processors */ 523 for (i=0; i<nrecvs; i++) { 524 for (j=0; j<len[i]; j++) { 525 node = recvs[i*nmax+j]-rstart; 526 if (nownedsenders[node] > 1) { 527 ownedsenders[starts[node]++] = source[i]; 528 } 529 } 530 } 531 532 /* wait on sends */ 533 if (nsends) { 534 send_status = (MPI_Status*)PetscMalloc(nsends*sizeof(MPI_Status));CHKPTRQ(send_status); 535 ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr); 536 ierr = PetscFree(send_status);CHKERRQ(ierr); 537 } 538 ierr = PetscFree(send_waits);CHKERRQ(ierr); 539 ierr = PetscFree(sends);CHKERRQ(ierr); 540 ierr = PetscFree(nownedsenders);CHKERRQ(ierr); 541 ierr = PetscFree(ownedsenders);CHKERRQ(ierr); 542 ierr = PetscFree(starts);CHKERRQ(ierr); 543 544 ierr = PetscFree(source);CHKERRQ(ierr); 545 ierr = PetscFree(recvs);CHKERRQ(ierr); 546 ierr = PetscFree(nprocs);CHKERRQ(ierr); 547 PetscFunctionReturn(0); 548 } 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568