Skip to content

Commit f68781e

Browse files
authored
Merge pull request #656 from pmgbergen/refactor-exporter
Refactor Exporter
2 parents 5f9f575 + 66dec10 commit f68781e

4 files changed

Lines changed: 6908 additions & 8401 deletions

File tree

src/porepy/utils/sort_points.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,104 @@ def sort_point_pairs(
102102
return sorted_lines, sort_ind
103103

104104

105+
def sort_multiple_point_pairs(lines: np.ndarray) -> np.ndarray:
106+
"""Function to sort multiple pairs of points to form circular chains.
107+
108+
The routine contains essentially the same functionality as sort_point_pairs,
109+
but stripped down to the special case of circular chains. Differently to
110+
sort_point_pairs, this variant sorts an arbitrary amount of independent
111+
point pairs. The chains are restricted by the assumption that each contains
112+
equally many line segments. Finally, this routine uses numba.
113+
114+
Parameters:
115+
lines (np.ndarray): Array of size 2 * num_chains x num_lines_per_chain,
116+
containing node indices. For each pair of two rows, each column
117+
represents a line segment connectng the two nodes in the two entries
118+
of this column.
119+
120+
Returns:
121+
np.ndarray: Sorted version of lines, where for each chain, the collection
122+
of l
123+
124+
Raises:
125+
ImportError ifine segments has been potentially flipped and sorted.
126+
"""
127+
128+
try:
129+
import numba
130+
except ImportError:
131+
raise ImportError("Numba not available on the system")
132+
133+
@numba.njit("f8[:,:](i4[:,:])", cache=True)
134+
def _function_to_compile(lines):
135+
"""
136+
Copy of pp.utils.sort_points.sort_point_pairs. This version is extended
137+
to multiple chains. Each chain is implicitly assumed to be circular.
138+
"""
139+
140+
# Retrieve number of chains and lines per chain from the shape.
141+
# Implicitly expect that all chains have the same length
142+
num_chains, chain_length = lines.shape
143+
# Since for each chain lines includes two rows, divide by two
144+
num_chains = int(num_chains / 2)
145+
146+
# Initialize array of sorted lines to be the final output
147+
sorted_lines = np.zeros((2 * num_chains, chain_length))
148+
# Fix the first line segment for each chain and identify
149+
# it as in place regarding the sorting.
150+
sorted_lines[:, 0] = lines[:, 0]
151+
# Keep track of which lines have been fixed and which are still candidates
152+
found = np.zeros(chain_length)
153+
found[0] = 1
154+
155+
# Loop over chains and consider each chain separately.
156+
for c in range(num_chains):
157+
# Initialize found making any line segment aside of the first a candidate
158+
found[1:] = 0
159+
160+
# Define the end point of the previous and starting point for the next
161+
# line segment
162+
prev = sorted_lines[2 * c + 1, 0]
163+
164+
# The sorting algorithm: Loop over all positions in the chain to be set next.
165+
# Find the right candidate to be moved to this position and possibly flipped
166+
# if needed. A candidate is identified as fitting if it contains one point
167+
# equal to the current starting point. This algorithm uses a double loop,
168+
# which is the most naive approach. However, assume chain_length is in
169+
# general small.
170+
for i in range(1, chain_length): # The first line has already been found
171+
for j in range(
172+
1, chain_length
173+
): # The first line has already been found
174+
# A candidate line segment with matching start and end point
175+
# in the first component of the point pair.
176+
if np.abs(found[j]) < 1e-6 and lines[2 * c, j] == prev:
177+
# Copy the segment to the right place
178+
sorted_lines[2 * c : 2 * c + 2, i] = lines[2 * c : 2 * c + 2, j]
179+
# Mark as used
180+
found[j] = 1
181+
# Define the starting point for the next line segment
182+
prev = lines[2 * c + 1, j]
183+
break
184+
# A candidate line segment with matching start and end point
185+
# in the second component of the point pair.
186+
elif np.abs(found[j]) < 1e-6 and lines[2 * c + 1, j] == prev:
187+
# Flip and copy the segment to the right place
188+
sorted_lines[2 * c, i] = lines[2 * c + 1, j]
189+
sorted_lines[2 * c + 1, i] = lines[2 * c, j]
190+
# Mark as used
191+
found[j] = 1
192+
# Define the starting point for the next line segment
193+
prev = lines[2 * c, j]
194+
break
195+
196+
# Return the sorted lines defining chains.
197+
return sorted_lines
198+
199+
# Run numba compiled function
200+
return _function_to_compile(lines)
201+
202+
105203
def sort_point_plane(
106204
pts: np.ndarray,
107205
centre: np.ndarray,

0 commit comments

Comments
 (0)