opm-common
TrackOrderingTSP.hpp
1 /*
2  Copyright 2026 Equinor ASA.
3 
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef OPM_TRACK_ORDERING_TSP_HPP
21 #define OPM_TRACK_ORDERING_TSP_HPP
22 
23 #include <algorithm>
24 #include <compare>
25 #include <concepts>
26 #include <cstddef>
27 #include <cstdint>
28 #include <initializer_list>
29 #include <span>
30 #include <type_traits>
31 #include <vector>
32 
33 namespace Opm {
34  class Connection;
35 } // namespace Opm
36 
37 namespace Opm {
38 
42 {
43 public:
46  {
48  double w_ij {1.0};
49 
51  double w_k {0.5};
52 
54  double w_z {0.05};
55 
58  double w_dir {0.25};
59 
77  double z_to_ij_scale {0.05};
78 
86  [[nodiscard]] constexpr bool isValid() const noexcept
87  {
88  auto&& [ij, k, z, dir, z_scale] = *this;
89 
90  []<typename... Ts>(Ts&&...) {
91  static_assert((std::same_as<double, std::decay_t<Ts>> && ...),
92  "TrackCostWeights must only contain double members.");
93  }(ij, k, z, dir, z_scale);
94 
95  const auto all_nonneg = std::ranges::
96  all_of(std::initializer_list {ij, k, z, dir, z_scale},
97  [](const auto w) { return w >= 0.0; });
98 
99  // Note: z_scale (z_to_ij_scale) is intentionally omitted from
100  // the check that at least one weight is positive. It is not a
101  // direct cost weight but rather a scale factor. If only the
102  // z_scale is positive, the edge cost function would be
103  // identically zero and thus not well-defined. The z_scale must
104  // still be non-negative, but that requirement is enforced by
105  // the all_nonneg check.
106  return all_nonneg
107  && std::ranges::any_of(std::initializer_list {ij, k, z, dir},
108  [](const auto w) { return w > 0.0; });
109  }
110  };
111 
113  TrackOrderingTSP(int headI, int headJ);
114 
125  TrackOrderingTSP& numberOfStartPoints(std::size_t numStarts);
126 
134  std::vector<std::size_t>
135  order(std::span<const Connection> connections) const;
136 
145  std::vector<std::size_t>
146  order(std::span<const Connection> connections,
147  const TrackCostWeights& weights) const;
148 
149 private:
156  struct CandidateStart
157  {
161  std::int_least64_t ijdist2 {};
162 
168  double zdiff {};
169 
173  std::size_t index {};
174 
179  auto operator<=>(const CandidateStart&) const = default;
180  };
181 
183  int headI_{};
184 
186  int headJ_{};
187 
192  std::size_t numStartPoints_{1};
193 
200  std::vector<CandidateStart>
201  determineStartPoints(std::span<const Connection> connections) const;
202 };
203 
204 } // namespace Opm
205 
206 #endif // OPM_TRACK_ORDERING_TSP_HPP
double w_k
Weight for logical K-index step distance.
Definition: TrackOrderingTSP.hpp:51
TrackOrderingTSP & numberOfStartPoints(std::size_t numStarts)
Set number of start points from which to explore path creation.
Definition: TrackOrderingTSP.cpp:298
TrackOrderingTSP(int headI, int headJ)
Construct with the well-head logical cartesian indices.
Definition: TrackOrderingTSP.cpp:292
double w_ij
Weight for horizontal logical-grid distance in the I/J plane.
Definition: TrackOrderingTSP.hpp:48
double w_dir
Weight for direction-misalignment penalty between successive connections and their step vector...
Definition: TrackOrderingTSP.hpp:58
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
std::vector< std::size_t > order(std::span< const Connection > connections) const
Return the permutation that puts connections in TRACK order, using default-constructed TrackCostWeigh...
Definition: TrackOrderingTSP.cpp:309
double w_z
Weight for geometric depth difference.
Definition: TrackOrderingTSP.hpp:54
constexpr bool isValid() const noexcept
Check if the weights are valid for use in the edge-cost function.
Definition: TrackOrderingTSP.hpp:86
double z_to_ij_scale
Scale factor that maps depth differences into the I/J distance metric used by the direction penalty t...
Definition: TrackOrderingTSP.hpp:77
Cost weights controlling the TRACK edge-cost function.
Definition: TrackOrderingTSP.hpp:45
Multi-start nearest-neighbour + 2-opt TSP heuristic for TRACK ordering of well connections.
Definition: TrackOrderingTSP.hpp:41