diff --git a/doc/changelog.d/3697.miscellaneous.md b/doc/changelog.d/3697.miscellaneous.md new file mode 100644 index 0000000000..38a98cf8a5 --- /dev/null +++ b/doc/changelog.d/3697.miscellaneous.md @@ -0,0 +1 @@ +feat: improving performance of save_selection \ No newline at end of file diff --git a/src/ansys/mapdl/core/mapdl_core.py b/src/ansys/mapdl/core/mapdl_core.py index aa71a1d014..b2d6ebf3ff 100644 --- a/src/ansys/mapdl/core/mapdl_core.py +++ b/src/ansys/mapdl/core/mapdl_core.py @@ -103,6 +103,24 @@ r"(\*\*\* ERROR \*\*\*).*[\r\n]+.*The distributed memory parallel solution does not support KRYLOV method", ] +_TMP_COMP = { + "KP": "cmp_kp", + "LINE": "cmp_line", + "AREA": "cmp_area", + "VOLU": "cmp_volu", + "NODE": "cmp_node", + "ELEM": "cmp_elem", +} + +ENTITIES_TO_SELECTION_MAPPING = { + "KP": "ksel", + "LINE": "lsel", + "AREA": "asel", + "VOLU": "vsel", + "NODE": "nsel", + "ELEM": "esel", +} + # test for png file PNG_IS_WRITTEN_TO_FILE = re.compile( "WRITTEN TO FILE" @@ -1434,32 +1452,41 @@ def __enter__(self): # Storing components selection = { - "cmsel": mapdl.components.names, - # "components_type": mapdl.components.types, - "nsel": mapdl.mesh.nnum, - "esel": mapdl.mesh.enum, - "ksel": mapdl.geometry.knum, - "lsel": mapdl.geometry.lnum, - "asel": mapdl.geometry.anum, - "vsel": mapdl.geometry.vnum, + "cmsel": mapdl.components._comp, } + id_ = random_string(5) + for each_type, each_name in _TMP_COMP.items(): + each_name = f"__{each_name}{id_}__" + selection[each_type] = each_name + mapdl.cm( + each_name, each_type, mute=True + ) # to hide ComponentNoData error self.selection.append(selection) def __exit__(self, *args): self._parent()._log.debug("Exiting saving selection context") - selection = self.selection.pop() + mapdl = self._parent() + mapdl.allsel() + mapdl.cmsel("None") + selection = self.selection.pop() cmps = selection.pop("cmsel") if cmps: - mapdl.components.select(cmps) + for each_name, each_value in cmps.items(): + mapdl.cmsel("a", each_name, each_value, mute=True) + + for each_type, each_name in selection.items(): + mapdl.cmsel("a", each_name, each_type, mute=True) + + selfun = getattr( + mapdl, ENTITIES_TO_SELECTION_MAPPING[each_type.upper()] + ) + selfun("s", vmin=each_name, mute=True) - for select_cmd, ids in selection.items(): - if ids.size > 0: - func = getattr(mapdl, select_cmd) - func(vmin=ids) + mapdl.cmdele(each_name, mute=True) class _chain_commands: """Store MAPDL commands and send one chained command.""" diff --git a/tests/test_mapdl.py b/tests/test_mapdl.py index 89b7cc1e95..bf611e38ab 100644 --- a/tests/test_mapdl.py +++ b/tests/test_mapdl.py @@ -2123,7 +2123,7 @@ def test_components_selection_keep_between_plots(mapdl, cube_solve): assert "mycm" in mapdl.components -def test_saving_selection_context(mapdl, cube_solve): +def test_save_selection_1(mapdl, cube_solve): mapdl.allsel() for i in range(1, 4): @@ -2221,6 +2221,108 @@ def test_saving_selection_context(mapdl, cube_solve): assert "nod_selection_4" not in mapdl.components +def test_save_selection_2(mapdl, cleared, make_block): + from ansys.mapdl.core.mapdl_core import _TMP_COMP + + n1 = 1 + mapdl.nsel(vmin=n1) + assert n1 in mapdl.mesh.nnum + mapdl.cm("nodes_cm", "NODE") + assert "nodes_cm" in mapdl.components + assert n1 in mapdl.components["nodes_cm"].items + assert "NODE" == mapdl.components["nodes_cm"].type + + e1 = 1 + mapdl.esel(vmin=e1) + assert e1 in mapdl.mesh.enum + mapdl.cm("elem_cm", "ELEM") + assert "elem_cm" in mapdl.components + assert e1 in mapdl.components["elem_cm"].items + assert "ELEM" == mapdl.components["elem_cm"].type + + kp1 = 1 + mapdl.ksel(vmin=kp1) + assert kp1 in mapdl.geometry.knum + mapdl.cm("kp_cm", "kp") + assert "kp_cm" in mapdl.components + assert kp1 in mapdl.components["kp_cm"].items + assert "KP" == mapdl.components["kp_cm"].type + + l1 = 1 + mapdl.lsel(vmin=l1) + assert l1 in mapdl.geometry.lnum + mapdl.cm("line_cm", "line") + assert "line_cm" in mapdl.components + assert l1 in mapdl.components["line_cm"].items + assert "LINE" == mapdl.components["line_cm"].type + + a1 = 1 + mapdl.asel(vmin=a1) + assert a1 in mapdl.geometry.anum + mapdl.cm("area_cm", "area") + assert "area_cm" in mapdl.components + assert a1 in mapdl.components["area_cm"].items + assert "AREA" == mapdl.components["area_cm"].type + + # Assert we have properly set the components + assert { + "AREA_CM": "AREA", + "ELEM_CM": "ELEM", + "KP_CM": "KP", + "LINE_CM": "LINE", + "NODES_CM": "NODE", + } == mapdl.components._comp + + # additional changes to the selections + kpoints = mapdl.ksel("u", vmin=1) + lines = mapdl.lsel("a", vmin=[2, 5, 6]) + areas = mapdl.asel("a", vmin=2) + nodes = mapdl.nsel("S", vmin=[4, 5]) + elem = mapdl.esel("s", vmin=[1, 3]) + + # checking all the elements are correct + assert np.allclose(kpoints, mapdl.geometry.knum) + assert np.allclose(lines, mapdl.geometry.lnum) + assert np.allclose(areas, mapdl.geometry.anum) + assert np.allclose(nodes, mapdl.mesh.nnum) + assert np.allclose(elem, mapdl.mesh.enum) + + ## storing... __enter__ + comp_selection = mapdl.components._comp + + print("Starting...") + with mapdl.save_selection: + + # do something + mapdl.allsel() + mapdl.cmsel("NONE") + mapdl.asel("NONE") + mapdl.nsel("s", vmin=[1, 2, 8, 9]) + mapdl.allsel() + mapdl.vsel("none") + mapdl.lsel("a", vmin=[9]) + mapdl.vsel("all") + mapdl.ksel("none") + + # checks + assert np.allclose(kpoints, mapdl.geometry.knum) + assert np.allclose(lines, mapdl.geometry.lnum) + assert np.allclose(areas, mapdl.geometry.anum) + assert np.allclose(nodes, mapdl.mesh.nnum) + assert np.allclose(elem, mapdl.mesh.enum) + + for each_key, each_value in comp_selection.items(): + assert ( + each_key in mapdl.components + ), f"Component '{each_key}' is not defined/selected" + assert ( + each_value == mapdl.components[each_key].type + ), f"Component '{each_key}' type is not correct" + + for each_tmp in _TMP_COMP.values(): + assert each_tmp not in mapdl.components + + def test_inquire_invalid(mapdl, cleared): with pytest.raises(ValueError, match="Arguments of this method have changed"): mapdl.inquire("directory")