Create contact entities between different blocks.
190{
191 int mpi_rank = 0;
192 int num_ranks = 1;
193#ifdef NIMBLE_HAVE_MPI
194 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
195 MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
196#endif
197
199
200 const double* coord_x = mesh.GetCoordinatesX();
201 const double* coord_y = mesh.GetCoordinatesY();
202 const double* coord_z = mesh.GetCoordinatesZ();
203
204 int max_node_global_id = mesh.GetMaxNodeGlobalId();
205#ifdef NIMBLE_HAVE_MPI
206 int global_max_node_global_id = max_node_global_id;
207 MPI_Allreduce(&max_node_global_id, &global_max_node_global_id, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
208 max_node_global_id = global_max_node_global_id;
209#endif
210
211
212
213
214
215 std::vector<std::vector<int>> primary_skin_faces, secondary_skin_faces;
216 std::vector<int> primary_skin_entity_ids, secondary_skin_entity_ids;
217 int contact_entity_id_offset = max_node_global_id;
218
219 SkinBlocks(mesh, primary_block_ids, contact_entity_id_offset, primary_skin_faces, primary_skin_entity_ids);
220 SkinBlocks(mesh, secondary_block_ids, contact_entity_id_offset, secondary_skin_faces, secondary_skin_entity_ids);
221
222
225
226
227
228 std::vector<int> partition_boundary_node_local_ids;
229 std::vector<int> min_rank_containing_partition_boundary_nodes;
230 myVecComm.GetPartitionBoundaryNodeLocalIds(
231 partition_boundary_node_local_ids, min_rank_containing_partition_boundary_nodes);
232
233 std::vector<int> ghosted_node_local_ids;
234 for (int i = 0; i < partition_boundary_node_local_ids.size(); i++) {
235 if (min_rank_containing_partition_boundary_nodes[i] != mpi_rank) {
236 ghosted_node_local_ids.push_back(partition_boundary_node_local_ids[i]);
237 }
238 }
239
240
241
242 std::set<int> node_ids_set;
243 for (auto const& face : primary_skin_faces) {
244 for (auto const& id : face) { node_ids_set.insert(id); }
245 }
246 for (auto const& face : secondary_skin_faces) {
247 for (auto const& id : face) { node_ids_set.insert(id); }
248 }
249 node_ids_ = std::vector<int>(node_ids_set.begin(), node_ids_set.end());
250
251 std::map<int, int> genesis_mesh_node_id_to_contact_submodel_id;
252 for (
unsigned int i_node = 0; i_node <
node_ids_.size(); ++i_node) {
253 genesis_mesh_node_id_to_contact_submodel_id[
node_ids_[i_node]] = i_node;
254 }
255
256
257
258 for (auto& primary_skin_face : primary_skin_faces) {
259 for (int& i_node : primary_skin_face) {
260 int genesis_mesh_node_id = i_node;
261 i_node = genesis_mesh_node_id_to_contact_submodel_id.at(genesis_mesh_node_id);
262 }
263 }
264 for (auto& secondary_skin_face : secondary_skin_faces) {
265 for (int& i_node : secondary_skin_face) {
266 int genesis_mesh_node_id = i_node;
267 i_node = genesis_mesh_node_id_to_contact_submodel_id.at(genesis_mesh_node_id);
268 }
269 }
270
271
272 std::vector<int> ghosted_contact_node_ids;
273 for (auto node_id : ghosted_node_local_ids) {
274 auto it = genesis_mesh_node_id_to_contact_submodel_id.find(node_id);
275 if (it != genesis_mesh_node_id_to_contact_submodel_id.end()) { ghosted_contact_node_ids.push_back(it->second); }
276 }
277
278
282 force_.resize(array_len, 0.0);
283 for (
unsigned int i_node = 0; i_node <
node_ids_.size(); i_node++) {
287 }
288
289
290
291 const int* genesis_node_global_ids = mesh.GetNodeGlobalIds();
292 std::vector<int> secondary_node_ids;
293 std::vector<int> secondary_node_entity_ids;
294 std::map<int, double> secondary_node_char_lens;
295 for (auto& face : secondary_skin_faces) {
296 int num_nodes_in_face = static_cast<int>(face.size());
297
298 double max_edge_length_square = std::numeric_limits<double>::lowest();
299 for (int i = 0; i < num_nodes_in_face; ++i) {
300 int node_id_1 = face[i];
301 int node_id_2 = face[0];
302 if (i + 1 < num_nodes_in_face) { node_id_2 = face[i + 1]; }
303 double edge_length_square =
305 (
coord_[3 * node_id_2 + 1] -
coord_[3 * node_id_1 + 1]) *
306 (
coord_[3 * node_id_2 + 1] -
coord_[3 * node_id_1 + 1]) +
307 (
coord_[3 * node_id_2 + 2] -
coord_[3 * node_id_1 + 2]) *
308 (
coord_[3 * node_id_2 + 2] -
coord_[3 * node_id_1 + 2]);
309 if (edge_length_square > max_edge_length_square) { max_edge_length_square = edge_length_square; }
310 }
311 double characteristic_length = sqrt(max_edge_length_square);
312 for (int i_node = 0; i_node < num_nodes_in_face; i_node++) {
313 int node_id = face[i_node];
314
315 if (std::find(ghosted_contact_node_ids.begin(), ghosted_contact_node_ids.end(), node_id) ==
316 ghosted_contact_node_ids.end()) {
317 if (std::find(secondary_node_ids.begin(), secondary_node_ids.end(), node_id) == secondary_node_ids.end()) {
318 secondary_node_ids.push_back(node_id);
319
320
321 int contact_node_entity_id = genesis_node_global_ids[
node_ids_[node_id]] + 1;
322 secondary_node_entity_ids.push_back(contact_node_entity_id);
323 secondary_node_char_lens[node_id] = characteristic_length;
324 } else {
325
326
327 if (secondary_node_char_lens[node_id] < characteristic_length) {
328 secondary_node_char_lens[node_id] = characteristic_length;
329 }
330 }
331 }
332 }
333 }
334
335
336 int num_contact_nodes = secondary_node_ids.size();
337 int num_contact_faces = 4 * primary_skin_faces.size();
338
340 for (
unsigned int i_node = 0; i_node <
node_ids_.size(); i_node++) { node_ids_h[i_node] =
node_ids_[i_node]; }
341
343 for (
unsigned int i_node = 0; i_node <
node_ids_.size(); i_node++) {
344 model_coord_h[3 * i_node] = coord_x[
node_ids_[i_node]];
345 model_coord_h[3 * i_node + 1] = coord_y[
node_ids_[i_node]];
346 model_coord_h[3 * i_node + 2] = coord_z[
node_ids_[i_node]];
347 }
348
351 Kokkos::resize(
coord_d_, array_len);
352 Kokkos::resize(
force_d_, array_len);
353
356 Kokkos::deep_copy(
coord_d_, model_coord_h);
358
359
360
361
362
366 primary_skin_faces,
367 primary_skin_entity_ids,
368 secondary_node_ids,
369 secondary_node_entity_ids,
370 secondary_node_char_lens,
373
378
379#ifdef NIMBLE_HAVE_MPI
380 std::vector<int> input(2);
381 std::vector<int> output(2);
382 input[0] = num_contact_faces;
383 input[1] = num_contact_nodes;
384 MPI_Reduce(input.data(), output.data(), input.size(), MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
385 num_contact_faces = output[0];
386 num_contact_nodes = output[1];
387#endif
388 if (mpi_rank == 0) {
389 std::cout << "Contact initialization:" << std::endl;
390 std::cout << " number of triangular contact facets (primary blocks): " << num_contact_faces << std::endl;
391 std::cout << " number of contact nodes (secondary blocks): " << num_contact_nodes << "\n" << std::endl;
392 }
393}
Kokkos::View< int *, kokkos_host > HostIntegerArrayView
Definition nimble_kokkos_defs.h:577