Changeset 23640
- Timestamp:
- 01/17/19 09:23:41 (6 years ago)
- Location:
- issm/trunk-jpl/src/c
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk-jpl/src/c/classes/Node.cpp
r23630 r23640 37 37 } 38 38 /*}}}*/ 39 Node::Node(int node_id,int node_sid,int node_lid,int node_pid,intio_index,bool node_clone,IoModel* iomodel,int node_analysis,int in_approximation,bool isamr){/*{{{*/39 Node::Node(int node_id,int node_sid,int io_index,bool node_clone,IoModel* iomodel,int node_analysis,int in_approximation,bool isamr){/*{{{*/ 40 40 41 41 /*id: */ 42 42 this->id = node_id; 43 43 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*/ 46 46 this->analysis_enum = node_analysis; 47 47 this->clone = node_clone; -
issm/trunk-jpl/src/c/classes/Node.h
r23630 r23640 26 26 int approximation; //For ice flow models, we need to know what ice flow approximation is employed on this node 27 27 bool clone; //this node is replicated from another one 28 29 28 int id; // unique arbitrary id. 30 29 int sid; // "serial" id (rank of this node if the dataset was serial on 1 cpu) 31 30 int lid; // "local" id (rank of this node in current partition) 32 31 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; 33 36 34 37 public: … … 64 67 /*Node constructors, destructors*/ 65 68 Node(); 66 Node(int node_id,int node_sid,int node_lid,int node_pid,intio_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); 67 70 ~Node(); 68 71 -
issm/trunk-jpl/src/c/classes/Nodes.cpp
r23638 r23640 20 20 /*Object constructors and destructor*/ 21 21 Nodes::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; 27 30 return; 28 31 } … … 61 64 /*Build id_offsets and sorted_ids*/ 62 65 int objsize = this->numsorted; 66 output->id_offsets=NULL; 67 output->sorted_ids=NULL; 63 68 if(this->sorted && objsize>0 && this->id_offsets){ 64 /*Allocate new ids*/65 69 output->id_offsets=xNew<int>(objsize); 66 70 xMemCpy<int>(output->id_offsets,this->id_offsets,objsize); 67 71 } 68 else output->id_offsets=NULL;69 72 if(this->sorted && objsize>0 && this->sorted_ids){ 70 /*Allocate new ids*/71 73 output->sorted_ids=xNew<int>(objsize); 72 74 xMemCpy<int>(output->sorted_ids,this->sorted_ids,objsize); 73 75 } 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; 76 81 77 82 if(this->common_recv){ … … 106 111 int test = num_procs; 107 112 MARSHALLING_ENUM(NodesEnum); 113 MARSHALLING(numberofnodes); 114 MARSHALLING(numberofnodes_local); 115 MARSHALLING(numberofmasters_local); 116 108 117 MARSHALLING(test); 109 118 if(test!=num_procs) _error_("number of cores is not the same as before"); … … 209 218 } 210 219 /*}}}*/ 220 void 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 }/*}}}*/ 211 297 int Nodes::MaxNumDofs(int setenum){/*{{{*/ 212 298 … … 271 357 int Nodes::NumberOfNodes(void){/*{{{*/ 272 358 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; 290 360 } 291 361 /*}}}*/ -
issm/trunk-jpl/src/c/classes/Nodes.h
r23629 r23640 18 18 class Nodes: public DataSet{ 19 19 20 private: 21 int numberofnodes; 22 int numberofnodes_local; 23 int numberofmasters_local; 20 24 public: 21 25 int* common_recv; … … 30 34 /*Objects virtual functions*/ 31 35 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); 33 37 34 38 /*numerics*/ 35 39 void DistributeDofs(int SETENUM); 40 void Finalize(void); 36 41 int MaxNumDofs(int setenum); 37 42 int NumberOfDofs(int setenum); -
issm/trunk-jpl/src/c/classes/Vertex.cpp
r23638 r23640 20 20 } 21 21 /*}}}*/ 22 Vertex::Vertex(int vertex_id, int vertex_sid, int vertex_pid,bool vertex_clone, IoModel* iomodel,bool isamr){/*{{{*/22 Vertex::Vertex(int vertex_id, int vertex_sid,bool vertex_clone, IoModel* iomodel,bool isamr){/*{{{*/ 23 23 24 24 /*Checks in debugging mode*/ … … 28 28 this->id = vertex_id; 29 29 this->sid = vertex_sid; 30 this->pid = vertex_pid;30 this->pid = -1; /*Assigned later*/ 31 31 this->lid = -1; /*Assigned later*/ 32 32 this->clone = vertex_clone; -
issm/trunk-jpl/src/c/classes/Vertex.h
r23638 r23640 37 37 /*Vertex constructors, destructors {{{*/ 38 38 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); 40 40 ~Vertex(); 41 41 /*}}}*/ -
issm/trunk-jpl/src/c/classes/Vertices.cpp
r23639 r23640 173 173 void Vertices::Finalize(){/*{{{*/ 174 174 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 175 182 /*recover my_rank:*/ 176 183 ISSM_MPI_Status status; … … 178 185 int num_procs = IssmComm::GetSize(); 179 186 180 /*1. set counters*/187 /*1. set number of vertices once for all*/ 181 188 this->numberofvertices_local=this->Size(); 182 189 this->numberofmasters_local=0; … … 198 205 } 199 206 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*/ 204 208 int* all_num_masters=xNew<int>(num_procs); 205 209 ISSM_MPI_Gather(&this->numberofmasters_local,1,ISSM_MPI_INT,all_num_masters,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 206 210 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*/209 211 int offset=0; 210 212 for(int i=0;i<my_rank;i++) offset+=all_num_masters[i]; 211 213 xDelete<int>(all_num_masters); 214 212 215 for(int i=0;i<this->Size();i++){ 213 216 Vertex* vertex=xDynamicCast<Vertex*>(this->GetObjectByOffset(i)); … … 215 218 } 216 219 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*/ 220 221 int* truepids = xNew<int>(this->Size()); //only one alloc 221 222 for(int rank=0;rank<num_procs;rank++){ -
issm/trunk-jpl/src/c/modules/ModelProcessorx/CreateElementsVerticesAndMaterials.cpp
r23638 r23640 262 262 void CreateVertices(Elements* elements,Vertices* vertices,IoModel* iomodel,int solution_type,bool isamr){/*{{{*/ 263 263 264 265 264 /*Get element partitionning*/ 266 265 int* epart = iomodel->epart; … … 296 295 297 296 /*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); 300 299 for(int i=0;i<iomodel->numberofvertices;i++){ 301 300 if(IsVertexInRank(vertices_ranks,vertices_proc_count,i,my_rank)){ 302 vertices_ lids[i] = lid++;301 vertices_offsets[i] = offset++; 303 302 } 304 303 else{ 305 vertices_ lids[i] = -1;304 vertices_offsets[i] = -1; 306 305 } 307 306 } … … 335 334 336 335 /*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; 338 337 339 338 /*Find in what column this rank belongs*/ … … 358 357 int rank = vertices_ranks[MAXCONNECTIVITY*i+j]; 359 358 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]; 361 360 } 362 361 common_send[rank]++; … … 368 367 int rank = vertices_ranks[MAXCONNECTIVITY*i+0]; 369 368 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]; 371 370 } 372 371 common_recv[rank]++; … … 374 373 } 375 374 } 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);398 375 399 376 /*Create Vertices, depending on the constructor type: */ … … 409 386 410 387 for(int i=0;i<iomodel->numberofvertices;i++){ 411 if(vertices_ lids[i]!=-1){388 if(vertices_offsets[i]!=-1){ 412 389 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)); 414 391 } 415 392 } … … 422 399 else{ 423 400 for(int i=0;i<iomodel->numberofvertices;i++){ 424 if(vertices_ lids[i]!=-1){401 if(vertices_offsets[i]!=-1){ 425 402 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); 433 408 434 409 /*Final step, create my_vertices*/ -
issm/trunk-jpl/src/c/modules/ModelProcessorx/CreateNodes.cpp
r23635 r23640 46 46 int* epart = iomodel->epart; 47 47 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)*/ 49 49 /*{{{*/ 50 50 if(iomodel->meshelementtype==TriaEnum){ … … 568 568 569 569 /*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); 572 572 for(int i=0;i<numnodes;i++){ 573 573 if(IsNodeInRank(nodes_ranks,nodes_proc_count,i,my_rank)){ 574 nodes_ lids[i] = lid++;574 nodes_offsets[i] = offset++; 575 575 } 576 576 else{ 577 nodes_ lids[i] = -1;577 nodes_offsets[i] = -1; 578 578 } 579 579 } … … 603 603 for(int i=0;i<numnodes;i++){ 604 604 /*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; 606 606 /*Find in what column this rank belongs*/ 607 607 int col = -1; … … 625 625 int rank = nodes_ranks[MAXCONNECTIVITY*i+j]; 626 626 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]; 628 628 } 629 629 common_send[rank]++; … … 635 635 int rank = nodes_ranks[MAXCONNECTIVITY*i+0]; 636 636 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]; 638 638 } 639 639 common_recv[rank]++; … … 643 643 xDelete<int>(nodes_proc_count); 644 644 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 667 645 /*Go ahead and create vertices now that we have all we need*/ 668 646 for(int i=0;i<numnodes;i++){ 669 if(nodes_ lids[i]!=-1){647 if(nodes_offsets[i]!=-1){ 670 648 bool isclone = (nodes_ranks[MAXCONNECTIVITY*i+0]!=my_rank); 671 649 int io_index = 0; 672 650 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); 674 652 if(finite_element==MINIcondensedEnum || finite_element==P1bubblecondensedEnum){ 675 653 /*Bubble function is collapsed, needs to constrain it, maybe this is not the best place to do this, but that's life!*/ … … 681 659 } 682 660 } 661 662 /*Free data: */ 683 663 xDelete<int>(nodes_approx); 684 664 xDelete<int>(nodes_ranks); 685 xDelete<int>(nodes_ lids);686 xDelete<int>(nodes_pids); 687 665 xDelete<int>(nodes_offsets); 666 667 /*Assign communicators*/ 688 668 nodes->common_send=common_send; 689 669 nodes->common_recv=common_recv; 690 670 nodes->common_send_ids=common_send_ids; 691 671 nodes->common_recv_ids=common_recv_ids; 672 673 /*Finalize Initialization*/ 674 nodes->Finalize(); 692 675 } 693
Note:
See TracChangeset
for help on using the changeset viewer.