KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
search_utilities.h
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ `
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Philipp Bucher
11 // Vicente Mataix Ferrandiz
12 
13 #pragma once
14 
15 // System includes
16 #include <vector>
17 #include <numeric>
18 
19 // External includes
20 
21 // Project includes
23 #include "geometries/point.h"
25 #include "includes/variables.h"
26 #include "includes/model_part.h"
29 
30 namespace Kratos
31 {
34 
38 
42 
46 
50 
59 {
61  using IndexType = std::size_t;
62 
64  using SizeType = std::size_t;
65 
66  std::vector<double> PointCoordinates;
67  std::vector<IndexType> Indexes;
68  std::vector<int> SearchRanks;
69  std::vector<std::vector<int>> Ranks;
70 
75  void Reserve(const SizeType Size)
76  {
77  PointCoordinates.reserve(Size * 3);
78  Indexes.reserve(Size);
79  SearchRanks.reserve(Size);
80  Ranks.reserve(Size);
81  }
82 
86  void Shrink()
87  {
88  PointCoordinates.shrink_to_fit();
89  Indexes.shrink_to_fit();
90  SearchRanks.shrink_to_fit();
91  Ranks.shrink_to_fit();
92  }
93 
97  void Clear()
98  {
99  PointCoordinates.clear();
100  Indexes.clear();
101  SearchRanks.clear();
102  Ranks.clear();
103  }
104 };
105 
115 {
116 public:
119 
121  using BoundingBoxType = std::array<double, 6>;
122 
124  using IndexType = long unsigned int;
125 
127  using SizeType = std::size_t;
128 
130  using RadiusArrayType = std::vector<double>;
131  using DistanceType = std::vector<double>;
132  using VectorDistanceType = std::vector<DistanceType>;
133 
135  static constexpr double ZeroTolerance = std::numeric_limits<double>::epsilon();
136 
140 
144 
153  template<class TPointType>
155  const BoundingBox<TPointType>& rBoundingBox,
156  const array_1d<double, 3>& rCoords
157  )
158  {
159  // Get the bounding box points
160  const auto& r_max_point = rBoundingBox.GetMaxPoint();
161  const auto& r_min_point = rBoundingBox.GetMinPoint();
162 
163  // The Bounding Box check
164  if (rCoords[0] < r_max_point[0] && rCoords[0] > r_min_point[0]) // check x-direction
165  if (rCoords[1] < r_max_point[1] && rCoords[1] > r_min_point[1]) // check y-direction
166  if (rCoords[2] < r_max_point[2] && rCoords[2] > r_min_point[2]) // check z-direction
167  return true;
168  return false;
169  }
170 
179  const BoundingBoxType& rBoundingBox,
180  const array_1d<double, 3>& rCoords
181  )
182  {
183  // The Bounding Box should have some tolerance already!
184  if (rCoords[0] < rBoundingBox[0] && rCoords[0] > rBoundingBox[1]) // check x-direction
185  if (rCoords[1] < rBoundingBox[2] && rCoords[1] > rBoundingBox[3]) // check y-direction
186  if (rCoords[2] < rBoundingBox[4] && rCoords[2] > rBoundingBox[5]) // check z-direction
187  return true;
188  return false;
189  }
190 
199  template<class TPointType>
201  const BoundingBox<TPointType>& rBoundingBox,
202  const array_1d<double, 3>& rCoords,
203  const double Tolerance
204  )
205  {
206  // Get the bounding box points
207  auto max_point = rBoundingBox.GetMaxPoint();
208  auto min_point = rBoundingBox.GetMinPoint();
209 
210  // Apply Tolerances (only in non zero BB cases)
211  const double epsilon = std::numeric_limits<double>::epsilon();
212  if (norm_2(max_point) > epsilon && norm_2(min_point) > epsilon) {
213  for (unsigned int i=0; i<3; ++i) {
214  max_point[i] += Tolerance;
215  min_point[i] -= Tolerance;
216  }
217  }
218 
219  // The Bounding Box check
220  if (rCoords[0] < max_point[0] && rCoords[0] > min_point[0]) // check x-direction
221  if (rCoords[1] < max_point[1] && rCoords[1] > min_point[1]) // check y-direction
222  if (rCoords[2] < max_point[2] && rCoords[2] > min_point[2]) // check z-direction
223  return true;
224  return false;
225  }
226 
234  const std::vector<double>& rBoundingBoxes,
235  const double Tolerance,
236  std::vector<double>& rBoundingBoxesWithTolerance
237  );
238 
247  const std::vector<double>& rBoundingBoxes,
248  const double Tolerance,
249  std::vector<double>& rBoundingBoxesWithTolerance
250  );
251 
261  template<typename TPointIteratorType>
263  TPointIteratorType itPointBegin,
264  TPointIteratorType itPointEnd,
265  std::vector<double>& rAllPointsCoordinates,
266  std::vector<IndexType>& rAllPointsIds,
267  const DataCommunicator& rDataCommunicator
268  )
269  {
270  // First check that the points are the same in all processes
271  int number_of_points, total_number_of_points;
272  CalculateNumberOfPoints(itPointBegin, itPointEnd, number_of_points, total_number_of_points, rDataCommunicator);
273 
274  KRATOS_DEBUG_ERROR_IF(number_of_points < 0) << "The number of points is negative" << std::endl;
275  KRATOS_DEBUG_ERROR_IF(total_number_of_points < 0) << "The total number of points is negative" << std::endl;
276 
277  // We synchronize the points
278  SynchronizePoints(itPointBegin, itPointEnd, rAllPointsCoordinates, rAllPointsIds, rDataCommunicator, number_of_points, total_number_of_points);
279  }
280 
294  template<typename TPointIteratorType, typename TBoundingBoxType>
295  static std::vector<IndexType> SynchronousPointSynchronizationWithBoundingBox(
296  TPointIteratorType itPointBegin,
297  TPointIteratorType itPointEnd,
298  DistributedSearchInformation& rSearchInfo,
299  const TBoundingBoxType& rBoundingBox,
300  const double ThresholdBoundingBox,
301  const DataCommunicator& rDataCommunicator,
302  const bool IndexItIsJustCounter = false
303  )
304  {
305  // First check that the points are the same in all processes
306  int number_of_points, total_number_of_points;
307  CalculateNumberOfPoints(itPointBegin, itPointEnd, number_of_points, total_number_of_points, rDataCommunicator);
308 
309  KRATOS_DEBUG_ERROR_IF(number_of_points < 0) << "The number of points is negative" << std::endl;
310  KRATOS_DEBUG_ERROR_IF(total_number_of_points < 0) << "The total number of points is negative" << std::endl;
311 
312  // We synchronize the points
313  return SynchronizePointsWithBoundingBox(itPointBegin, itPointEnd, rSearchInfo, rBoundingBox, ThresholdBoundingBox, rDataCommunicator, number_of_points, total_number_of_points, IndexItIsJustCounter);
314  }
315 
327  template<typename TPointIteratorType>
329  TPointIteratorType itPointBegin,
330  TPointIteratorType itPointEnd,
331  std::vector<double>& rAllPointsCoordinates,
332  std::vector<IndexType>& rAllPointsIds,
333  const DataCommunicator& rDataCommunicator
334  )
335  {
336  // First check that the points are the same in all processes
337  int number_of_points, total_number_of_points;
338  CalculateNumberOfPoints(itPointBegin, itPointEnd, number_of_points, total_number_of_points, rDataCommunicator);
339 
340  KRATOS_DEBUG_ERROR_IF(number_of_points < 0) << "The number of points is negative" << std::endl;
341  KRATOS_DEBUG_ERROR_IF(total_number_of_points < 0) << "The total number of points is negative" << std::endl;
342 
343  // We synchronize the points
344  return SynchronizePoints(itPointBegin, itPointEnd, rAllPointsCoordinates, rAllPointsIds, rDataCommunicator, number_of_points, total_number_of_points);
345  }
346 
359  template<typename TPointIteratorType>
360  static std::vector<double> SynchronousPointSynchronizationWithRadius(
361  TPointIteratorType itPointBegin,
362  TPointIteratorType itPointEnd,
363  std::vector<double>& rAllPointsCoordinates,
364  std::vector<IndexType>& rAllPointsIds,
365  const std::vector<double>& rRadius,
366  const DataCommunicator& rDataCommunicator
367  )
368  {
369  // First check that the points are the same in all processes
370  int number_of_points, total_number_of_points;
371  CalculateNumberOfPoints(itPointBegin, itPointEnd, number_of_points, total_number_of_points, rDataCommunicator);
372 
373  KRATOS_DEBUG_ERROR_IF(number_of_points < 0) << "The number of points is negative" << std::endl;
374  KRATOS_DEBUG_ERROR_IF(total_number_of_points < 0) << "The total number of points is negative" << std::endl;
375 
376  // We synchronize the points
377  const auto recv_sizes = SynchronizePoints(itPointBegin, itPointEnd, rAllPointsCoordinates, rAllPointsIds, rDataCommunicator, number_of_points, total_number_of_points);
378 
379  // Get radius
380  if (rDataCommunicator.IsDistributed()) { // If distributed
381  return SynchronizeRadius(recv_sizes, rRadius, rDataCommunicator);
382  } else { // If serial
383  return rRadius;
384  }
385  }
386 
396  template<class TContainer, class TResultType>
397  static std::vector<typename PointObject<typename TContainer::value_type>::Pointer> PrepareSearch(
398  const TContainer& rStructure,
399  const TContainer& rInput,
400  TResultType& rResults,
401  VectorDistanceType& rResultsDistance
402  )
403  {
404  // Resizing the results
405  PrepareOutputSearch(rInput, rResults, rResultsDistance);
406 
407  // Preparing the points
408  return PreparePointsSearch(rStructure);
409  }
410 
419  template<class TContainer, class TResultType>
420  static void PrepareOutputSearch(
421  const TContainer& rInput,
422  TResultType& rResults,
423  VectorDistanceType& rResultsDistance
424  )
425  {
426  // Resizing the results
427  const std::size_t input_size = rInput.size();
428  if (rResults.size() != input_size) {
429  rResults.resize(input_size);
430  }
431  if (rResultsDistance.size() != input_size) {
432  rResultsDistance.resize(input_size);
433  }
434  }
435 
441  template<class TContainer>
442  static std::vector<typename PointObject<typename TContainer::value_type>::Pointer> PreparePointsSearch(const TContainer& rStructure)
443  {
444  // Some definitions
445  using ObjectType = typename TContainer::value_type;
447  using PointTypePointer = typename PointType::Pointer;
448  using PointVector = std::vector<PointTypePointer>;
449 
450  // Creating the points
451  PointVector points;
452  const std::size_t structure_size = rStructure.size();
453  points.reserve(structure_size);
454  const auto it_begin = rStructure.begin();
455  for (std::size_t i = 0; i < structure_size; ++i) {
456  auto it = it_begin + i;
457  points.push_back(PointTypePointer(new PointType(*(it.base()))));
458  }
459 
460  return points;
461  }
462 
475  template<class TContainer, class TSpatialContainer, class TResultType>
476  static void ParallelSearch(
477  const TContainer& rInput,
478  const RadiusArrayType& rRadius,
479  TSpatialContainer& rSearch,
480  TResultType& rResults,
481  VectorDistanceType& rResultsDistance,
482  const int AllocationSize = 1000
483  )
484  {
485  // Some definitions
486  using ObjectType = typename TContainer::value_type;
488  using PointTypePointer = typename PointType::Pointer;
489  using PointVector = std::vector<PointTypePointer>;
490  using DistanceVector = std::vector<double>;
491  const std::size_t input_size = rInput.size();
492 
493  // Performing search
494  IndexPartition<std::size_t>(input_size).for_each([&](std::size_t i) {
495  auto it = rInput.begin() + i;
496  PointType aux_point(*(it.base()));
497  PointVector results(AllocationSize);
498  DistanceVector results_distances(AllocationSize);
499  const std::size_t number_of_results = rSearch.SearchInRadius(aux_point, rRadius[i], results.begin(), results_distances.begin(), AllocationSize);
500  if (number_of_results > 0) {
501  auto& r_results = rResults[i];
502  auto& r_results_distance = rResultsDistance[i];
503  r_results.reserve(number_of_results);
504  r_results_distance.reserve(number_of_results);
505  for (std::size_t j = 0; j < number_of_results; ++j) {
506  auto p_point = results[j];
507  r_results.push_back(p_point->pGetObject());
508  r_results_distance.push_back(results_distances[j]);
509  }
510  }
511  });
512  }
513 
515 private:
518 
532  template<typename TPointIteratorType>
533  static std::vector<int> SynchronizePoints(
534  TPointIteratorType itPointBegin,
535  TPointIteratorType itPointEnd,
536  std::vector<double>& rAllPointsCoordinates,
537  std::vector<IndexType>& rAllPointsIds,
538  const DataCommunicator& rDataCommunicator,
539  const int NumberOfPoints,
540  const int TotalNumberOfPoints
541  )
542  {
543  // Get the World Size and rank in MPI
544  const int world_size = rDataCommunicator.Size();
545  const int rank = rDataCommunicator.Rank();
546 
547  // Getting global number of points
548  std::vector<int> points_per_partition(world_size);
549  std::vector<int> send_points_per_partition(1, NumberOfPoints);
550  rDataCommunicator.AllGather(send_points_per_partition, points_per_partition);
551  std::size_t initial_id = 0;
552  if constexpr (!std::is_same<TPointIteratorType, ModelPart::NodeIterator>::value || std::is_same<TPointIteratorType, ModelPart::NodeConstantIterator>::value) {
553  initial_id = std::accumulate(points_per_partition.begin(), points_per_partition.begin() + rank, 0);
554  }
555 
556  // Initialize and resize vectors
557  if (rAllPointsCoordinates.size() != static_cast<unsigned int>(TotalNumberOfPoints * 3)) {
558  rAllPointsCoordinates.resize(TotalNumberOfPoints * 3);
559  }
560  if (rAllPointsIds.size() != static_cast<unsigned int>(TotalNumberOfPoints)) {
561  rAllPointsIds.resize(TotalNumberOfPoints);
562  }
563  std::vector<int> recv_sizes(world_size, 0);
564 
565  // Auxiliary variables
566  std::size_t counter = 0;
567  array_1d<double, 3> coordinates;
568  unsigned int i_coord;
569 
570  // If distributed
571  if (rDataCommunicator.IsDistributed()) {
572  // Initialize local points coordinates
573  std::vector<double> send_points_coordinates(NumberOfPoints * 3);
574  std::vector<IndexType> send_points_ids(NumberOfPoints);
575  for (auto it_point = itPointBegin ; it_point != itPointEnd ; ++it_point) {
576  // In case of considering nodes
577  if constexpr (std::is_same<TPointIteratorType, ModelPart::NodeIterator>::value || std::is_same<TPointIteratorType, ModelPart::NodeConstantIterator>::value) {
578  if (it_point->FastGetSolutionStepValue(PARTITION_INDEX) != rank) {
579  continue; // Skip if not local
580  }
581  }
582  noalias(coordinates) = it_point->Coordinates();
583  if constexpr (std::is_same<TPointIteratorType, ModelPart::NodeIterator>::value || std::is_same<TPointIteratorType, ModelPart::NodeConstantIterator>::value) {
584  send_points_ids[counter] = it_point->Id();
585  } else {
586  send_points_ids[counter] = initial_id + counter;
587  }
588  for (i_coord = 0; i_coord < 3; ++i_coord) {
589  send_points_coordinates[3 * counter + i_coord] = coordinates[i_coord];
590  }
591  ++counter;
592  }
593 
594  /* Sync coordinates */
595 
596  // Generate vectors with sizes for AllGatherv
597  for (int i_rank = 0; i_rank < world_size; ++i_rank) {
598  recv_sizes[i_rank] = 3 * points_per_partition[i_rank];
599  }
600  std::vector<int> recv_offsets(world_size, 0);
601  for (int i_rank = 1; i_rank < world_size; ++i_rank) {
602  recv_offsets[i_rank] = recv_offsets[i_rank - 1] + recv_sizes[i_rank - 1];
603  }
604 
605  // Invoke AllGatherv
606  rDataCommunicator.AllGatherv(send_points_coordinates, rAllPointsCoordinates, recv_sizes, recv_offsets);
607 
608  /* Sync Ids */
609 
610  // Generate vectors with sizes for AllGatherv
611  for (int i_rank = 0; i_rank < world_size; ++i_rank) {
612  recv_sizes[i_rank] = points_per_partition[i_rank];
613  }
614  for (int i_rank = 1; i_rank < world_size; ++i_rank) {
615  recv_offsets[i_rank] = recv_offsets[i_rank - 1] + recv_sizes[i_rank - 1];
616  }
617 
618  // Invoke AllGatherv
619  rDataCommunicator.AllGatherv(send_points_ids, rAllPointsIds, recv_sizes, recv_offsets);
620  } else { // Serial
621  // Assign values
622  for (auto it_point = itPointBegin ; it_point != itPointEnd ; ++it_point) {
623  noalias(coordinates) = it_point->Coordinates();
624  if constexpr (std::is_same<TPointIteratorType, ModelPart::NodeIterator>::value || std::is_same<TPointIteratorType, ModelPart::NodeConstantIterator>::value) {
625  rAllPointsIds[counter] = it_point->Id();
626  } else {
627  rAllPointsIds[counter] = initial_id + counter;
628  }
629  for (i_coord = 0; i_coord < 3; ++i_coord) {
630  rAllPointsCoordinates[3 * counter + i_coord] = coordinates[i_coord];
631  }
632  ++counter;
633  }
634  }
635 
636  // Return the recv sizes
637  return recv_sizes;
638  }
639 
654  template<typename TPointIteratorType>
655  static std::vector<int> SynchronizePointsWithRanks(
656  TPointIteratorType itPointBegin,
657  TPointIteratorType itPointEnd,
658  std::vector<double>& rAllPointsCoordinates,
659  std::vector<IndexType>& rAllPointsIds,
660  const DataCommunicator& rDataCommunicator,
661  const int NumberOfPoints,
662  const int TotalNumberOfPoints,
663  const bool IndexItIsJustCounter = false
664  )
665  {
666  // Define lambda to retrieve Id
667  const auto GetIdNode = [](std::vector<IndexType>& rIds, TPointIteratorType& ItPoint, const std::size_t Counter, const std::size_t InitialId) {
668  if constexpr (std::is_same<TPointIteratorType, ModelPart::NodeIterator>::value || std::is_same<TPointIteratorType, ModelPart::NodeConstantIterator>::value) {
669  rIds[Counter] = ItPoint->Id();
670  } else {
671  rIds[Counter] = InitialId + Counter;
672  }
673  };
674  const auto GetIdJustCounter = [](std::vector<IndexType>& rIds, TPointIteratorType& ItPoint, const std::size_t Counter, const std::size_t InitialId) {
675  rIds[Counter] = Counter;
676  };
677  const auto GetId = IndexItIsJustCounter ? GetIdJustCounter : GetIdNode;
678 
679  // Get the World Size and rank in MPI
680  const int world_size = rDataCommunicator.Size();
681  const int rank = rDataCommunicator.Rank();
682 
683  // Getting global number of points
684  std::vector<int> points_per_partition(world_size);
685  std::vector<int> send_points_per_partition(1, NumberOfPoints);
686  std::vector<int> all_points_ranks(TotalNumberOfPoints);
687  rDataCommunicator.AllGather(send_points_per_partition, points_per_partition);
688  std::size_t initial_id = 0;
689  if constexpr (!std::is_same<TPointIteratorType, ModelPart::NodeIterator>::value || std::is_same<TPointIteratorType, ModelPart::NodeConstantIterator>::value) {
690  initial_id = std::accumulate(points_per_partition.begin(), points_per_partition.begin() + rank, 0);
691  }
692 
693  // Initialize and resize vectors
694  if (rAllPointsCoordinates.size() != static_cast<std::size_t>(TotalNumberOfPoints * 3)) {
695  rAllPointsCoordinates.resize(TotalNumberOfPoints * 3);
696  }
697  if (rAllPointsIds.size() != static_cast<std::size_t>(TotalNumberOfPoints)) {
698  rAllPointsIds.resize(TotalNumberOfPoints);
699  }
700  std::vector<int> recv_sizes(world_size, 0);
701 
702  // Auxiliary variables
703  std::size_t counter = 0;
704  unsigned int i_coord;
705 
706  // If distributed
707  if (rDataCommunicator.IsDistributed()) {
708  // Initialize local points coordinates
709  std::vector<double> send_points_coordinates(NumberOfPoints * 3);
710  std::vector<IndexType> send_points_ids(NumberOfPoints);
711  std::vector<int> send_points_ranks(NumberOfPoints);
712  for (auto it_point = itPointBegin ; it_point != itPointEnd ; ++it_point) {
713  // In case of considering nodes
714  if constexpr (std::is_same<TPointIteratorType, ModelPart::NodeIterator>::value || std::is_same<TPointIteratorType, ModelPart::NodeConstantIterator>::value) {
715  if (it_point->FastGetSolutionStepValue(PARTITION_INDEX) != rank) {
716  continue; // Skip if not local
717  }
718  }
719  const auto& r_coordinates = it_point->Coordinates();
720  GetId(send_points_ids, it_point, counter, initial_id);
721  send_points_ranks[counter] = rank;
722  for (i_coord = 0; i_coord < 3; ++i_coord) {
723  send_points_coordinates[3 * counter + i_coord] = r_coordinates[i_coord];
724  }
725  ++counter;
726  }
727 
728  /* Sync coordinates */
729 
730  // Generate vectors with sizes for AllGatherv
731  for (int i_rank = 0; i_rank < world_size; ++i_rank) {
732  recv_sizes[i_rank] = 3 * points_per_partition[i_rank];
733  }
734  std::vector<int> recv_offsets(world_size, 0);
735  for (int i_rank = 1; i_rank < world_size; ++i_rank) {
736  recv_offsets[i_rank] = recv_offsets[i_rank - 1] + recv_sizes[i_rank - 1];
737  }
738 
739  // Invoke AllGatherv
740  rDataCommunicator.AllGatherv(send_points_coordinates, rAllPointsCoordinates, recv_sizes, recv_offsets);
741 
742  /* Sync Ids */
743 
744  // Generate vectors with sizes for AllGatherv
745  for (int i_rank = 0; i_rank < world_size; ++i_rank) {
746  recv_sizes[i_rank] = points_per_partition[i_rank];
747  }
748  for (int i_rank = 1; i_rank < world_size; ++i_rank) {
749  recv_offsets[i_rank] = recv_offsets[i_rank - 1] + recv_sizes[i_rank - 1];
750  }
751 
752  // Invoke AllGatherv
753  rDataCommunicator.AllGatherv(send_points_ids, rAllPointsIds, recv_sizes, recv_offsets);
754  rDataCommunicator.AllGatherv(send_points_ranks, all_points_ranks, recv_sizes, recv_offsets);
755  } else { // Serial
756  // Assign values
757  for (auto it_point = itPointBegin ; it_point != itPointEnd ; ++it_point) {
758  const auto& r_coordinates = it_point->Coordinates();
759  if constexpr (std::is_same<TPointIteratorType, ModelPart::NodeIterator>::value || std::is_same<TPointIteratorType, ModelPart::NodeConstantIterator>::value) {
760  rAllPointsIds[counter] = it_point->Id();
761  } else {
762  rAllPointsIds[counter] = initial_id + counter;
763  }
764  for (i_coord = 0; i_coord < 3; ++i_coord) {
765  rAllPointsCoordinates[3 * counter + i_coord] = r_coordinates[i_coord];
766  }
767  ++counter;
768  }
769  }
770 
771  // Return the ranks
772  return all_points_ranks;
773  }
774 
792  template<typename TPointIteratorType, typename TBoundingBoxType>
793  static std::vector<IndexType> SynchronizePointsWithBoundingBox(
794  TPointIteratorType itPointBegin,
795  TPointIteratorType itPointEnd,
796  DistributedSearchInformation& rSearchInfo,
797  const TBoundingBoxType& rBoundingBox,
798  const double ThresholdBoundingBox,
799  const DataCommunicator& rDataCommunicator,
800  const int NumberOfPoints,
801  const int TotalNumberOfPoints,
802  const bool IndexItIsJustCounter = false
803  )
804  {
805  // Initialize and resize vectors
806  rSearchInfo.Reserve(TotalNumberOfPoints);
807  std::vector<double> all_points_coordinates(TotalNumberOfPoints * 3);
808  std::vector<IndexType> all_points_ids(TotalNumberOfPoints);
809 
810  // Sync all points first
811  std::vector<int> all_points_ranks = SynchronizePointsWithRanks(itPointBegin, itPointEnd, all_points_coordinates, all_points_ids, rDataCommunicator, NumberOfPoints, TotalNumberOfPoints, IndexItIsJustCounter);
812 
813  // Some definitions
814  IndexType i_coord = 0;
815 
816  // If distributed
817  if (rDataCommunicator.IsDistributed()) {
818  // Prepare MPI data
819  const int rank = rDataCommunicator.Rank();
820  const int world_size = rDataCommunicator.Size();
821  std::vector<int> ranks(1, rank);
822  std::vector<int> inside_ranks(world_size);
823 
824  // Fill actual vectors
825  Point point_to_test;
826  for (IndexType i_point = 0; i_point < static_cast<IndexType>(TotalNumberOfPoints); ++i_point) {
827  point_to_test[0] = all_points_coordinates[3 * i_point + 0];
828  point_to_test[1] = all_points_coordinates[3 * i_point + 1];
829  point_to_test[2] = all_points_coordinates[3 * i_point + 2];
830  const bool is_inside = PointIsInsideBoundingBox(rBoundingBox, point_to_test, ThresholdBoundingBox);
831  const int search_rank = all_points_ranks[i_point];
832  const bool to_be_included = is_inside || search_rank == rank;
833  inside_ranks.resize(world_size);
834  if (to_be_included) {
835  for (i_coord = 0; i_coord < 3; ++i_coord) {
836  rSearchInfo.PointCoordinates.push_back(all_points_coordinates[3 * i_point + i_coord]);
837  }
838  rSearchInfo.Indexes.push_back(all_points_ids[i_point]);
839  ranks[0] = rank;
840  } else {
841  ranks[0] = -1;
842  }
843  rDataCommunicator.AllGather(ranks, inside_ranks);
844  // Use std::remove_if and vector::erase to remove elements less than 0
845  inside_ranks.erase(
846  std::remove_if(
847  inside_ranks.begin(),
848  inside_ranks.end(),
849  [](const int rank) { return rank < 0; }
850  ),
851  inside_ranks.end()
852  );
853 
854  // Now adding // NOTE: Should be ordered, so a priori is not required to reorder
855  if (to_be_included) {
856  rSearchInfo.Ranks.push_back(inside_ranks);
857  rSearchInfo.SearchRanks.push_back(search_rank);
858  }
859  }
860  } else { // Serial
861  // Assign values
862  const std::size_t total_number_of_points = itPointEnd - itPointBegin;
863  for (IndexType i_point = 0 ; i_point < total_number_of_points; ++i_point) {
864  auto it_point = itPointBegin + i_point;
865  if (PointIsInsideBoundingBox(rBoundingBox, *it_point, ThresholdBoundingBox)) {
866  const auto& r_coordinates = it_point->Coordinates();
867  for (i_coord = 0; i_coord < 3; ++i_coord) {
868  rSearchInfo.PointCoordinates.push_back(r_coordinates[i_coord]);
869  }
870  rSearchInfo.Indexes.push_back(all_points_ids[i_point]);
871  rSearchInfo.Ranks.push_back({0});
872  }
873  }
874  }
875 
876  // Shrink to actual size
877  rSearchInfo.Shrink();
878 
879  return all_points_ids;
880  }
881 
889  static std::vector<double> SynchronizeRadius(
890  const std::vector<int>& rRecvSizes,
891  const std::vector<double>& rRadius,
892  const DataCommunicator& rDataCommunicator
893  )
894  {
895  // First we calculate the total number of points to communicate
896  const int total_number_of_points = std::accumulate(rRecvSizes.begin(), rRecvSizes.end(), 0);
897 
898  // Synchronize radius
899  if (total_number_of_points == 0) { // If all points are the same
900  return rRadius;
901  } else { // If not
902  // The resulting radius
903  std::vector<double> all_points_radius(total_number_of_points);
904 
905  // MPI information
906  const int world_size = rDataCommunicator.Size();
907 
908  // Generate vectors with sizes for AllGatherv
909  std::vector<int> recv_offsets(world_size, 0);
910  for (int i_rank = 1; i_rank < world_size; ++i_rank) {
911  recv_offsets[i_rank] = recv_offsets[i_rank - 1] + rRecvSizes[i_rank - 1];
912  }
913 
914  // Invoke AllGatherv
915  rDataCommunicator.AllGatherv(rRadius, all_points_radius, rRecvSizes, recv_offsets);
916 
917  return all_points_radius;
918  }
919  }
920 
930  template<typename TPointIteratorType>
931  static void CalculateNumberOfPoints(
932  TPointIteratorType itPointBegin,
933  TPointIteratorType itPointEnd,
934  int& rNumberOfPoints,
935  int& rTotalNumberOfPoints,
936  const DataCommunicator& rDataCommunicator
937  )
938  {
939  // Getting local number of points
940  rNumberOfPoints = std::distance(itPointBegin, itPointEnd);
941 
942  // In case of considering nodes (and distributed)
943  if (rDataCommunicator.IsDistributed()) {
944  if constexpr (std::is_same<TPointIteratorType, ModelPart::NodeIterator>::value || std::is_same<TPointIteratorType, ModelPart::NodeConstantIterator>::value) {
945  // Get the rank in MPI
946  const int rank = rDataCommunicator.Rank();
947 
948  // Check if the nodes are local
949  for (auto it_node = itPointBegin; it_node < itPointEnd; ++it_node) {
950  if (it_node->FastGetSolutionStepValue(PARTITION_INDEX) != rank) {
951  --rNumberOfPoints; // Remove is not local
952  }
953  }
954  }
955 
956  // Sum all the nodes
957  rTotalNumberOfPoints = rDataCommunicator.SumAll(rNumberOfPoints);
958  } else { // Serial
959  rTotalNumberOfPoints = rNumberOfPoints;
960  }
961  }
962 
964 };
965 
966 } // namespace Kratos
Representing a bounding box by storing the min and max points.
Definition: bounding_box.h:39
TPointType & GetMinPoint()
Gets a reference to the minimum point.
Definition: bounding_box.h:179
TPointType & GetMaxPoint()
Gets a reference to the maximum point.
Definition: bounding_box.h:199
Serial (do-nothing) version of a wrapper class for MPI communication.
Definition: data_communicator.h:318
virtual int Size() const
Get the parallel size of this DataCommunicator.
Definition: data_communicator.h:597
virtual int Rank() const
Get the parallel rank for this DataCommunicator.
Definition: data_communicator.h:587
virtual bool IsDistributed() const
Check whether this DataCommunicator is aware of parallelism.
Definition: data_communicator.h:606
This class is useful for index iteration over containers.
Definition: parallel_utilities.h:451
void for_each(TUnaryFunction &&f)
Definition: parallel_utilities.h:514
Point class.
Definition: point.h:59
Custom Point container to be used by the search.
Definition: point_object.h:56
MPI utilities for searching geometrical objects.
Definition: search_utilities.h:115
static bool PointIsInsideBoundingBox(const BoundingBox< TPointType > &rBoundingBox, const array_1d< double, 3 > &rCoords)
Check if a point is inside a bounding box.
Definition: search_utilities.h:154
static std::vector< IndexType > SynchronousPointSynchronizationWithBoundingBox(TPointIteratorType itPointBegin, TPointIteratorType itPointEnd, DistributedSearchInformation &rSearchInfo, const TBoundingBoxType &rBoundingBox, const double ThresholdBoundingBox, const DataCommunicator &rDataCommunicator, const bool IndexItIsJustCounter=false)
SynchronousPointSynchronization prepares synchronously the coordinates of the points for MPI search.
Definition: search_utilities.h:295
static std::vector< typename PointObject< typename TContainer::value_type >::Pointer > PreparePointsSearch(const TContainer &rStructure)
This method prepares the points for search.
Definition: search_utilities.h:442
static bool PointIsInsideBoundingBox(const BoundingBoxType &rBoundingBox, const array_1d< double, 3 > &rCoords)
Check if a point is inside a bounding box.
Definition: search_utilities.h:178
static void ComputeBoundingBoxesWithToleranceCheckingNullBB(const std::vector< double > &rBoundingBoxes, const double Tolerance, std::vector< double > &rBoundingBoxesWithTolerance)
Compute the bounding boxes of the given bounding boxes from a given tolerance, additionally checking ...
Definition: search_utilities.cpp:51
std::array< double, 6 > BoundingBoxType
The Bounding Box type.
Definition: search_utilities.h:121
std::size_t SizeType
The size type definition.
Definition: search_utilities.h:127
static void PrepareOutputSearch(const TContainer &rInput, TResultType &rResults, VectorDistanceType &rResultsDistance)
This method prepares the search output.
Definition: search_utilities.h:420
static void ComputeBoundingBoxesWithTolerance(const std::vector< double > &rBoundingBoxes, const double Tolerance, std::vector< double > &rBoundingBoxesWithTolerance)
Compute the bounding boxes of the given bounding boxes from a given tolerance.
Definition: search_utilities.cpp:24
static std::vector< int > SynchronousPointSynchronizationWithRecvSizes(TPointIteratorType itPointBegin, TPointIteratorType itPointEnd, std::vector< double > &rAllPointsCoordinates, std::vector< IndexType > &rAllPointsIds, const DataCommunicator &rDataCommunicator)
SynchronousPointSynchronizationWithRecvSizes prepares synchronously the coordinates of the points for...
Definition: search_utilities.h:328
std::vector< double > DistanceType
Definition: search_utilities.h:131
static void SynchronousPointSynchronization(TPointIteratorType itPointBegin, TPointIteratorType itPointEnd, std::vector< double > &rAllPointsCoordinates, std::vector< IndexType > &rAllPointsIds, const DataCommunicator &rDataCommunicator)
SynchronousPointSynchronization prepares synchronously the coordinates of the points for MPI search.
Definition: search_utilities.h:262
static std::vector< double > SynchronousPointSynchronizationWithRadius(TPointIteratorType itPointBegin, TPointIteratorType itPointEnd, std::vector< double > &rAllPointsCoordinates, std::vector< IndexType > &rAllPointsIds, const std::vector< double > &rRadius, const DataCommunicator &rDataCommunicator)
SynchronousPointSynchronizationWithRadius prepares synchronously the coordinates of the points for MP...
Definition: search_utilities.h:360
static std::vector< typename PointObject< typename TContainer::value_type >::Pointer > PrepareSearch(const TContainer &rStructure, const TContainer &rInput, TResultType &rResults, VectorDistanceType &rResultsDistance)
This method prepares the search.
Definition: search_utilities.h:397
static constexpr double ZeroTolerance
Define zero tolerance as Epsilon.
Definition: search_utilities.h:135
static void ParallelSearch(const TContainer &rInput, const RadiusArrayType &rRadius, TSpatialContainer &rSearch, TResultType &rResults, VectorDistanceType &rResultsDistance, const int AllocationSize=1000)
This method performs the search in parallel.
Definition: search_utilities.h:476
long unsigned int IndexType
The index type definition.
Definition: search_utilities.h:124
std::vector< double > RadiusArrayType
Input/output types.
Definition: search_utilities.h:130
std::vector< DistanceType > VectorDistanceType
Definition: search_utilities.h:132
static bool PointIsInsideBoundingBox(const BoundingBox< TPointType > &rBoundingBox, const array_1d< double, 3 > &rCoords, const double Tolerance)
This method checks if a point is inside a bounding box considering a certain tolerance.
Definition: search_utilities.h:200
BOOST_UBLAS_INLINE size_type size() const
Definition: array_1d.h:370
BOOST_UBLAS_INLINE const_iterator begin() const
Definition: array_1d.h:606
#define KRATOS_DEBUG_ERROR_IF(conditional)
Definition: exception.h:171
TSpaceType::IndexType Size(TSpaceType &dummy, typename TSpaceType::VectorType const &rV)
Definition: add_strategies_to_python.cpp:111
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
TExpressionType::data_type norm_2(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression)
Definition: amatrix_interface.h:625
std::vector< PointTypePointer > PointVector
Definition: internal_variables_interpolation_process.h:53
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
PointType::Pointer PointTypePointer
Definition: internal_variables_interpolation_process.h:52
REACTION_CHECK_STIFFNESS_FACTOR int
Definition: contact_structural_mechanics_application_variables.h:75
std::vector< double > DistanceVector
Definition: internal_variables_interpolation_process.h:55
Point PointType
Geometric definitions.
Definition: mortar_classes.h:36
int j
Definition: quadrature.py:648
int counter
Definition: script_THERMAL_CORRECT.py:218
integer i
Definition: TensorModule.f:17
This struct provides information related with distributed search.
Definition: search_utilities.h:59
void Shrink()
Shrink the capacity of the point data vectors to fit the data.
Definition: search_utilities.h:86
std::vector< std::vector< int > > Ranks
Ranks where search is invoked.
Definition: search_utilities.h:69
std::size_t IndexType
Alias for the data type used to represent indices.
Definition: search_utilities.h:61
std::vector< int > SearchRanks
Vector to store point indices.
Definition: search_utilities.h:68
void Reserve(const SizeType Size)
Vector of vectors to store ranks.
Definition: search_utilities.h:75
std::size_t SizeType
Alias for the data type used to represent sizes.
Definition: search_utilities.h:64
std::vector< IndexType > Indexes
Vector to store point coordinates.
Definition: search_utilities.h:67
std::vector< double > PointCoordinates
Definition: search_utilities.h:66
void Clear()
Clear all the data in the point data vectors.
Definition: search_utilities.h:97