Changeset 23640


Ignore:
Timestamp:
01/17/19 09:23:41 (6 years ago)
Author:
Mathieu Morlighem
Message:

CHG: use same scheme for nodes, with Finalize that distributes pids and lids

Location:
issm/trunk-jpl/src/c
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk-jpl/src/c/classes/Node.cpp

    r23630 r23640  
    3737}
    3838/*}}}*/
    39 Node::Node(int node_id,int node_sid,int node_lid,int node_pid,int io_index,bool node_clone,IoModel* iomodel,int node_analysis,int in_approximation,bool isamr){/*{{{*/
     39Node::Node(int node_id,int node_sid,int io_index,bool node_clone,IoModel* iomodel,int node_analysis,int in_approximation,bool isamr){/*{{{*/
    4040
    4141        /*id: */
    4242        this->id            = node_id;
    4343        this->sid           = node_sid;
    44         this->lid           = node_lid;
    45         this->pid           = node_pid;
     44        this->lid           = -1; /*Assigned by Finalize*/
     45        this->pid           = -1; /*Assigned by Finalize*/
    4646        this->analysis_enum = node_analysis;
    4747        this->clone         = node_clone;
  • issm/trunk-jpl/src/c/classes/Node.h

    r23630 r23640  
    2626                int  approximation; //For ice flow models, we need to know what ice flow approximation is employed on this node
    2727                bool clone;  //this node is replicated from another one
    28 
    2928                int  id;    // unique arbitrary id.
    3029                int  sid;   // "serial" id (rank of this node if the dataset was serial on 1 cpu)
    3130                int  lid;   // "local"  id (rank of this node in current partition)
    3231                int  pid;   // parallel id (specific to this partition)
     32
     33                /*Only this function can access these private fields*/
     34                //friend void Nodes::Finalize();
     35                friend class Nodes;
    3336
    3437        public:
     
    6467                /*Node constructors, destructors*/
    6568                Node();
    66                 Node(int node_id,int node_sid,int node_lid,int node_pid,int io_index,bool isclone,IoModel* iomodel,int analysis_enum,int approximation_in,bool isamr);
     69                Node(int node_id,int node_sid,int io_index,bool isclone,IoModel* iomodel,int analysis_enum,int approximation_in,bool isamr);
    6770                ~Node();
    6871
  • issm/trunk-jpl/src/c/classes/Nodes.cpp

    r23638 r23640  
    2020/*Object constructors and destructor*/
    2121Nodes::Nodes(){/*{{{*/
    22         enum_type=NodesEnum;
    23         this->common_recv     = NULL;
    24         this->common_recv_ids = NULL;
    25         this->common_send     = NULL;
    26         this->common_send_ids = NULL;
     22        this->enum_type             = NodesEnum;
     23        this->common_recv           = NULL;
     24        this->common_recv_ids       = NULL;
     25        this->common_send           = NULL;
     26        this->common_send_ids       = NULL;
     27        this->numberofnodes         = -1;
     28        this->numberofnodes_local   = -1;
     29        this->numberofmasters_local = -1;
    2730        return;
    2831}
     
    6164        /*Build id_offsets and sorted_ids*/
    6265        int objsize = this->numsorted;
     66        output->id_offsets=NULL;
     67        output->sorted_ids=NULL;
    6368        if(this->sorted && objsize>0 && this->id_offsets){     
    64                 /*Allocate new ids*/
    6569                output->id_offsets=xNew<int>(objsize);
    6670                xMemCpy<int>(output->id_offsets,this->id_offsets,objsize);
    6771        }
    68         else output->id_offsets=NULL;
    6972        if(this->sorted && objsize>0 && this->sorted_ids){
    70                 /*Allocate new ids*/
    7173                output->sorted_ids=xNew<int>(objsize);
    7274                xMemCpy<int>(output->sorted_ids,this->sorted_ids,objsize);
    7375        }
    74         else output->sorted_ids=NULL;
    75 
     76
     77        /*Copy other fields*/
     78        output->numberofnodes         = this->numberofnodes;
     79        output->numberofnodes_local   = this->numberofnodes_local;
     80        output->numberofmasters_local = this->numberofmasters_local;
    7681
    7782        if(this->common_recv){
     
    106111        int test = num_procs;
    107112        MARSHALLING_ENUM(NodesEnum);
     113        MARSHALLING(numberofnodes);
     114        MARSHALLING(numberofnodes_local);
     115        MARSHALLING(numberofmasters_local);
     116
    108117        MARSHALLING(test);
    109118        if(test!=num_procs) _error_("number of cores is not the same as before");
     
    209218}
    210219/*}}}*/
     220void  Nodes::Finalize(){/*{{{*/
     221
     222        /*Here we do 4 things:
     223         * - count all nodes once for all so that we do not need to call MPI
     224         *   every time we need to know the total number of vertices
     225         * - Distribute lids (local ids): masters first, slaves second
     226         * - Distribute pids (parallel ids)
     227         * - Distribute Gset once for all
     228         */
     229
     230        /*recover my_rank:*/
     231        ISSM_MPI_Status status;
     232        int my_rank   = IssmComm::GetRank();
     233        int num_procs = IssmComm::GetSize();
     234
     235        /*1. set number of nodes once for all*/
     236        this->numberofnodes_local=this->Size();
     237        this->numberofmasters_local=0;
     238        for(int i=0;i<this->Size();i++){
     239                Node* node=xDynamicCast<Node*>(this->GetObjectByOffset(i));
     240                if(!node->clone) this->numberofmasters_local++;
     241        }
     242        ISSM_MPI_Allreduce((void*)&this->numberofmasters_local,(void*)&this->numberofnodes,1,ISSM_MPI_INT,ISSM_MPI_SUM,IssmComm::GetComm());
     243
     244        /*2. Distribute lids (First: masters, then clones)*/
     245        int lid = 0;
     246        for(int i=0;i<this->Size();i++){
     247                Node* node=xDynamicCast<Node*>(this->GetObjectByOffset(i));
     248                if(!node->clone) node->lid=lid++;
     249        }
     250        for(int i=0;i<this->Size();i++){
     251                Node* node=xDynamicCast<Node*>(this->GetObjectByOffset(i));
     252                if(node->clone) node->lid=lid++;
     253        }
     254
     255        /*3. Distribute pids based on lids and offsets*/
     256        int* all_num_masters=xNew<int>(num_procs);
     257        ISSM_MPI_Gather(&this->numberofmasters_local,1,ISSM_MPI_INT,all_num_masters,1,ISSM_MPI_INT,0,IssmComm::GetComm());
     258        ISSM_MPI_Bcast(all_num_masters,num_procs,ISSM_MPI_INT,0,IssmComm::GetComm());
     259        int offset=0;
     260        for(int i=0;i<my_rank;i++) offset+=all_num_masters[i];
     261        xDelete<int>(all_num_masters);
     262
     263        for(int i=0;i<this->Size();i++){
     264                Node* node=xDynamicCast<Node*>(this->GetObjectByOffset(i));
     265                node->pid = node->lid+offset;
     266        }
     267
     268        /* Share pids of masters and update pids of clones*/
     269        int* truepids = xNew<int>(this->Size()); //only one alloc
     270        for(int rank=0;rank<num_procs;rank++){
     271                if(this->common_send[rank]){
     272                        int  numids = this->common_send[rank];
     273                        for(int i=0;i<numids;i++){
     274                                Node* node=xDynamicCast<Node*>(this->GetObjectByOffset(this->common_send_ids[rank][i]));
     275                                truepids[i] = node->pid;
     276                        }
     277                        ISSM_MPI_Send(truepids,numids,ISSM_MPI_INT,rank,0,IssmComm::GetComm());
     278                }
     279        }
     280        for(int rank=0;rank<num_procs;rank++){
     281                if(this->common_recv[rank]){
     282                        int  numids = this->common_recv[rank];
     283                        ISSM_MPI_Recv(truepids,numids,ISSM_MPI_INT,rank,0,IssmComm::GetComm(),&status);
     284                        for(int i=0;i<numids;i++){
     285                                Node* node=xDynamicCast<Node*>(this->GetObjectByOffset(this->common_recv_ids[rank][i]));
     286                                node->pid = truepids[i];
     287                        }
     288                }
     289        }
     290        xDelete<int>(truepids);
     291
     292        /*4. Distribute G dofs once for all*/
     293        //this->DistributeDofs(GsetEnum);
     294
     295        return;
     296}/*}}}*/
    211297int   Nodes::MaxNumDofs(int setenum){/*{{{*/
    212298
     
    271357int   Nodes::NumberOfNodes(void){/*{{{*/
    272358
    273         /*Careful! only use once all clones have been setup for all nodes!: */
    274 
    275         int numnodes=0;
    276         int allnumnodes=0;
    277 
    278         /*Now go through all nodes, and get how many dofs they own, unless they are clone nodes: */
    279         for(int i=0;i<this->Size();i++){
    280                 Node* node=xDynamicCast<Node*>(this->GetObjectByOffset(i));
    281 
    282                 /*Ok, this object is a node, ask it to plug values into partition: */
    283                 if (!node->IsClone()) numnodes++;
    284         }
    285 
    286         /*Gather from all cpus: */
    287         ISSM_MPI_Allreduce((void*)&numnodes,(void*)&allnumnodes,1,ISSM_MPI_INT,ISSM_MPI_SUM,IssmComm::GetComm());
    288 
    289         return allnumnodes;
     359        return this->numberofnodes;
    290360}
    291361/*}}}*/
  • issm/trunk-jpl/src/c/classes/Nodes.h

    r23629 r23640  
    1818class Nodes: public DataSet{
    1919
     20        private:
     21                int numberofnodes;
     22                int numberofnodes_local;
     23                int numberofmasters_local;
    2024        public:
    2125                int*  common_recv;
     
    3034                /*Objects virtual functions*/
    3135                Nodes* Copy();
    32                 void Marshall(char** pmarshalled_data,int* pmarshalled_data_size, int marshall_direction);
     36                void   Marshall(char** pmarshalled_data,int* pmarshalled_data_size, int marshall_direction);
    3337
    3438                /*numerics*/
    3539                void  DistributeDofs(int SETENUM);
     40                void  Finalize(void);
    3641                int   MaxNumDofs(int setenum);
    3742                int   NumberOfDofs(int setenum);
  • issm/trunk-jpl/src/c/classes/Vertex.cpp

    r23638 r23640  
    2020}
    2121/*}}}*/
    22 Vertex::Vertex(int vertex_id, int vertex_sid,int vertex_pid,bool vertex_clone, IoModel* iomodel,bool isamr){/*{{{*/
     22Vertex::Vertex(int vertex_id, int vertex_sid,bool vertex_clone, IoModel* iomodel,bool isamr){/*{{{*/
    2323
    2424        /*Checks in debugging mode*/
     
    2828        this->id    = vertex_id;
    2929        this->sid   = vertex_sid;
    30         this->pid   = vertex_pid;
     30        this->pid   = -1; /*Assigned later*/
    3131        this->lid   = -1; /*Assigned later*/
    3232        this->clone = vertex_clone;
  • issm/trunk-jpl/src/c/classes/Vertex.h

    r23638 r23640  
    3737                /*Vertex constructors, destructors {{{*/
    3838                Vertex();
    39                 Vertex(int id, int sid,int pid,bool clone, IoModel* iomodel,bool isamr);
     39                Vertex(int id, int sid,bool clone, IoModel* iomodel,bool isamr);
    4040                ~Vertex();
    4141                /*}}}*/
  • issm/trunk-jpl/src/c/classes/Vertices.cpp

    r23639 r23640  
    173173void Vertices::Finalize(){/*{{{*/
    174174
     175        /*Here we do 3 things:
     176         * - count all vertices once for all so that we do not need to call MPI
     177         *   every time we need to know the total number of vertices
     178         * - Distribute lids (local ids): masters first, slaves second
     179         * - Distribute pids (parallel ids)
     180         *   */
     181
    175182        /*recover my_rank:*/
    176183        ISSM_MPI_Status status;
     
    178185        int num_procs = IssmComm::GetSize();
    179186
    180         /*1. set counters*/
     187        /*1. set number of vertices once for all*/
    181188        this->numberofvertices_local=this->Size();
    182189        this->numberofmasters_local=0;
     
    198205        }
    199206
    200         /* Now every object has distributed dofs, but locally, and with a dof count starting from
    201          * 0. This means the dofs between all the cpus are not unique. We now offset the dofs of each
    202          * cpus by the total last (master) dofs of the previus cpu, starting from 0.
    203          * First: get number of dofs for each cpu*/
     207        /*3. Distribute pids based on lids and offsets*/
    204208        int* all_num_masters=xNew<int>(num_procs);
    205209        ISSM_MPI_Gather(&this->numberofmasters_local,1,ISSM_MPI_INT,all_num_masters,1,ISSM_MPI_INT,0,IssmComm::GetComm());
    206210        ISSM_MPI_Bcast(all_num_masters,num_procs,ISSM_MPI_INT,0,IssmComm::GetComm());
    207 
    208         /* Every cpu should start its own dof count at the end of the dofcount from cpu-1*/
    209211        int offset=0;
    210212        for(int i=0;i<my_rank;i++) offset+=all_num_masters[i];
    211213        xDelete<int>(all_num_masters);
     214
    212215        for(int i=0;i<this->Size();i++){
    213216                Vertex* vertex=xDynamicCast<Vertex*>(this->GetObjectByOffset(i));
     
    215218        }
    216219
    217         /* Finally, remember that cpus may have skipped some objects, because they were clones. For every
    218          * object that is not a clone, tell them to show their dofs, so that later on, they can get picked
    219          * up by their clones: */
     220        /* Share pids of masters and update pids of clones*/
    220221        int* truepids = xNew<int>(this->Size()); //only one alloc
    221222        for(int rank=0;rank<num_procs;rank++){
  • issm/trunk-jpl/src/c/modules/ModelProcessorx/CreateElementsVerticesAndMaterials.cpp

    r23638 r23640  
    262262void CreateVertices(Elements* elements,Vertices* vertices,IoModel* iomodel,int solution_type,bool isamr){/*{{{*/
    263263
    264 
    265264        /*Get element partitionning*/
    266265        int* epart = iomodel->epart;
     
    296295
    297296        /*Create vector of size total numnodes, initialized with -1, that will keep track of local ids*/
    298         int  lid = 0;
    299         int* vertices_lids  = xNew<int>(iomodel->numberofvertices);
     297        int  offset = 0;
     298        int* vertices_offsets  = xNew<int>(iomodel->numberofvertices);
    300299        for(int i=0;i<iomodel->numberofvertices;i++){
    301300                if(IsVertexInRank(vertices_ranks,vertices_proc_count,i,my_rank)){
    302                         vertices_lids[i] = lid++;
     301                        vertices_offsets[i] = offset++;
    303302                }
    304303                else{
    305                         vertices_lids[i] = -1;
     304                        vertices_offsets[i] = -1;
    306305                }
    307306        }
     
    335334
    336335                        /*If we did not find this vertex in our current partition, go to next vertex*/
    337                         if(vertices_lids[i] == -1) continue;
     336                        if(vertices_offsets[i] == -1) continue;
    338337
    339338                        /*Find in what column this rank belongs*/
     
    358357                                                int rank = vertices_ranks[MAXCONNECTIVITY*i+j];
    359358                                                if(step==1){
    360                                                         common_send_ids[rank][common_send[rank]] = vertices_lids[i];
     359                                                        common_send_ids[rank][common_send[rank]] = vertices_offsets[i];
    361360                                                }
    362361                                                common_send[rank]++;
     
    368367                                int rank = vertices_ranks[MAXCONNECTIVITY*i+0];
    369368                                if(step==1){
    370                                         common_recv_ids[rank][common_recv[rank]] = vertices_lids[i];
     369                                        common_recv_ids[rank][common_recv[rank]] = vertices_offsets[i];
    371370                                }
    372371                                common_recv[rank]++;
     
    374373                }
    375374        }
    376 
    377         /*Final step: prepare pids (parallel ids), first count number of masters for each proc*/
    378         int*  num_masters = xNewZeroInit<int>(num_procs);
    379         for(int i=0;i<iomodel->numberofvertices;i++){
    380                 num_masters[vertices_ranks[MAXCONNECTIVITY*i+0]]++;
    381         }
    382         /*Now count offsets for each procs (by taking the sum of masters of procs<my_rank)*/
    383         int* rank_offsets  = xNewZeroInit<int>(num_procs);
    384         for(int i=0;i<num_procs;i++){
    385                 for(int j=i+1;j<num_procs;j++) rank_offsets[i]+=num_masters[j];
    386         }
    387         xDelete<int>(num_masters);
    388         /*Now create pids*/
    389         int* vertices_pids = xNew<int>(iomodel->numberofvertices);
    390         int* rank_counters = xNewZeroInit<int>(iomodel->numberofvertices);
    391         for(int i=0;i<iomodel->numberofvertices;i++){
    392                 int rank_master = vertices_ranks[MAXCONNECTIVITY*i+0];
    393                 vertices_pids[i] = rank_offsets[rank_master]+rank_counters[rank_master];
    394                 rank_counters[rank_master]++;
    395         }
    396         xDelete<int>(rank_counters);
    397         xDelete<int>(rank_offsets);
    398375
    399376        /*Create Vertices, depending on the constructor type: */
     
    409386
    410387                for(int i=0;i<iomodel->numberofvertices;i++){
    411                         if(vertices_lids[i]!=-1){
     388                        if(vertices_offsets[i]!=-1){
    412389                                bool isclone = (vertices_ranks[MAXCONNECTIVITY*i+0]!=my_rank);
    413                                 vertices->AddObject(new Vertex(i+1,i,vertices_pids[i],isclone,iomodel,isamr));
     390                                vertices->AddObject(new Vertex(i+1,i,isclone,iomodel,isamr));
    414391                        }
    415392                }
     
    422399        else{
    423400                for(int i=0;i<iomodel->numberofvertices;i++){
    424                         if(vertices_lids[i]!=-1){
     401                        if(vertices_offsets[i]!=-1){
    425402                                bool isclone = (vertices_ranks[MAXCONNECTIVITY*i+0]!=my_rank);
    426                                 vertices->AddObject(new Vertex(i+1,i,vertices_pids[i],isclone,iomodel,isamr));
    427                         }
    428                 }
    429         }
    430 
    431         xDelete<int>(vertices_lids);
    432         xDelete<int>(vertices_pids);
     403                                vertices->AddObject(new Vertex(i+1,i,isclone,iomodel,isamr));
     404                        }
     405                }
     406        }
     407        xDelete<int>(vertices_offsets);
    433408
    434409        /*Final step, create my_vertices*/
  • issm/trunk-jpl/src/c/modules/ModelProcessorx/CreateNodes.cpp

    r23635 r23640  
    4646        int*     epart = iomodel->epart;
    4747
    48         /*Determine how many nodes we have in total*/
     48        /*Determine how many nodes we have in total (which depends on the type of finite element)*/
    4949        /*{{{*/
    5050        if(iomodel->meshelementtype==TriaEnum){
     
    568568
    569569        /*Create vector of size total numnodes, initialized with -1, that will keep track of local ids*/
    570         int  lid = 0;
    571         int* nodes_lids  = xNew<int>(numnodes);
     570        int  offset = 0;
     571        int* nodes_offsets  = xNew<int>(numnodes);
    572572        for(int i=0;i<numnodes;i++){
    573573                if(IsNodeInRank(nodes_ranks,nodes_proc_count,i,my_rank)){
    574                         nodes_lids[i] = lid++;
     574                        nodes_offsets[i] = offset++;
    575575                }
    576576                else{
    577                         nodes_lids[i] = -1;
     577                        nodes_offsets[i] = -1;
    578578                }
    579579        }
     
    603603                for(int i=0;i<numnodes;i++){
    604604                        /*If we did not find this vertex in our current partition, go to next vertex*/
    605                         if(nodes_lids[i] == -1) continue;
     605                        if(nodes_offsets[i] == -1) continue;
    606606                        /*Find in what column this rank belongs*/
    607607                        int col = -1;
     
    625625                                                int rank = nodes_ranks[MAXCONNECTIVITY*i+j];
    626626                                                if(step==1){
    627                                                         common_send_ids[rank][common_send[rank]] = nodes_lids[i];
     627                                                        common_send_ids[rank][common_send[rank]] = nodes_offsets[i];
    628628                                                }
    629629                                                common_send[rank]++;
     
    635635                                int rank = nodes_ranks[MAXCONNECTIVITY*i+0];
    636636                                if(step==1){
    637                                         common_recv_ids[rank][common_recv[rank]] = nodes_lids[i];
     637                                        common_recv_ids[rank][common_recv[rank]] = nodes_offsets[i];
    638638                                }
    639639                                common_recv[rank]++;
     
    643643        xDelete<int>(nodes_proc_count);
    644644
    645         /*Final step: prepare pids (parallel ids), first count number of masters for each proc*/
    646         int*  num_masters = xNewZeroInit<int>(num_procs);
    647         for(int i=0;i<numnodes;i++){
    648                 num_masters[nodes_ranks[MAXCONNECTIVITY*i+0]]++;
    649         }
    650         /*Now count offsets for each procs (by taking the sum of masters of procs<my_rank)*/
    651         int* rank_offsets = xNewZeroInit<int>(num_procs);
    652         for(int i=0;i<num_procs;i++){
    653                 for(int j=i+1;j<num_procs;j++) rank_offsets[i]+=num_masters[j];
    654         }
    655         xDelete<int>(num_masters);
    656         /*Now create pids*/
    657         int* nodes_pids = xNew<int>(numnodes);
    658         int* rank_counters = xNewZeroInit<int>(numnodes);
    659         for(int i=0;i<numnodes;i++){
    660                 int rank_master = nodes_ranks[MAXCONNECTIVITY*i+0];
    661                 nodes_pids[i] = rank_offsets[rank_master]+rank_counters[rank_master];
    662                 rank_counters[rank_master]++;
    663         }
    664         xDelete<int>(rank_counters);
    665         xDelete<int>(rank_offsets);
    666 
    667645        /*Go ahead and create vertices now that we have all we need*/
    668646        for(int i=0;i<numnodes;i++){
    669                 if(nodes_lids[i]!=-1){
     647                if(nodes_offsets[i]!=-1){
    670648                        bool isclone = (nodes_ranks[MAXCONNECTIVITY*i+0]!=my_rank);
    671649                        int io_index = 0;
    672650                        if(i<iomodel->numberofvertices) io_index = i;
    673                         Node* node=new Node(i+1,i,nodes_lids[i],nodes_pids[i],io_index,isclone,iomodel,analysis,nodes_approx[i],isamr);
     651                        Node* node=new Node(i+1,i,io_index,isclone,iomodel,analysis,nodes_approx[i],isamr);
    674652                        if(finite_element==MINIcondensedEnum || finite_element==P1bubblecondensedEnum){
    675653                                /*Bubble function is collapsed, needs to constrain it, maybe this is not the best place to do this, but that's life!*/
     
    681659                }
    682660        }
     661
     662        /*Free data: */
    683663        xDelete<int>(nodes_approx);
    684664        xDelete<int>(nodes_ranks);
    685         xDelete<int>(nodes_lids);
    686         xDelete<int>(nodes_pids);
    687 
     665        xDelete<int>(nodes_offsets);
     666
     667        /*Assign communicators*/
    688668        nodes->common_send=common_send;
    689669        nodes->common_recv=common_recv;
    690670        nodes->common_send_ids=common_send_ids;
    691671        nodes->common_recv_ids=common_recv_ids;
     672
     673        /*Finalize Initialization*/
     674        nodes->Finalize();
    692675}
    693 
Note: See TracChangeset for help on using the changeset viewer.