@@ -66,7 +66,7 @@ class FFDParameters(object):
6666 Four vertex (non coplanar) are sufficient to uniquely identify a
6767 parallelepiped.
6868 If the four vertex are coplanar, an assert is thrown when
69- `affine_points_fit is used.
69+ `affine_points_fit` is used.
7070
7171 """
7272
@@ -127,6 +127,64 @@ def position_vertices(self):
127127 self .rotation_matrix .dot (np .diag (self .lenght_box )).T
128128 ])
129129
130+
131+ def reflect (self , axis = 0 ):
132+ """
133+ Reflect the lattice of control points along the direction defined
134+ by `axis`. In particular the origin point of the lattice is preserved.
135+ So, for instance, the reflection along x, is made with respect to the
136+ face of the lattice in the yz plane that is opposite to the origin.
137+ Same for the other directions. Only the weights (mu) along the chosen
138+ axis are reflected, while the others are preserved. The symmetry plane
139+ can not present deformations along the chosen axis.
140+ After the refletcion there will be 2n-1 control points along `axis`,
141+ witha doubled box length.
142+
143+ :param int axis: axis along which the reflection is performed.
144+ Default is 0. Possible values are 0, 1, or 2, corresponding
145+ to x, y, and z respectively.
146+ """
147+ # check axis value
148+ if axis not in (0 , 1 , 2 ):
149+ raise ValueError ("The axis has to be 0, 1, or 2. " + \
150+ "Current value {}." .format (axis ))
151+
152+ # check that the plane of symmetry is undeformed
153+ if (axis == 0 and np .sum (self .array_mu_x [- 1 , :, :]) != 0 ) or \
154+ (axis == 1 and np .sum (self .array_mu_y [:, - 1 , :]) != 0 ) or \
155+ (axis == 2 and np .sum (self .array_mu_z [:, :, - 1 ]) != 0 ):
156+ raise RuntimeError ("If you want to reflect the FFD " + \
157+ "bounding box along axis {} " .format (axis ) + \
158+ "you can not diplace the control points in the " + \
159+ "symmetry plane along that axis." )
160+
161+ # double the control points in the given axis minus 1 (the symmetry plane)
162+ self .n_control_points [axis ] = 2 * self .n_control_points [axis ] - 1
163+ # double the box length
164+ self .lenght_box [axis ] *= 2
165+
166+ # we have to reflect the dispacements only along the correct axis
167+ reflection = np .ones (3 )
168+ reflection [axis ] = - 1
169+
170+ # we need to select all the indeces but the ones in the plane of symmetry
171+ indeces = [slice (None ), slice (None ), slice (None )] # = [:, :, :]
172+ indeces [axis ] = slice (1 , None ) # = [1:]
173+ indeces = tuple (indeces )
174+
175+ # we append along the given axis all the displacements reflected
176+ # and in the reverse order
177+ self .array_mu_x = np .append (self .array_mu_x ,
178+ reflection [0 ] * np .flip (self .array_mu_x , axis )[indeces ],
179+ axis = axis )
180+ self .array_mu_y = np .append (self .array_mu_y ,
181+ reflection [1 ] * np .flip (self .array_mu_y , axis )[indeces ],
182+ axis = axis )
183+ self .array_mu_z = np .append (self .array_mu_z ,
184+ reflection [2 ] * np .flip (self .array_mu_z , axis )[indeces ],
185+ axis = axis )
186+
187+
130188 def read_parameters (self , filename = 'parameters.prm' ):
131189 """
132190 Reads in the parameters file and fill the self structure.
0 commit comments