Skip to content

Commit 09ef6f5

Browse files
authored
ThinCurr: Fix invalid behavior of holes script for large meshes (OpenFUSIONToolkit#336)
Issue introduced in 8db4231
1 parent 8db4231 commit 09ef6f5

1 file changed

Lines changed: 32 additions & 18 deletions

File tree

src/python/OpenFUSIONToolkit/ThinCurr/_homology_cli.py

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ def boundary_cycles(self, info=True):
359359
print(indent_level+' Found {0} boundary cycles'.format(k))
360360
return cycle_lists
361361

362-
def merge_cells(self,eflag):
362+
def merge_cells(self,eflag,pflag):
363363
''' Merge all possible cells while retaining marked edge features
364364
'''
365365
def flag_cells(face,cell_group):
@@ -390,7 +390,7 @@ def flag_cells(face,cell_group):
390390
cell_group = np.array(cell_group)
391391
# return cell_group, np.where(cell_group[self.lef[:,0]]!=cell_group[self.lef[:,1]])[0]
392392
keep_edges = np.where(cell_group[self.lef[:,0]]!=cell_group[self.lef[:,1]])[0]
393-
pt_flag = np.zeros((self.np,), dtype=np.int32)
393+
pt_flag = np.zeros((self.np,), dtype=np.int32) + pflag
394394
for i in keep_edges:
395395
pt_flag[self.le[i,0]] += 1
396396
pt_flag[self.le[i,1]] += 1
@@ -423,9 +423,9 @@ def update_svd_with_row(U, S, V_T, new_row):
423423

424424
# Compute SVD of the small core matrix
425425
# u_k, s_k, vt_k = np.linalg.svd(K_mat, full_matrices=False)
426-
u_k, s_k, vt_k, info = scipy.linalg.lapack.sgesdd(K_mat, full_matrices=0)
426+
u_k, s_k, vt_k, info = scipy.linalg.lapack.dgesdd(K_mat, full_matrices=0)
427427
if info != 0:
428-
u_k, s_k, vt_k, info = scipy.linalg.lapack.sgesvd(K_mat, full_matrices=0)
428+
u_k, s_k, vt_k, info = scipy.linalg.lapack.dgesvd(K_mat, full_matrices=0)
429429
if info != 0:
430430
raise np.linalg.LinAlgError("SVD did not converge")
431431

@@ -757,55 +757,69 @@ def compute_homology(in_file, out_file=None, plot_final=False, plot_steps=False,
757757
minima_counts = []
758758
he = []
759759
he_mark = np.zeros((mesh_covered.ne,))
760+
p_mark = np.zeros((mesh_covered.np,), dtype=np.int32)
760761
for i in range(len(minima_sets)):
761762
evec, distance = mesh_covered.get_loop_edge_vec(minima_sets[i])
762763
he.append(evec)
763764
minima_counts.append(distance)
764765
he_mark[abs(evec)>0] = 1
766+
p_mark[minima_sets[i][0]] = 1 # Mark base point for each cycle
765767

766768
# Shrink graph by grouping cells that don't cross cycles
767-
cell_flags, keep_edges = mesh_covered.merge_cells(he_mark)
769+
cell_flags, keep_edges = mesh_covered.merge_cells(he_mark,p_mark)
768770
ncoarse = np.max(cell_flags)+1
769771
print(indent_level + "[{2}/{3}] Reducing mesh to {0} macro cells with {1} macro edges".format(ncoarse,keep_edges.shape[0],j+1,len(hb)))
770772
bmat_tmp = bmat_dense_base[:,keep_edges]
771-
bmat_dense = np.zeros((ncoarse,keep_edges.shape[0]), np.float32)
773+
bmat_dense = np.zeros((ncoarse,keep_edges.shape[0]), dtype=np.float64)
772774
for i in range(ncoarse):
773775
bmat_dense[i,:] = np.sum(bmat_tmp[cell_flags==i,:],axis=0)
774776

775777
# Build list of cycles from smallest to largest
776-
# intial_rank = np.linalg.matrix_rank(bmat_dense)
778+
# initial_rank = np.linalg.matrix_rank(bmat_dense)
777779
# U, S, V_T = np.linalg.svd(bmat_dense, full_matrices=False)
778-
U, S, V_T, _ = scipy.linalg.lapack.sgesdd(bmat_dense, full_matrices=0)
779-
intial_rank = np.sum(S > 1e-10)
780+
U, S, V_T, _ = scipy.linalg.lapack.dgesdd(bmat_dense, full_matrices=0)
781+
initial_rank = np.sum(S > 1e-10)
780782
hb_out = []
781-
do_check = False
783+
do_check = True
782784
for i in np.argsort(minima_counts):
783785
bmat_tmp = np.vstack((bmat_dense,he[i][keep_edges]))
784786
if (not do_check) and (i >= len(hb)): # Only start checking once we are looking at new cycles
785787
do_check = True
786788
# Update SVD with final set of previously accepted cycles
787-
U, S, V_T, _ = scipy.linalg.lapack.sgesdd(bmat_dense, full_matrices=0)
789+
# U, S, V_T = np.linalg.svd(bmat_tmp, full_matrices=False)
790+
U, S, V_T, _ = scipy.linalg.lapack.dgesdd(bmat_dense, full_matrices=0)
791+
initial_rank = np.sum(S > 1e-10)
788792
if do_check:
789793
# aug_rank = np.linalg.matrix_rank(bmat_tmp)
794+
# Un, Sn, Vn_T, _ = scipy.linalg.lapack.dgesdd(bmat_tmp, full_matrices=0)
790795
try:
791-
U, S, V_T = update_svd_with_row(U, S, V_T, he[i][keep_edges])
796+
Un, Sn, Vn_T = update_svd_with_row(U, S, V_T, he[i][keep_edges])
792797
except np.linalg.LinAlgError: # Fall back to full factorization
793-
# U, S, V_T = np.linalg.svd(bmat_tmp, full_matrices=False)
794-
U, S, V_T, _ = scipy.linalg.lapack.sgesdd(bmat_tmp, full_matrices=0)
795-
aug_rank = np.sum(S > 1.e-10)
798+
Un, Sn, Vn_T, _ = scipy.linalg.lapack.dgesdd(bmat_tmp, full_matrices=0)
799+
aug_rank = np.sum(Sn > 1.e-10)
796800
else:
797-
aug_rank = intial_rank + 1
798-
if aug_rank != intial_rank:
801+
aug_rank = initial_rank + 1
802+
if aug_rank != initial_rank:
799803
if debug:
800804
print("Adding cycle {0}".format(i))
801805
bmat_dense = bmat_tmp
806+
U = Un
807+
S = Sn
808+
V_T = Vn_T
802809
hb_out.append(minima_sets[i])
803-
intial_rank = aug_rank
810+
initial_rank = aug_rank
804811
if len(hb_out) == len(hb):
805812
break
806813
else:
807814
if debug:
808815
print("Skipping cycle {0}".format(i))
816+
817+
# Verify that final rank matches expected rank for final hole group
818+
if j == len(hb)-1:
819+
U, S, V_T, _ = scipy.linalg.lapack.dgesdd(bmat_dense, full_matrices=0)
820+
final_rank = np.sum(S > 1e-10)
821+
if final_rank != initial_rank:
822+
raise ValueError("Error in hole optimization: Final rank {0} does not match expected rank {1}".format(final_rank, initial_rank))
809823
indent_level = indent_level[:-2]
810824

811825
# Save computed internal cycles to hole list

0 commit comments

Comments
 (0)