From 9c1d99179f6e21b7f0e92f50eae1d333d3ed755f Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Tue, 19 Jun 2018 19:29:50 +0200 Subject: [PATCH] Added first version of mesh boundaries calculation for BC --- src/main.cpp | 14 +++- src/mesh/Connectivity2D.hpp | 5 ++ src/mesh/MeshBoundary.hpp | 124 ++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 src/mesh/MeshBoundary.hpp diff --git a/src/main.cpp b/src/main.cpp index 58166eda7..187eed116 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,6 +23,8 @@ #include <BoundaryConditionDescriptor.hpp> +#include <MeshBoundary.hpp> + #include <GmshReader.hpp> #include <CLI/CLI.hpp> @@ -239,12 +241,22 @@ int main(int argc, char *argv[]) std::vector<BoundaryConditionHandler> bc_list; { +#warning Should extract boundaries from mesh itself to avoid inconsistencies + std::map<RefId, MeshBoundary<MeshType::dimension>> ref_boundary; for (const auto& bc_descriptor : bc_descriptor_list) { switch (bc_descriptor->type()) { case BoundaryConditionDescriptor::Type::symmetry: { const SymmetryBoundaryConditionDescriptor& sym_bc_descriptor = dynamic_cast<const SymmetryBoundaryConditionDescriptor&>(*bc_descriptor); - std::cout << sym_bc_descriptor << '\n'; + for (size_t i_ref_face_list=0; i_ref_face_list<mesh.connectivity().numberOfRefFaceList(); + ++i_ref_face_list) { + const RefFaceList& ref_face_list = mesh.connectivity().refFaceList(i_ref_face_list); + const RefId& ref = ref_face_list.refId(); + if (ref == sym_bc_descriptor.boundaryDescriptor()) { + std::cout << "Found mesh boundary to impose " << sym_bc_descriptor << '\n'; + ref_boundary[ref] = MeshFlatBoundary<MeshType::dimension>(mesh, ref_face_list.faceList()); + } + } break; } default: { diff --git a/src/mesh/Connectivity2D.hpp b/src/mesh/Connectivity2D.hpp index 290e826aa..19ea67e0c 100644 --- a/src/mesh/Connectivity2D.hpp +++ b/src/mesh/Connectivity2D.hpp @@ -266,6 +266,11 @@ private: return m_face_nb_cells; } + const Kokkos::View<const unsigned short*> faceNbNodes() const + { + return m_face_nb_nodes; + } + const Kokkos::View<const unsigned int**> nodeCells() const { return m_node_cells; diff --git a/src/mesh/MeshBoundary.hpp b/src/mesh/MeshBoundary.hpp new file mode 100644 index 000000000..8e3961e52 --- /dev/null +++ b/src/mesh/MeshBoundary.hpp @@ -0,0 +1,124 @@ +#ifndef MESH_BOUNDARY_HPP +#define MESH_BOUNDARY_HPP + +#include <Kokkos_Core.hpp> +#include <TinyVector.hpp> + +#include <iostream> + +#warning Must change rewrite that to compute associated node lists +template <size_t dimension> +class MeshBoundary +{ + public: + MeshBoundary& operator=(const MeshBoundary&) = default; + MeshBoundary& operator=(MeshBoundary&&) = default; + + template <typename MeshType> + MeshBoundary(const MeshType& mesh, + const Kokkos::View<const unsigned int*>& face_list) + { + static_assert(dimension == MeshType::dimension); + const Kokkos::View<const unsigned short*> face_nb_cells = mesh.connectivity().faceNbCells(); + + Kokkos::parallel_for(face_list.extent(0), KOKKOS_LAMBDA(const int& l){ + if (face_nb_cells[face_list[l]]>1) { + std::cerr << "internal faces cannot be used to define mesh boundaries\n"; + std::exit(1); + } + }); + } + + MeshBoundary() = default; + MeshBoundary(const MeshBoundary&) = default; + MeshBoundary(MeshBoundary&&) = default; + virtual ~MeshBoundary() = default; +}; + + +template <size_t dimension> +class MeshFlatBoundary + : public MeshBoundary<dimension> +{ + typedef TinyVector<dimension, double> Rd; + private: + const Rd m_outgoing_normal; + + template <typename MeshType> + inline Rd _getOutgoingNormal(const MeshType& mesh, + const Kokkos::View<const unsigned int*>& face_list); + public: + MeshFlatBoundary& operator=(const MeshFlatBoundary&) = default; + MeshFlatBoundary& operator=(MeshFlatBoundary&&) = default; + + template <typename MeshType> + MeshFlatBoundary(const MeshType& mesh, + const Kokkos::View<const unsigned int*>& face_list) + : MeshBoundary<dimension>(mesh, face_list), + m_outgoing_normal(_getOutgoingNormal(mesh, face_list)) + { + ; + } + + MeshFlatBoundary() = default; + MeshFlatBoundary(const MeshFlatBoundary&) = default; + MeshFlatBoundary(MeshFlatBoundary&&) = default; + virtual ~MeshFlatBoundary() = default; + +}; + +template <> +template <typename MeshType> +inline TinyVector<2,double> +MeshFlatBoundary<2>:: +_getOutgoingNormal(const MeshType& mesh, + const Kokkos::View<const unsigned int*>& face_list) +{ + static_assert(MeshType::dimension == 2); + typedef TinyVector<2,double> R2; + + const Kokkos::View<const unsigned short*> face_nb_nodes = mesh.connectivity().faceNbNodes(); + const Kokkos::View<const unsigned int**> face_nodes = mesh.connectivity().faceNodes(); + const Kokkos::View<const R2*> xr = mesh.xr(); + + R2 xmin(std::numeric_limits<double>::max(), + std::numeric_limits<double>::max()); + + R2 xmax(-std::numeric_limits<double>::max(), + -std::numeric_limits<double>::max()); + + if (face_list.extent(0)==0) { + std::cerr << "face_list is empty! Cannot compute normal!\n"; + std::exit(1); + } + + for (size_t l=0; l<face_list.extent(0); ++l) { + const unsigned int face_number = face_list[l]; + for (int r=0; r<face_nb_nodes(face_number); ++r) { + const R2& x = xr(face_nodes(face_number,r)); + if ((x[0]<xmin[0]) or ((x[0] == xmin[0]) and (x[1] < xmin[1]))) { + xmin = x; + } + if ((x[0]>xmax[0]) or ((x[0] == xmax[0]) and (x[1] > xmax[1]))) { + xmax = x; + } + } + } + + if (xmin == xmax) { + std::cerr << "xmin==xmax (" << xmin << "==" << xmax << ") unable to compute normal"; + std::exit(1); + } + + R2 dx = xmax-xmin; + dx *= 1./std::sqrt((dx,dx)); + + R2 normal(-dx[1], dx[0]); + + std::cout << "xmin=" << xmin << " xmax=" << xmax << " normal=" << normal << '\n'; + + return normal; +} + + +#endif // MESH_BOUNDARY_HPP -- GitLab