Skip to content

Commit a021f30

Browse files
committed
2 parents 15aafed + 9240eab commit a021f30

4 files changed

Lines changed: 114 additions & 32 deletions

File tree

lsdo_function_spaces/core/function.py

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# from lsdo_function_spaces.core.function_space import FunctionSpace
1616
import lsdo_function_spaces as lfs
1717
import vedo
18+
from lsdo_function_spaces.utils.internal_utilities import get_projection_squared_distances
1819

1920

2021

@@ -181,7 +182,7 @@ def integrate(self, area, grid_n=10, quadrature_order=2):
181182

182183
# compute areas of the quadrilaterals
183184
grid_values = area.evaluate(parametric_coordinates=parametric_grid.reshape(-1,2)).reshape((grid_n, grid_n, -1))
184-
output = csdl.Variable(value=np.zeros((grid_n-1, grid_n-1)))
185+
output = csdl.Variable(value=np.zeros(values.shape))
185186
for i in csdl.frange(grid_n-1):
186187
for j in csdl.frange(grid_n-1):
187188
area_1 = csdl.norm(csdl.cross(grid_values[i+1,j]-grid_values[i,j], grid_values[i,j+1]-grid_values[i,j]) + 1e-8)/2
@@ -265,7 +266,7 @@ def project(self, points:np.ndarray, direction:np.ndarray=None, grid_search_dens
265266
max_newton_iterations:int=100, newton_tolerance:float=1e-12, projection_tolerance:float=None,
266267
plot:bool=False, force_reproject:bool=False,
267268
grid_search_evaluation_cutoff:int=None, grid_search_subtraction_cutoff:int=None,
268-
do_pickles=True) -> csdl.Variable:
269+
do_pickles=True, grid_search_density_cutoff=50) -> csdl.Variable:
269270
'''
270271
Projects a set of points onto the function. The points to project must be provided. If a direction is provided, the projection will find
271272
the points on the function that are closest to the axis defined by the direction. If no direction is provided, the projection will find the
@@ -290,7 +291,8 @@ def project(self, points:np.ndarray, direction:np.ndarray=None, grid_search_dens
290291
projection_tolerance : float = None
291292
The tolerance for the projection. If None, the projection will not be refined. If not None, the projection will be refined
292293
using a finer grid search density parameter for the points that are not within the tolerance distance.
293-
NOTE: This is only for use when the points are within the geometry that they are being projected onto.
294+
NOTE: This is only for use when the points are within the geometry that they are being projected onto, or, if a direction is provided,
295+
the axis defined by the direction intersects the geometry.
294296
plot : bool = False
295297
Whether or not to plot the projection.
296298
force_reproject : bool = False
@@ -303,6 +305,9 @@ def project(self, points:np.ndarray, direction:np.ndarray=None, grid_search_dens
303305
will be subtracted in sections. If None, no bunching will be done.
304306
do_pickles : bool = True
305307
If True, the projection will be saved to a file. The file will be saved in the stored_files/projections directory.
308+
grid_search_density_cutoff : int = 50
309+
The cutoff for the grid search density during refinement. If the grid search density is greater than this, the refinement will be
310+
terminated and a warning will be printed.
306311
'''
307312
if isinstance(points, csdl.Variable):
308313
points = points.value
@@ -321,7 +326,7 @@ def project(self, points:np.ndarray, direction:np.ndarray=None, grid_search_dens
321326
grid_search_density_parameter, max_newton_iterations,
322327
newton_tolerance, projection_tolerance,
323328
grid_search_evaluation_cutoff, grid_search_subtraction_cutoff,
324-
do_pickles=do_pickles)
329+
do_pickles=do_pickles, grid_search_density_cutoff=grid_search_density_cutoff)
325330

326331
if plot:
327332
projection_results = self.evaluate(parametric_coordinates).value
@@ -363,7 +368,7 @@ def project(self, points:np.ndarray, direction:np.ndarray=None, grid_search_dens
363368
grid_search_values = np.zeros((num_grid_points, self.coefficients.shape[-1]))
364369
start_index = 0
365370
for i in range(num_sections):
366-
print(i, '/', num_sections)
371+
# print(i, '/', num_sections)
367372
end_index = start_index + section_size
368373
grid_search_values[start_index:end_index] = self.evaluate(parametric_coordinates=parametric_grid_search[start_index:end_index],
369374
coefficients=self.coefficients.value, non_csdl=True)
@@ -386,7 +391,7 @@ def project(self, points:np.ndarray, direction:np.ndarray=None, grid_search_dens
386391
section_size = int(np.ceil(points.shape[0]/num_sections))
387392
closest_point_indices = np.zeros((points.shape[0],), dtype=int)
388393
for i in range(num_sections):
389-
print(i, '/', num_sections)
394+
# print(i, '/', num_sections)
390395
start_index = i*section_size
391396
end_index = min((i+1)*section_size, points.shape[0])
392397
points_expanded = np.repeat(points[start_index:end_index,np.newaxis,:], grid_search_values.shape[0], axis=1)
@@ -603,7 +608,7 @@ def project(self, points:np.ndarray, direction:np.ndarray=None, grid_search_dens
603608
current_guess = self.refine_projection(points, current_guess, direction,
604609
grid_search_density_parameter, max_newton_iterations,
605610
newton_tolerance, projection_tolerance=projection_tolerance,
606-
do_pickles=do_pickles)
611+
do_pickles=False)
607612

608613
if plot:
609614
projection_results = self.evaluate(current_guess).value
@@ -627,12 +632,11 @@ def project(self, points:np.ndarray, direction:np.ndarray=None, grid_search_dens
627632
pickle.dump(current_guess, handle, protocol=pickle.HIGHEST_PROTOCOL)
628633

629634
return current_guess
630-
631635

632636
def refine_projection(self, points:np.ndarray, parametric_coordinates:np.ndarray, direction:np.ndarray, initial_grid_search_density_parameter:int=1,
633637
max_newton_iterations:int=100, newton_tolerance:float=1e-6, projection_tolerance:float=1e-6,
634638
grid_search_evaluation_cutoff:int=None, grid_search_subtraction_cutoff:int=None,
635-
do_pickles=True) -> np.ndarray:
639+
do_pickles=True, grid_search_density_cutoff=50) -> np.ndarray:
636640
'''
637641
For projections where the points are in the geometry, this method finds the points that are not within the tolerance distance and reprojects
638642
those points using a finer grid search density parameter.
@@ -641,27 +645,38 @@ def refine_projection(self, points:np.ndarray, parametric_coordinates:np.ndarray
641645
points = points.value
642646
points_flattened = points.reshape((-1,3))
643647
previous_projection_results = self.evaluate(parametric_coordinates=parametric_coordinates, non_csdl=True)
644-
distances = np.linalg.norm(points_flattened - previous_projection_results, axis=-1)
645-
points_to_reproject = np.where(distances > projection_tolerance)[0]
648+
649+
650+
squared_distances = get_projection_squared_distances(points_flattened, previous_projection_results, direction)
651+
points_to_reproject = np.where(squared_distances > projection_tolerance**2)[0]
652+
distances = np.sqrt(squared_distances[points_to_reproject])
653+
646654
if len(points_to_reproject) == 0:
647655
return parametric_coordinates
648656
else:
649657
counter = 0
650658
grid_search_density_parameter = initial_grid_search_density_parameter*1.2
651659
while len(points_to_reproject) > 0:
652-
print('Total tolerance norm: ', np.linalg.norm(distances))
653-
print(f'Refining projection on {len(points_to_reproject)} points with grid search density parameter:', grid_search_density_parameter)
660+
# print('Total tolerance norm: ', np.linalg.norm(distances))
661+
# print(f'Refining projection on {len(points_to_reproject)} points with grid search density parameter:', grid_search_density_parameter)
654662
new_parametric_coordinates = self.project(points_flattened[points_to_reproject], direction, grid_search_density_parameter=grid_search_density_parameter,
655663
max_newton_iterations=max_newton_iterations, newton_tolerance=newton_tolerance, force_reproject=False,
656664
grid_search_evaluation_cutoff=grid_search_evaluation_cutoff,
657665
grid_search_subtraction_cutoff=grid_search_subtraction_cutoff)
658666
parametric_coordinates[points_to_reproject] = new_parametric_coordinates
659667
new_projection_results = self.evaluate(parametric_coordinates=new_parametric_coordinates, non_csdl=True)
660-
distances = np.linalg.norm(points_flattened[points_to_reproject] - new_projection_results, axis=1)
661-
points_to_reproject = points_to_reproject[np.where(distances > projection_tolerance)[0]]
668+
669+
# distances = np.linalg.norm(points_flattened[points_to_reproject] - new_projection_results, axis=1)
670+
# points_to_reproject = points_to_reproject[np.where(distances > projection_tolerance)[0]]
671+
672+
squared_distances = get_projection_squared_distances(points_flattened[points_to_reproject], new_projection_results, direction)
673+
new_points_to_reproject = np.where(squared_distances > projection_tolerance**2)[0]
674+
distances = np.sqrt(squared_distances[new_points_to_reproject])
675+
points_to_reproject = points_to_reproject[new_points_to_reproject]
676+
662677
grid_search_density_parameter *= 1.5
663678
counter += 1
664-
if counter > 10:
679+
if grid_search_density_parameter > grid_search_density_cutoff:
665680
print('--'*50)
666681
print("WARNING: Projection refinement stopped because it took more than 10 refinement steps!")
667682
print("This is likely because not all of the points are within the function being projected onto.")

0 commit comments

Comments
 (0)