VertexCFD  0.0-dev
VertexCFD_Mesh_GeometryData.hpp
1 #ifndef VERTEXCFD_MESH_GEOMETRYDATA_HPP
2 #define VERTEXCFD_MESH_GEOMETRYDATA_HPP
3 
4 #include <Panzer_CellData.hpp>
5 #include <Panzer_CommonArrayFactories.hpp>
6 #include <Panzer_STK_Interface.hpp>
7 #include <Panzer_STK_SetupUtilities.hpp>
8 
9 #include <Intrepid2_CellData.hpp>
10 #include <Intrepid2_CellTools_Serial.hpp>
11 
12 #include <Shards_BasicTopologies.hpp>
13 #include <Shards_CellTopology.hpp>
14 
15 #include <Sacado.hpp>
16 
17 #include <Kokkos_Core.hpp>
18 
19 #include <functional>
20 #include <type_traits>
21 #include <vector>
22 
23 #include <mpi.h>
24 
25 namespace VertexCFD
26 {
27 namespace Mesh
28 {
29 namespace Topology
30 {
31 
33 {
34  public:
35  // Constructor
36  SidesetGeometry(const Teuchos::RCP<panzer_stk::STK_Interface>& mesh,
37  std::vector<std::string> walls)
38  {
39  // Get names of sidesets. Return on empty input.
40  std::vector<std::string> sideset_block_names;
41  mesh->getSidesetNames(sideset_block_names);
42  if (sideset_block_names.size() == 0)
43  return;
44 
45  std::vector<std::string> e_block_names;
46  mesh->getElementBlockNames(e_block_names);
47 
48  // Get topology information and ensure that the topology is Tet4's
49  for (long unsigned int block = 0; block < e_block_names.size(); ++block)
50  {
51  _topology = mesh->getCellTopology(e_block_names[block]);
52  if (_topology->getKey() != shards::Tetrahedron<4>::key
53  && _topology->getKey() != shards::Hexahedron<8>::key
54  && _topology->getKey() != shards::Triangle<3>::key
55  && _topology->getKey() != shards::Quadrilateral<4>::key)
56  {
57  const std::string msg = "Block topology is not Tet4 or Tri3";
58  throw std::runtime_error(msg);
59  }
60  }
61 
62  // Get the local set of sides declared as walls from all block/sideset
63  // combinations.
64  std::vector<stk::mesh::Entity> local_side_entities;
65  for (const auto& sb : sideset_block_names)
66  {
67  for (long unsigned int i = 0; i < walls.size(); ++i)
68  {
69  if (walls[i] == sb)
70  {
71  std::vector<stk::mesh::Entity> sideset_sides;
72  mesh->getMySides(sb, sideset_sides);
73  local_side_entities.insert(std::end(local_side_entities),
74  std::begin(sideset_sides),
75  std::end(sideset_sides));
76  break;
77  }
78  }
79  }
80 
81  Kokkos::DynRankView<double, PHX::Device> local_sides;
82  mesh->getElementVertices(local_side_entities, local_sides);
83 
84  // Extract the mpi communicator.
85  auto comm = mesh->getComm();
86  MPI_Comm mpi_comm = Teuchos::getRawMpiComm(*comm);
87 
88  // Get extents.
89  const int num_space_dim = _topology->getDimension();
90  const int nodes_per_side
91  = _topology->getVertexCount(num_space_dim - 1, 0);
92  const int side_data_count = nodes_per_side * num_space_dim;
93 
94  // Compose gather communication pattern.
95  std::vector<int> global_counts(comm->getSize(), 0);
96  int receive_counts;
97  receive_counts = local_sides.extent(0);
98  MPI_Allgather(&receive_counts,
99  1,
100  MPI_INT,
101  global_counts.data(),
102  1,
103  MPI_INT,
104  mpi_comm);
105  std::vector<int> receive_displacements(comm->getSize(), 0);
106  int global_num_side = 0;
107  for (int r = 0; r < comm->getSize(); ++r)
108  {
109  receive_displacements[r] = global_num_side * side_data_count;
110  global_num_side += global_counts[r];
111  }
112 
113  for (int rank = 0; rank < comm->getSize(); ++rank)
114  {
115  global_counts[rank] *= side_data_count;
116  }
117 
118  // Combine all sides into a replicated global set of sides on each
119  // rank so we can build a replicated, non-distributed tree on each
120  // rank.
121  _global_sides = Kokkos::View<double***, PHX::Device>(
122  Kokkos::ViewAllocateWithoutInitializing("Global side Nodes"),
123  global_num_side,
124  nodes_per_side,
125  num_space_dim);
126 
127  // Create host-side mirror for sides
128  auto local_sides_host = Kokkos::create_mirror_view(local_sides);
129  Kokkos::deep_copy(local_sides_host, local_sides);
130  auto global_sides_host = Kokkos::create_mirror_view(_global_sides);
131 
132  MPI_Allgatherv(local_sides_host.data(),
133  local_sides_host.size(),
134  MPI_DOUBLE,
135  global_sides_host.data(),
136  global_counts.data(),
137  receive_displacements.data(),
138  MPI_DOUBLE,
139  mpi_comm);
140  Kokkos::deep_copy(_global_sides, global_sides_host);
141  }
142 
143  // Get the side topology.
144  Teuchos::RCP<const shards::CellTopology> topology() const
145  {
146  return _topology;
147  }
148 
149  // Get the sides.
150  Kokkos::View<double***, PHX::Device> sides() const
151  {
152  return _global_sides;
153  }
154 
155  private:
156  // Side topology.
157  Teuchos::RCP<const shards::CellTopology> _topology;
158 
159  // Sides given as coordinates (side,node,dim)
160  Kokkos::View<double***, PHX::Device> _global_sides;
161 };
162 
163 } // end namespace Topology
164 } // end namespace Mesh
165 } // end namespace VertexCFD
166 
167 #endif // end VERTEXCFD_MESH_GEOMETRYDATA
VertexCFD
Definition: tstMethodManufacturedSolutionBC.cpp:23
VertexCFD::Mesh::Topology::SidesetGeometry
Definition: VertexCFD_Mesh_GeometryData.hpp:33