Skip to content

Commit 387e428

Browse files
authored
Implementing save_selection and small change in Components API (#2454)
* Implementing `save_selection` Fixing selection bug. Adding `components.select`. Making some methods, properties. * Adding image cache for new test * fixing name
1 parent 6f42c68 commit 387e428

File tree

9 files changed

+357
-209
lines changed

9 files changed

+357
-209
lines changed

doc/source/api/unit_testing.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ Here are some examples of how you use ``pytest``:
160160
161161
162162
def test_dunder_methods_keys(mapdl, basic_components):
163-
assert ["MYCOMP1", "MYCOMP2"] == list(mapdl.components.list())
163+
assert ["MYCOMP1", "MYCOMP2"] == list(mapdl.components.names())
164164
165165
166166
def test_dunder_methods_types(mapdl, basic_components):

src/ansys/mapdl/core/component.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,8 @@ def __iter__(self):
441441
"""
442442
yield from self._comp.keys()
443443

444-
def list(self):
444+
@property
445+
def names(self):
445446
"""
446447
Return a tuple that contains the components.
447448
@@ -453,6 +454,7 @@ def list(self):
453454
"""
454455
return tuple(self._comp.keys())
455456

457+
@property
456458
def types(self):
457459
"""
458460
Return the types of the components.
@@ -476,3 +478,24 @@ def items(self):
476478
477479
"""
478480
return self._comp.items()
481+
482+
def select(self, names: Union[str, list[str], tuple[str]], mute=False) -> None:
483+
"""Select Select components given their names
484+
485+
Select components given their names.
486+
487+
Parameters
488+
----------
489+
names : Union[str, list[str], tuple[str]]
490+
Name(s) of the components
491+
mute : bool, optional
492+
Whether to mute the `/CMSEL` command output or not, by default False.
493+
"""
494+
if isinstance(names, str):
495+
names = [names]
496+
497+
for i, each_name in enumerate(names):
498+
if i == 0:
499+
self._mapdl.cmsel("S", each_name, mute=mute)
500+
else:
501+
self._mapdl.cmsel("A", each_name, mute=mute)

src/ansys/mapdl/core/mapdl.py

Lines changed: 89 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,17 @@ def force_output(self):
648648
"""
649649
return self._force_output(self)
650650

651+
@property
652+
def save_selection(self):
653+
"""Save selection
654+
655+
Save the current selection (nodes, elements, keypoints, lines, areas,
656+
volumes and components) before entering in the context manager, and
657+
when exit returns to that selection.
658+
659+
"""
660+
return self._save_selection(self)
661+
651662
@property
652663
def solution(self) -> "Solution":
653664
"""Solution parameters of MAPDL.
@@ -816,6 +827,50 @@ def __exit__(self, *args):
816827
self._parent()._flush_stored()
817828
self._parent()._store_commands = False
818829

830+
class _save_selection:
831+
"""Save the selection and returns to it when exiting"""
832+
833+
def __init__(self, parent):
834+
self._parent = weakref.ref(parent)
835+
self.selection_sets = []
836+
self.selection_sets_comps = []
837+
838+
def __enter__(self):
839+
self._parent()._log.debug("Entering saving selection context")
840+
841+
selection_set_name = random_string(10)
842+
self.selection_sets.append(selection_set_name)
843+
self.selection_sets_comps.append(self._parent().components.names)
844+
845+
mapdl = self._parent()
846+
847+
prev_ier = mapdl.ignore_errors
848+
mapdl.ignore_errors = True
849+
for entity in ["kp", "lines", "area", "volu", "node", "elem"]:
850+
mapdl.cm(f"_{selection_set_name}_{entity}_", f"{entity}", mute=True)
851+
mapdl.ignore_errors = prev_ier
852+
853+
def __exit__(self, *args):
854+
self._parent()._log.debug("Exiting saving selection context")
855+
last_selection_name = self.selection_sets.pop()
856+
last_selection_cmps = self.selection_sets_comps.pop()
857+
858+
mapdl = self._parent()
859+
860+
# probably this is redundant
861+
prev_ier = mapdl.ignore_errors
862+
mapdl.ignore_errors = True
863+
for entity in ["kp", "lines", "area", "volu", "node", "elem"]:
864+
cmp_name = f"_{last_selection_name}_{entity}_"
865+
mapdl.cmsel("s", cmp_name, f"{entity}", mute=True)
866+
mapdl.cmdele(cmp_name)
867+
868+
mapdl.ignore_errors = prev_ier
869+
870+
# mute to avoid getting issues when the component wasn't created in
871+
# first place because there was no entities.
872+
self._parent().components.select(last_selection_cmps, mute=True)
873+
819874
class _chain_commands:
820875
"""Store MAPDL commands and send one chained command."""
821876

@@ -1718,45 +1773,39 @@ def vplot(
17181773
)
17191774
return general_plotter([], [], [], **kwargs)
17201775

1721-
cm_name_area = "__tmp_area2__"
1722-
cm_name_volu = "__tmp_volu2__"
1723-
self.cm(cm_name_area, "AREA", mute=True)
1724-
self.cm(cm_name_volu, "VOLU", mute=True)
1725-
1726-
volumes = self.geometry.vnum
1727-
meshes = []
1728-
points = []
1729-
labels = []
1730-
1731-
return_plotter = kwargs.pop("return_plotter", False)
1732-
color_areas = True
1733-
1734-
for each_volu in volumes:
1735-
self.vsel("S", vmin=each_volu)
1736-
self.aslv("S", mute=True) # select areas attached to active volumes
1737-
1738-
pl = self.aplot(
1739-
vtk=True,
1740-
color_areas=color_areas,
1741-
quality=quality,
1742-
show_area_numbering=show_area_numbering,
1743-
show_line_numbering=show_line_numbering,
1744-
show_lines=show_lines,
1745-
return_plotter=True,
1746-
**kwargs,
1747-
)
1748-
1749-
meshes_ = get_meshes_from_plotter(pl)
1776+
# Storing entities selection
1777+
with self.save_selection:
1778+
volumes = self.geometry.vnum
1779+
meshes = []
1780+
points = []
1781+
labels = []
1782+
1783+
return_plotter = kwargs.pop("return_plotter", False)
1784+
color_areas = True
1785+
1786+
for each_volu in volumes:
1787+
self.vsel("S", vmin=each_volu)
1788+
self.aslv("S", mute=True) # select areas attached to active volumes
1789+
1790+
pl = self.aplot(
1791+
vtk=True,
1792+
color_areas=color_areas,
1793+
quality=quality,
1794+
show_area_numbering=show_area_numbering,
1795+
show_line_numbering=show_line_numbering,
1796+
show_lines=show_lines,
1797+
return_plotter=True,
1798+
**kwargs,
1799+
)
17501800

1751-
for each_mesh in meshes_:
1752-
each_mesh.cell_data["entity_num"] = int(each_volu)
1801+
meshes_ = get_meshes_from_plotter(pl)
17531802

1754-
meshes.extend(meshes_)
1803+
for each_mesh in meshes_:
1804+
each_mesh.cell_data["entity_num"] = int(each_volu)
17551805

1756-
meshes = [{"mesh": meshes}]
1806+
meshes.extend(meshes_)
17571807

1758-
self.cmsel("S", cm_name_area, "AREA", mute=True)
1759-
self.cmsel("S", cm_name_volu, "VOLU", mute=True)
1808+
meshes = [{"mesh": meshes}]
17601809

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

1979-
lines = self.geometry.get_lines()
1980-
self.cmsel("S", "__area__", "AREA", mute=True)
2026+
with self.save_selection:
2027+
self.lsla("S", mute=True)
2028+
lines = self.geometry.get_lines()
19812029

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

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

49555004
# returning to previous selection
49565005
self.cmsel("s", "__tmp_cm__", entity=entity)
5006+
self.components.select(cmps_names)
49575007
return output

0 commit comments

Comments
 (0)