-
Notifications
You must be signed in to change notification settings - Fork 2
/
partition_domain.py
189 lines (138 loc) · 8.52 KB
/
partition_domain.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
"""
Function that partitions the domain
"""
import numpy as np
import math
from find_parametric_intersect import find_parametric_intersect
def partition_domain(act_frac_sys, frac_order_vec, tolerance_intersect, number_partitions_x, number_partitions_y):
"""
:param frac_order_vec:
:param act_frac_sys:
:param tolerance_intersect:
:param number_partitions_x:
:param number_partitions_y:
:return:
"""
# Define lowest and highest possible x and y values.
xmin = act_frac_sys[:, [0,2]].min(axis=None)
xmax = act_frac_sys[:, [0,2]].max(axis=None)
ymin = act_frac_sys[:, [1,3]].min(axis=None)
ymax = act_frac_sys[:, [1,3]].max(axis=None)
interval_x = (xmax - xmin) / number_partitions_x
interval_y = (ymax - ymin) / number_partitions_y
# Assume the maximum values found above define the domain.
# Then, to partition the domain:
partitions_x = np.zeros((number_partitions_x - 1, 4))
for i in range(1, number_partitions_x):
x_part = xmin + interval_x * i
partitions_x[i - 1, :] = np.array([x_part, ymin, x_part, ymax])
partitions_y = np.zeros((number_partitions_y - 1, 4))
for j in range(1, number_partitions_y):
y_part = ymin + interval_y * j
partitions_y[j - 1, :] = np.array([xmin, y_part, xmax, y_part])
# This array will contain information about the partitioning lines which which can be used to find intersections.
# [x0, y0, x1, y1]
partitions = np.vstack((partitions_x, partitions_y))
# We use this little trick to make sure the subdomains are determined correctly.
act_frac_sys[np.where(act_frac_sys == xmax)] = xmax - 0.01
act_frac_sys[np.where(act_frac_sys == ymax)] = ymax - 0.01
# Variables used to store information in an array later in the program.
old_index = 0
new_index = 0
subdomain_sys = np.transpose([np.floor((act_frac_sys[:, 0] - xmin) / interval_x),
np.floor((act_frac_sys[:, 1] - ymin) / interval_y),
np.floor((act_frac_sys[:, 2] - xmin) / interval_x),
np.floor((act_frac_sys[:, 3] - ymin) / interval_y)])
# Change back what we did to get the right subdomains
act_frac_sys[np.where(act_frac_sys == xmax - 0.01)] = xmax
act_frac_sys[np.where(act_frac_sys == ymax - 0.01)] = ymax
fracs_to_part_x = np.where(subdomain_sys[:, 0] != subdomain_sys[:, 2])[0]
fracs_to_part_y = np.where(subdomain_sys[:, 1] != subdomain_sys[:, 3])[0]
# An array of indices referring to fractures that must be split due to partitioning.
fracs_to_part = np.union1d(fracs_to_part_x, fracs_to_part_y)
part_frac_sys = act_frac_sys[fracs_to_part]
part_frac_subdomains = subdomain_sys[fracs_to_part]
# CHECK
tot_new_fracs = np.sum(np.abs(subdomain_sys[fracs_to_part, 2] - subdomain_sys[fracs_to_part, 0]) + \
np.abs(subdomain_sys[fracs_to_part, 3] - subdomain_sys[fracs_to_part, 1]), dtype=int) + len(fracs_to_part)
# Array where all newly found partitioned fractures will be stored. The number of rows is pretty arbitrary.
part_fracs = np.zeros((tot_new_fracs, 5))
# Arrays where all information is stored to, in the end, form frac_order_vec_list.
part_frac_order_vec = np.zeros(tot_new_fracs)
# To clear some memory, the subdomains which are in part_frac_subdomains can now be deleted from the original array.
subdomain_sys = np.delete(subdomain_sys, fracs_to_part, axis=0)
ii = -1
for ii_frac in part_frac_sys:
ii += 1
# The subdomains of points in this fracture
ii_subdomains = part_frac_subdomains[ii, :]
# I do not expect a fracture to cross more than 6 partition lines. Still an estimate though.
num_ints = int(abs(ii_subdomains[2] - ii_subdomains[0]) + abs(ii_subdomains[3] - ii_subdomains[1]))
part_int = np.zeros((num_ints, 2))
# Counts the amount of intersections between the given ii fracture and all partitioning lines.
int_counter = 0
# Partition IDs. [subdomain xmin, subdomain xmax, subdomain ymin, subdomain ymax]
# (an offset was added to subdomains of y to establish the difference between x and y)
partition_ids = [int(min(ii_subdomains[0], ii_subdomains[2])),
int(max(ii_subdomains[0], ii_subdomains[2])),
int(number_partitions_x - 1 + min(ii_subdomains[1], ii_subdomains[3])),
int(number_partitions_x - 1 + max(ii_subdomains[1], ii_subdomains[3]))]
# x partitions
for jj_part in partitions[partition_ids[0]:partition_ids[1]]:
t, s, int_coord = find_parametric_intersect(ii_frac, jj_part)
if (t >= (0 - tolerance_intersect) and t <= (1 + tolerance_intersect)) and \
(s >= (0 - tolerance_intersect) and s <= (1 + tolerance_intersect)):
# Only store intersections of segments that don't already share a node:
if not (np.linalg.norm(ii_frac[:2] - jj_part[:2]) < tolerance_intersect or
np.linalg.norm(ii_frac[:2] - jj_part[2:]) < tolerance_intersect or
np.linalg.norm(ii_frac[2:] - jj_part[:2]) < tolerance_intersect or
np.linalg.norm(ii_frac[2:] - jj_part[2:]) < tolerance_intersect):
# Store the intersection coordinates in part_int
part_int[int_counter, :] = np.array([int_coord[0], int_coord[1]])
int_counter += 1
# y partitions
for jj_part in partitions[partition_ids[2]:partition_ids[3]]:
t, s, int_coord = find_parametric_intersect(ii_frac, jj_part)
if (t >= (0 - tolerance_intersect) and t <= (1 + tolerance_intersect)) and \
(s >= (0 - tolerance_intersect) and s <= (1 + tolerance_intersect)):
# Only store intersections of segments that don't already share a node:
if not (np.linalg.norm(ii_frac[:2] - jj_part[:2]) < tolerance_intersect or
np.linalg.norm(ii_frac[:2] - jj_part[2:]) < tolerance_intersect or
np.linalg.norm(ii_frac[2:] - jj_part[:2]) < tolerance_intersect or
np.linalg.norm(ii_frac[2:] - jj_part[2:]) < tolerance_intersect):
# Store the intersection coordinates in part_int
part_int[int_counter, :] = np.array([int_coord[0], int_coord[1]])
int_counter += 1
# Add x0 and y0 of fracture ii to start of part_int, and x1 and y1 to the end of it.
part_int = np.vstack((np.vstack((ii_frac[:2], part_int)), ii_frac[2:]))
# Sort on x values
part_int = part_int[np.lexsort((part_int[:, 1], part_int[:, 0]))]
# Initialization of the array that will contain the information about the new fractures.
new_fracs = np.zeros((num_ints+1, 5))
for mm in range(0, num_ints + 1):
x0, y0, x1, y1 = part_int[mm, 0], part_int[mm, 1], part_int[mm + 1, 0], part_int[mm + 1, 1]
# This is how we find out in which subdomain the fracture will be. We add this ID to new_fracs
subdomain_id = math.floor((((x0 + x1) / 2) - xmin) / interval_x) + \
math.floor((((y0 + y1) / 2) - ymin) / interval_y) * number_partitions_x
new_fracs[mm, :] = np.array([x0, y0, x1, y1, subdomain_id])
new_index += num_ints+1
# Add fractures to the array that combines them all
part_fracs[old_index:new_index] = new_fracs
part_frac_order_vec[old_index:new_index] = np.ones(new_index - old_index) * frac_order_vec[fracs_to_part[ii]]
old_index = new_index
act_frac_sys = np.delete(act_frac_sys, fracs_to_part, axis=0)
num_old_fracs = len(subdomain_sys[:, 0])
subdomains_old = subdomain_sys[:, 0] + subdomain_sys[:, 1] * number_partitions_x
subdomains_old = subdomains_old.reshape((num_old_fracs,1))
act_frac_sys = np.hstack((act_frac_sys, subdomains_old))
act_frac_sys = np.vstack((act_frac_sys, part_fracs))
frac_order_vec = np.delete(frac_order_vec, fracs_to_part, axis=0)
frac_order_vec = np.hstack((frac_order_vec, part_frac_order_vec))
act_frac_sys_list = []
frac_order_vec_list = []
num_subdomains = number_partitions_x * number_partitions_y
for p in range(0, num_subdomains):
indices = np.where(act_frac_sys[:, 4] == p)
act_frac_sys_list.append(act_frac_sys[indices, :4][0])
frac_order_vec_list.append(frac_order_vec[indices])
return act_frac_sys_list, frac_order_vec_list, partitions