Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing save_selection and small change in Components API #2454

Merged
merged 5 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/api/unit_testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ Here are some examples of how you use ``pytest``:


def test_dunder_methods_keys(mapdl, basic_components):
assert ["MYCOMP1", "MYCOMP2"] == list(mapdl.components.list())
assert ["MYCOMP1", "MYCOMP2"] == list(mapdl.components.names())


def test_dunder_methods_types(mapdl, basic_components):
Expand Down
25 changes: 24 additions & 1 deletion src/ansys/mapdl/core/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,8 @@
"""
yield from self._comp.keys()

def list(self):
@property
def names(self):
"""
Return a tuple that contains the components.
germa89 marked this conversation as resolved.
Show resolved Hide resolved

Expand All @@ -453,6 +454,7 @@
"""
return tuple(self._comp.keys())

@property
def types(self):
"""
Return the types of the components.
Expand All @@ -476,3 +478,24 @@

"""
return self._comp.items()

def select(self, names: Union[str, list[str], tuple[str]], mute=False) -> None:
"""Select Select components given their names

Select components given their names.

Parameters
----------
names : Union[str, list[str], tuple[str]]
Name(s) of the components
germa89 marked this conversation as resolved.
Show resolved Hide resolved
mute : bool, optional
Whether to mute the `/CMSEL` command output or not, by default False.
"""
if isinstance(names, str):
names = [names]

Check warning on line 495 in src/ansys/mapdl/core/component.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/mapdl/core/component.py#L495

Added line #L495 was not covered by tests

for i, each_name in enumerate(names):
if i == 0:
self._mapdl.cmsel("S", each_name, mute=mute)
else:
self._mapdl.cmsel("A", each_name, mute=mute)
128 changes: 89 additions & 39 deletions src/ansys/mapdl/core/mapdl.py
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,17 @@ def force_output(self):
"""
return self._force_output(self)

@property
def save_selection(self):
"""Save selection

Save the current selection (nodes, elements, keypoints, lines, areas,
volumes and components) before entering in the context manager, and
when exit returns to that selection.

"""
return self._save_selection(self)
germa89 marked this conversation as resolved.
Show resolved Hide resolved

@property
def solution(self) -> "Solution":
"""Solution parameters of MAPDL.
Expand Down Expand Up @@ -816,6 +827,50 @@ def __exit__(self, *args):
self._parent()._flush_stored()
self._parent()._store_commands = False

class _save_selection:
"""Save the selection and returns to it when exiting"""

def __init__(self, parent):
self._parent = weakref.ref(parent)
self.selection_sets = []
self.selection_sets_comps = []

def __enter__(self):
self._parent()._log.debug("Entering saving selection context")

selection_set_name = random_string(10)
self.selection_sets.append(selection_set_name)
self.selection_sets_comps.append(self._parent().components.names)

mapdl = self._parent()

prev_ier = mapdl.ignore_errors
mapdl.ignore_errors = True
for entity in ["kp", "lines", "area", "volu", "node", "elem"]:
mapdl.cm(f"_{selection_set_name}_{entity}_", f"{entity}", mute=True)
mapdl.ignore_errors = prev_ier

def __exit__(self, *args):
self._parent()._log.debug("Exiting saving selection context")
last_selection_name = self.selection_sets.pop()
last_selection_cmps = self.selection_sets_comps.pop()

mapdl = self._parent()

# probably this is redundant
prev_ier = mapdl.ignore_errors
mapdl.ignore_errors = True
for entity in ["kp", "lines", "area", "volu", "node", "elem"]:
cmp_name = f"_{last_selection_name}_{entity}_"
mapdl.cmsel("s", cmp_name, f"{entity}", mute=True)
mapdl.cmdele(cmp_name)

mapdl.ignore_errors = prev_ier

# mute to avoid getting issues when the component wasn't created in
# first place because there was no entities.
self._parent().components.select(last_selection_cmps, mute=True)

class _chain_commands:
"""Store MAPDL commands and send one chained command."""

Expand Down Expand Up @@ -1718,45 +1773,39 @@ def vplot(
)
return general_plotter([], [], [], **kwargs)

cm_name_area = "__tmp_area2__"
cm_name_volu = "__tmp_volu2__"
self.cm(cm_name_area, "AREA", mute=True)
self.cm(cm_name_volu, "VOLU", mute=True)

volumes = self.geometry.vnum
meshes = []
points = []
labels = []

return_plotter = kwargs.pop("return_plotter", False)
color_areas = True

for each_volu in volumes:
self.vsel("S", vmin=each_volu)
self.aslv("S", mute=True) # select areas attached to active volumes

pl = self.aplot(
vtk=True,
color_areas=color_areas,
quality=quality,
show_area_numbering=show_area_numbering,
show_line_numbering=show_line_numbering,
show_lines=show_lines,
return_plotter=True,
**kwargs,
)

meshes_ = get_meshes_from_plotter(pl)
# Storing entities selection
with self.save_selection:
volumes = self.geometry.vnum
meshes = []
points = []
labels = []

return_plotter = kwargs.pop("return_plotter", False)
color_areas = True

for each_volu in volumes:
self.vsel("S", vmin=each_volu)
self.aslv("S", mute=True) # select areas attached to active volumes

pl = self.aplot(
vtk=True,
color_areas=color_areas,
quality=quality,
show_area_numbering=show_area_numbering,
show_line_numbering=show_line_numbering,
show_lines=show_lines,
return_plotter=True,
**kwargs,
)

for each_mesh in meshes_:
each_mesh.cell_data["entity_num"] = int(each_volu)
meshes_ = get_meshes_from_plotter(pl)

meshes.extend(meshes_)
for each_mesh in meshes_:
each_mesh.cell_data["entity_num"] = int(each_volu)

meshes = [{"mesh": meshes}]
meshes.extend(meshes_)

self.cmsel("S", cm_name_area, "AREA", mute=True)
self.cmsel("S", cm_name_volu, "VOLU", mute=True)
meshes = [{"mesh": meshes}]

return general_plotter(
meshes, points, labels, return_plotter=return_plotter, **kwargs
Expand Down Expand Up @@ -1973,11 +2022,10 @@ def aplot(
if show_lines or show_line_numbering:
kwargs.setdefault("line_width", 2)
# subselect lines belonging to the current areas
self.cm("__area__", "AREA", mute=True)
self.lsla("S", mute=True)

lines = self.geometry.get_lines()
self.cmsel("S", "__area__", "AREA", mute=True)
with self.save_selection:
self.lsla("S", mute=True)
lines = self.geometry.get_lines()

if show_lines:
meshes.append(
Expand Down Expand Up @@ -4933,6 +4981,7 @@ def cmplot(self, label: str = "", entity: str = "", keyword: str = "", **kwargs)
if entity[:4] not in ["NODE", "ELEM", "KP", "LINE", "AREA", "VOLU"]:
raise ValueError(f"The entity '{entity}' is not allowed.")

cmps_names = self.components.names
self.cm("__tmp_cm__", entity=entity)
if label == "ALL":
self.cmsel("ALL", entity=entity)
Expand All @@ -4954,4 +5003,5 @@ def cmplot(self, label: str = "", entity: str = "", keyword: str = "", **kwargs)

# returning to previous selection
self.cmsel("s", "__tmp_cm__", entity=entity)
self.components.select(cmps_names)
return output
Loading