diff --git a/include/entity.h b/include/entity.h index 20d70b3deee341c1641304cf668e5ea44aacdf55..9779db4c210210e738def4c442aa4af60ffa60f1 100644 --- a/include/entity.h +++ b/include/entity.h @@ -56,7 +56,7 @@ class entity void populate_normals(entity_data_cpu&) const; public: - entity() = delete; + entity() {}// = delete; entity(const entity&) = delete; entity(entity&&) = default; entity& operator=(const entity&) = delete; diff --git a/include/gmsh_io.h b/include/gmsh_io.h index 885dcf09fb121c9877137622e075f4f64ed88eae..5d917b6f947b36801fa2a7e2a73237948595b7d7 100644 --- a/include/gmsh_io.h +++ b/include/gmsh_io.h @@ -36,7 +36,9 @@ enum class face_type : int NONE = 0, INTERFACE, BOUNDARY, +#ifdef USE_MPI INTERPROCESS_BOUNDARY +#endif }; struct boundary_descriptor @@ -84,6 +86,9 @@ class model /* Map from the partition number to the entities belonging to that partition */ std::map<int, std::vector<int>> partition_map; + /* Map from 3D entity tag to partition */ + std::map<int, int> partition_inverse_map; + std::vector<entity> entities; std::vector<boundary_descriptor> bnd_descriptors; element_connectivity<element_key> conn; @@ -92,13 +97,16 @@ class model std::map<size_t, entofs_pair> etag_to_entity_offset; void map_boundaries(void); - void import_gmsh_entities(void); + void import_gmsh_entities_rank0(void); void update_connectivity(const entity&, size_t); void populate_from_gmsh_rank0(void); #ifdef USE_MPI + bool is_interprocess_boundary(int); void populate_from_gmsh_rankN(void); + void import_gmsh_entities_rankN(void); + int my_partition(void) const; #endif void make_boundary_to_faces_map(void); diff --git a/include/gmsh_mpi.h b/include/gmsh_mpi.h index cce679e74e1cc14a1fda2b1baa44d064e3f14988..6f824d1bb1145d0b7eed2184a0fa35fd82f9d9d7 100644 --- a/include/gmsh_mpi.h +++ b/include/gmsh_mpi.h @@ -14,7 +14,7 @@ assert(__rank == 0); \ } #else - #define ASSERT_MPI_RANK_0 (void) 0 + #define ASSERT_MPI_RANK_0 ((void) 0) #endif template<typename T> diff --git a/src/gmsh_io.cpp b/src/gmsh_io.cpp index faf396d9b1f384c88759e6b49350c2eb0a6ef497..9e8142119024ca9c283a299b8c45a0ed488dc395 100644 --- a/src/gmsh_io.cpp +++ b/src/gmsh_io.cpp @@ -57,7 +57,9 @@ model::~model() void model::make_boundary_to_faces_map(void) { +#ifdef USE_MPI ASSERT_MPI_RANK_0; +#endif /* USE_MPI */ gvp_t gmsh_entities; @@ -105,7 +107,9 @@ model::make_boundary_to_faces_map(void) void model::make_partition_to_entities_map() { +#ifdef USE_MPI ASSERT_MPI_RANK_0; +#endif /* USE_MPI */ gvp_t gmsh_entities; @@ -127,6 +131,7 @@ model::make_partition_to_entities_map() assert(parts.size() == 1); gm::getPartitions(dim, tag, parts); partition_map[ parts[0] ].push_back(tag); + partition_inverse_map[tag] = parts[0]; } } @@ -137,7 +142,9 @@ model::make_partition_to_entities_map() void model::update_connectivity(const entity& e, size_t entity_index) { +#ifdef USE_MPI ASSERT_MPI_RANK_0; +#endif /* USE_MPI */ for (size_t iT = 0; iT < e.num_cells(); iT++) { @@ -151,9 +158,25 @@ model::update_connectivity(const entity& e, size_t entity_index) } } +#ifdef USE_MPI +int +model::my_partition(void) const +{ + /* Here we are assuming that GMSH enumerates mesh partitions + * sequentially and starting from 1. */ + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + return rank+1; +} +#endif /* USE_MPI */ + void -model::import_gmsh_entities(void) +model::import_gmsh_entities_rank0(void) { +#ifdef USE_MPI + ASSERT_MPI_RANK_0; +#endif /* USE_MPI */ + gvp_t gmsh_entities; gm::getEntities(gmsh_entities, DIMENSION(3)); @@ -189,6 +212,24 @@ model::import_gmsh_entities(void) e.sort_by_orientation(); +#ifdef USE_MPI + if (num_partitions > 1) + { + auto mp = my_partition(); + auto tag_partition = partition_inverse_map.at(tag); + bool entity_is_remote = ( tag_partition != mp ); + + if (entity_is_remote) + { + assert(tag_partition > 0); + int rank = tag_partition - 1; + e.mpi_send(rank, MPI_COMM_WORLD); + std::cout << "Sending entity " << tag << " to " << rank << std::endl; + continue; + } + } + std::cout << "Keeping entity " << tag << std::endl; +#endif /* USE_MPI */ for (size_t i = 0; i < e.num_cells(); i++) { const auto& pe = e.cell(i); @@ -211,12 +252,65 @@ model::import_gmsh_entities(void) entity_index++; } } + std::cout << dof_base << " " << flux_base << std::endl; +} + +#ifdef USE_MPI +void +model::import_gmsh_entities_rankN(void) +{ + int mp = my_partition(); + + size_t entity_index = 0; + size_t dof_base = 0; + size_t flux_base = 0; + size_t index_base = 0; + + for (auto& rtag : partition_map.at(mp)) + { + std::cout << "Receiving " << rtag << ", rank " << mp-1 << std::endl; + entity e; + e.mpi_recv(0, MPI_COMM_WORLD); + + for (size_t i = 0; i < e.num_cells(); i++) + { + const auto& pe = e.cell(i); + auto eitor = etag_to_entity_offset.find( pe.element_tag() ); + if ( eitor != etag_to_entity_offset.end() ) + throw std::logic_error("Duplicate tag"); + + etag_to_entity_offset[ pe.element_tag() ] = std::make_pair(entity_index, i); + } + + e.base(dof_base, flux_base, index_base); + e.number(entity_index); + dof_base += e.num_dofs(); + flux_base += e.num_fluxes(); + index_base += e.num_cells(); + + update_connectivity(e, entity_index); + + entities.push_back( std::move(e) ); + entity_index++; + } + + std::cout << dof_base << " " << flux_base << std::endl; } +bool +model::is_interprocess_boundary(int tag) +{ + return comm_map.at(tag).size() == 2; +} + +#endif /* USE_MPI */ + void model::map_boundaries(void) { +#ifdef USE_MPI ASSERT_MPI_RANK_0; +#endif /* USE_MPI */ /* Make a vector mapping element_key to entity tag */ using bfk_t = std::pair<element_key, int>; @@ -253,9 +347,18 @@ model::map_boundaries(void) boundary_descriptor bd; /* determine if it is an interface or a boundary */ if (conn.num_neighbours(fk) == 1) - bd.type = face_type::BOUNDARY; + { +#ifdef USE_MPI + if ( is_interprocess_boundary( (*itor).second ) ) + bd.type = face_type::INTERPROCESS_BOUNDARY; + else +#endif /* USE_MPI */ + bd.type = face_type::BOUNDARY; + } else + { bd.type = face_type::INTERFACE; + } /* and store the gmsh tag in the descriptor. */ bd.gmsh_entity = (*itor).second; @@ -277,7 +380,9 @@ model::map_boundaries(void) case face_type::NONE: normal++; break; case face_type::INTERFACE: interface++; break; case face_type::BOUNDARY: boundary++; break; +#ifdef USE_MPI case face_type::INTERPROCESS_BOUNDARY: ipc_boundary++; break; +#endif /* USE_MPI */ } } @@ -288,7 +393,9 @@ model::map_boundaries(void) void model::populate_from_gmsh_rank0() { +#ifdef USE_MPI ASSERT_MPI_RANK_0; +#endif /* USE_MPI */ gmm::setOrder( geometric_order ); make_boundary_to_faces_map(); @@ -321,7 +428,7 @@ model::populate_from_gmsh_rank0() #endif /* USE_MPI */ entities.clear(); - import_gmsh_entities(); + import_gmsh_entities_rank0(); map_boundaries(); /* This must happen after import_gmsh_entities(). */ } @@ -344,6 +451,10 @@ model::populate_from_gmsh_rankN() std::cout << v << " "; std::cout << std::endl; } + + entities.clear(); + import_gmsh_entities_rankN(); + map_boundaries(); } #endif /* USE_MPI */