Skip to content

Commit 4f5a831

Browse files
sc-itamtezzele
authored andcommitted
unvhandler fixes and freeform performances improved (#91)
* improved performance in freeform (~25%) * fixed bug and improved flexibility in unvhandler * new write comparison in unv tests
1 parent 2406a4a commit 4f5a831

File tree

3 files changed

+82
-85
lines changed

3 files changed

+82
-85
lines changed

pygem/freeform.py

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ class FFD(object):
6767
>>> original_mesh_points = np.load('tests/test_datasets/meshpoints_sphere_orig.npy')
6868
>>> free_form = ffd.FFD(ffd_parameters, original_mesh_points)
6969
>>> free_form.perform()
70-
>>> new_mesh_points = free_form.modified_mesh_points
71-
"""
70+
>>> new_mesh_points = free_form.modified_mesh_points
71+
"""
7272
def __init__(self, ffd_parameters, original_mesh_points):
7373
self.parameters = ffd_parameters
7474
self.original_mesh_points = original_mesh_points
@@ -81,22 +81,31 @@ def perform(self):
8181
it sets `self.modified_mesh_points`.
8282
8383
.. todo::
84-
In order to improve the performances, we need to perform the FFD only on the points inside
85-
the lattice.
86-
"""
87-
(n_rows_mesh, n_cols_mesh) = self.original_mesh_points.shape
8884
85+
"""
8986
# translation and then affine transformation
9087
translation = self.parameters.origin_box
9188

92-
fisical_frame = np.array([self.parameters.position_vertex_1 - translation, \
93-
self.parameters.position_vertex_2 - translation, \
94-
self.parameters.position_vertex_3 - translation, \
95-
[0, 0, 0]])
89+
physical_frame = np.array([self.parameters.position_vertex_1 - translation,
90+
self.parameters.position_vertex_2 - translation,
91+
self.parameters.position_vertex_3 - translation,
92+
[0, 0, 0]])
9693
reference_frame = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1], [0, 0, 0]])
9794

98-
transformation = at.affine_points_fit(fisical_frame, reference_frame)
99-
inverse_transformation = at.affine_points_fit(reference_frame, fisical_frame)
95+
transformation = at.affine_points_fit(physical_frame, reference_frame)
96+
inverse_transformation = at.affine_points_fit(reference_frame, physical_frame)
97+
98+
# apply transformation to original mesh points
99+
reference_frame_mesh_points = self._transform_points(self.original_mesh_points - translation, transformation)
100+
101+
# select mesh points inside bounding box
102+
mesh_points = reference_frame_mesh_points[(reference_frame_mesh_points[:,0] >= 0.) &
103+
(reference_frame_mesh_points[:,0] <= 1.) &
104+
(reference_frame_mesh_points[:,1] >= 0.) &
105+
(reference_frame_mesh_points[:,1] <= 1.) &
106+
(reference_frame_mesh_points[:,2] >= 0.) &
107+
(reference_frame_mesh_points[:,2] <= 1.)]
108+
(n_rows_mesh, n_cols_mesh) = mesh_points.shape
100109

101110
# Initialization. In order to exploit the contiguity in memory the following are transposed
102111
(dim_n_mu, dim_m_mu, dim_t_mu) = self.parameters.array_mu_x.shape
@@ -105,22 +114,19 @@ def perform(self):
105114
bernstein_z = np.zeros((dim_t_mu, n_rows_mesh))
106115
shift_mesh_points = np.zeros((n_cols_mesh, n_rows_mesh))
107116

108-
reference_frame_mesh_points = self._transform_points(self.original_mesh_points - translation, \
109-
transformation)
110-
111117
for i in range(0, dim_n_mu):
112-
aux1 = np.power((1-reference_frame_mesh_points[:, 0]), dim_n_mu-1-i)
113-
aux2 = np.power(reference_frame_mesh_points[:, 0], i)
118+
aux1 = np.power((1-mesh_points[:, 0]), dim_n_mu-1-i)
119+
aux2 = np.power(mesh_points[:, 0], i)
114120
bernstein_x[i, :] = special.binom(dim_n_mu-1, i) * np.multiply(aux1, aux2)
115121

116122
for i in range(0, dim_m_mu):
117-
aux1 = np.power((1-reference_frame_mesh_points[:, 1]), dim_m_mu-1-i)
118-
aux2 = np.power(reference_frame_mesh_points[:, 1], i)
123+
aux1 = np.power((1-mesh_points[:, 1]), dim_m_mu-1-i)
124+
aux2 = np.power(mesh_points[:, 1], i)
119125
bernstein_y[i, :] = special.binom(dim_m_mu-1, i) * np.multiply(aux1, aux2)
120126

121127
for i in range(0, dim_t_mu):
122-
aux1 = np.power((1-reference_frame_mesh_points[:, 2]), dim_t_mu-1-i)
123-
aux2 = np.power(reference_frame_mesh_points[:, 2], i)
128+
aux1 = np.power((1-mesh_points[:, 2]), dim_t_mu-1-i)
129+
aux2 = np.power(mesh_points[:, 2], i)
124130
bernstein_z[i, :] = special.binom(dim_t_mu-1, i) * np.multiply(aux1, aux2)
125131

126132

@@ -138,18 +144,22 @@ def perform(self):
138144
shift_mesh_points[0, :] += aux_x
139145
shift_mesh_points[1, :] += aux_y
140146
shift_mesh_points[2, :] += aux_z
141-
142-
# Splitting points inside and outside the lattice: TODO not very efficient
143-
for i in range(0, n_rows_mesh):
144-
if (reference_frame_mesh_points[i, 0] < 0) or (reference_frame_mesh_points[i, 1] < 0) \
145-
or (reference_frame_mesh_points[i, 2] < 0) or (reference_frame_mesh_points[i, 0] > 1) \
146-
or (reference_frame_mesh_points[i, 1] > 1) or (reference_frame_mesh_points[i, 2] > 1):
147-
shift_mesh_points[:, i] = 0
148-
149-
# Here shift_mesh_points needs to be transposed to be summed with reference_frame_mesh_points
150-
self.modified_mesh_points = self._transform_points(np.transpose(shift_mesh_points) + \
151-
reference_frame_mesh_points, inverse_transformation) + translation
152-
147+
148+
# shift_mesh_points needs to be transposed to be summed with mesh_points
149+
# apply inverse transformation to shifted mesh points
150+
new_mesh_points = self._transform_points(np.transpose(shift_mesh_points) +
151+
mesh_points, inverse_transformation) + \
152+
translation
153+
154+
# merge non-shifted mesh points with shifted ones
155+
self.modified_mesh_points = np.copy(self.original_mesh_points)
156+
self.modified_mesh_points[(reference_frame_mesh_points[:,0] >= 0.) &
157+
(reference_frame_mesh_points[:,0] <= 1.) &
158+
(reference_frame_mesh_points[:,1] >= 0.) &
159+
(reference_frame_mesh_points[:,1] <= 1.) &
160+
(reference_frame_mesh_points[:,2] >= 0.) &
161+
(reference_frame_mesh_points[:,2] <= 1.)] \
162+
= new_mesh_points
153163

154164
@staticmethod
155165
def _transform_points(original_points, transformation):
@@ -170,3 +180,4 @@ def _transform_points(original_points, transformation):
170180
modified_points[i, :] = transformation(original_points[i])
171181

172182
return modified_points
183+

pygem/unvhandler.py

Lines changed: 37 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -34,41 +34,26 @@ def parse(self, filename):
3434

3535
self.infile = filename
3636

37+
index = -9
38+
mesh_points = []
3739
with open(self.infile, 'r') as input_file:
38-
nline = 0
39-
while True:
40-
line = input_file.readline()
41-
nline += 1
42-
if not line:
43-
break
44-
if line.startswith(' -1'):
45-
section_id = input_file.readline().strip()
46-
nline += 1
47-
if section_id == '2411':
48-
count = 0
49-
while not input_file.readline().startswith(' -1'):
50-
count += 1
51-
start_line = nline + 2
52-
last_line = start_line + count
40+
for num, line in enumerate(input_file):
41+
if line.startswith(' 2411'):
42+
index = num
43+
if num == index + 2:
44+
if line.startswith(' -1'):
45+
break
5346
else:
54-
while not input_file.readline().startswith(' -1'):
55-
nline += 1
56-
57-
n_points = count/2
58-
mesh_points = np.zeros(shape=(n_points, 3))
59-
60-
nline = 0
61-
i = 0
62-
with open(self.infile, 'r') as input_file:
63-
for line in input_file:
64-
nline += 1
65-
if nline % 2 == 1 and start_line < nline < last_line:
66-
line = line.strip()
67-
j = 0
68-
for number in line.split():
69-
mesh_points[i][j] = float(number)
70-
j += 1
71-
i += 1
47+
line = line.replace('D', 'E')
48+
l = []
49+
for t in line.split():
50+
try:
51+
l.append(float(t))
52+
except ValueError:
53+
pass
54+
mesh_points.append(l)
55+
index = num
56+
mesh_points = np.array(mesh_points)
7257

7358
return mesh_points
7459

@@ -89,16 +74,23 @@ def write(self, mesh_points, filename):
8974

9075
self.outfile = filename
9176

92-
n_points = mesh_points.shape[0]
93-
nrow = 0
77+
index = -9
9478
i = 0
95-
with open(self.infile, 'r') as input_file, open(self.outfile, 'w') as output_file:
96-
for line in input_file:
97-
nrow += 1
98-
if nrow % 2 == 1 and 20 < nrow <= (20 + n_points * 2):
99-
for j in range(0, 3):
100-
output_file.write(' ' + str(mesh_points[i][j]))
101-
output_file.write('\n')
102-
i += 1
103-
elif nrow > 17:
104-
output_file.write(line)
79+
with open(self.outfile, 'w') as output_file:
80+
with open(self.infile, 'r') as input_file:
81+
for num, line in enumerate(input_file):
82+
if line.startswith(' 2411'):
83+
index = num
84+
if num == index + 2:
85+
if line.startswith(' -1'):
86+
index = -9
87+
output_file.write(line)
88+
else:
89+
for j in range(0, 3):
90+
output_file.write(3*' ' + '{:.16E}'.format(mesh_points[i][j]))
91+
output_file.write('\n')
92+
i += 1
93+
index = num
94+
else:
95+
output_file.write(line)
96+

tests/test_unvhandler.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,9 @@ def test_unv_write_outfile(self):
116116
def test_unv_write_comparison(self):
117117
unv_handler = uh.UnvHandler()
118118
mesh_points = unv_handler.parse('tests/test_datasets/test_square.unv')
119-
mesh_points[0][0] = 2.2
120-
mesh_points[5][1] = 4.3
121-
mesh_points[9][2] = 0.5
122-
mesh_points[45][0] = 7.2
123-
mesh_points[132][1] = -1.2
124-
mesh_points[255][2] = -3.6
125119

126120
outfilename = 'tests/test_datasets/test_square_out.unv'
127-
outfilename_expected = 'tests/test_datasets/test_square_out_true.unv'
121+
outfilename_expected = 'tests/test_datasets/test_square.unv'
128122

129123
unv_handler.write(mesh_points, outfilename)
130124
self.assertTrue(filecmp.cmp(outfilename, outfilename_expected))

0 commit comments

Comments
 (0)