Changeset 924
- Timestamp:
- 09/02/16 09:41:27 (8 years ago)
- Location:
- XIOS/trunk
- Files:
-
- 4 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
XIOS/trunk/src/client_client_dht_decl.cpp
r832 r924 13 13 14 14 template class CClientClientDHTTemplate<int>; 15 template class CClientClientDHTTemplate<size_t>; 15 16 template class CClientClientDHTTemplate<PairIntInt>; 16 17 -
XIOS/trunk/src/client_client_dht_template.hpp
r892 r924 125 125 126 126 typedef CClientClientDHTTemplate<int> CClientClientDHTInt; 127 typedef CClientClientDHTTemplate<size_t> CClientClientDHTSizet; 127 128 typedef CClientClientDHTTemplate<PairIntInt> CClientClientDHTPairIntInt; 128 129 -
XIOS/trunk/src/dht_auto_indexing.cpp
r892 r924 12 12 { 13 13 14 /*! 15 Constructor with initial distribution information and the corresponding index 16 Each process holds a piece of hash value, which has no information (global index) associated. 17 The constructor tries to assign this information to each process basing on their rank. 18 The global index (information) are assigned across processes in the incremental manner. 19 The process has lower rank will have low global index. 20 \param [in] hashValue Carray contains hash value 21 \param [in] clientIntraComm communicator of clients 22 */ 14 CDHTAutoIndexing::~CDHTAutoIndexing() 15 { 16 } 23 17 24 CDHTAutoIndexing::CDHTAutoIndexing(const CArray<size_t,1>& hashValue, 25 const MPI_Comm& clientIntraComm) 26 : CClientClientDHTTemplate<size_t>(clientIntraComm) 27 { 28 Index2VectorInfoTypeMap indexToVecInfoMap; 29 indexToVecInfoMap.rehash(std::ceil(hashValue.size()/indexToVecInfoMap.max_load_factor())); 30 CArray<size_t,1>::const_iterator it = hashValue.begin(), ite = hashValue.end(); 18 /*! 19 \param [in] 20 \param [in] 21 */ 31 22 32 // Just use a dummy value to initialize33 int nbLvl = this->getNbLevel();34 for (; it != ite; ++it)23 CDHTAutoIndexing::CDHTAutoIndexing(const CArray<size_t,1>& hashValue, 24 const MPI_Comm& clientIntraComm) 25 : CClientClientDHTTemplate<size_t>(clientIntraComm) 35 26 { 36 indexToVecInfoMap[*it].resize(1); 37 indexToVecInfoMap[*it][0] = 0; 27 28 nbIndexOnProc_ = hashValue.size(); 29 size_t nbIndexAccum; 30 MPI_Scan(&nbIndexOnProc_, &nbIndexAccum, 1, MPI_UNSIGNED_LONG, MPI_SUM, clientIntraComm); 31 32 // Broadcasting the total number of indexes 33 int rank, size; 34 MPI_Comm_rank(clientIntraComm, &rank); 35 MPI_Comm_size(clientIntraComm, &size); 36 if (rank == (size-1)) nbIndexesGlobal_ = nbIndexAccum; 37 MPI_Bcast(&nbIndexesGlobal_, 1, MPI_UNSIGNED_LONG, size-1, clientIntraComm); 38 39 CArray<size_t,1>::const_iterator itbIdx = hashValue.begin(), itIdx, 40 iteIdx = hashValue.end(); 41 42 size_t idx = 0; 43 beginIndexOnProc_ = nbIndexAccum - nbIndexOnProc_; 44 globalIndex_.resize(nbIndexOnProc_); 45 for (itIdx = itbIdx; itIdx != iteIdx; ++itIdx) 46 { 47 globalIndex_[idx] = beginIndexOnProc_ + idx; 48 ++idx ; 49 } 38 50 } 39 computeDistributedIndex(indexToVecInfoMap, clientIntraComm, nbLvl-1);40 51 41 // Find out number of index on other proc 42 size_t nbIndexOnProc = index2InfoMapping_.size(); 43 size_t nbIndexAccum; 52 /*! 53 * \fn void CDHTAutoIndexing::CDHTAutoIndexing(Index2VectorInfoTypeMap& hashInitMap, const MPI_Comm& clientIntraComm) 54 * Assigns a global index to unique input indexes. 55 * The returned map has unique indexes as a key and global indexes as a mapped value. 56 * \param [in] hashInitMap map<size_t, vector<size_t>> is a map of unique indexes. 57 * \param [in] clientIntraComm 58 */ 59 CDHTAutoIndexing::CDHTAutoIndexing(Index2VectorInfoTypeMap& hashInitMap, 60 const MPI_Comm& clientIntraComm) 61 : CClientClientDHTTemplate<size_t>(clientIntraComm) 62 { 44 63 45 MPI_Scan(&nbIndexOnProc, &nbIndexAccum, 1, MPI_UNSIGNED_LONG, MPI_SUM, clientIntraComm); 64 nbIndexOnProc_ = hashInitMap.size(); 65 size_t nbIndexAccum; 66 MPI_Scan(&nbIndexOnProc_, &nbIndexAccum, 1, MPI_UNSIGNED_LONG, MPI_SUM, clientIntraComm); 46 67 47 Index2VectorInfoTypeMap::iterator itbIdx = index2InfoMapping_.begin(), itIdx, 48 iteIdx = index2InfoMapping_.end(); 49 size_t idx = 0; 50 size_t idxBegin = nbIndexAccum - nbIndexOnProc; 51 for (itIdx = itbIdx; itIdx != iteIdx; ++itIdx) 68 int rank, size; 69 MPI_Comm_rank(clientIntraComm, &rank); 70 MPI_Comm_size(clientIntraComm, &size); 71 if (rank == (size-1)) nbIndexesGlobal_ = nbIndexAccum; 72 MPI_Bcast(&nbIndexesGlobal_, 1, MPI_UNSIGNED_LONG, size-1, clientIntraComm); 73 74 Index2VectorInfoTypeMap::iterator itbIdx = hashInitMap.begin(), itIdx, 75 iteIdx = hashInitMap.end(); 76 size_t idx = 0; 77 beginIndexOnProc_ = nbIndexAccum - nbIndexOnProc_; 78 globalIndex_.resize(nbIndexOnProc_); 79 for (itIdx = itbIdx; itIdx != iteIdx; ++itIdx) 80 { 81 (itIdx->second)[0] = beginIndexOnProc_ + idx; 82 globalIndex_[idx] = beginIndexOnProc_ + idx; 83 ++idx ; 84 } 85 } 86 87 /*! 88 * \fn size_t CDHTAutoIndexing::getNbIndexesGlobal() const 89 * Returns the total number of global indexes. 90 */ 91 size_t CDHTAutoIndexing::getNbIndexesGlobal() const 52 92 { 53 (itIdx->second)[0] = idxBegin + idx; 54 ++idx ; 93 return nbIndexesGlobal_; 55 94 } 56 } 95 96 /*! 97 * \fn size_t CDHTAutoIndexing::getIndexStart() const 98 * Returns the starting global index for a proc. 99 */ 100 size_t CDHTAutoIndexing::getIndexStart() const 101 { 102 return beginIndexOnProc_; 103 } 104 105 /*! 106 * \fn size_t CDHTAutoIndexing::getIndexCount() const 107 * Returns the number of global indexes on a proc. 108 */ 109 size_t CDHTAutoIndexing::getIndexCount() const 110 { 111 return nbIndexOnProc_; 112 } 57 113 58 114 } -
XIOS/trunk/src/dht_auto_indexing.hpp
r892 r924 22 22 class CDHTAutoIndexing: public CClientClientDHTTemplate<size_t> 23 23 { 24 public: 25 CDHTAutoIndexing(const CArray<size_t,1>& hashValue, 26 const MPI_Comm& clientIntraComm); 24 public: 25 26 CDHTAutoIndexing(const CArray<size_t,1>& hashValue, 27 const MPI_Comm& clientIntraComm); 28 29 CDHTAutoIndexing(Index2VectorInfoTypeMap& hashInitMap, 30 const MPI_Comm& clientIntraComm); 31 32 size_t getNbIndexesGlobal() const; 33 size_t getIndexStart() const; 34 size_t getIndexCount() const; 27 35 28 36 /** Default destructor */ 29 37 virtual ~CDHTAutoIndexing(); 38 39 protected: 40 std::vector<size_t> globalIndex_; 41 size_t nbIndexesGlobal_; 42 size_t nbIndexOnProc_ ; 43 size_t beginIndexOnProc_ ; 30 44 }; 31 45 -
XIOS/trunk/src/io/nc4_data_output.cpp
r902 r924 26 26 CNc4DataOutput::CNc4DataOutput 27 27 (const StdString & filename, bool exist, bool useClassicFormat, bool useCFConvention, 28 MPI_Comm comm_file, bool multifile, bool isCollective, const StdString& timeCounterName)28 MPI_Comm comm_file, bool multifile, bool isCollective, const StdString& timeCounterName) 29 29 : SuperClass() 30 30 , SuperClassWriter(filename, exist, useClassicFormat, useCFConvention, &comm_file, multifile, timeCounterName) … … 449 449 StdString domid = domain->getDomainOutputName(); 450 450 StdString domainName = domain->name; 451 domain->assignMesh(domainName );452 domain->mesh->createMesh(domain->lonvalue_srv, domain->latvalue_srv, domain->bounds_lon_srv, domain->bounds_lat_srv);453 //domain->mesh->createMeshEpsilon(server->intraComm, domain->lonvalue_srv, domain->latvalue_srv, domain->bounds_lon_srv, domain->bounds_lat_srv);451 domain->assignMesh(domainName, domain->nvertex); 452 //domain->mesh->createMesh(domain->lonvalue_srv, domain->latvalue_srv, domain->bounds_lon_srv, domain->bounds_lat_srv); 453 domain->mesh->createMeshEpsilon(server->intraComm, domain->lonvalue_srv, domain->latvalue_srv, domain->bounds_lon_srv, domain->bounds_lat_srv); 454 454 455 455 StdString node_x = domainName + "_node_x"; … … 479 479 SuperClassWriter::addVariable(domainName, NC_INT, dim0); 480 480 SuperClassWriter::addAttribute("cf_role", StdString("mesh_topology"), &domainName); 481 SuperClassWriter::addAttribute("long_name", StdString("Topology data of 2D unstructured mesh"), &domainName); 482 SuperClassWriter::addAttribute("topology_dimension", 2, &domainName); 481 483 SuperClassWriter::addAttribute("node_coordinates", node_x + " " + node_y, &domainName); 482 484 } … … 498 500 SuperClassWriter::addVariable(node_x, NC_FLOAT, dim0); 499 501 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &node_x); 500 SuperClassWriter::addAttribute("long name_name", StdString("Longitude of mesh nodes."), &node_x);502 SuperClassWriter::addAttribute("long_name", StdString("Longitude of mesh nodes."), &node_x); 501 503 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &node_x); 502 504 SuperClassWriter::addVariable(node_y, NC_FLOAT, dim0); 503 505 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &node_y); 504 SuperClassWriter::addAttribute("long name_name", StdString("Latitude of mesh nodes."), &node_y);506 SuperClassWriter::addAttribute("long_name", StdString("Latitude of mesh nodes."), &node_y); 505 507 SuperClassWriter::addAttribute("units", StdString("degrees_north"), &node_y); 506 508 } … … 512 514 if (!SuperClassWriter::varExist(node_x) || !SuperClassWriter::varExist(node_y)) 513 515 { 514 SuperClassWriter::addDimension(dimNode, domain->mesh->nbNodes );516 SuperClassWriter::addDimension(dimNode, domain->mesh->nbNodesGlo); 515 517 dim0.clear(); 516 518 dim0.push_back(dimNode); 517 519 SuperClassWriter::addVariable(node_x, NC_FLOAT, dim0); 518 520 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &node_x); 519 SuperClassWriter::addAttribute("long name_name", StdString("Longitude of mesh nodes."), &node_x);521 SuperClassWriter::addAttribute("long_name", StdString("Longitude of mesh nodes."), &node_x); 520 522 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &node_x); 521 523 SuperClassWriter::addVariable(node_y, NC_FLOAT, dim0); 522 524 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &node_y); 523 SuperClassWriter::addAttribute("longname_name", StdString("Latitude of mesh nodes."), &node_y); 525 SuperClassWriter::addAttribute("long_name", StdString("Latitude of mesh nodes."), &node_y); 526 SuperClassWriter::addAttribute("units", StdString("degrees_north"), &node_y); 527 } 528 SuperClassWriter::addAttribute("edge_node_connectivity", edge_nodes, &domainName); 529 SuperClassWriter::addAttribute("edge_coordinates", edge_x + " " + edge_y, &domainName); 530 SuperClassWriter::addDimension(dimEdge, domain->ni_glo); 531 dim0.clear(); 532 dim0.push_back(dimEdge); 533 SuperClassWriter::addVariable(edge_x, NC_FLOAT, dim0); 534 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &edge_x); 535 SuperClassWriter::addAttribute("long_name", StdString("Characteristic longitude of mesh edges."), &edge_x); 536 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &edge_x); 537 SuperClassWriter::addVariable(edge_y, NC_FLOAT, dim0); 538 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &edge_y); 539 SuperClassWriter::addAttribute("long_name", StdString("Characteristic latitude of mesh edges."), &edge_y); 540 SuperClassWriter::addAttribute("units", StdString("degrees_north"), &edge_y); 541 dim0.clear(); 542 dim0.push_back(dimEdge); 543 dim0.push_back(dimTwo); 544 SuperClassWriter::addVariable(edge_nodes, NC_INT, dim0); 545 SuperClassWriter::addAttribute("cf_role", StdString("edge_node_connectivity"), &edge_nodes); 546 SuperClassWriter::addAttribute("long_name", StdString("Maps every edge/link to two nodes that it connects."), &edge_nodes); 547 SuperClassWriter::addAttribute("start_index", 0, &edge_nodes); 548 } // domain->nvertex == 2 549 550 // Adding faces, edges, and nodes, if edges and nodes have not been defined previously 551 if (domain->nvertex > 2) 552 { 553 // Nodes 554 if (!SuperClassWriter::varExist(node_x) || !SuperClassWriter::varExist(node_y)) 555 { 556 SuperClassWriter::addDimension(dimNode, domain->mesh->nbNodesGlo); 557 dim0.clear(); 558 dim0.push_back(dimNode); 559 SuperClassWriter::addVariable(node_x, NC_FLOAT, dim0); 560 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &node_x); 561 SuperClassWriter::addAttribute("long_name", StdString("Longitude of mesh nodes."), &node_x); 562 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &node_x); 563 SuperClassWriter::addVariable(node_y, NC_FLOAT, dim0); 564 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &node_y); 565 SuperClassWriter::addAttribute("long_name", StdString("Latitude of mesh nodes."), &node_y); 524 566 SuperClassWriter::addAttribute("units", StdString("degrees_north"), &node_y); 525 567 } 526 568 if (!SuperClassWriter::varExist(edge_x) || !SuperClassWriter::varExist(edge_y)) 527 569 { 570 SuperClassWriter::addAttribute("edge_coordinates", edge_x + " " + edge_y, &domainName); 528 571 SuperClassWriter::addAttribute("edge_node_connectivity", edge_nodes, &domainName); 529 SuperClassWriter::addAttribute("edge_coordinates", edge_x + " " + edge_y, &domainName); 530 SuperClassWriter::addDimension(dimEdge, domain->mesh->nbEdges); 572 SuperClassWriter::addDimension(dimEdge, domain->mesh->nbEdgesGlo); 531 573 dim0.clear(); 532 574 dim0.push_back(dimEdge); 533 575 SuperClassWriter::addVariable(edge_x, NC_FLOAT, dim0); 534 576 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &edge_x); 535 SuperClassWriter::addAttribute("long name_name", StdString("Characteristic longitude of mesh edges."), &edge_x);577 SuperClassWriter::addAttribute("long_name", StdString("Characteristic longitude of mesh edges."), &edge_x); 536 578 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &edge_x); 537 579 SuperClassWriter::addVariable(edge_y, NC_FLOAT, dim0); 538 580 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &edge_y); 539 SuperClassWriter::addAttribute("long name_name", StdString("Characteristic latitude of mesh edges."), &edge_y);581 SuperClassWriter::addAttribute("long_name", StdString("Characteristic latitude of mesh edges."), &edge_y); 540 582 SuperClassWriter::addAttribute("units", StdString("degrees_north"), &edge_y); 541 583 dim0.clear(); … … 547 589 SuperClassWriter::addAttribute("start_index", 0, &edge_nodes); 548 590 } 549 } // domain->nvertex == 2 550 551 // Adding faces, edges, and nodes, if edges and nodes have not been defined previously 552 if (domain->nvertex > 2) 553 { 554 // Nodes 555 if (!SuperClassWriter::varExist(node_x) || !SuperClassWriter::varExist(node_y)) 556 { 557 SuperClassWriter::addDimension(dimNode, domain->mesh->nbNodes); 558 dim0.clear(); 559 dim0.push_back(dimNode); 560 SuperClassWriter::addVariable(node_x, NC_FLOAT, dim0); 561 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &node_x); 562 SuperClassWriter::addAttribute("longname_name", StdString("Longitude of mesh nodes."), &node_x); 563 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &node_x); 564 SuperClassWriter::addVariable(node_y, NC_FLOAT, dim0); 565 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &node_y); 566 SuperClassWriter::addAttribute("longname_name", StdString("Latitude of mesh nodes."), &node_y); 567 SuperClassWriter::addAttribute("units", StdString("degrees_north"), &node_y); 568 } 569 if (!SuperClassWriter::varExist(edge_x) || !SuperClassWriter::varExist(edge_y)) 570 { 571 SuperClassWriter::addAttribute("edge_coordinates", edge_x + " " + edge_y, &domainName); 572 SuperClassWriter::addAttribute("edge_node_connectivity", edge_nodes, &domainName); 573 SuperClassWriter::addDimension(dimEdge, domain->mesh->nbEdges); 574 dim0.clear(); 575 dim0.push_back(dimEdge); 576 SuperClassWriter::addVariable(edge_x, NC_FLOAT, dim0); 577 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &edge_x); 578 SuperClassWriter::addAttribute("longname_name", StdString("Characteristic longitude of mesh edges."), &edge_x); 579 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &edge_x); 580 SuperClassWriter::addVariable(edge_y, NC_FLOAT, dim0); 581 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &edge_y); 582 SuperClassWriter::addAttribute("longname_name", StdString("Characteristic latitude of mesh edges."), &edge_y); 583 SuperClassWriter::addAttribute("units", StdString("degrees_north"), &edge_y); 584 dim0.clear(); 585 dim0.push_back(dimEdge); 586 dim0.push_back(dimTwo); 587 SuperClassWriter::addVariable(edge_nodes, NC_INT, dim0); 588 SuperClassWriter::addAttribute("cf_role", StdString("edge_node_connectivity"), &edge_nodes); 589 SuperClassWriter::addAttribute("long_name", StdString("Maps every edge/link to two nodes that it connects."), &edge_nodes); 590 SuperClassWriter::addAttribute("start_index", 0, &edge_nodes); 591 } 592 SuperClassWriter::addAttribute("face_coordinates", face_x + " " + face_y, &domainName); 593 SuperClassWriter::addAttribute("face_node_connectivity", face_nodes, &domainName); 594 SuperClassWriter::addDimension(dimFace, domain->mesh->nbFaces); 595 SuperClassWriter::addDimension(dimVertex, domain->mesh->nvertex); 596 dim0.clear(); 597 dim0.push_back(dimFace); 598 SuperClassWriter::addVariable(face_x, NC_FLOAT, dim0); 599 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &face_x); 600 SuperClassWriter::addAttribute("longname_name", StdString("Characteristic longitude of mesh faces."), &face_x); 601 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &face_x); 602 SuperClassWriter::addVariable(face_y, NC_FLOAT, dim0); 603 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &face_y); 604 SuperClassWriter::addAttribute("longname_name", StdString("Characteristic latitude of mesh faces."), &face_y); 605 SuperClassWriter::addAttribute("units", StdString("degrees_north"), &face_y); 606 dim0.clear(); 607 dim0.push_back(dimFace); 608 dim0.push_back(dimVertex); 609 SuperClassWriter::addVariable(face_nodes, NC_INT, dim0); 610 SuperClassWriter::addAttribute("cf_role", StdString("face_node_connectivity"), &face_nodes); 611 SuperClassWriter::addAttribute("long_name", StdString("Maps every face to its corner nodes."), &face_nodes); 612 SuperClassWriter::addAttribute("start_index", 0, &face_nodes); 613 dim0.clear(); 614 dim0.push_back(dimFace); 615 dim0.push_back(dimVertex); 616 SuperClassWriter::addVariable(face_edges, NC_INT, dim0); 617 SuperClassWriter::addAttribute("cf_role", StdString("face_edge_connectivity"), &face_edges); 618 SuperClassWriter::addAttribute("long_name", StdString("Maps every face to its edges."), &face_edges); 619 SuperClassWriter::addAttribute("start_index", 0, &face_edges); 620 dim0.clear(); 621 dim0.push_back(dimEdge); 622 dim0.push_back(dimTwo); 623 SuperClassWriter::addVariable(edge_faces, NC_INT, dim0); 624 SuperClassWriter::addAttribute("cf_role", StdString("edge_face connectivity"), &edge_faces); 625 SuperClassWriter::addAttribute("long_name", StdString("neighbor faces for edges"), &edge_faces); 626 SuperClassWriter::addAttribute("start_index", 0, &edge_faces); 627 SuperClassWriter::addAttribute("_FillValue", -999, &edge_faces); 628 SuperClassWriter::addAttribute("comment", StdString("missing neighbor faces are indicated using _FillValue"), &edge_faces); 629 dim0.clear(); 630 dim0.push_back(dimFace); 631 dim0.push_back(dimVertex); 632 SuperClassWriter::addVariable(face_faces, NC_INT, dim0); 633 SuperClassWriter::addAttribute("cf_role", StdString("face_face connectivity"), &face_faces); 634 SuperClassWriter::addAttribute("long_name", StdString("Indicates which other faces neighbor each face"), &face_faces); 635 SuperClassWriter::addAttribute("start_index", 0, &face_faces); 636 SuperClassWriter::addAttribute("flag_values", -1, &face_faces); 637 SuperClassWriter::addAttribute("flag_meanings", StdString("out_of_mesh"), &face_faces); 591 SuperClassWriter::addAttribute("face_coordinates", face_x + " " + face_y, &domainName); 592 SuperClassWriter::addAttribute("face_node_connectivity", face_nodes, &domainName); 593 SuperClassWriter::addDimension(dimFace, domain->ni_glo); 594 SuperClassWriter::addDimension(dimVertex, domain->nvertex); 595 dim0.clear(); 596 dim0.push_back(dimFace); 597 SuperClassWriter::addVariable(face_x, NC_FLOAT, dim0); 598 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &face_x); 599 SuperClassWriter::addAttribute("long_name", StdString("Characteristic longitude of mesh faces."), &face_x); 600 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &face_x); 601 SuperClassWriter::addVariable(face_y, NC_FLOAT, dim0); 602 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &face_y); 603 SuperClassWriter::addAttribute("long_name", StdString("Characteristic latitude of mesh faces."), &face_y); 604 SuperClassWriter::addAttribute("units", StdString("degrees_north"), &face_y); 605 dim0.clear(); 606 dim0.push_back(dimFace); 607 dim0.push_back(dimVertex); 608 SuperClassWriter::addVariable(face_nodes, NC_INT, dim0); 609 SuperClassWriter::addAttribute("cf_role", StdString("face_node_connectivity"), &face_nodes); 610 SuperClassWriter::addAttribute("long_name", StdString("Maps every face to its corner nodes."), &face_nodes); 611 SuperClassWriter::addAttribute("start_index", 0, &face_nodes); 612 dim0.clear(); 613 dim0.push_back(dimFace); 614 dim0.push_back(dimVertex); 615 SuperClassWriter::addVariable(face_edges, NC_INT, dim0); 616 SuperClassWriter::addAttribute("cf_role", StdString("face_edge_connectivity"), &face_edges); 617 SuperClassWriter::addAttribute("long_name", StdString("Maps every face to its edges."), &face_edges); 618 SuperClassWriter::addAttribute("start_index", 0, &face_edges); 619 dim0.clear(); 620 dim0.push_back(dimEdge); 621 dim0.push_back(dimTwo); 622 SuperClassWriter::addVariable(edge_faces, NC_INT, dim0); 623 SuperClassWriter::addAttribute("cf_role", StdString("edge_face connectivity"), &edge_faces); 624 SuperClassWriter::addAttribute("long_name", StdString("neighbor faces for edges"), &edge_faces); 625 SuperClassWriter::addAttribute("start_index", 0, &edge_faces); 626 SuperClassWriter::addAttribute("_FillValue", -999, &edge_faces); 627 SuperClassWriter::addAttribute("comment", StdString("missing neighbor faces are indicated using _FillValue"), &edge_faces); 628 dim0.clear(); 629 dim0.push_back(dimFace); 630 dim0.push_back(dimVertex); 631 SuperClassWriter::addVariable(face_faces, NC_INT, dim0); 632 SuperClassWriter::addAttribute("cf_role", StdString("face_face connectivity"), &face_faces); 633 SuperClassWriter::addAttribute("long_name", StdString("Indicates which other faces neighbor each face"), &face_faces); 634 SuperClassWriter::addAttribute("start_index", 0, &face_faces); 635 SuperClassWriter::addAttribute("flag_values", -1, &face_faces); 636 SuperClassWriter::addAttribute("flag_meanings", StdString("out_of_mesh"), &face_faces); 638 637 } // domain->nvertex > 2 639 638 640 639 SuperClassWriter::definition_end(); 641 640 642 std::vector<StdSize> start (1) ;643 std::vector<StdSize> count (1) ;644 if (domain->isEmpty())645 {646 start[0]=0;647 count[0]=0;648 }649 else650 {651 start[0]=domain->zoom_ibegin_srv-domain->global_zoom_ibegin;652 count[0]=domain->zoom_ni_srv;653 }641 std::vector<StdSize> startEdges(1) ; 642 std::vector<StdSize> countEdges(1) ; 643 std::vector<StdSize> startNodes(1) ; 644 std::vector<StdSize> countNodes(1) ; 645 std::vector<StdSize> startFaces(1) ; 646 std::vector<StdSize> countFaces(1) ; 647 std::vector<StdSize> startEdgeNodes(2) ; 648 std::vector<StdSize> countEdgeNodes(2) ; 649 std::vector<StdSize> startEdgeFaces(2) ; 650 std::vector<StdSize> countEdgeFaces(2) ; 651 std::vector<StdSize> startFaceConctv(2) ; 652 std::vector<StdSize> countFaceConctv(2) ; 654 653 655 654 if (!isWrittenDomain(domid)) … … 657 656 if (domain->nvertex == 1) 658 657 { 659 SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0, &start, &count); 660 SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0, &start, &count); 658 if (domain->isEmpty()) 659 { 660 startNodes[0]=0 ; 661 countNodes[0]=0 ; 662 } 663 else 664 { 665 startNodes[0] = domain->zoom_ibegin_srv-domain->global_zoom_ibegin; 666 countNodes[0] = domain->zoom_ni_srv ; 667 } 668 669 SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0, &startNodes, &countNodes); 670 SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0, &startNodes, &countNodes); 661 671 } 662 672 else if (domain->nvertex == 2) 663 { 664 SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0); 665 SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0); 666 SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0); 667 SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0); 668 SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes); 669 } 673 { 674 if (domain->isEmpty()) 675 { 676 startEdges[0]=0 ; 677 countEdges[0]=0 ; 678 startNodes[0]=0 ; 679 countNodes[0]=0 ; 680 startEdgeNodes[0]=0; 681 startEdgeNodes[1]=0; 682 countEdgeNodes[0]=0; 683 countEdgeNodes[1]=0; 684 685 } 686 else 687 { 688 startEdges[0] = domain->zoom_ibegin_srv-domain->global_zoom_ibegin; 689 countEdges[0] = domain->zoom_ni_srv ; 690 startNodes[0] = domain->mesh->node_start; 691 countNodes[0] = domain->mesh->node_count; 692 startEdgeNodes[0] = domain->zoom_ibegin_srv-domain->global_zoom_ibegin; 693 startEdgeNodes[1] = 0; 694 countEdgeNodes[0] = domain->zoom_ni_srv; 695 countEdgeNodes[1]= 2; 696 } 697 SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0, &startNodes, &countNodes); 698 SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0, &startNodes, &countNodes); 699 SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0, &startEdges, &countEdges); 700 SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0, &startEdges, &countEdges); 701 SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes, isCollective, 0, &startEdgeNodes, &countEdgeNodes); 702 } 670 703 else 671 704 { 672 SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0); 673 SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0); 674 SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0); 675 SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0); 676 SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes); 677 SuperClassWriter::writeData(domain->mesh->face_lat, face_y, isCollective, 0); 678 SuperClassWriter::writeData(domain->mesh->face_lon, face_x, isCollective, 0); 679 SuperClassWriter::writeData(domain->mesh->face_nodes, face_nodes); 680 SuperClassWriter::writeData(domain->mesh->face_edges, face_edges); 681 SuperClassWriter::writeData(domain->mesh->edge_faces, edge_faces); 682 SuperClassWriter::writeData(domain->mesh->face_faces, face_faces); 705 if (domain->isEmpty()) 706 { 707 startFaces[0] = 0 ; 708 countFaces[0] = 0 ; 709 startNodes[0] = 0; 710 countNodes[0] = 0; 711 startEdges[0] = 0; 712 countEdges[0] = 0; 713 startEdgeFaces[0] = 0; 714 startEdgeFaces[1] = 0; 715 countEdgeFaces[0] = 0; 716 countEdgeFaces[1] = 0; 717 startFaceConctv[0] = 0; 718 startFaceConctv[1] = 0; 719 countFaceConctv[0] = 0; 720 countFaceConctv[1] = 0; 721 } 722 else 723 { 724 startFaces[0] = domain->zoom_ibegin_srv-domain->global_zoom_ibegin; 725 countFaces[0] = domain->zoom_ni_srv ; 726 startNodes[0] = domain->mesh->node_start; 727 countNodes[0] = domain->mesh->node_count; 728 startEdges[0] = domain->mesh->edge_start; 729 countEdges[0] = domain->mesh->edge_count; 730 startEdgeNodes[0] = domain->mesh->edge_start; 731 startEdgeNodes[1] = 0; 732 countEdgeNodes[0] = domain->mesh->edge_count; 733 countEdgeNodes[1]= 2; 734 startEdgeFaces[0] = domain->mesh->edge_start; 735 startEdgeFaces[1]= 0; 736 countEdgeFaces[0] = domain->mesh->edge_count; 737 countEdgeFaces[1]= 2; 738 startFaceConctv[0] = domain->zoom_ibegin_srv-domain->global_zoom_ibegin; 739 startFaceConctv[1] = 0; 740 countFaceConctv[0] = domain->zoom_ni_srv; 741 countFaceConctv[1] = domain->nvertex; 742 } 743 SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0, &startNodes, &countNodes); 744 SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0, &startNodes, &countNodes); 745 SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0, &startEdges, &countEdges); 746 SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0, &startEdges, &countEdges); 747 SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes, isCollective, 0, &startEdgeNodes, &countEdgeNodes); 748 SuperClassWriter::writeData(domain->mesh->face_lat, face_y, isCollective, 0, &startFaces, &countFaces); 749 SuperClassWriter::writeData(domain->mesh->face_lon, face_x, isCollective, 0, &startFaces, &countFaces); 750 SuperClassWriter::writeData(domain->mesh->face_nodes, face_nodes, isCollective, 0, &startFaceConctv, &countFaceConctv); 751 SuperClassWriter::writeData(domain->mesh->face_edges, face_edges, isCollective, 0, &startFaceConctv, &countFaceConctv); 752 SuperClassWriter::writeData(domain->mesh->edge_faces, edge_faces, isCollective, 0, &startEdgeFaces, &countEdgeFaces); 753 SuperClassWriter::writeData(domain->mesh->face_faces, face_faces, isCollective, 0, &startFaceConctv, &countFaceConctv); 683 754 } 684 755 setWrittenDomain(domid); … … 686 757 else 687 758 { 688 if (domain->nvertex == 1)689 {690 if ( (!domain->mesh->edgesAreWritten) && (!domain->mesh->facesAreWritten) )691 {692 SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0);693 SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0);694 }695 }696 759 if (domain->nvertex == 2) 697 760 { 698 if (!domain->mesh->facesAreWritten) 699 { 700 if (!domain->mesh->nodesAreWritten) 701 { 702 SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0); 703 SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0); 704 } 705 SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0); 706 SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0); 707 SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes); 708 } 761 startEdges[0] = domain->zoom_ibegin_srv-domain->global_zoom_ibegin; 762 countEdges[0] = domain->zoom_ni_srv ; 763 startEdgeNodes[0] = domain->zoom_ibegin_srv-domain->global_zoom_ibegin; 764 startEdgeNodes[1] = 0; 765 countEdgeNodes[0] = domain->zoom_ni_srv; 766 countEdgeNodes[1]= 2; 767 SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0, &startEdges, &countEdges); 768 SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0, &startEdges, &countEdges); 769 SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes, isCollective, 0, &startEdgeNodes, &countEdgeNodes); 709 770 } 710 771 if (domain->nvertex > 2) 711 772 { 773 712 774 if (!domain->mesh->edgesAreWritten) 713 775 { 714 if (!domain->mesh->nodesAreWritten) 715 { 716 SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0); 717 SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0); 718 } 719 SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0); 720 SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0); 721 SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes); 776 startEdges[0] = domain->mesh->edge_start; 777 countEdges[0] = domain->mesh->edge_count; 778 startEdgeNodes[0] = domain->mesh->edge_start; 779 startEdgeNodes[1] = 0; 780 countEdgeNodes[0] = domain->mesh->edge_count; 781 countEdgeNodes[1]= 2; 782 SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0, &startEdges, &countEdges); 783 SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0, &startEdges, &countEdges); 784 SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes, isCollective, 0, &startEdgeNodes, &countEdgeNodes); 722 785 } 723 SuperClassWriter::writeData(domain->mesh->face_lat, face_y, isCollective, 0); 724 SuperClassWriter::writeData(domain->mesh->face_lon, face_x, isCollective, 0); 725 SuperClassWriter::writeData(domain->mesh->face_nodes, face_nodes); 726 SuperClassWriter::writeData(domain->mesh->face_edges, face_edges); 727 SuperClassWriter::writeData(domain->mesh->edge_faces, edge_faces); 728 SuperClassWriter::writeData(domain->mesh->face_faces, face_faces); 786 startFaces[0] = domain->zoom_ibegin_srv-domain->global_zoom_ibegin; 787 countFaces[0] = domain->zoom_ni_srv; 788 startEdgeFaces[0] = domain->mesh->edge_start; 789 startEdgeFaces[1]= 0; 790 countEdgeFaces[0] = domain->mesh->edge_count; 791 countEdgeFaces[1]= 2; 792 startFaceConctv[0] = domain->zoom_ibegin_srv-domain->global_zoom_ibegin; 793 startFaceConctv[1] = 0; 794 countFaceConctv[0] = domain->zoom_ni_srv; 795 countFaceConctv[1]= domain->nvertex; 796 SuperClassWriter::writeData(domain->mesh->face_lat, face_y, isCollective, 0, &startFaces, &countFaces); 797 SuperClassWriter::writeData(domain->mesh->face_lon, face_x, isCollective, 0, &startFaces, &countFaces); 798 SuperClassWriter::writeData(domain->mesh->face_nodes, face_nodes, isCollective, 0, &startFaceConctv, &countFaceConctv); 799 SuperClassWriter::writeData(domain->mesh->face_edges, face_edges, isCollective, 0, &startFaceConctv, &countFaceConctv); 800 SuperClassWriter::writeData(domain->mesh->edge_faces, edge_faces, isCollective, 0, &startEdgeFaces, &countEdgeFaces); 801 SuperClassWriter::writeData(domain->mesh->face_faces, face_faces, isCollective, 0, &startFaceConctv, &countFaceConctv); 729 802 } 730 803 }// isWrittenDomain … … 754 827 msg.append(context->getId()); msg.append("\n"); 755 828 msg.append(e.what()); 756 ERROR("CNc4DataOutput::writeUnstructuredDomain (CDomain* domain)", << msg);829 ERROR("CNc4DataOutput::writeUnstructuredDomainUgrid(CDomain* domain)", << msg); 757 830 } 758 831 -
XIOS/trunk/src/io/onetcdf4_decl.cpp
r685 r924 10 10 11 11 macro(int, 1) 12 macro(int, 2) 12 13 macro(double, 1) 13 14 macro(double, 2) -
XIOS/trunk/src/node/domain.cpp
r911 r924 36 36 , isRedistributed_(false) 37 37 { 38 //mesh = new CMesh(); 39 } 38 } 40 39 41 40 CDomain::CDomain(const StdString & id) … … 47 46 , isRedistributed_(false) 48 47 { 49 //mesh = new CMesh(); 50 } 48 } 51 49 52 50 CDomain::~CDomain(void) 53 51 { 54 //delete mesh;55 52 } 56 53 57 54 ///--------------------------------------------------------------- 58 55 59 void CDomain::assignMesh(const StdString meshName )60 { 61 mesh = CMesh::getMesh(meshName );56 void CDomain::assignMesh(const StdString meshName, const int nvertex) 57 { 58 mesh = CMesh::getMesh(meshName, nvertex); 62 59 } 63 60 … … 1897 1894 1898 1895 buffer >> lon; 1896 1899 1897 if (hasBounds) buffer >> boundslon; 1900 1898 -
XIOS/trunk/src/node/domain.hpp
r893 r924 67 67 68 68 CMesh* mesh; 69 void assignMesh(const StdString );69 void assignMesh(const StdString, const int); 70 70 71 71 virtual void parse(xml::CXMLNode & node); -
XIOS/trunk/src/node/mesh.cpp
r901 r924 11 11 /// ////////////////////// Définitions ////////////////////// /// 12 12 13 CMesh::CMesh(void) : nbFaces{0}, nbNodes{0}, nbEdges{0} 14 , nvertex{0} 13 CMesh::CMesh(void) : nbNodesGlo{0}, nbEdgesGlo{0} 14 , node_start{0}, node_count{0} 15 , edge_start{0}, edge_count{0} 16 , nbFaces{0}, nbNodes{0}, nbEdges{0} 15 17 , nodesAreWritten{false}, edgesAreWritten{false}, facesAreWritten{false} 16 18 , node_lon(), node_lat() … … 18 20 , face_lon(), face_lat() 19 21 , face_nodes() 22 , pNodeGlobalIndex{NULL}, pEdgeGlobalIndex{NULL} 20 23 { 21 24 } … … 24 27 CMesh::~CMesh(void) 25 28 { 29 if (pNodeGlobalIndex != NULL) delete pNodeGlobalIndex; 30 if (pEdgeGlobalIndex != NULL) delete pEdgeGlobalIndex; 26 31 } 27 32 28 33 std::map <StdString, CMesh> CMesh::meshList = std::map <StdString, CMesh>(); 29 //CMesh* CMesh::getMesh;34 std::map <StdString, vector<int> > CMesh::domainList = std::map <StdString, vector<int> >(); 30 35 31 36 ///--------------------------------------------------------------- … … 34 39 * Returns a pointer to a mesh. If a mesh has not been created, creates it and adds its name to the list of meshes meshList. 35 40 * \param [in] meshName The name of a mesh ("name" attribute of a domain). 41 * \param [in] nvertex Number of verteces (1 for nodes, 2 for edges, 3 and up for faces). 36 42 */ 37 CMesh* CMesh::getMesh (StdString meshName )43 CMesh* CMesh::getMesh (StdString meshName, int nvertex) 38 44 { 45 CMesh::domainList[meshName].push_back(nvertex); 46 39 47 if ( CMesh::meshList.begin() != CMesh::meshList.end() ) 40 48 { … … 60 68 61 69 ///---------------------------------------------------------------- 62 int hashPair(int first, int second)70 size_t hashPair(size_t first, size_t second) 63 71 { 64 int seed = first + 0x9e3779b9 ; 65 seed ^= second + 0x9e3779b9 + (seed << 6) + (seed >> 2); 72 HashXIOS<size_t> sizetHash; 73 size_t seed = sizetHash(first) + 0x9e3779b9 ; 74 seed ^= sizetHash(second) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 75 return seed ; 76 } 77 78 ///---------------------------------------------------------------- 79 size_t hashPairOrdered(size_t first, size_t second) 80 { 81 size_t seed; 82 HashXIOS<size_t> sizetHash; 83 if (first < second) 84 { 85 seed = sizetHash(first) + 0x9e3779b9 ; 86 seed ^= sizetHash(second) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 87 } 88 else 89 { 90 seed = sizetHash(second) + 0x9e3779b9 ; 91 seed ^= sizetHash(first) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 92 } 93 return seed ; 94 } 95 96 ///---------------------------------------------------------------- 97 /*! 98 * \fn size_t generateEdgeIndex(size_t first, size_t second, int rank) 99 * Generates an edge index. 100 * If the same edge is generated by two processes, each process will have its own edge index. 101 * \param [in] first Edge node. 102 * \param [in] second Edge node. 103 * \param [in] rank MPI process rank. 104 */ 105 size_t generateEdgeIndex(size_t first, size_t second, int rank) 106 { 107 size_t seed = rank ; 108 if (first < second) 109 { 110 seed = hashPair(seed, first); 111 seed = hashPair(seed, second); 112 } 113 else 114 { 115 seed = hashPair(seed, second); 116 seed = hashPair(seed, first); 117 } 118 119 return seed ; 120 } 121 122 ///---------------------------------------------------------------- 123 /*! 124 * \fn size_t generateNodeIndex(vector<size_t>& valList, int rank) 125 * Generates a node index. 126 * If the same node is generated by two processes, each process will have its own node index. 127 * \param [in] valList Vector storing four node hashes. 128 * \param [in] rank MPI process rank. 129 */ 130 size_t generateNodeIndex(vector<size_t>& valList, int rank) 131 { 132 // Sort is needed to avoid problems for nodes with lon = 0 generated by faces in east and west semisphere 133 vector<size_t> vec = valList; 134 sort (vec.begin(), vec.end()); 135 size_t seed = rank ; 136 int it = 0; 137 for(; it != vec.size(); ++it) 138 { 139 seed = hashPair(seed, vec[it]); 140 } 66 141 return seed ; 67 142 } … … 144 219 ///---------------------------------------------------------------- 145 220 /*! 146 * \fn CArray<size_t,1>& CMesh::createHashes ( double lon, double lat)221 * \fn CArray<size_t,1>& CMesh::createHashes (const double longitude, const double latitude) 147 222 * Creates two hash values for each dimension, longitude and latitude. 148 * \param [in] lon Node longitude in degrees.149 * \param [in] lat Node latitude in degrees ranged from 0 to 360.223 * \param [in] longitude Node longitude in degrees. 224 * \param [in] latitude Node latitude in degrees ranged from 0 to 360. 150 225 */ 151 226 152 vector<size_t> CMesh::createHashes ( double lon, double lat)227 vector<size_t> CMesh::createHashes (const double longitude, const double latitude) 153 228 { 154 229 double minBoundLon = 0. ; 155 230 double maxBoundLon = 360. ; 156 double minBoundLat = -90 ;157 double maxBoundLat = 90 ;231 double minBoundLat = -90. ; 232 double maxBoundLat = 90. ; 158 233 double prec=1e-11 ; 159 234 double precLon=prec ; 160 235 double precLat=prec ; 236 double lon = longitude; 237 double lat = latitude; 238 239 if (lon > (360.- prec)) lon = 0.; 161 240 162 241 size_t maxsize_t=numeric_limits<size_t>::max() ; … … 213 292 return std::pair<int,int>(b,a); 214 293 } 215 216 ///----------------------------------------------------------------217 //#include <random>218 // size_t randNum()219 // {220 // typedef mt19937 rng;221 // size_t max = numeric_limits<size_t>::max();222 // uniform_int_distribution<> distr(0, max);223 // return distr(rng);224 // }225 294 226 295 ///---------------------------------------------------------------- … … 237 306 const CArray<double, 2>& bounds_lon, const CArray<double, 2>& bounds_lat) 238 307 { 239 nvertex = (bounds_lon.numElements() == 0) ? 1 : bounds_lon.rows();308 int nvertex = (bounds_lon.numElements() == 0) ? 1 : bounds_lon.rows(); 240 309 241 310 if (nvertex == 1) … … 357 426 edge_lon(nbEdges) = ( abs( node_lon(face_nodes(nv1,nf)) - node_lon(face_nodes(nv2,nf))) < 180.) ? 358 427 (( node_lon(face_nodes(nv1,nf)) + node_lon(face_nodes(nv2,nf))) * 0.5) : 359 (( node_lon(face_nodes(nv1,nf)) + node_lon(face_nodes(nv2,nf))) * 0.5 -180.); ;428 (( node_lon(face_nodes(nv1,nf)) + node_lon(face_nodes(nv2,nf))) * 0.5 -180.); 360 429 edge_lat(nbEdges) = ( node_lat(face_nodes(nv1,nf)) + node_lat(face_nodes(nv2,nf)) ) * 0.5; 361 430 ++nbEdges; … … 418 487 * Creates or updates a mesh for the three types of mesh elements: nodes, edges, and faces. 419 488 * Precision check is implemented with two hash values for each dimension, longitude and latitude. 489 * \param [in] comm 420 490 * \param [in] lonvalue Array of longitudes. 421 491 * \param [in] latvalue Array of latitudes. … … 423 493 * \param [in] bounds_lat Array of boundary latitudes. Its size depends on the element type. 424 494 */ 425 void CMesh::createMeshEpsilon(const MPI_Comm& comm, const CArray<double, 1>& lonvalue, const CArray<double, 1>& latvalue, 426 const CArray<double, 2>& bounds_lon, const CArray<double, 2>& bounds_lat) 495 void CMesh::createMeshEpsilon(const MPI_Comm& comm, 496 const CArray<double, 1>& lonvalue, const CArray<double, 1>& latvalue, 497 const CArray<double, 2>& bounds_lon, const CArray<double, 2>& bounds_lat) 427 498 { 428 499 429 nvertex = (bounds_lon.numElements() == 0) ? 1 : bounds_lon.rows(); 500 int nvertex = (bounds_lon.numElements() == 0) ? 1 : bounds_lon.rows(); 501 int mpiRank, mpiSize; 502 MPI_Comm_rank(comm, &mpiRank); 503 MPI_Comm_size(comm, &mpiSize); 430 504 431 505 if (nvertex == 1) 432 506 { 433 507 nbNodes = lonvalue.numElements(); 434 435 // CClientClientDHTSizet::Index2VectorInfoTypeMap hash2Idx; // map <hash, idx>436 vector<size_t> hashValues(4); // temporary vector for storing hashes for each node437 vector<size_t> globalIndexes(nbNodes); // Probably a map ?438 CArray<size_t,1> hashList(nbNodes*4); // Do I need it?439 CArray<size_t,1> idxList(nbNodes);440 441 // Assign a unique index for each node represented by four hashes442 // The first hash will serve as the unique index443 size_t randomIdx;444 int rank, size;445 MPI_Comm_rank(comm, &rank);446 MPI_Comm_size(comm, &size);447 srand((unsigned)time(NULL)+rank*size);448 449 for (size_t nn = 0; nn < nbNodes; ++nn)450 {451 hashValues = CMesh::createHashes(lonvalue(nn), latvalue(nn));452 idxList(nn) = hashValues[nn];453 // randomIdx = rand() % numeric_limits<size_t>::max();454 // idxList(nn) = randomIdx;455 // for (size_t nh = 0; nh < 4; ++nh)456 // {457 // hash2Idx[hashValues[nh]].push_back(randomIdx);458 // hashList(nn*4 + nh) = hashValues[nh];459 // }460 }461 462 463 // CClientClientDHTSizet dhtSizet(hash2Idx, comm);464 // dhtSizet.computeIndexInfoMapping(hashList);465 // CClientClientDHTSizet::Index2VectorInfoTypeMap& hashIdxList = dhtSizet.getInfoIndexMap();466 467 // // (2.1) Create a list of indexes for each hush468 // CClientClientDHTSizet dhtSizet(hash2Idx, comm);469 // dhtSizet.computeIndexInfoMapping(hashList);470 // CClientClientDHTSizet::Index2VectorInfoTypeMap& hashIdxList = dhtSizet.getInfoIndexMap();471 //472 // // (2.2) If more than one index assigned to a hush, set the larger value to be equal to the smaller473 // int iidx = 0;474 // for (CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = hashIdxList.begin(); it != hashIdxList.end(); ++it, ++iidx)475 // {476 // vector<size_t> tmp = it->second;477 // size_t idxMinValue = it->second[0];478 // for (int i = 1; i < it->second.size(); ++i)479 // {480 // if (it->second[i] < idxMinValue )481 // idxMinValue = it->second[i];482 // }483 // if ( (iidx % 4) == 0 )484 // idxList(iidx/4) = idxMinValue;485 // }486 487 // Unique global indexing488 // CDHTAutoIndexing dhtSizetIdx = CDHTAutoIndexing(idxList, comm);489 // CClientClientDHTSizet* pDhtSizet = &dhtSizetIdx;490 // pDhtSizet->computeIndexInfoMapping(idxList);491 492 //globalIndexes = dhtSizetIdx.getGlobalIndex();493 494 508 node_lon.resize(nbNodes); 495 509 node_lat.resize(nbNodes); … … 497 511 node_lat = latvalue; 498 512 513 // Global node indexes 514 vector<size_t> hashValues(4); 515 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeHash2IdxGlo; 516 for (size_t nn = 0; nn < nbNodes; ++nn) 517 { 518 hashValues = CMesh::createHashes(lonvalue(nn), latvalue(nn)); 519 for (size_t nh = 0; nh < 4; ++nh) 520 { 521 nodeHash2IdxGlo[hashValues[nh]].push_back(mpiRank*nbNodes + nn); 522 } 523 } 524 pNodeGlobalIndex = new CClientClientDHTSizet (nodeHash2IdxGlo, comm); 499 525 nodesAreWritten = true; 500 501 526 } 502 527 … … 504 529 { 505 530 nbEdges = bounds_lon.shape()[1]; 506 507 vector<size_t> hashValues(4); 508 for (int ne = 0; ne < nbEdges; ++ne) 531 edge_lon.resize(nbEdges); 532 edge_lat.resize(nbEdges); 533 edge_lon = lonvalue; 534 edge_lat = latvalue; 535 edge_nodes.resize(nvertex, nbEdges); 536 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeHash2IdxGlo; 537 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeHash2Idx; 538 539 // Case (1): node indexes have been generated by domain "nodes" 540 if (nodesAreWritten) 509 541 { 510 for (int nv = 0; nv < nvertex; ++nv) 511 { 512 hashValues = CMesh::createHashes(bounds_lon(nv, ne), bounds_lat(nv, ne)); 513 // for (size_t nh = 0; nh < 4; ++nh) 514 // { 515 // hash2Idx[hashValues[nh]].push_back(randomIdx); 516 // hashList(nn*4 + nh) = hashValues[nh]; 517 // } 518 519 542 vector<size_t> hashValues(4); 543 CArray<size_t,1> nodeHashList(nbEdges*nvertex*4); 544 for (int ne = 0; ne < nbEdges; ++ne) // size_t doesn't work with CArray<double, 2> 545 { 546 for (int nv = 0; nv < nvertex; ++nv) 547 { 548 hashValues = CMesh::createHashes(bounds_lon(nv, ne), bounds_lat(nv, ne)); 549 for (int nh = 0; nh < 4; ++nh) 550 { 551 nodeHashList((ne*nvertex + nv)*4 + nh) = hashValues[nh]; 552 } 553 } 554 } 555 556 // Recuperating the node global indexing and writing edge_nodes 557 // Creating map edgeHash2IdxGlo <hash, idxGlo> 558 pNodeGlobalIndex->computeIndexInfoMapping(nodeHashList); 559 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeHash2IdxGlo = pNodeGlobalIndex->getInfoIndexMap(); 560 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it; 561 vector <size_t> edgeNodes; 562 for (int ne = 0; ne < nbEdges; ++ne) 563 { 564 for (int nv = 0; nv < nvertex; ++nv) 565 { 566 int nh = 0; 567 it = nodeHash2IdxGlo.find(nodeHashList((ne*nvertex + nv)*4 + nh)); 568 // The loop below is needed in case if a hash generated by domain "edges" differs 569 // from that generated by domain "nodes" because of possible precision issues 570 while (it == nodeHash2IdxGlo.end()) 571 { 572 ++nh; 573 it = nodeHash2IdxGlo.find(nodeHashList((ne*nvertex + nv)*4 + nh)); 574 } 575 edge_nodes(nv,ne) = it->second[0]; 576 edgeNodes.push_back(it->second[0]); 577 } 578 edgeHash2IdxGlo[ hashPairOrdered(edgeNodes[0], edgeNodes[1]) ].push_back(nbEdges*mpiRank + ne); 579 } 580 } // nodesAreWritten 581 582 // Case (2): node indexes have not been generated previously 583 else 584 { 585 // (2.1) Creating a list of hashes for each node and a map nodeHash2Idx <hash, <idx,rank> > 586 vector<size_t> hashValues(4); 587 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeHash2Idx; 588 CArray<size_t,1> nodeHashList(nbEdges*nvertex*4); 589 for (int ne = 0; ne < nbEdges; ++ne) 590 { 591 for (int nv = 0; nv < nvertex; ++nv) 592 { 593 hashValues = CMesh::createHashes(bounds_lon(nv, ne), bounds_lat(nv, ne)); 594 for (int nh = 0; nh < 4; ++nh) 595 { 596 if (nodeHash2Idx[hashValues[nh]].size() == 0) 597 { 598 nodeHash2Idx[hashValues[nh]].push_back(generateNodeIndex(hashValues, mpiRank)); 599 nodeHash2Idx[hashValues[nh]].push_back(mpiRank); 600 } 601 nodeHashList((ne*nvertex + nv)*4 + nh) = hashValues[nh]; 602 } 603 } 604 } 605 606 // (2.2) Generating global node indexes 607 // The ownership criterion: priority of the process holding the smaller index 608 // Maps generated in this step are: 609 // nodeHash2Info = <hash, [[idx1, rank1], [idx2, rank2], [idx3, rank3]..]> 610 // nodeIdx2IdxMin = <idx, idxMin> 611 // nodeIdx2IdxGlo = <idxMin, idxMin> 612 613 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeIdx2IdxMin; 614 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeIdx2IdxGlo; 615 CArray<size_t,1> nodeIdxMinList(nbEdges*nvertex); 616 617 CClientClientDHTSizet dhtNodeHash(nodeHash2Idx, comm); 618 dhtNodeHash.computeIndexInfoMapping(nodeHashList); 619 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeHash2Info = dhtNodeHash.getInfoIndexMap(); 620 size_t iIdxMin = 0; 621 622 for (CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = nodeHash2Info.begin(); it != nodeHash2Info.end(); ++it) 623 { 624 size_t idx = (it->second)[0]; 625 size_t idxMin = (it->second)[0]; 626 for (int i = 2; i < (it->second).size();) 627 { 628 if (mpiRank == (it->second)[i+1]) 629 { 630 idx = (it->second)[i]; 631 } 632 if ((it->second)[i] < idxMin) 633 { 634 idxMin = (it->second)[i]; 635 (it->second)[i] = (it->second)[i-2]; 636 } 637 i += 2; 638 } 639 (it->second)[0] = idxMin; 640 if (nodeIdx2IdxMin.count(idx) == 0) 641 { 642 nodeIdx2IdxMin[idx].push_back(idxMin); 643 if (idx == idxMin) 644 nodeIdx2IdxGlo[idxMin].push_back(idxMin); 645 nodeIdxMinList(iIdxMin) = idxMin; 646 ++iIdxMin; 647 } 648 } 649 nodeIdxMinList.resizeAndPreserve(iIdxMin); 650 CDHTAutoIndexing dhtNodeIdxGlo = CDHTAutoIndexing(nodeIdx2IdxGlo, comm); 651 CClientClientDHTSizet dhtNodeIdx(nodeIdx2IdxGlo, comm); 652 dhtNodeIdx.computeIndexInfoMapping(nodeIdxMinList); 653 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeIdxMin2IdxGlo = dhtNodeIdx.getInfoIndexMap(); 654 // nodeIdx2IdxGlo holds global indexes only for nodes owned by a process 655 // nodeIdxMin2IdxGlo holds global indexes for all nodes generated by a process 656 657 // (2.3) Saving variables: node_lon, node_lat, edge_nodes 658 // Creating map nodeHash2IdxGlo <hash, idxGlo> 659 // Creating map edgeHash2IdxGlo <hash, idxGlo> 660 nbNodesGlo = dhtNodeIdxGlo.getNbIndexesGlobal(); 661 node_count = dhtNodeIdxGlo.getIndexCount(); 662 node_start = dhtNodeIdxGlo.getIndexStart(); 663 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeHash2IdxGlo; 664 node_lon.resize(node_count); 665 node_lat.resize(node_count); 666 vector <size_t> edgeNodes; 667 size_t idxGlo = 0; 668 669 for (int ne = 0; ne < nbEdges; ++ne) 670 { 671 for (int nv = 0; nv < nvertex; ++nv) 672 { 673 hashValues = CMesh::createHashes(bounds_lon(nv, ne), bounds_lat(nv, ne)); 674 size_t myIdx = generateNodeIndex(hashValues, mpiRank); 675 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = nodeIdx2IdxMin.find(myIdx); 676 size_t ownerIdx = (itIdx->second)[0]; 677 678 if (myIdx == ownerIdx) 679 { 680 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = nodeIdx2IdxGlo.find(myIdx); 681 idxGlo = (itIdxGlo->second)[0]; 682 // node_lon(idxGlo - node_start) = (bounds_lon(nv, ne) == 360.) ? (0.) : (bounds_lon(nv, ne)); 683 node_lon(idxGlo - node_start) = bounds_lon(nv, ne); 684 node_lat(idxGlo - node_start) = bounds_lat(nv, ne); 685 } 686 else 687 { 688 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = nodeIdxMin2IdxGlo.find(ownerIdx); 689 idxGlo = (itIdxGlo->second)[0]; 690 } 691 692 edge_nodes(nv,ne) = idxGlo; 693 for (int nh = 0; nh < 4; ++nh) 694 nodeHash2IdxGlo[hashValues[nh]].push_back(idxGlo); 695 edgeNodes.push_back(idxGlo); 696 } 697 edgeHash2IdxGlo[ hashPairOrdered(edgeNodes[0], edgeNodes[1]) ].push_back(nbEdges*mpiRank + ne); 698 edgeNodes.clear(); 699 } 700 pNodeGlobalIndex = new CClientClientDHTSizet (nodeHash2IdxGlo, comm); 701 } // !nodesAreWritten 702 703 pEdgeGlobalIndex = new CClientClientDHTSizet (edgeHash2IdxGlo, comm); 704 edgesAreWritten = true; 705 } //nvertex = 2 706 707 else 708 { 709 nbFaces = bounds_lon.shape()[1]; 710 face_lon.resize(nbFaces); 711 face_lat.resize(nbFaces); 712 face_lon = lonvalue; 713 face_lat = latvalue; 714 face_nodes.resize(nvertex, nbFaces); 715 face_edges.resize(nvertex, nbFaces); 716 717 // Case (1): edges have been previously generated 718 if (edgesAreWritten) 719 { 720 // (1.1) Recuperating node global indexing and saving face_nodes 721 vector<size_t> hashValues(4); 722 CArray<size_t,1> nodeHashList(nbFaces*nvertex*4); 723 for (int nf = 0; nf < nbFaces; ++nf) 724 { 725 for (int nv = 0; nv < nvertex; ++nv) 726 { 727 hashValues = CMesh::createHashes(bounds_lon(nv, nf), bounds_lat(nv, nf)); 728 for (int nh = 0; nh < 4; ++nh) 729 nodeHashList((nf*nvertex + nv)*4 + nh) = hashValues[nh]; 730 } 731 } 732 pNodeGlobalIndex->computeIndexInfoMapping(nodeHashList); 733 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeHash2IdxGlo = pNodeGlobalIndex->getInfoIndexMap(); 734 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it1, it2; 735 CArray<size_t,1> edgeHashList(nbFaces*nvertex); 736 for (int nf = 0; nf < nbFaces; ++nf) 737 { 738 for (int nv1 = 0; nv1 < nvertex; ++nv1) 739 { 740 int nh1 = 0; 741 int nv2 = (nv1 < nvertex -1 ) ? (nv1 + 1) : (nv1 + 1 - nvertex); // cyclic rotation 742 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 743 while (it1 == nodeHash2IdxGlo.end()) 744 { 745 ++nh1; 746 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 747 } 748 int nh2 = 0; 749 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv2)*4 + nh2)); 750 while (it2 == nodeHash2IdxGlo.end()) 751 { 752 ++nh2; 753 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh2)); 754 } 755 face_nodes(nv1,nf) = it1->second[0]; 756 edgeHashList(nf*nvertex + nv1) = hashPairOrdered(it1->second[0], it2->second[0]); 757 758 } 759 } 760 761 // (1.2) Recuperating edge global indexing and saving face_edges 762 pEdgeGlobalIndex->computeIndexInfoMapping(edgeHashList); 763 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeHash2IdxGlo = pEdgeGlobalIndex->getInfoIndexMap(); 764 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itEdgeHash; 765 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeHash2Rank; 766 767 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdxGlo2Face; 768 CArray<size_t,1> edgeIdxGloList(nbFaces*nvertex); 769 size_t iIdx = 0; 770 771 for (int nf = 0; nf < nbFaces; ++nf) 772 { 773 for (int nv1 = 0; nv1 < nvertex; ++nv1) 774 { 775 int nh1 = 0; 776 int nv2 = (nv1 < nvertex -1 ) ? (nv1 + 1) : (nv1 + 1 - nvertex); // cyclic rotation 777 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 778 while (it1 == nodeHash2IdxGlo.end()) 779 { 780 ++nh1; 781 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 782 } 783 int nh2 = 0; 784 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv2)*4 + nh2)); 785 while (it2 == nodeHash2IdxGlo.end()) 786 { 787 ++nh2; 788 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh2)); 789 } 790 size_t faceIdxGlo = mpiRank * nbFaces + nf; 791 size_t edgeHash = hashPairOrdered(it1->second[0], it2->second[0]); 792 itEdgeHash = edgeHash2IdxGlo.find(edgeHash); 793 size_t edgeIdxGlo = itEdgeHash->second[0]; 794 face_edges(nv1,nf) = edgeIdxGlo; 795 if (edgeIdxGlo2Face.count(edgeIdxGlo) == 0) 796 { 797 edgeIdxGloList(iIdx) = edgeIdxGlo; 798 ++iIdx; 799 } 800 edgeIdxGlo2Face[edgeIdxGlo].push_back(faceIdxGlo); 801 edgeHash2Rank[edgeHash].push_back(itEdgeHash->first); 802 edgeHash2Rank[edgeHash].push_back(mpiRank); 803 } 804 } 805 edgeIdxGloList.resizeAndPreserve(iIdx); 806 807 // (1.3) Saving remaining variables edge_faces and face_faces 808 809 // Establishing edge ownership 810 // The ownership criterion: priority of the process with smaller rank 811 CClientClientDHTSizet dhtEdgeHash (edgeHash2Rank, comm); 812 dhtEdgeHash.computeIndexInfoMapping(edgeHashList); 813 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeHash2Info = dhtEdgeHash.getInfoIndexMap(); 814 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeHashMin2IdxGlo; // map is needed purely for counting 815 816 // edgeHash2Info = <edgeHash, <idxGlo, rank1, idxGlo, rank2>> 817 // edgeHashMin2IdxGlo edgeHash2Info = <edgeHashMin, idxGlo> 818 for (CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = edgeHash2Info.begin(); it != edgeHash2Info.end(); ++it) 819 { 820 vector <size_t> edgeInfo = it->second; 821 if (edgeInfo.size() == 4) // two processes generate the same edge 822 if (edgeInfo[1] > edgeInfo[3]) 823 edgeInfo[1] = edgeInfo[3]; 824 if (edgeInfo[1] == mpiRank) 825 edgeHashMin2IdxGlo[it->first].push_back(edgeInfo[0]); 826 } 827 828 CDHTAutoIndexing dhtEdgeIdxGlo = CDHTAutoIndexing(edgeHashMin2IdxGlo, comm); 829 edge_count = dhtEdgeIdxGlo.getIndexCount(); 830 edge_start = dhtEdgeIdxGlo.getIndexStart(); 831 832 edge_faces.resize(2, edge_count); 833 face_faces.resize(nvertex, nbFaces); 834 835 CClientClientDHTSizet dhtEdge2Face (edgeIdxGlo2Face, comm); 836 dhtEdge2Face.computeIndexInfoMapping(edgeIdxGloList); 837 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeIdxGlo2FaceIdx = dhtEdge2Face.getInfoIndexMap(); 838 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itFace1, itFace2; 839 840 for (int nf = 0; nf < nbFaces; ++nf) 841 { 842 for (int nv1 = 0; nv1 < nvertex; ++nv1) 843 { 844 int nh1 = 0; 845 int nv2 = (nv1 < nvertex -1 ) ? (nv1 + 1) : (nv1 + 1 - nvertex); // cyclic rotation 846 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 847 while (it1 == nodeHash2IdxGlo.end()) 848 { 849 ++nh1; 850 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 851 } 852 int nh2 = 0; 853 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv2)*4 + nh2)); 854 while (it2 == nodeHash2IdxGlo.end()) 855 { 856 ++nh2; 857 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh2)); 858 } 859 size_t faceIdxGlo = mpiRank * nbFaces + nf; 860 size_t edgeHash = hashPairOrdered(it1->second[0], it2->second[0]); 861 itEdgeHash = edgeHash2Info.find(edgeHash); 862 size_t edgeOwnerRank = itEdgeHash->second[1]; 863 int edgeIdxGlo = itEdgeHash->second[0]; 864 865 if (mpiRank == edgeOwnerRank) 866 { 867 itFace1 = edgeIdxGlo2FaceIdx.find(edgeIdxGlo); 868 int face1 = itFace1->second[0]; 869 if (itFace1->second.size() == 1) 870 { 871 edge_faces(0, edgeIdxGlo - edge_start) = face1; 872 edge_faces(1, edgeIdxGlo - edge_start) = -999; 873 face_faces(nv1, nf) = -1; 874 } 875 else 876 { 877 int face2 = itFace1->second[1]; 878 edge_faces(0, edgeIdxGlo - edge_start) = face1; 879 edge_faces(1, edgeIdxGlo - edge_start) = face2; 880 face_faces(nv1, nf) = (faceIdxGlo == face1 ? face2 : face1); 881 } 882 } 883 else 884 { 885 itFace1 = edgeIdxGlo2FaceIdx.find(edgeIdxGlo); 886 int face1 = itFace1->second[0]; 887 int face2 = itFace1->second[1]; 888 face_faces(nv1, nf) = (faceIdxGlo == face1 ? face2 : face1); 889 } 890 } 891 } 892 } // edgesAreWritten 893 894 // Case (2): nodes have been previously generated 895 else if (nodesAreWritten) 896 { 897 // (2.1) Generating nodeHashList 898 vector<size_t> hashValues(4); 899 CArray<size_t,1> nodeHashList(nbFaces*nvertex*4); 900 for (int nf = 0; nf < nbFaces; ++nf) 901 { 902 for (int nv = 0; nv < nvertex; ++nv) 903 { 904 hashValues = CMesh::createHashes(bounds_lon(nv, nf), bounds_lat(nv, nf)); 905 for (int nh = 0; nh < 4; ++nh) 906 nodeHashList((nf*nvertex + nv)*4 + nh) = hashValues[nh]; 907 } 908 } 909 910 // (2.2) Recuperating node global indexing and saving face_nodes 911 // Generating edgeHash2Info = <hash, <idx, rank>> and edgeHashList 912 pNodeGlobalIndex->computeIndexInfoMapping(nodeHashList); 913 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeHash2IdxGlo = pNodeGlobalIndex->getInfoIndexMap(); 914 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeHash2Idx; 915 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it1, it2; 916 CArray<size_t,1> edgeHashList(nbFaces*nvertex); 917 for (int nf = 0; nf < nbFaces; ++nf) 918 { 919 for (int nv1 = 0; nv1 < nvertex; ++nv1) 920 { 921 int nh1 = 0; 922 int nv2 = (nv1 < nvertex -1 ) ? (nv1 + 1) : (nv1 + 1 - nvertex); // cyclic rotation 923 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 924 while (it1 == nodeHash2IdxGlo.end()) 925 { 926 ++nh1; 927 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 928 } 929 int nh2 = 0; 930 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv2)*4 + nh2)); 931 while (it2 == nodeHash2IdxGlo.end()) 932 { 933 ++nh2; 934 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh2)); 935 } 936 face_nodes(nv1,nf) = it1->second[0]; 937 size_t edgeHash = hashPairOrdered(it1->second[0], it2->second[0]); 938 edgeHash2Idx[edgeHash].push_back(generateEdgeIndex(it1->second[0], it2->second[0], mpiRank)); 939 edgeHash2Idx[edgeHash].push_back(mpiRank); 940 edgeHashList(nf*nvertex + nv1) = edgeHash; 941 } 942 } 943 944 // (2.2) Generating global edge indexes 945 // The ownership criterion: priority of the process holding the smaller index 946 // Maps generated in this step are: 947 // edgeHash2Info = <hash, [[idx1, rank1], [idx2, rank2], [idx3, rank3]..]> 948 // edgeIdx2IdxMin = = <idx, idxMin> 949 // edgeIdx2IdxGlo = <idxMin, idxGlo> 950 951 CClientClientDHTSizet dhtEdgeHash(edgeHash2Idx, comm); 952 dhtEdgeHash.computeIndexInfoMapping(edgeHashList); 953 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeHash2Info = dhtEdgeHash.getInfoIndexMap(); 954 955 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdx2IdxMin; 956 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdx2IdxGlo; 957 CArray<size_t,1> edgeIdxMinList(nbFaces*nvertex); 958 size_t iIdxMin = 0; 959 960 for (CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = edgeHash2Info.begin(); it != edgeHash2Info.end(); ++it) 961 { 962 size_t idxMin = (it->second)[0]; 963 size_t idx = (it->second)[0]; 964 for (int i = 2; i < (it->second).size();) 965 { 966 if (mpiRank == (it->second)[i+1]) 967 { 968 idx = (it->second)[i]; 969 } 970 if ((it->second)[i] < idxMin) 971 { 972 idxMin = (it->second)[i]; 973 (it->second)[i] = (it->second)[i-2]; 974 } 975 i += 2; 976 } 977 (it->second)[0] = idxMin; 978 if (edgeIdx2IdxMin.count(idx) == 0) 979 { 980 edgeIdx2IdxMin[idx].push_back(idxMin); 981 if (idx == idxMin) 982 edgeIdx2IdxGlo[idxMin].push_back(idxMin); 983 edgeIdxMinList(iIdxMin) = idxMin; 984 ++iIdxMin; 985 } 986 } 987 edgeIdxMinList.resizeAndPreserve(iIdxMin); 988 CDHTAutoIndexing dhtEdgeIdxGlo = CDHTAutoIndexing(edgeIdx2IdxGlo, comm); 989 CClientClientDHTSizet dhtEdgeIdx(edgeIdx2IdxGlo, comm); 990 dhtEdgeIdx.computeIndexInfoMapping(edgeIdxMinList); 991 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeIdxMin2IdxGlo = dhtEdgeIdx.getInfoIndexMap(); 992 // edgeIdx2IdxGlo holds global indexes only for edges owned by a process 993 // edgeIdxMin2IdxGlo holds global indexes for all edges generated by a process 994 995 // (2.3) Saving variables: edge_lon, edge_lat, face_edges 996 nbEdgesGlo = dhtEdgeIdxGlo.getNbIndexesGlobal(); 997 edge_count = dhtEdgeIdxGlo.getIndexCount(); 998 edge_start = dhtEdgeIdxGlo.getIndexStart(); 999 edge_lon.resize(edge_count); 1000 edge_lat.resize(edge_count); 1001 edge_nodes.resize(2, edge_count); 1002 face_edges.resize(nvertex, nbFaces); 1003 1004 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdxGlo2Face; 1005 CArray<size_t,1> edgeIdxGloList(nbFaces*nvertex); 1006 size_t iIdx = 0; 1007 1008 for (int nf = 0; nf < nbFaces; ++nf) 1009 { 1010 for (int nv1 = 0; nv1 < nvertex; ++nv1) 1011 { 1012 // Getting global indexes of edge's nodes 1013 int nh1 = 0; 1014 int nv2 = (nv1 < nvertex -1 ) ? (nv1 + 1) : (nv1 + 1 - nvertex); // cyclic rotation 1015 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 1016 while (it1 == nodeHash2IdxGlo.end()) 1017 { 1018 ++nh1; 1019 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 1020 } 1021 int nh2 = 0; 1022 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv2)*4 + nh2)); 1023 while (it2 == nodeHash2IdxGlo.end()) 1024 { 1025 ++nh2; 1026 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh2)); 1027 } 1028 // Getting edge global index 1029 size_t nodeIdxGlo1 = it1->second[0]; 1030 size_t nodeIdxGlo2 = it2->second[0]; 1031 size_t myIdx = generateEdgeIndex(nodeIdxGlo1, nodeIdxGlo2, mpiRank); 1032 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = edgeIdx2IdxMin.find(myIdx); 1033 size_t ownerIdx = (itIdx->second)[0]; 1034 int edgeIdxGlo = 0; 1035 size_t faceIdxGlo = mpiRank * nbFaces + nf; 1036 1037 if (myIdx == ownerIdx) 1038 { 1039 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdx2IdxGlo.find(myIdx); 1040 edgeIdxGlo = (itIdxGlo->second)[0]; 1041 edge_lon(edgeIdxGlo - edge_start) = ( abs( bounds_lon(nv1, nf) - bounds_lon(nv2, nf)) < 180.) ? 1042 (( bounds_lon(nv1, nf) + bounds_lon(nv2, nf)) * 0.5) : 1043 (( bounds_lon(nv1, nf) + bounds_lon(nv2, nf)) * 0.5 -180.); 1044 edge_lat(edgeIdxGlo - edge_start) = ( bounds_lat(nv1, nf) + bounds_lat(nv2, nf) ) * 0.5; 1045 edge_nodes(0, edgeIdxGlo - edge_start) = nodeIdxGlo1; 1046 edge_nodes(1, edgeIdxGlo - edge_start) = nodeIdxGlo2; 1047 } 1048 else 1049 { 1050 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdxMin2IdxGlo.find(ownerIdx); 1051 edgeIdxGlo = (itIdxGlo->second)[0]; 1052 } 1053 face_edges(nv1,nf) = edgeIdxGlo; 1054 if (edgeIdxGlo2Face.count(edgeIdxGlo) == 0) 1055 { 1056 edgeIdxGloList(iIdx) = edgeIdxGlo; 1057 ++iIdx; 1058 } 1059 edgeIdxGlo2Face[edgeIdxGlo].push_back(faceIdxGlo); 1060 } 1061 } 1062 edgeIdxGloList.resizeAndPreserve(iIdx); 1063 1064 // (2.4) Saving remaining variables edge_faces and face_faces 1065 edge_faces.resize(2, edge_count); 1066 face_faces.resize(nvertex, nbFaces); 1067 1068 CClientClientDHTSizet dhtEdge2Face (edgeIdxGlo2Face, comm); 1069 dhtEdge2Face.computeIndexInfoMapping(edgeIdxGloList); 1070 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeIdxGlo2FaceIdx = dhtEdge2Face.getInfoIndexMap(); 1071 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itNodeIdxGlo1, itNodeIdxGlo2; 1072 1073 for (int nf = 0; nf < nbFaces; ++nf) 1074 { 1075 for (int nv1 = 0; nv1 < nvertex; ++nv1) 1076 { 1077 // Getting global indexes of edge's nodes 1078 int nh1 = 0; 1079 int nv2 = (nv1 < nvertex -1 ) ? (nv1 + 1) : (nv1 + 1 - nvertex); // cyclic rotation 1080 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 1081 while (it1 == nodeHash2IdxGlo.end()) 1082 { 1083 ++nh1; 1084 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 1085 } 1086 int nh2 = 0; 1087 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv2)*4 + nh2)); 1088 while (it2 == nodeHash2IdxGlo.end()) 1089 { 1090 ++nh2; 1091 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh2)); 1092 } 1093 size_t nodeIdxGlo1 = it1->second[0]; 1094 size_t nodeIdxGlo2 = it2->second[0]; 1095 1096 size_t myIdx = generateEdgeIndex(nodeIdxGlo1, nodeIdxGlo2, mpiRank); 1097 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = edgeIdx2IdxMin.find(myIdx); 1098 size_t ownerIdx = (itIdx->second)[0]; 1099 size_t faceIdxGlo = mpiRank * nbFaces + nf; 1100 1101 if (myIdx == ownerIdx) 1102 { 1103 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdx2IdxGlo.find(myIdx); 1104 int edgeIdxGlo = (itIdxGlo->second)[0]; 1105 it1 = edgeIdxGlo2FaceIdx.find(edgeIdxGlo); 1106 int face1 = it1->second[0]; 1107 if (it1->second.size() == 1) 1108 { 1109 edge_faces(0, edgeIdxGlo - edge_start) = face1; 1110 edge_faces(1, edgeIdxGlo - edge_start) = -999; 1111 face_faces(nv1, nf) = -1; 1112 } 1113 else 1114 { 1115 int face2 = it1->second[1]; 1116 edge_faces(0, edgeIdxGlo - edge_start) = face1; 1117 edge_faces(1, edgeIdxGlo - edge_start) = face2; 1118 face_faces(nv1, nf) = (faceIdxGlo == face1 ? face2 : face1); 1119 } 1120 } 1121 else 1122 { 1123 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdxMin2IdxGlo.find(ownerIdx); 1124 size_t edgeIdxGlo = (itIdxGlo->second)[0]; 1125 it1 = edgeIdxGlo2FaceIdx.find(edgeIdxGlo); 1126 int face1 = it1->second[0]; 1127 int face2 = it1->second[1]; 1128 face_faces(nv1, nf) = (faceIdxGlo == face1 ? face2 : face1); 1129 } 1130 } 1131 } 1132 } // nodesAreWritten 1133 1134 // Case (3): Neither nodes nor edges have been previously generated 1135 else 1136 { 1137 // (3.1) Creating a list of hashes for each node and a map nodeHash2Idx <hash, <idx,rank> > 1138 vector<size_t> hashValues(4); 1139 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeHash2Idx; 1140 CArray<size_t,1> nodeHashList(nbFaces*nvertex*4); 1141 size_t iHash = 0; 1142 for (int nf = 0; nf < nbFaces; ++nf) 1143 { 1144 for (int nv = 0; nv < nvertex; ++nv) 1145 { 1146 hashValues = CMesh::createHashes(bounds_lon(nv, nf), bounds_lat(nv, nf)); 1147 size_t nodeIndex = generateNodeIndex(hashValues, mpiRank); 1148 for (int nh = 0; nh < 4; ++nh) 1149 { 1150 if (nodeHash2Idx.count(hashValues[nh])==0) 1151 { 1152 nodeHash2Idx[hashValues[nh]].push_back(nodeIndex); 1153 nodeHash2Idx[hashValues[nh]].push_back(mpiRank); 1154 nodeHashList(iHash) = hashValues[nh]; 1155 ++iHash; 1156 } 1157 } 1158 } 1159 } 1160 nodeHashList.resizeAndPreserve(iHash); 1161 1162 // (3.2) Generating global node indexes 1163 // The ownership criterion: priority of the process holding the smaller index 1164 // Maps generated in this step are: 1165 // nodeHash2Info = <hash, [[idxMin, rankMin], [idx1, rank1], [idx3, rank3]..]> 1166 // nodeIdx2IdxMin = = <idx, idxMin> 1167 // nodeIdx2IdxGlo = <idxMin, idxGlo> 1168 1169 CClientClientDHTSizet dhtNodeHash(nodeHash2Idx, comm); 1170 dhtNodeHash.computeIndexInfoMapping(nodeHashList); 1171 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeHash2Info = dhtNodeHash.getInfoIndexMap(); 1172 1173 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeIdx2IdxMin; 1174 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeIdx2IdxGlo; 1175 CArray<size_t,1> nodeIdxMinList(nbFaces*nvertex*4); 1176 size_t iIdxMin = 0; 1177 1178 for (CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = nodeHash2Info.begin(); it != nodeHash2Info.end(); ++it) 1179 { 1180 size_t idxMin = (it->second)[0]; 1181 size_t idx = (it->second)[0]; 1182 for (int i = 2; i < (it->second).size();) 1183 { 1184 if (mpiRank == (it->second)[i+1]) 1185 { 1186 idx = (it->second)[i]; 1187 } 1188 if ((it->second)[i] < idxMin) 1189 { 1190 idxMin = (it->second)[i]; 1191 (it->second)[i] = (it->second)[i-2]; 1192 } 1193 i += 2; 1194 } 1195 (it->second)[0] = idxMin; 1196 if (nodeIdx2IdxMin.count(idx) == 0) 1197 { 1198 nodeIdx2IdxMin[idx].push_back(idxMin); 1199 if (idx == idxMin) 1200 nodeIdx2IdxGlo[idxMin].push_back(idxMin); 1201 nodeIdxMinList(iIdxMin) = idxMin; 1202 ++iIdxMin; 1203 } 1204 } 1205 1206 nodeIdxMinList.resizeAndPreserve(iIdxMin); 1207 CDHTAutoIndexing dhtNodeIdxGlo = CDHTAutoIndexing(nodeIdx2IdxGlo, comm); 1208 CClientClientDHTSizet dhtNodeIdx(nodeIdx2IdxGlo, comm); 1209 dhtNodeIdx.computeIndexInfoMapping(nodeIdxMinList); 1210 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeIdxMin2IdxGlo = dhtNodeIdx.getInfoIndexMap(); 1211 1212 // (3.3) Saving node data: node_lon, node_lat, and face_nodes 1213 // Generating edgeHash2Info = <hash, <idx, rank>> and edgeHashList 1214 nbNodesGlo = dhtNodeIdxGlo.getNbIndexesGlobal(); 1215 node_count = dhtNodeIdxGlo.getIndexCount(); 1216 node_start = dhtNodeIdxGlo.getIndexStart(); 1217 node_lon.resize(node_count); 1218 node_lat.resize(node_count); 1219 size_t nodeIdxGlo1 = 0; 1220 size_t nodeIdxGlo2 = 0; 1221 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeHash2Idx; 1222 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itNodeIdxGlo1, itNodeIdxGlo2; 1223 CArray<size_t,1> edgeHashList(nbFaces*nvertex); 1224 1225 for (int nf = 0; nf < nbFaces; ++nf) 1226 { 1227 for (int nv1 = 0; nv1 < nvertex; ++nv1) 1228 { 1229 int nv2 = (nv1 < nvertex -1 ) ? (nv1 + 1) : (nv1 + 1 - nvertex); // cyclic rotation 1230 vector<size_t> hashValues1 = CMesh::createHashes(bounds_lon(nv1, nf), bounds_lat(nv1, nf)); 1231 vector<size_t> hashValues2 = CMesh::createHashes(bounds_lon(nv2, nf), bounds_lat(nv2, nf)); 1232 size_t myNodeIdx1 = generateNodeIndex(hashValues1, mpiRank); 1233 size_t myNodeIdx2 = generateNodeIndex(hashValues2, mpiRank); 1234 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itNodeIdx1 = nodeIdx2IdxMin.find(myNodeIdx1); 1235 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itNodeIdx2 = nodeIdx2IdxMin.find(myNodeIdx2); 1236 size_t ownerNodeIdx = (itNodeIdx1->second)[0]; 1237 1238 if (myNodeIdx1 == ownerNodeIdx) 1239 { 1240 itNodeIdxGlo1 = nodeIdx2IdxGlo.find(myNodeIdx1); 1241 nodeIdxGlo1 = (itNodeIdxGlo1->second)[0]; 1242 node_lon(nodeIdxGlo1 - node_start) = bounds_lon(nv1, nf); 1243 node_lat(nodeIdxGlo1 - node_start) = bounds_lat(nv1, nf); 1244 } 1245 else 1246 { 1247 itNodeIdxGlo1 = nodeIdxMin2IdxGlo.find(ownerNodeIdx); 1248 nodeIdxGlo1 = (itNodeIdxGlo1->second)[0]; 1249 } 1250 itNodeIdxGlo2 = nodeIdxMin2IdxGlo.find((itNodeIdx2->second)[0]); 1251 nodeIdxGlo2 = (itNodeIdxGlo2->second)[0]; 1252 size_t edgeHash = hashPairOrdered(nodeIdxGlo1, nodeIdxGlo2); 1253 edgeHash2Idx[edgeHash].push_back(generateEdgeIndex(nodeIdxGlo1, nodeIdxGlo2, mpiRank)); 1254 edgeHash2Idx[edgeHash].push_back(mpiRank); 1255 edgeHashList(nf*nvertex + nv1) = edgeHash; 1256 face_nodes(nv1,nf) = nodeIdxGlo1; 1257 } 1258 } 1259 1260 // (3.4) Generating global edge indexes 1261 // Maps generated in this step are: 1262 // edgeIdx2IdxMin = = <idx, idxMin> 1263 // edgeIdx2IdxGlo = <idxMin, idxGlo> 1264 1265 CClientClientDHTSizet dhtEdgeHash(edgeHash2Idx, comm); 1266 dhtEdgeHash.computeIndexInfoMapping(edgeHashList); 1267 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeHash2Info = dhtEdgeHash.getInfoIndexMap(); 1268 // edgeHash2Info = <hash, [[idx1, rank1], [idx2, rank2], [idx3, rank3]..]> 1269 1270 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdx2IdxMin; 1271 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdx2IdxGlo; 1272 CArray<size_t,1> edgeIdxMinList(nbFaces*nvertex); 1273 iIdxMin = 0; 1274 1275 for (CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = edgeHash2Info.begin(); it != edgeHash2Info.end(); ++it) 1276 { 1277 size_t idxMin = (it->second)[0]; 1278 size_t idx = (it->second)[0]; 1279 1280 for (int i = 2; i < (it->second).size();) 1281 { 1282 if (mpiRank == (it->second)[i+1]) 1283 { 1284 idx = (it->second)[i]; 1285 } 1286 if ((it->second)[i] < idxMin) 1287 { 1288 idxMin = (it->second)[i]; 1289 (it->second)[i] = (it->second)[i-2]; 1290 } 1291 i += 2; 1292 } 1293 (it->second)[0] = idxMin; 1294 if (edgeIdx2IdxMin.count(idx) == 0) 1295 { 1296 edgeIdx2IdxMin[idx].push_back(idxMin); 1297 if (idx == idxMin) 1298 edgeIdx2IdxGlo[idxMin].push_back(idxMin); 1299 edgeIdxMinList(iIdxMin) = idxMin; 1300 ++iIdxMin; 1301 } 1302 } 1303 edgeIdxMinList.resizeAndPreserve(iIdxMin); 1304 CDHTAutoIndexing dhtEdgeIdxGlo = CDHTAutoIndexing(edgeIdx2IdxGlo, comm); 1305 CClientClientDHTSizet dhtEdgeIdx(edgeIdx2IdxGlo, comm); 1306 dhtEdgeIdx.computeIndexInfoMapping(edgeIdxMinList); 1307 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeIdxMin2IdxGlo = dhtEdgeIdx.getInfoIndexMap(); 1308 1309 // (3.5) Saving variables: edge_lon, edge_lat, face_edges 1310 // Creating map edgeIdxGlo2Face <idxGlo, face> 1311 1312 nbEdgesGlo = dhtEdgeIdxGlo.getNbIndexesGlobal(); 1313 edge_count = dhtEdgeIdxGlo.getIndexCount(); 1314 edge_start = dhtEdgeIdxGlo.getIndexStart(); 1315 edge_lon.resize(edge_count); 1316 edge_lat.resize(edge_count); 1317 edge_nodes.resize(2, edge_count); 1318 face_edges.resize(nvertex, nbFaces); 1319 1320 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it1, it2; 1321 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdxGlo2Face; 1322 CArray<size_t,1> edgeIdxGloList(nbFaces*nvertex); 1323 size_t iIdx = 0; 1324 1325 for (int nf = 0; nf < nbFaces; ++nf) 1326 { 1327 for (int nv1 = 0; nv1 < nvertex; ++nv1) 1328 { 1329 // Getting global indexes of edge's nodes 1330 int nv2 = (nv1 < nvertex -1 ) ? (nv1 + 1) : (nv1 + 1 - nvertex); // cyclic rotation 1331 vector<size_t> hashValues1 = CMesh::createHashes(bounds_lon(nv1, nf), bounds_lat(nv1, nf)); 1332 vector<size_t> hashValues2 = CMesh::createHashes(bounds_lon(nv2, nf), bounds_lat(nv2, nf)); 1333 1334 size_t myNodeIdx1 = generateNodeIndex(hashValues1, mpiRank); 1335 size_t myNodeIdx2 = generateNodeIndex(hashValues2, mpiRank); 1336 it1 = nodeIdx2IdxMin.find(myNodeIdx1); 1337 it2 = nodeIdx2IdxMin.find(myNodeIdx2); 1338 itNodeIdxGlo1 = nodeIdxMin2IdxGlo.find((it1->second)[0]); 1339 itNodeIdxGlo2 = nodeIdxMin2IdxGlo.find((it2->second)[0]); 1340 size_t nodeIdxGlo1 = (itNodeIdxGlo1->second)[0]; 1341 size_t nodeIdxGlo2 = (itNodeIdxGlo2->second)[0]; 1342 1343 size_t myIdx = generateEdgeIndex(nodeIdxGlo1, nodeIdxGlo2, mpiRank); 1344 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = edgeIdx2IdxMin.find(myIdx); 1345 size_t ownerIdx = (itIdx->second)[0]; 1346 1347 int edgeIdxGlo = 0; 1348 size_t faceIdxGlo = mpiRank * nbFaces + nf; 1349 1350 if (myIdx == ownerIdx) 1351 { 1352 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdx2IdxGlo.find(myIdx); 1353 edgeIdxGlo = (itIdxGlo->second)[0]; 1354 edge_lon(edgeIdxGlo - edge_start) = ( abs( bounds_lon(nv1, nf) - bounds_lon(nv2, nf)) < 180.) ? 1355 (( bounds_lon(nv1, nf) + bounds_lon(nv2, nf)) * 0.5) : 1356 (( bounds_lon(nv1, nf) + bounds_lon(nv2, nf)) * 0.5 -180.); 1357 edge_lat(edgeIdxGlo-edge_start) = ( bounds_lat(nv1, nf) + bounds_lat(nv2, nf) ) * 0.5; 1358 edge_nodes(0, edgeIdxGlo - edge_start) = nodeIdxGlo1; 1359 edge_nodes(1, edgeIdxGlo - edge_start) = nodeIdxGlo2; 1360 } 1361 else 1362 { 1363 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdxMin2IdxGlo.find(ownerIdx); 1364 edgeIdxGlo = (itIdxGlo->second)[0]; 1365 } 1366 face_edges(nv1,nf) = edgeIdxGlo; 1367 if (edgeIdxGlo2Face.count(edgeIdxGlo) == 0) 1368 { 1369 edgeIdxGloList(iIdx) = edgeIdxGlo; 1370 ++iIdx; 1371 } 1372 edgeIdxGlo2Face[edgeIdxGlo].push_back(faceIdxGlo); 1373 } 1374 } 1375 edgeIdxGloList.resizeAndPreserve(iIdx); 1376 1377 // (3.6) Saving remaining variables edge_faces and face_faces 1378 edge_faces.resize(2, edge_count); 1379 face_faces.resize(nvertex, nbFaces); 1380 1381 CClientClientDHTSizet dhtEdge2Face (edgeIdxGlo2Face, comm); 1382 dhtEdge2Face.computeIndexInfoMapping(edgeIdxGloList); 1383 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeIdxGlo2FaceIdx = dhtEdge2Face.getInfoIndexMap(); 1384 1385 for (int nf = 0; nf < nbFaces; ++nf) 1386 { 1387 for (int nv1 = 0; nv1 < nvertex; ++nv1) 1388 { 1389 // Getting global indexes of edge's nodes 1390 int nv2 = (nv1 < nvertex -1 ) ? (nv1 + 1) : (nv1 + 1 - nvertex); // cyclic rotation 1391 vector<size_t> hashValues1 = CMesh::createHashes(bounds_lon(nv1, nf), bounds_lat(nv1, nf)); 1392 vector<size_t> hashValues2 = CMesh::createHashes(bounds_lon(nv2, nf), bounds_lat(nv2, nf)); 1393 1394 size_t myNodeIdx1 = generateNodeIndex(hashValues1, mpiRank); 1395 size_t myNodeIdx2 = generateNodeIndex(hashValues2, mpiRank); 1396 it1 = nodeIdx2IdxMin.find(myNodeIdx1); 1397 it2 = nodeIdx2IdxMin.find(myNodeIdx2); 1398 itNodeIdxGlo1 = nodeIdxMin2IdxGlo.find((it1->second)[0]); 1399 itNodeIdxGlo2 = nodeIdxMin2IdxGlo.find((it2->second)[0]); 1400 size_t nodeIdxGlo1 = (itNodeIdxGlo1->second)[0]; 1401 size_t nodeIdxGlo2 = (itNodeIdxGlo2->second)[0]; 1402 1403 size_t myIdx = generateEdgeIndex(nodeIdxGlo1, nodeIdxGlo2, mpiRank); 1404 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = edgeIdx2IdxMin.find(myIdx); 1405 size_t ownerIdx = (itIdx->second)[0]; 1406 size_t faceIdxGlo = mpiRank * nbFaces + nf; 1407 1408 if (myIdx == ownerIdx) 1409 { 1410 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdx2IdxGlo.find(myIdx); 1411 int edgeIdxGlo = (itIdxGlo->second)[0]; 1412 it1 = edgeIdxGlo2FaceIdx.find(edgeIdxGlo); 1413 int face1 = it1->second[0]; 1414 if (it1->second.size() == 1) 1415 { 1416 edge_faces(0, edgeIdxGlo - edge_start) = face1; 1417 edge_faces(1, edgeIdxGlo - edge_start) = -999; 1418 face_faces(nv1, nf) = -1; 1419 } 1420 else 1421 { 1422 size_t face2 = it1->second[1]; 1423 edge_faces(0, edgeIdxGlo - edge_start) = face1; 1424 edge_faces(1, edgeIdxGlo - edge_start) = face2; 1425 face_faces(nv1, nf) = (faceIdxGlo == face1 ? face2 : face1); 1426 } 1427 } 1428 else 1429 { 1430 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdxMin2IdxGlo.find(ownerIdx); 1431 size_t edgeIdxGlo = (itIdxGlo->second)[0]; 1432 it1 = edgeIdxGlo2FaceIdx.find(edgeIdxGlo); 1433 int face1 = it1->second[0]; 1434 int face2 = it1->second[1]; 1435 face_faces(nv1, nf) = (faceIdxGlo == face1 ? face2 : face1); 1436 } 1437 } 520 1438 } 521 1439 } 522 // Create nodes and edge_node connectivity 523 524 node_lon.resizeAndPreserve(nbEdges*nvertex); // Max possible number of nodes 525 node_lat.resizeAndPreserve(nbEdges*nvertex); 526 edge_nodes.resizeAndPreserve(nvertex, nbEdges); 527 528 // for (int ne = 0; ne < nbEdges; ++ne) 529 // { 530 // for (int nv = 0; nv < nvertex; ++nv) 531 // { 532 // if ( nodeIndex(bounds_lon(nv, ne), bounds_lat(nv ,ne)) == -1) 533 // { 534 // edge_nodes(nv,ne) = nbNodes ; 535 // node_lon(nbNodes) = bounds_lon(nv, ne); 536 // node_lat(nbNodes) = bounds_lat(nv, ne); 537 // ++nbNodes ; 538 // } 539 // else 540 // edge_nodes(nv,ne) = nodeIndex(bounds_lon(nv, ne), bounds_lat(nv ,ne)); 541 // } 542 // } 543 // node_lon.resizeAndPreserve(nbNodes); 544 // node_lat.resizeAndPreserve(nbNodes); 545 546 // Create edges 547 edge_lon.resizeAndPreserve(nbEdges); 548 edge_lat.resizeAndPreserve(nbEdges); 549 550 for (int ne = 0; ne < nbEdges; ++ne) 551 { 552 if (map_edges.find(make_ordered_pair (edge_nodes(0,ne), edge_nodes(1,ne))) == map_edges.end()) 553 { 554 map_edges[make_ordered_pair ( edge_nodes(0,ne), edge_nodes(1,ne) )] = ne ; 555 edge_lon(ne) = lonvalue(ne); 556 edge_lat(ne) = latvalue(ne); 557 } 558 } 559 edgesAreWritten = true; 560 } // nvertex = 2 561 else 562 { 563 nbFaces = bounds_lon.shape()[1]; 564 565 // Create nodes and face_node connectivity 566 node_lon.resizeAndPreserve(nbFaces*nvertex); // Max possible number of nodes 567 node_lat.resizeAndPreserve(nbFaces*nvertex); 568 face_nodes.resize(nvertex, nbFaces); 569 570 /*for (int nf = 0; nf < nbFaces; ++nf) 571 { 572 for (int nv = 0; nv < nvertex; ++nv) 573 { 574 if ( nodeIndex(bounds_lon(nv, nf), bounds_lat(nv ,nf)) == -1) 575 { 576 face_nodes(nv,nf) = nbNodes ; 577 node_lon(nbNodes) = bounds_lon(nv, nf); 578 node_lat(nbNodes) = bounds_lat(nv ,nf); 579 ++nbNodes ; 580 } 581 else 582 { 583 face_nodes(nv,nf) = nodeIndex(bounds_lon(nv, nf), bounds_lat(nv ,nf)); 584 } 585 } 586 } 587 node_lon.resizeAndPreserve(nbNodes); 588 node_lat.resizeAndPreserve(nbNodes);*/ 589 590 591 // Create edges and edge_nodes connectivity 592 // edge_lon.resizeAndPreserve(nbFaces*nvertex); // Max possible number of edges 593 // edge_lat.resizeAndPreserve(nbFaces*nvertex); 594 // edge_nodes.resizeAndPreserve(2, nbFaces*nvertex); 595 // for (int nf = 0; nf < nbFaces; ++nf) 596 // { 597 // for (int nv1 = 0; nv1 < nvertex; ++nv1) 598 // { 599 // int nv2 = (nv1 < nvertex -1 ) ? (nv1 + 1) : (nv1 + 1 - nvertex); // cyclic rotation 600 // if (map_edges.find(make_ordered_pair (face_nodes(nv1,nf), face_nodes(nv2,nf))) == map_edges.end()) 601 // { 602 // map_edges[make_ordered_pair (face_nodes(nv1,nf), face_nodes(nv2,nf))] = nbEdges ; 603 // edge_nodes(Range::all(),nbEdges) = face_nodes(nv1,nf), face_nodes(nv2,nf); 604 // edge_lon(nbEdges) = ( abs( node_lon(face_nodes(nv1,nf)) - node_lon(face_nodes(nv2,nf))) < 180.) ? 605 // (( node_lon(face_nodes(nv1,nf)) + node_lon(face_nodes(nv2,nf))) * 0.5) : 606 // (( node_lon(face_nodes(nv1,nf)) + node_lon(face_nodes(nv2,nf))) * 0.5 -180.);; 607 // edge_lat(nbEdges) = ( node_lat(face_nodes(nv1,nf)) + node_lat(face_nodes(nv2,nf)) ) * 0.5; 608 // ++nbEdges; 609 // } 610 // } 611 // } 612 // edge_nodes.resizeAndPreserve(2, nbEdges); 613 // edge_lon.resizeAndPreserve(nbEdges); 614 // edge_lat.resizeAndPreserve(nbEdges); 615 616 // Create faces 617 // face_lon.resize(nbFaces); 618 // face_lat.resize(nbFaces); 619 // face_lon = lonvalue; 620 // face_lat = latvalue; 621 // facesAreWritten = true; 622 1440 facesAreWritten = true; 623 1441 } // nvertex >= 3 624 1442 … … 626 1444 627 1445 } // namespace xios 628 629 // void CMesh::createMeshEpsilon(const MPI_Comm& comm, const CArray<double, 1>& lonvalue, const CArray<double, 1>& latvalue,630 // const CArray<double, 2>& bounds_lon, const CArray<double, 2>& bounds_lat)631 // {632 //633 // nvertex = (bounds_lon.numElements() == 0) ? 1 : bounds_lon.rows();634 //635 // if (nvertex == 1)636 // {637 // nbNodes = lonvalue.numElements();638 // node_lon.resizeAndPreserve(nbNodes);639 // node_lat.resizeAndPreserve(nbNodes);640 // for (int nn = 0; nn < nbNodes; ++nn)641 // {642 // if ( nodeIndex(lonvalue(nn), latvalue(nn)) == -1 )643 // {644 // node_lon(nn) = lonvalue(nn);645 // node_lat(nn) = latvalue(nn);646 // }647 // }648 //649 // nodesAreWritten = true;650 // }651 // else if (nvertex == 2)652 // {653 // nbEdges = bounds_lon.shape()[1];654 //655 // // Create nodes and edge_node connectivity656 // node_lon.resizeAndPreserve(nbEdges*nvertex); // Max possible number of nodes657 // node_lat.resizeAndPreserve(nbEdges*nvertex);658 // edge_nodes.resizeAndPreserve(nvertex, nbEdges);659 //660 // for (int ne = 0; ne < nbEdges; ++ne)661 // {662 // for (int nv = 0; nv < nvertex; ++nv)663 // {664 // if ( nodeIndex(bounds_lon(nv, ne), bounds_lat(nv ,ne)) == -1)665 // {666 // edge_nodes(nv,ne) = nbNodes ;667 // node_lon(nbNodes) = bounds_lon(nv, ne);668 // node_lat(nbNodes) = bounds_lat(nv, ne);669 // ++nbNodes ;670 // }671 // else672 // edge_nodes(nv,ne) = nodeIndex(bounds_lon(nv, ne), bounds_lat(nv ,ne));673 // }674 // }675 // node_lon.resizeAndPreserve(nbNodes);676 // node_lat.resizeAndPreserve(nbNodes);677 //678 // // Create edges679 // edge_lon.resizeAndPreserve(nbEdges);680 // edge_lat.resizeAndPreserve(nbEdges);681 //682 // for (int ne = 0; ne < nbEdges; ++ne)683 // {684 // if (map_edges.find(make_ordered_pair (edge_nodes(0,ne), edge_nodes(1,ne))) == map_edges.end())685 // {686 // map_edges[make_ordered_pair ( edge_nodes(0,ne), edge_nodes(1,ne) )] = ne ;687 // edge_lon(ne) = lonvalue(ne);688 // edge_lat(ne) = latvalue(ne);689 // }690 // }691 // edgesAreWritten = true;692 // } // nvertex = 2693 // else694 // {695 // nbFaces = bounds_lon.shape()[1];696 //697 // // Create nodes and face_node connectivity698 // node_lon.resizeAndPreserve(nbFaces*nvertex); // Max possible number of nodes699 // node_lat.resizeAndPreserve(nbFaces*nvertex);700 // face_nodes.resize(nvertex, nbFaces);701 //702 // for (int nf = 0; nf < nbFaces; ++nf)703 // {704 // for (int nv = 0; nv < nvertex; ++nv)705 // {706 // if ( nodeIndex(bounds_lon(nv, nf), bounds_lat(nv ,nf)) == -1)707 // {708 // face_nodes(nv,nf) = nbNodes ;709 // node_lon(nbNodes) = bounds_lon(nv, nf);710 // node_lat(nbNodes) = bounds_lat(nv ,nf);711 // ++nbNodes ;712 // }713 // else714 // {715 // face_nodes(nv,nf) = nodeIndex(bounds_lon(nv, nf), bounds_lat(nv ,nf));716 // }717 // }718 // }719 // node_lon.resizeAndPreserve(nbNodes);720 // node_lat.resizeAndPreserve(nbNodes);721 //722 // // Create edges and edge_nodes connectivity723 // edge_lon.resizeAndPreserve(nbFaces*nvertex); // Max possible number of edges724 // edge_lat.resizeAndPreserve(nbFaces*nvertex);725 // edge_nodes.resizeAndPreserve(2, nbFaces*nvertex);726 // for (int nf = 0; nf < nbFaces; ++nf)727 // {728 // for (int nv1 = 0; nv1 < nvertex; ++nv1)729 // {730 // int nv2 = (nv1 < nvertex -1 ) ? (nv1 + 1) : (nv1 + 1 - nvertex); // cyclic rotation731 // if (map_edges.find(make_ordered_pair (face_nodes(nv1,nf), face_nodes(nv2,nf))) == map_edges.end())732 // {733 // map_edges[make_ordered_pair (face_nodes(nv1,nf), face_nodes(nv2,nf))] = nbEdges ;734 // edge_nodes(Range::all(),nbEdges) = face_nodes(nv1,nf), face_nodes(nv2,nf);735 // edge_lon(nbEdges) = ( abs( node_lon(face_nodes(nv1,nf)) - node_lon(face_nodes(nv2,nf))) < 180.) ?736 // (( node_lon(face_nodes(nv1,nf)) + node_lon(face_nodes(nv2,nf))) * 0.5) :737 // (( node_lon(face_nodes(nv1,nf)) + node_lon(face_nodes(nv2,nf))) * 0.5 -180.);;738 // edge_lat(nbEdges) = ( node_lat(face_nodes(nv1,nf)) + node_lat(face_nodes(nv2,nf)) ) * 0.5;739 // ++nbEdges;740 // }741 // }742 // }743 // edge_nodes.resizeAndPreserve(2, nbEdges);744 // edge_lon.resizeAndPreserve(nbEdges);745 // edge_lat.resizeAndPreserve(nbEdges);746 //747 // // Create faces748 // face_lon.resize(nbFaces);749 // face_lat.resize(nbFaces);750 // face_lon = lonvalue;751 // face_lat = latvalue;752 // facesAreWritten = true;753 // } // nvertex >= 3754 //755 // } // createMeshEpsilon -
XIOS/trunk/src/node/mesh.hpp
r900 r924 9 9 10 10 #include "array_new.hpp" 11 #include "client_client_dht_template_impl.hpp"12 11 #include "dht_auto_indexing.hpp" 13 12 … … 32 31 ~CMesh(void); 33 32 34 int nbNodes; 35 int nbEdges; 36 int nbFaces; 37 int nvertex; 33 int nbNodesGlo; 34 int nbEdgesGlo; 35 36 int node_start; 37 int node_count; 38 int edge_start; 39 int edge_count; 38 40 39 41 bool nodesAreWritten; … … 56 58 57 59 void createMesh(const CArray<double, 1>&, const CArray<double, 1>&, 58 const CArray<double, 2>&, const CArray<double, 2>& );60 const CArray<double, 2>&, const CArray<double, 2>& ); 59 61 60 void createMeshEpsilon(const MPI_Comm&, const CArray<double, 1>&, const CArray<double, 1>&, 61 const CArray<double, 2>&, const CArray<double, 2>& ); 62 void createMeshEpsilon(const MPI_Comm&, 63 const CArray<double, 1>&, const CArray<double, 1>&, 64 const CArray<double, 2>&, const CArray<double, 2>& ); 62 65 63 static CMesh* getMesh(StdString );66 static CMesh* getMesh(StdString, int); 64 67 65 68 private: 66 69 70 int nbNodes; 71 int nbEdges; 72 int nbFaces; 73 67 74 static std::map <StdString, CMesh> meshList; 68 vector<size_t> createHashes (double, double); 75 static std::map <StdString, vector<int> > domainList; 76 CClientClientDHTSizet* pNodeGlobalIndex; // pointer to a map <nodeHash, nodeIdxGlo> 77 CClientClientDHTSizet* pEdgeGlobalIndex; // pointer to a map <edgeHash, edgeIdxGlo> 78 79 vector<size_t> createHashes (const double, const double); 69 80 70 81 size_t nodeIndex (double, double); // redundant in parallel version with epsilon precision
Note: See TracChangeset
for help on using the changeset viewer.