Logo Search packages:      
Sourcecode: madlib version File versions  Download package

void MAd::E_createInfoInterface ( pMesh  mesh,
pMeshDataId  tagEdge 
)

Create edge correspondance and assure coherent orientation.

Fill the attached pointer containing the distant proc numbers and the distant edge pointers.

Definition at line 1191 of file MeshDataBaseParallelInterface.cc.

References MAd::E_align(), MAd::E_corresponds(), MAd::E_exist(), MAd::E_isPotentialInterface(), MAd::E_vertex(), MAd::EN_attachDataPtr(), MAd::EN_deleteData(), MAd::EN_getDataPtr(), MAd::EN_id(), MAd::M_edgeIter(), and MAd::V_corresponds().

Referenced by MAd::M_load().

  { 
    
    int nproc = 1;
    int myrank = 0;

    size_t nbConnections = 0;

#ifdef PARALLEL
    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
#endif

    // --- Delete previous information ---
    
    EIter eit = M_edgeIter(mesh);
    while ( pEdge pe = EIter_next(eit) ) {
      void * tmp_ptr;
      if( EN_getDataPtr((pEntity) pe, tagEdge, &tmp_ptr) ) {
        EN_deleteData((pEntity) pe, tagEdge);
      }
    }
    EIter_delete(eit);


    // --- establish local connections and assure coherent orientation --- 
    // 
    //     * coherent reorientation on other partitions assumes coherent orientation here 
    //     * all periodic edges have same connections across partititions
    //       hence subsequent reorientation should remain coherent
    
    eit = M_edgeIter(mesh);
    
    while ( pEdge pe = EIter_next(eit) ) {

      std::vector<edge_comm> remote;
      
      int id0 = EN_id((pEntity) E_vertex(pe,0));
      int id1 = EN_id((pEntity) E_vertex(pe,1));

      std::pair<int,int> lNodeID(std::min(id0,id1),
                                 std::max(id0,id1));
      
      if (E_isPotentialInterface(mesh,pe,remote)) {
        
        std::vector<edge_comm >::const_iterator riter = remote.begin();


        pVertex p1Local = E_vertex(pe,0);
        pVertex p2Local = E_vertex(pe,1);
        

        for (;riter!=remote.end();++riter) {
        
          int distProc = riter->distProc;

          if (distProc == myrank) {
            
            edge_comm comm = *riter;
            
            pVertex p1 = comm.p1;
            pVertex p2 = comm.p2;
            
            pEdge remoteEdge = E_exist(p1,p2);
            
            if (remoteEdge) {
              

              // get points again, since alignment may be different from comm 

              pVertex p1Remote = E_vertex(remoteEdge,0);
              pVertex p2Remote = E_vertex(remoteEdge,1);

              // verify orientation 

              int orientation = 0;
              if (V_corresponds(p1Remote,p1Local) && V_corresponds(p2Remote,p2Local)) orientation =  1;
              if (V_corresponds(p1Remote,p2Local) && V_corresponds(p2Remote,p1Local)) orientation = -1;
                
              if (orientation == 0) {
                MAdMsgSgl::instance().error(__LINE__,__FILE__,
                                            "Got a locally periodic edge connection from %d-%d to %d-%d which does not correspond nodewise",
                                            EN_id((pEntity) p1),EN_id((pEntity) p2),
                                            EN_id((pEntity) p1Local),EN_id((pEntity) p2Local));
              }
              
              std::pair<int,int> rNodeID(std::min(EN_id((pEntity) p1Remote),EN_id((pEntity) p2Remote)),
                                         std::max(EN_id((pEntity) p1Remote),EN_id((pEntity) p2Remote))); 
  
            
              if (rNodeID < lNodeID) { 
                lNodeID = rNodeID; // remember to what we aligned the edge 
                if (orientation == -1) {
                  int dir = E_align(pe,p2Local,p1Local);
                  if (dir != -1) std::cout << "misalignment of edges " << std::endl;
                }
              }
              
              void* tmp_ptr;
              std::multimap<int,pEdge>* list;
              
              if(EN_getDataPtr((pEntity) pe, tagEdge, (void**)&tmp_ptr)) {
                list = (std::multimap<int,pEdge>*) tmp_ptr;
              }
              else {
                list = new std::multimap<int,pEdge> ;
                EN_attachDataPtr((pEntity) pe,tagEdge,list);
              }

              list->insert(std::make_pair(myrank,remoteEdge));
              nbConnections++;
            }
          }
        }
      }
    }
    EIter_delete(eit);
    
#ifdef PARALLEL
    
    int *sendcounts = new int[nproc];
    for(int i=0;i<nproc;i++)sendcounts[i]=0;
    
    // --- send edge info ---

    eit = M_edgeIter(mesh);
    while ( pEdge pe = EIter_next(eit) ) {

      std::vector<edge_comm> remote;

      if (E_isPotentialInterface(mesh,pe,remote)) {

        std::vector<edge_comm >::const_iterator riter = remote.begin();

        for (;riter!=remote.end();++riter) {
        
          int distProc = riter->distProc;

          if (distProc != myrank) {
            void *buf = AP_alloc(distProc,446,sizeof(edge_comm));
            edge_comm *castbuf = (edge_comm *) buf;
            castbuf->p1  = riter->p1;
            castbuf->p2  = riter->p2;
            castbuf->id1 = riter->id1;
            castbuf->id2 = riter->id2;
            castbuf->pe = pe;
            AP_send(buf);
            sendcounts[distProc]++;
          }
        }
      }
    }
    EIter_delete(eit);
    
    // --- synchronise sends --- 
    
    AP_check_sends(AP_NOFLAGS);
    AP_reduce_nsends(sendcounts);
    //AP_flush();

    // --- Receive edge info ---
    
    int message=0,count;
    while (!AP_recv_count(&count) ||message<count) {

      void *msg;
      int from;
      int tag;
      int size;
      int rc;

      rc=AP_recv(MPI_ANY_SOURCE,446, AP_BLOCKING|AP_DROPOUT,
                 &msg, &size, &from, &tag);
      
      if (rc) {
        message++;
        edge_comm * comm = (edge_comm*) msg;
        pEdge pe = E_exist(comm->p1,comm->p2);
        if(pe) {
        
          int lowestRank = myrank;

          // avoid connections between two edges that span full periodicity
          // ie. periodic nodes n1 and n3 while both edges n1-n2 and n2-n3 exist

          int id1 = comm->id1;
          int id2 = comm->id2;

          if (E_corresponds(pe,id1,id2)) {
            
            std::multimap<int,pEdge>* list;
            if(EN_getDataPtr((pEntity) pe, tagEdge, (void**)&list)) {
              lowestRank = std::min(list->begin()->first,lowestRank);
            }
            else {
              list = new std::multimap<int,pEdge>;
              EN_attachDataPtr((pEntity) pe, tagEdge, (void*)list);
            }
            
            list->insert(std::pair<int,pEdge>(from,comm->pe));
            if (from < lowestRank) {
              int dir = E_align(pe,comm->p1,comm->p2);
            }
          }
        }
        AP_free(msg);
      }
    }

    // --- synchronise receives --- 
    
    AP_check_sends(AP_WAITALL);
    MPI_Barrier(MPI_COMM_WORLD);
    
    // --- clean ship ---
    
    delete [] sendcounts;
    
#endif
    
    // --- verify !! --- 
    
    MDB_CommCheck cc;
    exchangeDataOnEdges(mesh,cc);

  }


Generated by  Doxygen 1.6.0   Back to index