diff --git a/examples/config/viewer.yaml b/examples/config/viewer.yaml index 13bd107..e900ce3 100644 --- a/examples/config/viewer.yaml +++ b/examples/config/viewer.yaml @@ -46,14 +46,14 @@ "title": "Graph" "colormap": "Accent" "opacity": 1.0 -"voxelization": +"mesh": "framework": "pyvista" - "layout": "voxelization" - "title": "Voxelization" + "layout": "mesh" + "title": "Mesh" "data_window": !include cfg_data_window.yaml "data_options": !include cfg_data_pyvista.yaml "data_plot": - "title": "Voxelization" + "title": "Mesh" "color_voxel": "red" "color_reference": "blue" "opacity_voxel": 0.5 diff --git a/examples/examples_voxel/anisotropic/geometry.yaml b/examples/examples_voxel/anisotropic/geometry.yaml index bccb38c..350885a 100644 --- a/examples/examples_voxel/anisotropic/geometry.yaml +++ b/examples/examples_voxel/anisotropic/geometry.yaml @@ -21,10 +21,12 @@ "use_resample": false "resampling_factor": [1, 1, 1] "pts_cloud": [] -"check_cloud": true -"check_conflict": true -"check_connection": true +"resolve_cloud": true +"resolve_conflict": true +"check_integrity": true "random_resolution": false "domain_conflict": [] "domain_connection": "connect": {"domain_group": [["cond"], ["src"], ["sink"]], "connected": true} +"domain_adjacent": + "connect": {"domain_group": [["cond"], ["src"], ["sink"]], "connected": true} diff --git a/examples/examples_voxel/core/geometry.yaml b/examples/examples_voxel/core/geometry.yaml index 14a1aed..48775e4 100644 --- a/examples/examples_voxel/core/geometry.yaml +++ b/examples/examples_voxel/core/geometry.yaml @@ -40,11 +40,15 @@ - [+00.00e-3, -50.00e-3, -30.00e-3] - [+00.00e-3, -50.00e-3, -10.00e-3] - [+00.00e-3, -50.00e-3, +10.00e-3] -"check_cloud": true -"check_conflict": true -"check_connection": true +"resolve_cloud": true +"resolve_conflict": true +"check_integrity": true "random_resolution": false "domain_conflict": [] "domain_connection": "connect": {"domain_group": [["cond"], ["src"], ["sink"]], "connected": true} "core": {"domain_group": [["cond"], ["core"]], "connected": false} +"domain_adjacent": + "connect": {"domain_group": [["cond"], ["src"], ["sink"]], "connected": true} + "dfdf": {"domain_group": [["src"], ["sink"]], "connected": false} + "core": {"domain_group": [["cond"], ["core"]], "connected": false} diff --git a/examples/examples_voxel/distributed/geometry.yaml b/examples/examples_voxel/distributed/geometry.yaml index 6d3084e..d23fd2b 100644 --- a/examples/examples_voxel/distributed/geometry.yaml +++ b/examples/examples_voxel/distributed/geometry.yaml @@ -21,10 +21,12 @@ "use_resample": false "resampling_factor": [1, 1, 1] "pts_cloud": [] -"check_cloud": true -"check_conflict": true -"check_connection": true +"resolve_cloud": true +"resolve_conflict": true +"check_integrity": true "random_resolution": false "domain_conflict": [] "domain_connection": "connect": {"domain_group": [["cond"], ["src"], ["sink"]], "connected": true} +"domain_adjacent": + "connect": {"domain_group": [["cond"], ["src"], ["sink"]], "connected": true} diff --git a/pypeec/lib_check/check_data_visualization.py b/pypeec/lib_check/check_data_visualization.py index 3a1c533..a0981d1 100644 --- a/pypeec/lib_check/check_data_visualization.py +++ b/pypeec/lib_check/check_data_visualization.py @@ -254,10 +254,10 @@ def _check_data_plot_viewer(layout, data_plot): """ # check plot type - datachecker.check_choice("layout", layout, ["domain", "graph", "voxelization"]) + datachecker.check_choice("layout", layout, ["domain", "graph", "mesh"]) # check the material options - if layout == "voxelization": + if layout == "mesh": # check type key_list = ["color_voxel", "color_reference", "opacity_voxel", "opacity_reference"] datachecker.check_dict("data_plot", data_plot, key_list=key_list) diff --git a/pypeec/lib_mesher/voxel_integrity.py b/pypeec/lib_mesher/voxel_integrity.py index 013ab29..37a40a2 100644 --- a/pypeec/lib_mesher/voxel_integrity.py +++ b/pypeec/lib_mesher/voxel_integrity.py @@ -23,26 +23,29 @@ def _get_all_indices(domain_def): # get the indices and colors for tag in domain_def: - idx_tmp = domain_def[tag] - idx = np.append(idx, idx_tmp) + idx = np.append(idx, domain_def[tag]) return idx -def _get_tag_indices(domain_def, domain_list): +def _get_group_indices(domain_def, domain_group): """ Get the indices of the non-empty voxels for the given domains. """ - # init - idx = np.empty(0, dtype=np.int_) + group_def = [] + for domain_group_tmp in domain_group: + # init + idx_tmp = np.empty(0, dtype=np.int_) - # get the indices and colors - for tag in domain_list: - idx_tmp = domain_def[tag] - idx = np.append(idx, idx_tmp) + # get the indices and colors + for tag in domain_group_tmp: + idx_tmp = np.append(idx_tmp, domain_def[tag]) - return idx + if len(idx_tmp) > 0: + group_def.append(idx_tmp) + + return group_def def _get_connection_matrix(n): @@ -65,37 +68,46 @@ def _get_connection_matrix(n): idx = idx_x+idx_y*nx+idx_z*nx*ny # create the sparse matrix - voxel_connection = sps.csc_matrix((nv, nv), dtype=np.int_) + voxel_matrix = sps.csc_matrix((nv, nv), dtype=np.int_) + + # self connections + idx_col = np.arange(nv) + idx_row = np.arange(nv) + data = np.ones(nv, dtype=np.int_) + voxel_matrix += sps.csc_matrix((data, (idx_row, idx_col)), shape=(nv, nv), dtype=np.int_) # connections along x direction - idx_col = idx[0:-1, :, :].flatten() - idx_row = idx[1:, :, :].flatten() + idx_col = idx[:-1, :, :].flatten() + idx_row = idx[+1:, :, :].flatten() data = np.ones((nx-1)*ny*nz, dtype=np.int_) - voxel_connection += sps.csc_matrix((data, (idx_row, idx_col)), shape=(nv, nv), dtype=np.int_) + voxel_matrix += sps.csc_matrix((data, (idx_row, idx_col)), shape=(nv, nv), dtype=np.int_) + voxel_matrix += sps.csc_matrix((data, (idx_col, idx_row)), shape=(nv, nv), dtype=np.int_) # connections along y direction - idx_col = idx[:, 0:-1, :].flatten() - idx_row = idx[:, 1:, :].flatten() + idx_col = idx[:, :-1, :].flatten() + idx_row = idx[:, +1:, :].flatten() data = np.ones(nx*(ny-1)*nz, dtype=np.int_) - voxel_connection += sps.csc_matrix((data, (idx_row, idx_col)), shape=(nv, nv), dtype=np.int_) + voxel_matrix += sps.csc_matrix((data, (idx_row, idx_col)), shape=(nv, nv), dtype=np.int_) + voxel_matrix += sps.csc_matrix((data, (idx_col, idx_row)), shape=(nv, nv), dtype=np.int_) # connections along z direction - idx_col = idx[:, :, 0:-1].flatten() - idx_row = idx[:, :, 1:].flatten() + idx_col = idx[:, :, :-1].flatten() + idx_row = idx[:, :, +1:].flatten() data = np.ones(nx*ny*(nz-1), dtype=np.int_) - voxel_connection += sps.csc_matrix((data, (idx_row, idx_col)), shape=(nv, nv), dtype=np.int_) + voxel_matrix += sps.csc_matrix((data, (idx_row, idx_col)), shape=(nv, nv), dtype=np.int_) + voxel_matrix += sps.csc_matrix((data, (idx_col, idx_row)), shape=(nv, nv), dtype=np.int_) - return voxel_connection + return voxel_matrix -def _get_connected_components(graph_connection, idx): +def _get_connected_components(graph_matrix, idx): """ Get the connected components in the graph. """ # find the connected components in the graph (n_comp, labels) = csg.connected_components( - csgraph=graph_connection, + csgraph=graph_matrix, directed=False, return_labels=True, ) @@ -110,7 +122,7 @@ def _get_connected_components(graph_connection, idx): return graph_def -def _check_domain_connection(domain_def, graph, domain_connection, tag): +def _check_domain_connection(domain_def, graph_def, domain_connection, tag): """ Check that the given connections between the domain exists. """ @@ -120,19 +132,15 @@ def _check_domain_connection(domain_def, graph, domain_connection, tag): connected = domain_connection["connected"] # merge group and remove empty domains - idx_group = [] - for domain_group_tmp in domain_group: - idx_tmp = _get_tag_indices(domain_def, domain_group_tmp) - if len(idx_tmp) > 0: - idx_group.append(idx_tmp) + group_def = _get_group_indices(domain_def, domain_group) # init the connection matrix - matrix = np.full((len(graph), len(idx_group)), True, dtype=bool) + matrix = np.full((len(graph_def), len(group_def)), True, dtype=bool) # fill the connection matrix - for i, idx_graph in enumerate(graph): - for j, idx_domain in enumerate(idx_group): - idx_shared = np.intersect1d(idx_graph, idx_domain) + for i, idx_graph in enumerate(graph_def): + for j, idx_group in enumerate(group_def): + idx_shared = np.intersect1d(idx_graph, idx_group) matrix[i, j] = len(idx_shared) > 0 # count connection @@ -140,7 +148,42 @@ def _check_domain_connection(domain_def, graph, domain_connection, tag): # check validity if connected: - idx_ok = vector == len(idx_group) + idx_ok = vector == len(group_def) + if not np.any(idx_ok): + raise RuntimeError("domain connection is missing: %s" % tag) + else: + idx_ok = np.logical_or(vector == 0, vector == 1) + if not np.all(idx_ok): + raise RuntimeError("domain connection is illegal: %s" % tag) + + +def _check_domain_adjacent(domain_def, voxel_matrix, domain_connection, tag): + """ + Check that the given connections between the domain exists. + """ + + # extract the data + domain_group = domain_connection["domain_group"] + connected = domain_connection["connected"] + + # merge group and remove empty domains + group_def = _get_group_indices(domain_def, domain_group) + + # init the connection matrix + matrix = np.full((len(group_def), len(group_def)), True, dtype=bool) + + # fill the connection matrix + for i, idx_group_i in enumerate(group_def): + for j, idx_group_j in enumerate(group_def): + idx_shared = voxel_matrix[idx_group_i, :][:, idx_group_j] + matrix[i, j] = idx_shared.count_nonzero() > 0 + + # count connection + vector = np.count_nonzero(matrix, axis=1) + + # check validity + if connected: + idx_ok = vector == len(group_def) if not np.any(idx_ok): raise RuntimeError("domain connection is missing: %s" % tag) else: @@ -158,22 +201,22 @@ def get_integrity(n, domain_def, domain_connection, domain_adjacent): idx = _get_all_indices(domain_def) # get the connection matrix between the voxels - voxel_connection = _get_connection_matrix(n) + voxel_matrix = _get_connection_matrix(n) # get the graph matrix - graph_connection = voxel_connection - graph_connection = graph_connection[idx, :] - graph_connection = graph_connection[:, idx] + graph_matrix = voxel_matrix + graph_matrix = graph_matrix[idx, :] + graph_matrix = graph_matrix[:, idx] # find the connected components in the graph - graph_def = _get_connected_components(graph_connection, idx) + graph_def = _get_connected_components(graph_matrix, idx) - # check the connection between the domains + # check the connections between the adjacent domains + for tag, domain_adjacent_tmp in domain_adjacent.items(): + _check_domain_adjacent(domain_def, voxel_matrix, domain_adjacent_tmp, tag) + + # check the connection between the connected components for tag, domain_connection_tmp in domain_connection.items(): _check_domain_connection(domain_def, graph_def, domain_connection_tmp, tag) - # check the connections between the domains - # for tag, domain_connection_tmp in domain_connection.items(): - # _check_domain_connection(domain_def, graph, domain_connection_tmp, tag) - return graph_def diff --git a/pypeec/lib_visualization/manage_pyvista.py b/pypeec/lib_visualization/manage_pyvista.py index 90a62c6..84f4286 100644 --- a/pypeec/lib_visualization/manage_pyvista.py +++ b/pypeec/lib_visualization/manage_pyvista.py @@ -501,7 +501,7 @@ def _plot_geometry(pl, voxel, data_plot, plot_clip, plot_theme, var): _get_clip_mesh(pl, voxel_tmp, arg, plot_clip) -def _plot_voxelization(pl, voxel, reference, data_plot, plot_clip, plot_theme): +def _plot_mesh(pl, voxel, reference, data_plot, plot_clip, plot_theme): """ Plot the reference and voxelized structures in order to assess the voxelization error. """ @@ -558,8 +558,8 @@ def get_plot_viewer(pl, grid, voxel, point, reference, layout, data_plot, data_o _plot_geometry(pl, voxel, data_plot, plot_clip, plot_theme, "domain") elif layout == "graph": _plot_geometry(pl, voxel, data_plot, plot_clip, plot_theme, "graph") - elif layout == "voxelization": - _plot_voxelization(pl, voxel, reference, data_plot, plot_clip, plot_theme) + elif layout == "mesh": + _plot_mesh(pl, voxel, reference, data_plot, plot_clip, plot_theme) else: raise ValueError("invalid plot type and plot feature")