00001 #ifdef FEM_PARALLEL_PART
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <assert.h>
00013 #include <parmetis.h>
00014 #include "fem_impl.h"
00015 #include "fem.h"
00016 #include "fem.decl.h"
00017 #include "msa/msa.h"
00018 #include "cklists.h"
00019 #include "pup.h"
00020 #include "parallel_part.h"
00021
00022
00023 int FEM_Mesh_Parallel_broadcast(int fem_mesh,int masterRank,FEM_Comm_t comm_context){
00024 int myRank;
00025 MPI_Comm_rank((MPI_Comm)comm_context,&myRank);
00026 printf("[%d] FEM_Mesh_Parallel_broadcast called for mesh %d\n",myRank,fem_mesh);
00027 int new_mesh;
00028 if(myRank == masterRank){
00029
00030
00031 printf("[%d] Memory usage on vp 0 at the begining of partition %d \n",CkMyPe(),CmiMemoryUsage());
00032 new_mesh=FEM_master_parallel_part(fem_mesh,masterRank,comm_context);
00033
00034 }else{
00035 new_mesh=FEM_slave_parallel_part(fem_mesh,masterRank,comm_context);
00036 }
00037
00038 MPI_Barrier((MPI_Comm)comm_context);
00039 printf("[%d] Partitioned mesh number %d \n",myRank,new_mesh);
00040 return new_mesh;
00041 }
00042
00043 int FEM_master_parallel_part(int fem_mesh,int masterRank,FEM_Comm_t comm_context){
00044 const char *caller="FEM_Create_connmsa";
00045 FEMAPI(caller);
00046 FEMchunk *c=FEMchunk::get(caller);
00047 FEM_Mesh *m=c->lookup(fem_mesh,caller);
00048 m->setAbsoluteGlobalno();
00049 int nelem = m->nElems();
00050 int numChunks;
00051 MPI_Comm_size((MPI_Comm)comm_context,&numChunks);
00052 printf("master -> number of elements %d \n",nelem);
00053 DEBUG(m->print(0));
00054
00055
00056
00057
00058
00059 MSA1DINT eptr(nelem,numChunks);
00060 MSA1DINT eind(nelem*10,numChunks);
00061
00062
00063
00064
00065 struct conndata data;
00066 data.nelem = nelem;
00067 data.nnode = m->node.size();
00068 data.arr1 = eptr;
00069 data.arr2 = eind;
00070 MPI_Bcast_pup(data,masterRank,(MPI_Comm)comm_context);
00071
00072 eptr.enroll(numChunks);
00073 eind.enroll(numChunks);
00074 int indcount=0,ptrcount=0;
00075 for(int t=0;t<m->elem.size();t++){
00076 if(m->elem.has(t)){
00077 FEM_Elem &k=m->elem[t];
00078 for(int e=0;e<k.size();e++){
00079 eptr.set(ptrcount)=indcount;
00080 ptrcount++;
00081 for(int n=0;n<k.getNodesPer();n++){
00082 eind.set(indcount)=k.getConn(e,n);
00083 indcount++;
00084 }
00085 }
00086 }
00087 }
00088 eptr.set(ptrcount) = indcount;
00089 printf("master -> ptrcount %d indcount %d \n",ptrcount,indcount);
00090
00091
00092
00093
00094
00095
00096
00097 FEM_Mesh *mesh_array=FEM_break_mesh(m,ptrcount,numChunks);
00098
00099
00100
00101 sendBrokenMeshes(mesh_array,comm_context);
00102 delete [] mesh_array;
00103 FEM_Mesh mypiece;
00104 MPI_Recv_pup(mypiece,masterRank,MESH_CHUNK_TAG,(MPI_Comm)comm_context);
00105
00106
00107
00108
00109 struct partconndata *partdata = FEM_call_parmetis(data,comm_context);
00110
00111 printf("done with parmetis \n");
00112
00113
00114
00115
00116
00117 int totalNodes = m->node.size();
00118 MSA1DINTLIST nodepart(totalNodes,numChunks);
00119 MPI_Bcast_pup(nodepart,masterRank,(MPI_Comm)comm_context);
00120 nodepart.enroll(numChunks);
00121
00122 FEM_write_nodepart(nodepart,partdata);
00123
00124
00125
00126
00127 MSA1DNODELIST part2node(numChunks,numChunks);
00128 MPI_Bcast_pup(part2node,masterRank,(MPI_Comm)comm_context);
00129 part2node.enroll(numChunks);
00130
00131 FEM_write_part2node(nodepart,part2node,partdata,(MPI_Comm)comm_context);
00132
00133
00134
00135
00136 MSA1DINTLIST part2elem(numChunks,numChunks);
00137 MPI_Bcast_pup(part2elem,masterRank,(MPI_Comm)comm_context);
00138 part2elem.enroll(numChunks);
00139
00140 FEM_write_part2elem(part2elem,partdata,(MPI_Comm)comm_context);
00141
00142
00143
00144
00145 NodeList lnodes = part2node.get(masterRank);
00146 IntList lelems = part2elem.get(masterRank);
00147
00148
00149
00150
00151
00152 MSA1DFEMMESH part2mesh(numChunks,numChunks);
00153 MPI_Bcast_pup(part2mesh,masterRank,(MPI_Comm)comm_context);
00154 part2mesh.enroll(numChunks);
00155 FEM_write_part2mesh(part2mesh,partdata, &data,nodepart,numChunks,masterRank,&mypiece);
00156
00157
00158
00159 MeshElem me = part2mesh.get(masterRank);
00160 printf("[%d] Number of elements in my partitioned mesh %d number of nodes %d \n",masterRank,me.m->nElems(),me.m->node.size());
00161
00162 addIDXLists(me.m,lnodes,masterRank);
00163
00164
00165
00166
00167 DEBUG(printf("[%d] Length of udata vector in master %d \n",masterRank,m->udata.size()));
00168 MPI_Bcast_pup(m->udata,masterRank,(MPI_Comm)comm_context);
00169 me.m->udata = m->udata;
00170
00171
00172 delete partdata;
00173
00174
00175
00176 struct ghostdata *gdata = gatherGhosts();
00177 printf("[%d] number of ghost layers %d \n",masterRank,gdata->numLayers);
00178 MPI_Bcast_pup(*gdata,masterRank,(MPI_Comm)comm_context);
00179
00180
00181
00182
00183 makeGhosts(me.m,(MPI_Comm)comm_context,masterRank,gdata->numLayers,gdata->layers);
00184 delete gdata;
00185
00186 me.m->becomeGetting();
00187 FEMchunk *chunk = FEMchunk::get("FEM_Mesh_Parallel_broadcast");
00188 int tempMeshNo = chunk->meshes.put(me.m);
00189 int new_mesh = FEM_Mesh_copy(tempMeshNo);
00190
00191 FEM_Mesh *nmesh = c->lookup(new_mesh,"master_parallel_broadcast");
00192 DEBUG(printf("[%d] Length of udata vector in master new_mesh %d \n",masterRank,nmesh->udata.size()));
00193
00194 return new_mesh;
00195 };
00196
00197 int FEM_slave_parallel_part(int fem_mesh,int masterRank,FEM_Comm_t comm_context){
00198 int myRank;
00199 MPI_Comm_rank((MPI_Comm)comm_context,&myRank);
00200 int numChunks;
00201 MPI_Comm_size((MPI_Comm)comm_context,&numChunks);
00202
00203
00204
00205 struct conndata data;
00206 MPI_Bcast_pup(data,masterRank,(MPI_Comm)comm_context);
00207 data.arr1.enroll(numChunks);
00208 data.arr2.enroll(numChunks);
00209 DEBUG(printf("Recv -> %d \n",data.nelem));
00210
00211
00212
00213
00214
00215
00216 FEM_Mesh mypiece;
00217 MPI_Recv_pup(mypiece,masterRank,MESH_CHUNK_TAG,(MPI_Comm)comm_context);
00218
00219
00220
00221
00222 struct partconndata *partdata = FEM_call_parmetis(data,comm_context);
00223
00224
00225
00226
00227 MSA1DINTLIST nodepart;
00228 MPI_Bcast_pup(nodepart,masterRank,(MPI_Comm)comm_context);
00229 nodepart.enroll(numChunks);
00230
00231 FEM_write_nodepart(nodepart,partdata);
00232
00233
00234
00235
00236
00237 MSA1DNODELIST part2node;
00238 MPI_Bcast_pup(part2node,masterRank,(MPI_Comm)comm_context);
00239 part2node.enroll(numChunks);
00240
00241 FEM_write_part2node(nodepart,part2node,partdata,(MPI_Comm)comm_context);
00242
00243
00244
00245
00246 MSA1DINTLIST part2elem;
00247 MPI_Bcast_pup(part2elem,masterRank,(MPI_Comm)comm_context);
00248 part2elem.enroll(numChunks);
00249
00250 FEM_write_part2elem(part2elem,partdata,(MPI_Comm)comm_context);
00251
00252
00253
00254 NodeList lnodes = part2node.get(myRank);
00255 IntList lelems = part2elem.get(myRank);
00256
00257
00258
00259
00260 MSA1DFEMMESH part2mesh;
00261 MPI_Bcast_pup(part2mesh,masterRank,(MPI_Comm)comm_context);
00262 part2mesh.enroll(numChunks);
00263 FEM_write_part2mesh(part2mesh,partdata,&data,nodepart,numChunks,myRank,&mypiece);
00264
00265
00266
00267
00268 MeshElem me = part2mesh.get(myRank);
00269 printf("[%d] Number of elements in my partitioned mesh %d number of nodes %d \n",myRank,me.m->nElems(),me.m->node.size());
00270
00271 addIDXLists(me.m,lnodes,myRank);
00272
00273
00274
00275
00276 MPI_Bcast_pup(me.m->udata,masterRank,(MPI_Comm)comm_context);
00277 DEBUG(printf("[%d] Length of udata vector %d \n",myRank,me.m->udata.size()));
00278
00279 delete partdata;
00280
00281 struct ghostdata *gdata = new ghostdata;
00282 MPI_Bcast_pup(*gdata,masterRank,(MPI_Comm)comm_context);
00283 printf("[%d] number of ghost layers %d \n",myRank,gdata->numLayers);
00284
00285
00286
00287
00288 makeGhosts(me.m,(MPI_Comm )comm_context,masterRank,gdata->numLayers,gdata->layers);
00289
00290 me.m->becomeGetting();
00291 FEMchunk *chunk = FEMchunk::get("FEM_Mesh_Parallel_broadcast");
00292 int tempMeshNo = chunk->meshes.put(me.m);
00293 int new_mesh = FEM_Mesh_copy(tempMeshNo);
00294
00295 delete gdata;
00296 return new_mesh;
00297 }
00298
00299
00300
00301
00302
00303
00304 struct partconndata * FEM_call_parmetis(struct conndata &data,FEM_Comm_t comm_context){
00305 int myRank,numChunks;
00306 MPI_Comm_size((MPI_Comm)comm_context,&numChunks);
00307 MPI_Comm_rank((MPI_Comm)comm_context,&myRank);
00308
00309 int nelem = data.nelem;
00310
00311
00312
00313
00314
00315
00316
00317 int *elmdist = new int[numChunks+1];
00318 DEBUG(printf("[%d] elmdist \n",myRank));
00319 for(int i=0;i<=numChunks;i++){
00320 elmdist[i] = (i*nelem)/numChunks;
00321 DEBUG(printf(" %d ",elmdist[i]));
00322 }
00323 DEBUG(printf("\n"));
00324 int startindex = elmdist[myRank];
00325 int endindex = elmdist[myRank+1];
00326 data.arr1.sync();
00327 data.arr2.sync();
00328 int numindices = endindex - startindex;
00329 int *eptr = new int[numindices+1];
00330
00331
00332
00333
00334 int startConn = data.arr1.get(startindex);
00335 int endConn = data.arr1.get(endindex);
00336 int numConn = endConn - startConn;
00337 int *eind = new int[numConn];
00338 DEBUG(printf("%d startindex %d endindex %d startConn %d endConn %d \n",myRank,startindex,endindex,startConn,endConn));
00339 for(int i=startindex;i<endindex;i++){
00340 int conn1 = data.arr1.get(i);
00341 int conn2 = data.arr1.get(i+1);
00342 eptr[i-startindex] = conn1 - startConn;
00343 for(int j=conn1;j<conn2;j++){
00344 eind[j-startConn] = data.arr2.get(j);
00345 }
00346 }
00347 eptr[numindices] = endConn - startConn;
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 data.arr1.sync();
00362 data.arr2.sync();
00363 int wgtflag=0,numflag=0,ncon=1,ncommonnodes=2,options[5],edgecut=0;
00364 double ubvec = 1.05;
00365 double *tpwgts = new double[numChunks];
00366 int *parts = new int[numindices+1];
00367 for(int i=0;i<numChunks;i++){
00368 tpwgts[i]=1/(double)numChunks;
00369 }
00370 options[0]=0;
00371 MPI_Barrier((MPI_Comm)comm_context);
00372 ParMETIS_V3_PartMeshKway (elmdist,eptr,eind,NULL,&wgtflag,&numflag,&ncon,&ncommonnodes,&numChunks,tpwgts,&ubvec,options,&edgecut,parts,(MPI_Comm *)&comm_context);
00373 DEBUG(CkPrintf("%d partition ",myRank);)
00374 for(int i=0;i<numindices;i++){
00375 DEBUG(CkPrintf(" <%d %d> ",i+startindex,parts[i]));
00376 }
00377 DEBUG(CkPrintf("\n"));
00378 delete []elmdist;
00379 delete []tpwgts;
00380 struct partconndata *retval = new struct partconndata;
00381 retval->nelem = numindices;
00382 retval->eind = eind;
00383 retval->eptr = eptr;
00384 retval->part = parts;
00385 retval->startindex = startindex;
00386 return retval;
00387 }
00388
00389
00390
00391
00392
00393 void FEM_write_nodepart(MSA1DINTLIST &nodepart,struct partconndata *data){
00394 nodepart.sync();
00395 for(int i=0;i<data->nelem;i++){
00396 int start=data->eptr[i];
00397 int end = data->eptr[i+1];
00398 for(int j=start;j<end;j++){
00399 nodepart.accumulate(data->eind[j],data->part[i]);
00400
00401 }
00402 }
00403 nodepart.sync();
00404 }
00405
00406
00407
00408
00409
00410 void FEM_write_part2node(MSA1DINTLIST &nodepart,MSA1DNODELIST &part2node,struct partconndata *data,MPI_Comm comm_context){
00411 int nodes = nodepart.length();
00412 int myRank,numChunks;
00413
00414
00415
00416
00417 MPI_Comm_rank(comm_context,&myRank);
00418 MPI_Comm_size(comm_context,&numChunks);
00419 int start = (nodes*myRank)/numChunks;
00420 int end = (nodes*(myRank+1))/numChunks;
00421 part2node.sync();
00422 for(int i=start;i<end;i++){
00423 IntList t = nodepart.get(i);
00424 int num=0;
00425 if(t.vec->size()>1){
00426 num = t.vec->size();
00427 }
00428 NodeElem n(i,num);
00429 if(num != 0){
00430 for(int k=0;k<t.vec->size();k++){
00431 n.shared[k] =(*t.vec)[k];
00432 }
00433 }
00434
00435 for(int j=0;j<t.vec->size();j++){
00436 ElemList <NodeElem> en(n);
00437 part2node.accumulate((*t.vec)[j],en);
00438 }
00439 }
00440 part2node.sync();
00441 DEBUG(printf("done write_part2node\n"));
00442 }
00443
00444
00445
00446
00447 void FEM_write_part2elem(MSA1DINTLIST &part2elem,struct partconndata *data,MPI_Comm comm_context){
00448 part2elem.sync();
00449 for(int i=0;i<data->nelem;i++){
00450 part2elem.accumulate(data->part[i],data->startindex+i);
00451 }
00452 part2elem.sync();
00453 }
00454
00455
00456
00457
00458
00459 FEM_Mesh * FEM_break_mesh(FEM_Mesh *m,int numElements,int numChunks){
00460 FEM_Mesh *mesh_array = new FEM_Mesh[numChunks];
00461 int *elmdist = new int[numChunks+1];
00462 int *nodedist = new int[numChunks+1];
00463 int numNodes = m->node.size();
00464
00465 for(int i=0;i<=numChunks;i++){
00466 elmdist[i] = (i*numElements)/numChunks;
00467 nodedist[i] = (i*numNodes)/numChunks;
00468 }
00469
00470 int elcount=0;
00471 int mcount=0;
00472 mesh_array[mcount].copyShape(*m);
00473 for(int t=0;t<m->elem.size();t++){
00474 if(m->elem.has(t)){
00475 FEM_Elem &k=m->elem[t];
00476 for(int e=0;e<k.size();e++){
00477 mesh_array[mcount].elem[t].push_back(k,e);
00478 elcount++;
00479 if(elcount == elmdist[mcount+1]){
00480 mcount++;
00481 if(mcount != numChunks){
00482 mesh_array[mcount].copyShape(*m);
00483 }
00484 }
00485
00486 }
00487 }
00488 }
00489 mcount=0;
00490 for(int i=0;i<m->node.size();i++){
00491 if(i == nodedist[mcount+1]){
00492 mcount++;
00493 }
00494 mesh_array[mcount].node.push_back(m->node,i);
00495 }
00496 delete [] elmdist;
00497 delete [] nodedist;
00498 return mesh_array;
00499 }
00500
00501
00502
00503 void sendBrokenMeshes(FEM_Mesh *mesh_array,FEM_Comm_t comm_context){
00504 int numChunks;
00505 MPI_Comm_size((MPI_Comm)comm_context,&numChunks);
00506 for(int i=0;i<numChunks;i++){
00507 MPI_Send_pup(mesh_array[i],i,MESH_CHUNK_TAG,(MPI_Comm)comm_context);
00508 }
00509 }
00510 void FEM_write_part2mesh(MSA1DFEMMESH &part2mesh,struct partconndata *partdata,struct conndata *data,MSA1DINTLIST &nodepart,int numChunks,int myChunk,FEM_Mesh *m){
00511 part2mesh.sync();
00512 int count=0;
00515 for(int t=0;t<m->elem.size();t++){
00516 if(m->elem.has(t)){
00517 const FEM_Elem &k=(m)->elem[t];
00518 for(int e=0;e<k.size();e++){
00519 int chunkID = partdata->part[count];
00520 MeshElem &myme=part2mesh.accumulate(chunkID);
00521 (myme.m->elem[t]).copyShape(m->elem[t]);
00522 (myme.m->elem[t]).push_back(m->elem[t],e);
00523 count++;
00524 }
00525 }
00526 }
00527 nodepart.sync();
00529 int startnode=(myChunk * data->nnode)/numChunks;
00530 for(int i=0;i<m->node.size();i++){
00531 IntList chunks = nodepart.get(i+startnode);
00532 for(int j=0;j<chunks.vec->size();j++){
00533 MeshElem &myme = part2mesh.accumulate((*(chunks.vec))[j]);
00534 (myme.m->node).copyShape(m->node);
00535 (myme.m->node).push_back(m->node,i);
00536 }
00537 }
00538 part2mesh.sync();
00539 }
00540
00541
00542
00543 void sortNodeList(NodeList &lnodes){
00544 CkVec<NodeElem> *vec = lnodes.vec;
00545 for(int i=0;i<vec->size();i++){
00546 for(int j=i+1;j<vec->size();j++){
00547 if((*vec)[i].global > (*vec)[j].global){
00548 NodeElem t = (*vec)[i];
00549 (*vec)[i] = (*vec)[j];
00550 (*vec)[j] = t;
00551 }
00552 }
00553 }
00554 }
00555
00556
00557 void addIDXLists(FEM_Mesh *m,NodeList &lnodes,int myChunk){
00558
00559
00560
00561 sortNodeList(lnodes);
00562
00563 CkVec<NodeElem> *vec = lnodes.vec;
00564
00565
00566
00567 CkHashtableT<CkHashtableAdaptorT<int>,int> global2local;
00568 for(int i=0;i<m->node.size();i++){
00569 int nodeno = m->node.getGlobalno(i);
00570 global2local.put(nodeno)=i;
00571 }
00572
00573
00574
00575
00576
00577
00578
00580 for(int i=0;i<vec->size();i++){
00582 int global = (*vec)[i].global;
00584 int local = global2local.get(global);
00585
00586 m->node.setPrimary(local,true);
00587
00588 if(((*vec)[i]).numShared > 0){
00590 int *shared = (*vec)[i].shared;
00591
00592 for(int j=0;j<((*vec)[i]).numShared;j++){
00593 if(shared[j] != myChunk){
00594
00595 m->node.shared.addList(shared[j]).push_back(local);
00596 }
00597 if(shared[j] < myChunk){
00598 m->node.setPrimary(local,false);
00599 }
00600 }
00601 }
00602 }
00603 DEBUG(m->node.shared.print());
00604
00605
00606
00607
00608
00609 for(int i=0;i<m->elem.size();i++){
00610 if(m->elem.has(i)){
00611 FEM_Elem &el=m->elem[i];
00612 for(int j=0;j<el.size();j++){
00613 int *conn = el.connFor(j);
00614 for(int k=0;k<el.getNodesPer();k++){
00615 int gnode = conn[k];
00616 int lnode = global2local.get(gnode);
00617 conn[k] = lnode;
00618 }
00619 }
00620 }
00621 }
00622 }
00623
00624
00625
00626
00627
00628
00629 struct ghostdata *gatherGhosts(){
00630 struct ghostdata *res = new struct ghostdata;
00631 FEM_Partition &part = FEM_curPartition();
00632 res->numLayers = part.getRegions();
00633 res->layers = new FEM_Ghost_Layer *[res->numLayers];
00634 int count=0;
00635
00636 for(int i=0;i<res->numLayers;i++){
00637 const FEM_Ghost_Region ®ion = part.getRegion(i);
00638 if(region.layer != NULL){
00639 res->layers[count]=region.layer;
00640 count++;
00641 }
00642 }
00643 res->numLayers = count;
00644 return res;
00645 }
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657 void makeGhosts(FEM_Mesh *m,MPI_Comm comm,int masterRank,int numLayers,FEM_Ghost_Layer **layers){
00658 int myChunk;
00659 int numChunks;
00660 MPI_Comm_rank((MPI_Comm)comm,&myChunk);
00661 MPI_Comm_size((MPI_Comm)comm,&numChunks);
00662
00663 if(numChunks == 1){
00664 return;
00665 }
00666
00667
00668
00669
00670
00671 FEM_Comm *shared = &m->node.shared;
00672 int count=0;
00673 CkHashtableT<CkHashtableAdaptorT<int>,char> countedSharedNode;
00674 for(int i=0;i<shared->size();i++){
00675 const FEM_Comm_List &list = shared->getLocalList(i);
00676
00677
00678
00679
00680
00681
00682
00683 if(list.getDest() > myChunk){
00684 for(int j=0;j<list.size();j++){
00685 if(countedSharedNode.get(list[j]) == 0){
00686 count++;
00687 countedSharedNode.put(list[j]) = 1;
00688 }
00689 }
00690 }else{
00691 for(int j=0;j<list.size();j++){
00692 if(countedSharedNode.get(list[j]) == 1){
00693 count--;
00694 }
00695 countedSharedNode.put(list[j]) = 2;
00696 }
00697 }
00698 }
00699 int totalShared;
00700 MPI_Allreduce(&count, &totalShared,1, MPI_INT,
00701 MPI_SUM, comm);
00702 printf("[%d] Total number of shared nodes %d \n",myChunk,totalShared);
00703
00704
00705
00706 FEM_IndexAttribute *nchunkattr = (FEM_IndexAttribute *)m->node.lookup(FEM_CHUNK,"makeGhosts");
00707 int *nchunk = nchunkattr->get().getData();
00708 for(int i=0;i<nchunkattr->getLength();i++){
00709 nchunk[i] = myChunk;
00710 }
00711 for(int e = 0; e < m->elem.size();e++){
00712 if(m->elem.has(e)){
00713 FEM_IndexAttribute *echunkattr = (FEM_IndexAttribute *)m->elem[e].lookup(FEM_CHUNK,"makeGhosts");
00714 int *echunk = echunkattr->get().getData();
00715 for(int i=0;i<echunkattr->getLength();i++){
00716 echunk[i] = myChunk;
00717 }
00718 }
00719 }
00720
00721
00722
00723
00724
00725
00726
00727 CkHashtableT<CkHashtableAdaptorT<int>,int> global2local;
00728 for(int i=0;i<m->node.size();i++){
00729 global2local.put(m->node.getGlobalno(i))=i+1;
00730 }
00731
00732 for(int i=0;i<numLayers;i++){
00733 printf("[%d] Making ghost layer %d \n",myChunk,i);
00734 makeGhost(m,comm,masterRank,totalShared,layers[i],countedSharedNode,global2local);
00735 }
00736 };
00737
00738
00739
00740
00741 bool listContains(FEM_Comm_List &list,int entry){
00742 for(int i=0;i<list.size();i++){
00743 if(entry == list[i]){
00744 return true;
00745 }
00746 }
00747 return false;
00748 };
00749
00750 void makeGhost(FEM_Mesh *m,MPI_Comm comm,int masterRank,int totalShared,FEM_Ghost_Layer *layer, CkHashtableT<CkHashtableAdaptorT<int>,char> &sharedNode,CkHashtableT<CkHashtableAdaptorT<int>,int> &global2local){
00751 int myChunk;
00752 int numChunks;
00753 MPI_Comm_rank((MPI_Comm)comm,&myChunk);
00754 MPI_Comm_size((MPI_Comm)comm,&numChunks);
00755
00756
00757
00758
00759
00760 MsaHashtable *distTab;
00761 if(myChunk == masterRank){
00762 distTab = new MsaHashtable(totalShared,numChunks);
00763 }else{
00764 distTab = new MsaHashtable;
00765 }
00766 printf("[%d] starting ghost generation \n",myChunk);
00767 MPI_Bcast_pup(*distTab,masterRank,comm);
00768 distTab->table.enroll(numChunks);
00769 DEBUG(printf("[%d] distributed table calling sync \n",myChunk));
00770
00771 distTab->table.sync();
00772
00773 DEBUG(printf("Chunk %d Mesh: *********************************** \n",myChunk));
00774 DEBUG(m->print(0));
00775 DEBUG(printf("**********************************\n"));
00776
00777 printf("Chunk %d Ghost layer nodesPerTuple %d numSlots %d \n",myChunk,layer->nodesPerTuple,distTab->numSlots);
00778
00779
00780
00781
00782
00783 CkVec<Hashnode::tupledata> tupleVec;
00784 CkVec<int> indexVec;
00785 CkVec<int> elementVec;
00786
00787 for(int i=0;i<m->elem.size();i++){
00788 if(m->elem.has(i)){
00789
00790 if(layer->elem[i].add){
00791
00792 for(int e=0;e<m->elem[i].size();e++){
00793 const int *conn = m->elem[i].connFor(e);
00794
00795 for(int t=0;t< layer->elem[i].tuplesPerElem;t++){
00796 bool possibleGhost=true;
00797
00798 int globalNodeTuple[Hashnode::tupledata::MAX_TUPLE];
00799
00800
00801
00802
00803
00804 int nodesPerTuple = layer->nodesPerTuple;
00805 for(int n = 0;n<layer->nodesPerTuple;n++){
00806 int nodeindex=(layer->elem[i].elem2tuple)[t*layer->nodesPerTuple+n];
00807
00808
00809
00810
00811 if(nodeindex == -1){
00812 nodesPerTuple--;
00813 globalNodeTuple[n] =-1;
00814 continue;
00815 }
00816 int node=conn[nodeindex];
00817 globalNodeTuple[n]=m->node.getGlobalno(node);
00818 if(sharedNode.get(node) == 0){
00819 possibleGhost = false;
00820 break;
00821 }
00822 }
00823
00824 if(possibleGhost){
00825 int index=distTab->addTuple(globalNodeTuple,nodesPerTuple,myChunk,m->nElems(i)+e);
00826 tupleVec.push_back(Hashnode::tupledata(globalNodeTuple));
00827 indexVec.push_back(index);
00828 elementVec.push_back(i);
00829 elementVec.push_back(e);
00830 }
00831 }
00832 }
00833 }
00834 }
00835 }
00836
00837
00838
00839
00840 int ghostcount=0;
00841 for(int i=0;i<m->elem.size();i++){
00842 if(m->elem.has(i)){
00843 if(layer->elem[i].add){
00844 FEM_Elem *ghostElems = (FEM_Elem *)m->elem[i].getGhost();
00845 for(int e=0;e<ghostElems->size();e++){
00846 ghostcount++;
00847 const int *conn = ghostElems->connFor(e);
00848 for(int t=0;t<layer->elem[i].tuplesPerElem;t++){
00849 int globalNodeTuple[Hashnode::tupledata::MAX_TUPLE];
00850 FEM_Node *ghostNodes = (FEM_Node *)m->node.getGhost();
00851 int nodesPerTuple = layer->nodesPerTuple;
00852 for(int n=0;n<layer->nodesPerTuple;n++){
00853 int nodeindex=(layer->elem[i].elem2tuple)[t*layer->nodesPerTuple+n];
00854 if(nodeindex == -1){
00855 nodesPerTuple--;
00856 globalNodeTuple[n] = -1;
00857 continue;
00858 }
00859 int node=conn[nodeindex];
00860 if(FEM_Is_ghost_index(node)){
00861 globalNodeTuple[n]=ghostNodes->getGlobalno(FEM_From_ghost_index(node));
00862 }else{
00863 globalNodeTuple[n]=m->node.getGlobalno(node);
00864 }
00865 }
00866
00867 distTab->addTuple(globalNodeTuple,nodesPerTuple,myChunk,ghostcount);
00868 }
00869 }
00870 }
00871 }
00872 }
00873 distTab->table.sync();
00874
00875
00876 if(myChunk == masterRank){
00877 DEBUG(distTab->print());
00878 }
00879 distTab->sync();
00880
00881 MSA1DFEMMESH *ghostmeshes;
00882 if(myChunk == masterRank){
00883 ghostmeshes = new MSA1DFEMMESH(numChunks,numChunks);
00884 }else{
00885 ghostmeshes = new MSA1DFEMMESH;
00886 }
00887 MPI_Bcast_pup(*ghostmeshes,masterRank,comm);
00888 ghostmeshes->enroll(numChunks);
00889 ghostmeshes->sync();
00890
00891
00892
00893
00894
00895
00896 char str[100];
00897 for(int i=0;i<tupleVec.size();i++){
00898 const Hashtuple &listTuple = distTab->get(indexVec[i]);
00899
00900 int elType = elementVec[2*i];
00901 int elNo = elementVec[2*i+1];
00902 for(int j=0;j<listTuple.vec->size();j++){
00903
00904
00905 if((*listTuple.vec)[j].equals(tupleVec[i])){
00906 int destChunk=(*listTuple.vec)[j].chunk;
00907
00908
00909
00910 if(destChunk != myChunk){
00911
00912
00913
00914
00915 FEM_Comm &sendGhostSide = m->elem[elType].setGhostSend();
00916 FEM_Comm_List &sendGhostList = sendGhostSide.addList(destChunk);
00917 if(listContains(sendGhostList,elNo)){
00918
00919
00920
00921
00922 continue;
00923 }
00924
00925
00926 sendGhostList.push_back(elNo);
00927
00928
00929
00930 MeshElem &myme = ghostmeshes->accumulate(destChunk);
00931 myme.m->elem[elType].copyShape(m->elem[elType]);
00932 int index=myme.m->elem[elType].push_back(m->elem[elType],elNo);
00933 int globalelem = m->elem[elType].getGlobalno(elNo);
00934 DEBUG(printf("[%d] For chunk %d ghost element global no %d \n",myChunk,destChunk,globalelem));
00935
00936
00937
00938
00939 int *conn = myme.m->elem[elType].connFor(index);
00940 for(int k=0;k<m->elem[elType].getNodesPer();k++){
00941 int lnode = conn[k];
00942
00943 if(lnode < 0){
00944 continue;
00945 }
00946
00947
00948
00949 if(sharedNode.get(lnode) == 0){
00950 sharedNode.put(lnode)=3;
00951 }
00952 int globalnode = m->node.getGlobalno(lnode);
00953 conn[k] = globalnode;
00954 assert(conn[k] >= 0);
00955
00956
00957
00958
00959 if(layer->addNodes && lnode >= 0){
00960
00961
00962
00963
00964
00965 if(!sharedWith(lnode,(*listTuple.vec)[j].chunk,m)){
00966 FEM_Comm &sendNodeGhostSide = m->node.setGhostSend();
00967 FEM_Comm_List &sendNodeGhostList = sendNodeGhostSide.addList((*listTuple.vec)[j].chunk);
00968 if(!listContains(sendNodeGhostList,lnode)){
00969 myme.m->node.copyShape(m->node);
00970 myme.m->node.push_back(m->node,lnode);
00971 DEBUG(printf("[%d] Ghost node (send) global no %d \n",myChunk,globalnode));
00972
00973 sendNodeGhostList.push_back(lnode);
00974 }
00975 }
00976 }
00977 }
00978 }
00979 }
00980 }
00981
00982 }
00983 CmiMemoryCheck();
00984 DEBUG(printf("[%d] finished creating ghost mesh \n",myChunk));
00985 ghostmeshes->sync();
00986
00987
00988
00989
00990
00991
00992 FEM_Mesh *gmesh = ghostmeshes->get(myChunk).m;
00993 DEBUG(printf("[%d] my ghost mesh is at %p \n",myChunk,gmesh));
00994
00995 FEM_Node *gnodes = (FEM_Node *)m->node.getGhost();
00996 gnodes->copyShape(m->node);
00997 FEM_IndexAttribute *nodeSrcChunkAttr = (FEM_IndexAttribute *)gmesh->node.lookup(FEM_CHUNK,"makeGhosts");
00998 int *nodeSrcChunkNo = nodeSrcChunkAttr->get().getData();
00999
01000 DEBUG(printf("[%d] gmesh->node.size() = %d \n",myChunk,gmesh->node.size()));
01001 for(int i=0;i<gmesh->node.size();i++){
01002 int gnum = gmesh->node.getGlobalno(i);
01003 int lindex = global2local.get(gnum);
01004
01005 if(lindex == 0){
01006 int countgnodes = gnodes->push_back(gmesh->node,i);
01007 global2local.put(gnum) = -(countgnodes+1);
01008 lindex = -(countgnodes+1);
01009 }
01010 DEBUG(CkPrintf("[%d] Ghost node (recv) global node %d lindex %d \n",myChunk,gnum,lindex));
01011
01012 FEM_Comm &recvNodeGhostSide = m->node.setGhostRecv();
01013 FEM_Comm_List &recvNodeGhostList = recvNodeGhostSide.addList(nodeSrcChunkNo[i]);
01014 recvNodeGhostList.push_back(-lindex-1);
01015
01016 }
01017
01018
01019
01020
01021
01022
01023
01024
01025 for(int elType = 0;elType < gmesh->elem.size();elType++){
01026 if(gmesh->elem.has(elType)){
01027 FEM_IndexAttribute *elemSrcChunkAttr = (FEM_IndexAttribute *)gmesh->elem[elType].lookup(FEM_CHUNK,"makeGhosts");
01028 int *elemSrcChunkNo = elemSrcChunkAttr->get().getData();
01029
01030 for(int e=0;e<gmesh->elem[elType].size();e++){
01031 m->elem[elType].getGhost()->copyShape(gmesh->elem[elType]);
01032 int lghostelem = m->elem[elType].getGhost()->push_back(gmesh->elem[elType],e);
01033 int *conn = ((FEM_Elem *)m->elem[elType].getGhost())->connFor(lghostelem);
01034 for(int n=0;n<gmesh->elem[elType].getNodesPer();n++){
01035 int gnode = conn[n];
01036 assert(gnode>=0);
01037 if(gnode >= 0){
01038 int lnode = global2local.get(gnode);
01039
01040 if(lnode == 0){
01041 if(layer->addNodes){
01042 CkPrintf("[%d]Unknown global number %d \n",myChunk,gnode);
01043 CkAbort("Unknown global number for node in ghost element connectivity");
01044 }
01045 conn[n] = -1;
01046 }
01047
01048 if(lnode > 0){
01049 conn[n] = lnode -1;
01050 }
01051
01052 if(lnode < 0){
01053 conn[n] = FEM_To_ghost_index((-lnode-1));
01054 }
01055 }else{
01056 conn[n] = -1;
01057 }
01058 }
01059 FEM_Comm &recvGhostSide = m->elem[elType].setGhostRecv();
01060 FEM_Comm_List &recvGhostList = recvGhostSide.addList(elemSrcChunkNo[e]);
01061 recvGhostList.push_back(lghostelem);
01062
01063 }
01064 }
01065 }
01066 DEBUG(printf("[%d] Send ghost nodes \n",myChunk));
01067 DEBUG(m->node.getGhostSend().print());
01068 DEBUG(printf("[%d] Recv ghost nodes \n",myChunk));
01069 DEBUG(m->node.getGhostRecv().print());
01070
01071 delete distTab;
01072 delete ghostmeshes;
01073 MPI_Barrier(comm);
01074 }
01075
01076
01077
01078 bool sharedWith(int lnode,int chunk,FEM_Mesh *m){
01079 int lindex = m->node.shared.findLocalList(chunk);
01080 if(lindex != -1){
01081 const IDXL_List & llist = m->node.shared.getLocalList(lindex);
01082 for(int i=0;i<llist.size();i++){
01083 if(llist[i] == lnode){
01084 return true;
01085 }
01086 }
01087 return false;
01088 }else{
01089 return false;
01090 }
01091 }
01092 #include "fem.def.h"
01093 #endif