@@ -2832,69 +2832,77 @@ template <
28322832 return ret;
28332833 }
28342834
2835- std::map< int , std::vector< uint64_t > > get_vlasov_neighbors (
2835+ std::set< uint64_t > get_vlasov_neighbors (
28362836 const uint64_t cell,
28372837 const int neighborhood_id,
28382838 const int dimension,
28392839 const int stencil_width
28402840 ) const {
2841- std::map<int , std::vector<uint64_t >> ret;
2842- int my_ref {mapping.get_refinement_level (cell)};
2843- std::vector<std::pair<uint64_t , std::array<int , 4 >>> neighs;
2841+ std::set<uint64_t > ret;
28442842 const auto * p = get_neighbors_of (cell, neighborhood_id);
28452843 if (!p) {
28462844 std::cerr << " Cell " << cell << " , neighborhood " << neighborhood_id << " , dimension " << dimension << " not found" << std::endl;
28472845 return ret;
28482846 }
28492847
2850- neighs = *p;
2851- // We still need to sort since more refined cells are in xyz order
2852- std::stable_sort (neighs.begin (), neighs.end (),
2853- [this , dimension] (const std::pair<uint64_t , std::array<int , 4 >>& a, const std::pair<uint64_t , std::array<int , 4 >>& b) {
2854- return distance_to_double (a.second )[dimension] < distance_to_double (b.second )[dimension];
2848+ // Create list of unique distances
2849+ std::set<int > distances_plus;
2850+ std::set<int > distances_minus;
2851+ std::set<uint64_t > found_neighbors_plus;
2852+ std::set<uint64_t > found_neighbors_minus;
2853+ /* * Using sets of cells as well, we should only get one distance per
2854+ (potentially less refined) cell. This should result in safe behaviour
2855+ as long as the neighborhood of a cell does not contain cells with a
2856+ refinement level more than 1 level apart from the cell itself.
2857+ */
2858+ for (const auto & [neighbor, coords] : *p) {
2859+ if (coords[dimension] > 0 ) {
2860+ if (!found_neighbors_plus.count (neighbor)) {
2861+ distances_plus.insert (coords[dimension]);
2862+ found_neighbors_plus.insert (neighbor);
2863+ }
28552864 }
2856- );
2857-
2858- auto it = neighs.cbegin ();
2859- while (it < neighs.cend () && it->second [dimension] < 0 ) {
2860- ++it;
2861- }
2862-
2863- int found {0 };
2864- std::uint64_t previous_cell {error_cell};
2865- double previous_offset {0.0 };
2866- for (auto neg = std::make_reverse_iterator (it); neg != neighs.crend (); ++neg) {
2867- double offset = distance_to_double (neg->second )[dimension];
2868- if (neg->first == previous_cell || neg->first == error_cell) {
2869- continue ;
2870- } else if (offset < previous_offset) {
2871- if (++found > stencil_width)
2872- break ;
2865+ if (coords[dimension] < 0 ) {
2866+ if (!found_neighbors_minus.count (neighbor)) {
2867+ distances_minus.insert (-coords[dimension]);
2868+ found_neighbors_minus.insert (neighbor);
2869+ }
28732870 }
2874-
2875- ret[-found].push_back (neg->first );
2876- previous_cell = neg->first ;
28772871 }
28782872
2879- while (it < neighs.cend () && it->second [dimension] <= 0 ) {
2880- ++it;
2881- }
2882-
2883- found = 0 ;
2884- previous_cell = error_cell;
2885- previous_offset = 0.0 ;
2886- for (auto pos = it; pos != neighs.cend (); ++pos) {
2887- double offset = distance_to_double (pos->second )[dimension];
2888- if (pos->first == previous_cell || pos->first == error_cell) {
2889- continue ;
2890- } else if (offset > previous_offset) {
2891- if (++found > stencil_width)
2892- break ;
2893- }
2894-
2895- ret[found].push_back (pos->first );
2896- previous_cell = pos->first ;
2897- }
2873+ int iSrc = stencil_width - 1 ;
2874+ // Iterate through positive distances for VLASOV_STENCIL_WIDTH elements starting from the smallest distance.
2875+ for (const auto & distance : distances_plus) {
2876+ if (iSrc < 0 )
2877+ break ; // found enough elements
2878+ for (const auto & [neighbor, coords] : *p) {
2879+ if (neighbor == error_cell)
2880+ continue ;
2881+ if (coords[dimension] == distance) {
2882+ if (ret.count (neighbor))
2883+ continue ;
2884+ ret.insert (neighbor);
2885+ }
2886+ } // end loop over neighbors
2887+ iSrc--;
2888+ } // end loop over positive distances
2889+
2890+ iSrc = stencil_width - 1 ;
2891+ // Iterate through negtive distances for VLASOV_STENCIL_WIDTH elements starting from the smallest distance.
2892+ for (const auto & distance : distances_minus) {
2893+ if (iSrc < 0 )
2894+ break ; // found enough elements
2895+ for (const auto & [neighbor, coords] : *p) {
2896+ if (neighbor == error_cell)
2897+ continue ;
2898+ if (coords[dimension] == distance) {
2899+ if (ret.count (neighbor))
2900+ continue ;
2901+ ret.insert (neighbor);
2902+ }
2903+ } // end loop over neighbors
2904+ iSrc--;
2905+ } // end loop over negative distances
28982906
28992907 return ret;
29002908 }
@@ -2922,9 +2930,8 @@ template <
29222930
29232931 std::set<uint64_t > ret;
29242932 for (int dim = 0 ; dim < 3 ; ++dim) {
2925- for (auto & [dist, cells] : get_vlasov_neighbors (cell, partitioning_neighborhood_id + dim, dim, stencil_width)) {
2926- ret.insert (cells.begin (), cells.end ());
2927- }
2933+ auto neighs_dim = get_vlasov_neighbors (cell, partitioning_neighborhood_id + dim, dim, stencil_width);
2934+ ret.insert (neighs_dim.begin (), neighs_dim.end ());
29282935 }
29292936 return ret;
29302937 }
0 commit comments