diff --git a/include/gmsh_mpi.h b/include/gmsh_mpi.h index 28361d6b51c4326a765274a18ca07737c2886f2b..cce679e74e1cc14a1fda2b1baa44d064e3f14988 100644 --- a/include/gmsh_mpi.h +++ b/include/gmsh_mpi.h @@ -83,6 +83,22 @@ priv_MPI_Recv(std::vector<T>& vec, int src, MPI_Comm comm) MPI_Recv(vec.data(), vec.size()*sizeof(T), MPI_PACKED, src, 0, comm, &status); } +template<typename T> +void +priv_MPI_Send(T& elem, int dst, MPI_Comm comm) +{ + static_assert(std::is_trivially_copyable<T>::value, "Type must be trivially copyable"); + MPI_Send(&elem, sizeof(T), MPI_PACKED, dst, 0, comm); +} + +template<typename T> +void +priv_MPI_Recv(T& elem, int src, MPI_Comm comm) +{ + static_assert(std::is_trivially_copyable<T>::value, "Type must be trivially copyable"); + MPI_Status status; + MPI_Recv(&elem, sizeof(T), MPI_PACKED, src, 0, comm, &status); +} template<typename T> diff --git a/include/physical_element.h b/include/physical_element.h index b8dad8c262954a5d952dd056d8005ee04584b39a..87e798f54afeb3a7ad3fe511f7e3ff172572802a 100644 --- a/include/physical_element.h +++ b/include/physical_element.h @@ -5,6 +5,10 @@ #include "eigen.h" #include "types.h" +#ifdef USE_MPI +#include "gmsh_mpi.h" +#endif /* USE_MPI */ + /* This is a key for a basis function. Did this * class to protect the code from the GMSH api, * which is apparently changing */ @@ -72,6 +76,11 @@ public: point_3d barycenter(void) const; double measure(void) const; +#ifdef USE_MPI + void mpi_send(int dst, MPI_Comm comm); + void mpi_recv(int src, MPI_Comm comm); +#endif /* USE_MPI */ + /* This class is not intended to be constructed * by the user but by the appropriate factory */ friend class physical_elements_factory; diff --git a/src/physical_element.cpp b/src/physical_element.cpp index ed18d55a2339024ac093b105f4f0d7d2b549a77e..9c9dc3059ef821db5f028938f2a9ec8e9a933698 100644 --- a/src/physical_element.cpp +++ b/src/physical_element.cpp @@ -232,6 +232,76 @@ physical_elements_factory::get_elements() return ret; } +#ifdef USE_MPI +void +physical_element::mpi_send(int dst, MPI_Comm comm) +{ + MPI_Send(&m_original_position, 1, MPI_UNSIGNED_LONG_LONG, dst, 0, comm); + MPI_Send(&m_dimension, 1, MPI_INT, dst, 0, comm); + MPI_Send(&m_orientation, 1, MPI_INT, dst, 0, comm); + MPI_Send(&m_parent_entity_tag, 1, MPI_INT, dst, 0, comm); + MPI_Send(&m_gmsh_elemtype, 1, MPI_INT, dst, 0, comm); + MPI_Send(&m_element_tag, 1, MPI_UNSIGNED_LONG_LONG, dst, 0, comm); + priv_MPI_Send(m_node_tags, dst, comm); + priv_MPI_Send(m_determinants, dst, comm); + + std::vector<double> jacs; + jacs.resize( m_jacobians.size() * 9 ); + for (size_t i = 0; i < m_jacobians.size(); i++) + { + auto& M = m_jacobians[i]; + for (size_t mi = 0; mi < 3; mi++) + for (size_t mj = 0; mj < 3; mj++) + jacs[9*i + 3*mi + mj] = M(mi, mj); + } + priv_MPI_Send(jacs, dst, comm); + + priv_MPI_Send(m_phys_quadpoints, dst, comm); + priv_MPI_Send(m_barycenter, dst, comm); + MPI_Send(&m_measure, 1, MPI_DOUBLE, dst, 0, comm); + MPI_Send(&m_geometric_order, 1, MPI_INT, dst, 0, comm); + MPI_Send(&m_approximation_order, 1, MPI_INT, dst, 0, comm); + priv_MPI_Send(m_bf_keys, dst, comm); +} + +void +physical_element::mpi_recv(int src, MPI_Comm comm) +{ + MPI_Status status; + MPI_Recv(&m_original_position, 1, MPI_UNSIGNED_LONG_LONG, src, 0, comm, &status); + MPI_Recv(&m_dimension, 1, MPI_INT, src, 0, comm, &status); + MPI_Recv(&m_orientation, 1, MPI_INT, src, 0, comm, &status); + MPI_Recv(&m_parent_entity_tag, 1, MPI_INT, src, 0, comm, &status); + MPI_Recv(&m_gmsh_elemtype, 1, MPI_INT, src, 0, comm, &status); + MPI_Recv(&m_element_tag, 1, MPI_UNSIGNED_LONG_LONG, src, 0, comm, &status); + priv_MPI_Recv(m_node_tags, src, comm); + priv_MPI_Recv(m_determinants, src, comm); + + std::vector<double> jacs; + priv_MPI_Recv(jacs, src, comm); + m_jacobians.resize( jacs.size() / 9 ); + assert( m_jacobians.size() * 9 == jacs.size() ); + for (size_t i = 0; i < m_jacobians.size(); i++) + { + auto& M = m_jacobians[i]; + for (size_t mi = 0; mi < 3; mi++) + for (size_t mj = 0; mj < 3; mj++) + M(mi, mj) = jacs[9*i + 3*mi + mj]; + } + + priv_MPI_Recv(m_phys_quadpoints, src, comm); + priv_MPI_Recv(m_barycenter, src, comm); + MPI_Recv(&m_measure, 1, MPI_DOUBLE, src, 0, comm, &status); + MPI_Recv(&m_geometric_order, 1, MPI_INT, src, 0, comm, &status); + MPI_Recv(&m_approximation_order, 1, MPI_INT, src, 0, comm, &status); + priv_MPI_Recv(m_bf_keys, src, comm); +} +#endif /* USE_MPI */ + + + + + element_key::element_key() {}