1 2 /* 3 The memory scalable AO application ordering routines. These store the 4 local orderings on each processor. 5 */ 6 7 #include <../src/vec/is/ao/aoimpl.h> /*I "petscao.h" I*/ 8 9 typedef struct { 10 PetscInt *app_loc; /* app_loc[i] is the partner for the ith local PETSc slot */ 11 PetscInt *petsc_loc; /* petsc_loc[j] is the partner for the jth local app slot */ 12 PetscLayout map; /* determines the local sizes of ao */ 13 } AO_MemoryScalable; 14 15 /* 16 All processors have the same data so processor 1 prints it 17 */ 18 #undef __FUNCT__ 19 #define __FUNCT__ "AOView_MemoryScalable" 20 PetscErrorCode AOView_MemoryScalable(AO ao,PetscViewer viewer) 21 { 22 PetscErrorCode ierr; 23 PetscMPIInt rank,size; 24 AO_MemoryScalable *aomems = (AO_MemoryScalable*)ao->data; 25 PetscBool iascii; 26 PetscMPIInt tag_app,tag_petsc; 27 PetscLayout map = aomems->map; 28 PetscInt *app,*app_loc,*petsc,*petsc_loc,len,i,j; 29 MPI_Status status; 30 31 PetscFunctionBegin; 32 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 33 if (!iascii) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Viewer type %s not supported for AO MemoryScalable",((PetscObject)viewer)->type_name); 34 35 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)ao),&rank);CHKERRQ(ierr); 36 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)ao),&size);CHKERRQ(ierr); 37 38 ierr = PetscObjectGetNewTag((PetscObject)ao,&tag_app);CHKERRQ(ierr); 39 ierr = PetscObjectGetNewTag((PetscObject)ao,&tag_petsc);CHKERRQ(ierr); 40 41 if (!rank) { 42 ierr = PetscViewerASCIIPrintf(viewer,"Number of elements in ordering %D\n",ao->N);CHKERRQ(ierr); 43 ierr = PetscViewerASCIIPrintf(viewer, "PETSc->App App->PETSc\n");CHKERRQ(ierr); 44 45 ierr = PetscMalloc2(map->N,&app,map->N,&petsc);CHKERRQ(ierr); 46 len = map->n; 47 /* print local AO */ 48 ierr = PetscViewerASCIIPrintf(viewer,"Process [%D]\n",rank);CHKERRQ(ierr); 49 for (i=0; i<len; i++) { 50 ierr = PetscViewerASCIIPrintf(viewer,"%3D %3D %3D %3D\n",i,aomems->app_loc[i],i,aomems->petsc_loc[i]);CHKERRQ(ierr); 51 } 52 53 /* recv and print off-processor's AO */ 54 for (i=1; i<size; i++) { 55 len = map->range[i+1] - map->range[i]; 56 app_loc = app + map->range[i]; 57 petsc_loc = petsc+ map->range[i]; 58 ierr = MPI_Recv(app_loc,(PetscMPIInt)len,MPIU_INT,i,tag_app,PetscObjectComm((PetscObject)ao),&status);CHKERRQ(ierr); 59 ierr = MPI_Recv(petsc_loc,(PetscMPIInt)len,MPIU_INT,i,tag_petsc,PetscObjectComm((PetscObject)ao),&status);CHKERRQ(ierr); 60 ierr = PetscViewerASCIIPrintf(viewer,"Process [%D]\n",i);CHKERRQ(ierr); 61 for (j=0; j<len; j++) { 62 ierr = PetscViewerASCIIPrintf(viewer,"%3D %3D %3D %3D\n",map->range[i]+j,app_loc[j],map->range[i]+j,petsc_loc[j]);CHKERRQ(ierr); 63 } 64 } 65 ierr = PetscFree2(app,petsc);CHKERRQ(ierr); 66 67 } else { 68 /* send values */ 69 ierr = MPI_Send((void*)aomems->app_loc,map->n,MPIU_INT,0,tag_app,PetscObjectComm((PetscObject)ao));CHKERRQ(ierr); 70 ierr = MPI_Send((void*)aomems->petsc_loc,map->n,MPIU_INT,0,tag_petsc,PetscObjectComm((PetscObject)ao));CHKERRQ(ierr); 71 } 72 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 73 PetscFunctionReturn(0); 74 } 75 76 #undef __FUNCT__ 77 #define __FUNCT__ "AODestroy_MemoryScalable" 78 PetscErrorCode AODestroy_MemoryScalable(AO ao) 79 { 80 AO_MemoryScalable *aomems = (AO_MemoryScalable*)ao->data; 81 PetscErrorCode ierr; 82 83 PetscFunctionBegin; 84 ierr = PetscFree2(aomems->app_loc,aomems->petsc_loc);CHKERRQ(ierr); 85 ierr = PetscLayoutDestroy(&aomems->map);CHKERRQ(ierr); 86 ierr = PetscFree(aomems);CHKERRQ(ierr); 87 PetscFunctionReturn(0); 88 } 89 90 /* 91 Input Parameters: 92 + ao - the application ordering context 93 . n - the number of integers in ia[] 94 . ia - the integers; these are replaced with their mapped value 95 - maploc - app_loc or petsc_loc in struct "AO_MemoryScalable" 96 97 Output Parameter: 98 . ia - the mapped interges 99 */ 100 #undef __FUNCT__ 101 #define __FUNCT__ "AOMap_MemoryScalable_private" 102 PetscErrorCode AOMap_MemoryScalable_private(AO ao,PetscInt n,PetscInt *ia,PetscInt *maploc) 103 { 104 PetscErrorCode ierr; 105 AO_MemoryScalable *aomems = (AO_MemoryScalable*)ao->data; 106 MPI_Comm comm; 107 PetscMPIInt rank,size,tag1,tag2; 108 PetscInt *owner,*start,*sizes,nsends,nreceives; 109 PetscInt nmax,count,*sindices,*rindices,i,j,idx,lastidx,*sindices2,*rindices2; 110 PetscInt *owners = aomems->map->range; 111 MPI_Request *send_waits,*recv_waits,*send_waits2,*recv_waits2; 112 MPI_Status recv_status; 113 PetscMPIInt nindices,source,widx; 114 PetscInt *rbuf,*sbuf; 115 MPI_Status *send_status,*send_status2; 116 117 PetscFunctionBegin; 118 ierr = PetscObjectGetComm((PetscObject)ao,&comm);CHKERRQ(ierr); 119 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 120 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 121 122 /* first count number of contributors to each processor */ 123 ierr = PetscMalloc2(2*size,&sizes,size,&start);CHKERRQ(ierr); 124 ierr = PetscMemzero(sizes,2*size*sizeof(PetscInt));CHKERRQ(ierr); 125 ierr = PetscCalloc1(n,&owner);CHKERRQ(ierr); 126 127 j = 0; 128 lastidx = -1; 129 for (i=0; i<n; i++) { 130 /* if indices are NOT locally sorted, need to start search at the beginning */ 131 if (lastidx > (idx = ia[i])) j = 0; 132 lastidx = idx; 133 for (; j<size; j++) { 134 if (idx >= owners[j] && idx < owners[j+1]) { 135 sizes[2*j]++; /* num of indices to be sent */ 136 sizes[2*j+1] = 1; /* send to proc[j] */ 137 owner[i] = j; 138 break; 139 } 140 } 141 } 142 sizes[2*rank]=sizes[2*rank+1]=0; /* do not receive from self! */ 143 nsends = 0; 144 for (i=0; i<size; i++) nsends += sizes[2*i+1]; 145 146 /* inform other processors of number of messages and max length*/ 147 ierr = PetscMaxSum(comm,sizes,&nmax,&nreceives);CHKERRQ(ierr); 148 149 /* allocate arrays */ 150 ierr = PetscObjectGetNewTag((PetscObject)ao,&tag1);CHKERRQ(ierr); 151 ierr = PetscObjectGetNewTag((PetscObject)ao,&tag2);CHKERRQ(ierr); 152 153 ierr = PetscMalloc2(nreceives*nmax,&rindices,nreceives,&recv_waits);CHKERRQ(ierr); 154 ierr = PetscMalloc2(nsends*nmax,&rindices2,nsends,&recv_waits2);CHKERRQ(ierr); 155 156 ierr = PetscMalloc3(n,&sindices,nsends,&send_waits,nsends,&send_status);CHKERRQ(ierr); 157 ierr = PetscMalloc3(n,&sindices2,nreceives,&send_waits2,nreceives,&send_status2);CHKERRQ(ierr); 158 159 /* post 1st receives: receive others requests 160 since we don't know how long each individual message is we 161 allocate the largest needed buffer for each receive. Potentially 162 this is a lot of wasted space. 163 */ 164 for (i=0,count=0; i<nreceives; i++) { 165 ierr = MPI_Irecv(rindices+nmax*i,nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+count++);CHKERRQ(ierr); 166 } 167 168 /* do 1st sends: 169 1) starts[i] gives the starting index in svalues for stuff going to 170 the ith processor 171 */ 172 start[0] = 0; 173 for (i=1; i<size; i++) start[i] = start[i-1] + sizes[2*i-2]; 174 for (i=0; i<n; i++) { 175 j = owner[i]; 176 if (j != rank) { 177 sindices[start[j]++] = ia[i]; 178 } else { /* compute my own map */ 179 if (ia[i] >= owners[rank] && ia[i] < owners[rank+1]) { 180 ia[i] = maploc[ia[i]-owners[rank]]; 181 } else { 182 ia[i] = -1; /* ia[i] is not in the range of 0 and N-1, maps it to -1 */ 183 } 184 } 185 } 186 187 start[0] = 0; 188 for (i=1; i<size; i++) start[i] = start[i-1] + sizes[2*i-2]; 189 for (i=0,count=0; i<size; i++) { 190 if (sizes[2*i+1]) { 191 /* send my request to others */ 192 ierr = MPI_Isend(sindices+start[i],sizes[2*i],MPIU_INT,i,tag1,comm,send_waits+count);CHKERRQ(ierr); 193 /* post receive for the answer of my request */ 194 ierr = MPI_Irecv(sindices2+start[i],sizes[2*i],MPIU_INT,i,tag2,comm,recv_waits2+count);CHKERRQ(ierr); 195 count++; 196 } 197 } 198 if (nsends != count) SETERRQ2(comm,PETSC_ERR_SUP,"nsends %d != count %d",nsends,count); 199 200 /* wait on 1st sends */ 201 if (nsends) { 202 ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr); 203 } 204 205 /* 1st recvs: other's requests */ 206 for (j=0; j< nreceives; j++) { 207 ierr = MPI_Waitany(nreceives,recv_waits,&widx,&recv_status);CHKERRQ(ierr); /* idx: index of handle for operation that completed */ 208 ierr = MPI_Get_count(&recv_status,MPIU_INT,&nindices);CHKERRQ(ierr); 209 rbuf = rindices+nmax*widx; /* global index */ 210 source = recv_status.MPI_SOURCE; 211 212 /* compute mapping */ 213 sbuf = rbuf; 214 for (i=0; i<nindices; i++) sbuf[i] = maploc[rbuf[i]-owners[rank]]; 215 216 /* send mapping back to the sender */ 217 ierr = MPI_Isend(sbuf,nindices,MPIU_INT,source,tag2,comm,send_waits2+widx);CHKERRQ(ierr); 218 } 219 220 /* wait on 2nd sends */ 221 if (nreceives) { 222 ierr = MPI_Waitall(nreceives,send_waits2,send_status2);CHKERRQ(ierr); 223 } 224 225 /* 2nd recvs: for the answer of my request */ 226 for (j=0; j< nsends; j++) { 227 ierr = MPI_Waitany(nsends,recv_waits2,&widx,&recv_status);CHKERRQ(ierr); 228 ierr = MPI_Get_count(&recv_status,MPIU_INT,&nindices);CHKERRQ(ierr); 229 source = recv_status.MPI_SOURCE; 230 /* pack output ia[] */ 231 rbuf = sindices2+start[source]; 232 count = 0; 233 for (i=0; i<n; i++) { 234 if (source == owner[i]) ia[i] = rbuf[count++]; 235 } 236 } 237 238 /* free arrays */ 239 ierr = PetscFree2(sizes,start);CHKERRQ(ierr); 240 ierr = PetscFree(owner);CHKERRQ(ierr); 241 ierr = PetscFree2(rindices,recv_waits);CHKERRQ(ierr); 242 ierr = PetscFree2(rindices2,recv_waits2);CHKERRQ(ierr); 243 ierr = PetscFree3(sindices,send_waits,send_status);CHKERRQ(ierr); 244 ierr = PetscFree3(sindices2,send_waits2,send_status2);CHKERRQ(ierr); 245 PetscFunctionReturn(0); 246 } 247 248 #undef __FUNCT__ 249 #define __FUNCT__ "AOPetscToApplication_MemoryScalable" 250 PetscErrorCode AOPetscToApplication_MemoryScalable(AO ao,PetscInt n,PetscInt *ia) 251 { 252 PetscErrorCode ierr; 253 AO_MemoryScalable *aomems = (AO_MemoryScalable*)ao->data; 254 PetscInt *app_loc = aomems->app_loc; 255 256 PetscFunctionBegin; 257 ierr = AOMap_MemoryScalable_private(ao,n,ia,app_loc);CHKERRQ(ierr); 258 PetscFunctionReturn(0); 259 } 260 261 #undef __FUNCT__ 262 #define __FUNCT__ "AOApplicationToPetsc_MemoryScalable" 263 PetscErrorCode AOApplicationToPetsc_MemoryScalable(AO ao,PetscInt n,PetscInt *ia) 264 { 265 PetscErrorCode ierr; 266 AO_MemoryScalable *aomems = (AO_MemoryScalable*)ao->data; 267 PetscInt *petsc_loc = aomems->petsc_loc; 268 269 PetscFunctionBegin; 270 ierr = AOMap_MemoryScalable_private(ao,n,ia,petsc_loc);CHKERRQ(ierr); 271 PetscFunctionReturn(0); 272 } 273 274 static struct _AOOps AOOps_MemoryScalable = { 275 AOView_MemoryScalable, 276 AODestroy_MemoryScalable, 277 AOPetscToApplication_MemoryScalable, 278 AOApplicationToPetsc_MemoryScalable, 279 0, 280 0, 281 0, 282 0 283 }; 284 285 #undef __FUNCT__ 286 #define __FUNCT__ "AOCreateMemoryScalable_private" 287 PetscErrorCode AOCreateMemoryScalable_private(MPI_Comm comm,PetscInt napp,const PetscInt from_array[],const PetscInt to_array[],AO ao, PetscInt *aomap_loc) 288 { 289 PetscErrorCode ierr; 290 AO_MemoryScalable *aomems = (AO_MemoryScalable*)ao->data; 291 PetscLayout map = aomems->map; 292 PetscInt n_local = map->n,i,j; 293 PetscMPIInt rank,size,tag; 294 PetscInt *owner,*start,*sizes,nsends,nreceives; 295 PetscInt nmax,count,*sindices,*rindices,idx,lastidx; 296 PetscInt *owners = aomems->map->range; 297 MPI_Request *send_waits,*recv_waits; 298 MPI_Status recv_status; 299 PetscMPIInt nindices,widx; 300 PetscInt *rbuf; 301 PetscInt n=napp,ip,ia; 302 MPI_Status *send_status; 303 304 PetscFunctionBegin; 305 ierr = PetscMemzero(aomap_loc,n_local*sizeof(PetscInt));CHKERRQ(ierr); 306 307 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 308 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 309 310 /* first count number of contributors (of from_array[]) to each processor */ 311 ierr = PetscCalloc1(2*size,&sizes);CHKERRQ(ierr); 312 ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr); 313 314 j = 0; 315 lastidx = -1; 316 for (i=0; i<n; i++) { 317 /* if indices are NOT locally sorted, need to start search at the beginning */ 318 if (lastidx > (idx = from_array[i])) j = 0; 319 lastidx = idx; 320 for (; j<size; j++) { 321 if (idx >= owners[j] && idx < owners[j+1]) { 322 sizes[2*j] += 2; /* num of indices to be sent - in pairs (ip,ia) */ 323 sizes[2*j+1] = 1; /* send to proc[j] */ 324 owner[i] = j; 325 break; 326 } 327 } 328 } 329 sizes[2*rank]=sizes[2*rank+1]=0; /* do not receive from self! */ 330 nsends = 0; 331 for (i=0; i<size; i++) nsends += sizes[2*i+1]; 332 333 /* inform other processors of number of messages and max length*/ 334 ierr = PetscMaxSum(comm,sizes,&nmax,&nreceives);CHKERRQ(ierr); 335 336 /* allocate arrays */ 337 ierr = PetscObjectGetNewTag((PetscObject)ao,&tag);CHKERRQ(ierr); 338 ierr = PetscMalloc2(nreceives*nmax,&rindices,nreceives,&recv_waits);CHKERRQ(ierr); 339 ierr = PetscMalloc3(2*n,&sindices,nsends,&send_waits,nsends,&send_status);CHKERRQ(ierr); 340 ierr = PetscMalloc1(size,&start);CHKERRQ(ierr); 341 342 /* post receives: */ 343 for (i=0; i<nreceives; i++) { 344 ierr = MPI_Irecv(rindices+nmax*i,nmax,MPIU_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);CHKERRQ(ierr); 345 } 346 347 /* do sends: 348 1) starts[i] gives the starting index in svalues for stuff going to 349 the ith processor 350 */ 351 start[0] = 0; 352 for (i=1; i<size; i++) start[i] = start[i-1] + sizes[2*i-2]; 353 for (i=0; i<n; i++) { 354 j = owner[i]; 355 if (j != rank) { 356 ip = from_array[i]; 357 ia = to_array[i]; 358 sindices[start[j]++] = ip; 359 sindices[start[j]++] = ia; 360 } else { /* compute my own map */ 361 ip = from_array[i] - owners[rank]; 362 ia = to_array[i]; 363 aomap_loc[ip] = ia; 364 } 365 } 366 367 start[0] = 0; 368 for (i=1; i<size; i++) start[i] = start[i-1] + sizes[2*i-2]; 369 for (i=0,count=0; i<size; i++) { 370 if (sizes[2*i+1]) { 371 ierr = MPI_Isend(sindices+start[i],sizes[2*i],MPIU_INT,i,tag,comm,send_waits+count);CHKERRQ(ierr); 372 count++; 373 } 374 } 375 if (nsends != count) SETERRQ2(comm,PETSC_ERR_SUP,"nsends %d != count %d",nsends,count); 376 377 /* wait on sends */ 378 if (nsends) { 379 ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr); 380 } 381 382 /* recvs */ 383 count=0; 384 for (j= nreceives; j>0; j--) { 385 ierr = MPI_Waitany(nreceives,recv_waits,&widx,&recv_status);CHKERRQ(ierr); 386 ierr = MPI_Get_count(&recv_status,MPIU_INT,&nindices);CHKERRQ(ierr); 387 rbuf = rindices+nmax*widx; /* global index */ 388 389 /* compute local mapping */ 390 for (i=0; i<nindices; i+=2) { /* pack aomap_loc */ 391 ip = rbuf[i] - owners[rank]; /* local index */ 392 ia = rbuf[i+1]; 393 aomap_loc[ip] = ia; 394 } 395 count++; 396 } 397 398 ierr = PetscFree(start);CHKERRQ(ierr); 399 ierr = PetscFree3(sindices,send_waits,send_status);CHKERRQ(ierr); 400 ierr = PetscFree2(rindices,recv_waits);CHKERRQ(ierr); 401 ierr = PetscFree(owner);CHKERRQ(ierr); 402 ierr = PetscFree(sizes);CHKERRQ(ierr); 403 PetscFunctionReturn(0); 404 } 405 406 #undef __FUNCT__ 407 #define __FUNCT__ "AOCreate_MemoryScalable" 408 PETSC_EXTERN PetscErrorCode AOCreate_MemoryScalable(AO ao) 409 { 410 PetscErrorCode ierr; 411 IS isapp=ao->isapp,ispetsc=ao->ispetsc; 412 const PetscInt *mypetsc,*myapp; 413 PetscInt napp,n_local,N,i,start,*petsc,*lens,*disp; 414 MPI_Comm comm; 415 AO_MemoryScalable *aomems; 416 PetscLayout map; 417 PetscMPIInt size,rank; 418 419 PetscFunctionBegin; 420 if (!isapp) SETERRQ(PetscObjectComm((PetscObject)ao),PETSC_ERR_ARG_WRONGSTATE,"AOSetIS() must be called before AOSetType()"); 421 /* create special struct aomems */ 422 ierr = PetscNewLog(ao,&aomems);CHKERRQ(ierr); 423 ao->data = (void*) aomems; 424 ierr = PetscMemcpy(ao->ops,&AOOps_MemoryScalable,sizeof(struct _AOOps));CHKERRQ(ierr); 425 ierr = PetscObjectChangeTypeName((PetscObject)ao,AOMEMORYSCALABLE);CHKERRQ(ierr); 426 427 /* transmit all local lengths of isapp to all processors */ 428 ierr = PetscObjectGetComm((PetscObject)isapp,&comm);CHKERRQ(ierr); 429 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 430 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 431 ierr = PetscMalloc2(size,&lens,size,&disp);CHKERRQ(ierr); 432 ierr = ISGetLocalSize(isapp,&napp);CHKERRQ(ierr); 433 ierr = MPI_Allgather(&napp, 1, MPIU_INT, lens, 1, MPIU_INT, comm);CHKERRQ(ierr); 434 435 N = 0; 436 for (i = 0; i < size; i++) { 437 disp[i] = N; 438 N += lens[i]; 439 } 440 441 /* If ispetsc is 0 then use "natural" numbering */ 442 if (napp) { 443 if (!ispetsc) { 444 start = disp[rank]; 445 ierr = PetscMalloc1(napp+1, &petsc);CHKERRQ(ierr); 446 for (i=0; i<napp; i++) petsc[i] = start + i; 447 } else { 448 ierr = ISGetIndices(ispetsc,&mypetsc);CHKERRQ(ierr); 449 petsc = (PetscInt*)mypetsc; 450 } 451 } 452 453 /* create a map with global size N - used to determine the local sizes of ao - shall we use local napp instead of N? */ 454 ierr = PetscLayoutCreate(comm,&map);CHKERRQ(ierr); 455 map->bs = 1; 456 map->N = N; 457 ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 458 459 ao->N = N; 460 ao->n = map->n; 461 aomems->map = map; 462 463 /* create distributed indices app_loc: petsc->app and petsc_loc: app->petsc */ 464 n_local = map->n; 465 ierr = PetscMalloc2(n_local, &aomems->app_loc,n_local,&aomems->petsc_loc);CHKERRQ(ierr); 466 ierr = PetscLogObjectMemory((PetscObject)ao,2*n_local*sizeof(PetscInt));CHKERRQ(ierr); 467 ierr = PetscMemzero(aomems->app_loc,n_local*sizeof(PetscInt));CHKERRQ(ierr); 468 ierr = PetscMemzero(aomems->petsc_loc,n_local*sizeof(PetscInt));CHKERRQ(ierr); 469 ierr = ISGetIndices(isapp,&myapp);CHKERRQ(ierr); 470 471 ierr = AOCreateMemoryScalable_private(comm,napp,petsc,myapp,ao,aomems->app_loc);CHKERRQ(ierr); 472 ierr = AOCreateMemoryScalable_private(comm,napp,myapp,petsc,ao,aomems->petsc_loc);CHKERRQ(ierr); 473 474 ierr = ISRestoreIndices(isapp,&myapp);CHKERRQ(ierr); 475 if (napp) { 476 if (ispetsc) { 477 ierr = ISRestoreIndices(ispetsc,&mypetsc);CHKERRQ(ierr); 478 } else { 479 ierr = PetscFree(petsc);CHKERRQ(ierr); 480 } 481 } 482 ierr = PetscFree2(lens,disp);CHKERRQ(ierr); 483 PetscFunctionReturn(0); 484 } 485 486 #undef __FUNCT__ 487 #define __FUNCT__ "AOCreateMemoryScalable" 488 /*@C 489 AOCreateMemoryScalable - Creates a memory scalable application ordering using two integer arrays. 490 491 Collective on MPI_Comm 492 493 Input Parameters: 494 + comm - MPI communicator that is to share AO 495 . napp - size of integer arrays 496 . myapp - integer array that defines an ordering 497 - mypetsc - integer array that defines another ordering (may be NULL to 498 indicate the natural ordering, that is 0,1,2,3,...) 499 500 Output Parameter: 501 . aoout - the new application ordering 502 503 Level: beginner 504 505 Notes: The arrays myapp and mypetsc must contain the all the integers 0 to napp-1 with no duplicates; that is there cannot be any "holes" 506 in the indices. Use AOCreateMapping() or AOCreateMappingIS() if you wish to have "holes" in the indices. 507 Comparing with AOCreateBasic(), this routine trades memory with message communication. 508 509 .keywords: AO, create 510 511 .seealso: AOCreateMemoryScalableIS(), AODestroy(), AOPetscToApplication(), AOApplicationToPetsc() 512 @*/ 513 PetscErrorCode AOCreateMemoryScalable(MPI_Comm comm,PetscInt napp,const PetscInt myapp[],const PetscInt mypetsc[],AO *aoout) 514 { 515 PetscErrorCode ierr; 516 IS isapp,ispetsc; 517 const PetscInt *app=myapp,*petsc=mypetsc; 518 519 PetscFunctionBegin; 520 ierr = ISCreateGeneral(comm,napp,app,PETSC_USE_POINTER,&isapp);CHKERRQ(ierr); 521 if (mypetsc) { 522 ierr = ISCreateGeneral(comm,napp,petsc,PETSC_USE_POINTER,&ispetsc);CHKERRQ(ierr); 523 } else { 524 ispetsc = NULL; 525 } 526 ierr = AOCreateMemoryScalableIS(isapp,ispetsc,aoout);CHKERRQ(ierr); 527 ierr = ISDestroy(&isapp);CHKERRQ(ierr); 528 if (mypetsc) { 529 ierr = ISDestroy(&ispetsc);CHKERRQ(ierr); 530 } 531 PetscFunctionReturn(0); 532 } 533 534 #undef __FUNCT__ 535 #define __FUNCT__ "AOCreateMemoryScalableIS" 536 /*@C 537 AOCreateMemoryScalableIS - Creates a memory scalable application ordering using two index sets. 538 539 Collective on IS 540 541 Input Parameters: 542 + isapp - index set that defines an ordering 543 - ispetsc - index set that defines another ordering (may be NULL to use the 544 natural ordering) 545 546 Output Parameter: 547 . aoout - the new application ordering 548 549 Level: beginner 550 551 Notes: The index sets isapp and ispetsc must contain the all the integers 0 to napp-1 (where napp is the length of the index sets) with no duplicates; 552 that is there cannot be any "holes". 553 Comparing with AOCreateBasicIS(), this routine trades memory with message communication. 554 .keywords: AO, create 555 556 .seealso: AOCreateMemoryScalable(), AODestroy() 557 @*/ 558 PetscErrorCode AOCreateMemoryScalableIS(IS isapp,IS ispetsc,AO *aoout) 559 { 560 PetscErrorCode ierr; 561 MPI_Comm comm; 562 AO ao; 563 564 PetscFunctionBegin; 565 ierr = PetscObjectGetComm((PetscObject)isapp,&comm);CHKERRQ(ierr); 566 ierr = AOCreate(comm,&ao);CHKERRQ(ierr); 567 ierr = AOSetIS(ao,isapp,ispetsc);CHKERRQ(ierr); 568 ierr = AOSetType(ao,AOMEMORYSCALABLE);CHKERRQ(ierr); 569 ierr = AOViewFromOptions(ao,NULL,"-ao_view");CHKERRQ(ierr); 570 *aoout = ao; 571 PetscFunctionReturn(0); 572 } 573