diff --git a/doc/changelog.d/3556.added.md b/doc/changelog.d/3556.added.md new file mode 100644 index 0000000000..64f1caa881 --- /dev/null +++ b/doc/changelog.d/3556.added.md @@ -0,0 +1 @@ +refactor: increase post module coverage \ No newline at end of file diff --git a/src/ansys/mapdl/core/post.py b/src/ansys/mapdl/core/post.py index f665d46930..3beca9c2d6 100644 --- a/src/ansys/mapdl/core/post.py +++ b/src/ansys/mapdl/core/post.py @@ -130,22 +130,12 @@ def __init__(self, mapdl): if not isinstance(mapdl, MapdlBase): # pragma: no cover raise TypeError("Must be initialized using Mapdl instance") self._mapdl_weakref = weakref.ref(mapdl) - self._set_loaded = False @property def _mapdl(self): """Return the weakly referenced instance of MAPDL""" return self._mapdl_weakref() - @property - def _log(self): - """Alias for mapdl log""" - return self._mapdl._log - - def _set_log_level(self, level): - """Alias for mapdl._set_log_level""" - return self._mapdl._set_log_level(level) - @supress_logging def __repr__(self): info = "PyMAPDL PostProcessing Instance\n" @@ -157,7 +147,7 @@ def __repr__(self): if self._mapdl.parameters.routine == "POST1": info += "\n\n" + self._mapdl.set("LIST") else: - info += "\n\n Enable routine POST1 to see a table of available results" + info += "\n\nEnable routine POST1 to see a table of available results" return info @@ -208,10 +198,6 @@ def frequency_values(self) -> np.ndarray: # Because in MAPDL is the same. return self.time_values - def _reset_cache(self): - """Reset local cache""" - self._set_loaded = False - @property def filename(self) -> str: """Return the current result file name without extension. @@ -732,19 +718,6 @@ def _plot_cell_scalars(self, scalars, show_elem_numbering=False, **kwargs): pl.plot(meshes, [], labels, mapdl=self, **kwargs) return pl.show(**kwargs) - @property - @supress_logging - def _all_nnum(self): - with self._mapdl.save_selection: - self._mapdl.allsel() - nnum = self._mapdl.get_array("NODE", item1="NLIST") - - # rerun if encountered weird edge case of negative first index. - if nnum[0] == -1: - nnum = self._mapdl.get_array("NODE", item1="NLIST") - - return nnum.astype(np.int32, copy=False) - @property @supress_logging def _all_enum(self): @@ -1046,7 +1019,7 @@ def plot_nodal_displacement( if isinstance(component, str): if component.upper() == "ALL": raise ValueError( - '"ALL" not allowed in this context. Select a ' + '"ALL" not allowed in this context. Select a ' 'single displacement component (e.g. "X")' ) @@ -1156,7 +1129,7 @@ def plot_nodal_rotation(self, component, show_node_numbering=False, **kwargs): if isinstance(component, str): if component.upper() == "ALL": raise ValueError( - '"ALL" not allowed in this context. Select a ' + '"ALL" not allowed in this context. Select a ' 'single component (e.g. "X")' ) @@ -1293,7 +1266,7 @@ def plot_element_displacement( """ if component.upper() == "ALL": raise ValueError( - '"ALL" not allowed in this context. Select a ' + '"ALL" not allowed in this context. Select a ' 'single displacement component (e.g. "X" or "NORM")' ) @@ -1364,6 +1337,8 @@ def element_stress(self, component, option="AVG") -> np.ndarray: 0. , 0. ]) """ + if not isinstance(component, str): + component = str(component) component = elem_check_inputs(component, option, STRESS_TYPES) return self.element_values("S", component, option) @@ -2119,8 +2094,6 @@ def nodal_total_component_strain(self, component) -> np.ndarray: array([ 1, 2, 3, ..., 7215, 7216, 7217], dtype=int32) """ - if isinstance(component, int): - component = str(component) component = check_comp(component, COMPONENT_STRESS_TYPE) return self.nodal_values("EPTO", component) @@ -2497,8 +2470,6 @@ def nodal_elastic_component_strain(self, component) -> np.ndarray: array([ 1, 2, 3, ..., 7215, 7216, 7217], dtype=int32) """ - if isinstance(component, int): - component = str(component) component = check_comp(component, COMPONENT_STRESS_TYPE) return self.nodal_values("EPEL", component) @@ -2838,7 +2809,7 @@ def plot_nodal_elastic_eqv_strain(self, show_node_numbering=False, **kwargs): """ scalars = self.nodal_elastic_eqv_strain() kwargs.setdefault( - "scalar_bar_args", {"title": "Elastic Nodal\n Equivalent Strain"} + "scalar_bar_args", {"title": "Elastic Nodal\nEquivalent Strain"} ) return self._plot_point_scalars( scalars, show_node_numbering=show_node_numbering, **kwargs @@ -2878,8 +2849,6 @@ def nodal_plastic_component_strain(self, component) -> np.ndarray: array([ 1, 2, 3, ..., 7215, 7216, 7217], dtype=int32) """ - if isinstance(component, int): - component = str(component) component = check_comp(component, COMPONENT_STRESS_TYPE) return self.nodal_values("EPPL", component) @@ -3221,7 +3190,7 @@ def plot_nodal_plastic_eqv_strain(self, show_node_numbering=False, **kwargs): """ scalars = self.nodal_plastic_eqv_strain() kwargs.setdefault( - "scalar_bar_args", {"title": "Plastic Nodal\n Equivalent Strain"} + "scalar_bar_args", {"title": "Plastic Nodal\nEquivalent Strain"} ) return self._plot_point_scalars( scalars, show_node_numbering=show_node_numbering, **kwargs @@ -3262,8 +3231,6 @@ def nodal_thermal_component_strain(self, component) -> np.ndarray: array([ 1, 2, 3, ..., 7215, 7216, 7217], dtype=int32) """ - if isinstance(component, int): - component = str(component) component = check_comp(component, COMPONENT_STRESS_TYPE) return self.nodal_values("EPTH", component) @@ -3424,7 +3391,7 @@ def nodal_thermal_strain_intensity(self) -> np.ndarray: Equivalent MAPDL command: - * ``PRNSOL, EPTH, PRIN`` + * ``PRNSOL, EPTH, INT`` Returns ------- @@ -3611,7 +3578,7 @@ def plot_nodal_thermal_eqv_strain(self, show_node_numbering=False, **kwargs): """ scalars = self.nodal_thermal_eqv_strain() kwargs.setdefault( - "scalar_bar_args", {"title": "Thermal Nodal\n Equivalent Strain"} + "scalar_bar_args", {"title": "Thermal Nodal\nEquivalent Strain"} ) return self._plot_point_scalars( scalars, show_node_numbering=show_node_numbering, **kwargs @@ -3702,7 +3669,7 @@ def plot_nodal_contact_friction_stress(self, show_node_numbering=False, **kwargs """ kwargs.setdefault( - "scalar_bar_args", {"title": "Nodal Contact\n Friction Stress"} + "scalar_bar_args", {"title": "Nodal Contact\nFriction Stress"} ) return self._plot_point_scalars( self.nodal_contact_friction_stress(), diff --git a/tests/test_post.py b/tests/test_post.py index 5092c5d98c..fd1b1d45a7 100644 --- a/tests/test_post.py +++ b/tests/test_post.py @@ -27,7 +27,7 @@ import numpy as np import pytest -from conftest import has_dependency, requires +from conftest import NullContext, has_dependency, requires if has_dependency("ansys-tools-visualization_interface"): from pyvista.plotting.renderer import CameraPosition @@ -44,6 +44,22 @@ ) +def test_repr(mapdl, cleared): + mapdl.prep7() + print(mapdl.post_processing) + repr_ = mapdl.post_processing.__repr__() + + assert "Number of result sets" in repr_ + assert "Current load step" in repr_ + assert "Number of result sets" in repr_ + assert "Enable routine POST1 to see a table of available results" in repr_ + + mapdl.post1() + repr_ = mapdl.post_processing.__repr__() + assert "Enable routine POST1 to see a table of available results" not in repr_ + assert mapdl.set("LIST") in repr_ + + class Test_static_solve: @staticmethod @@ -170,14 +186,24 @@ def test_disp_norm_all(mapdl, static_solve): @staticmethod @requires("ansys-tools-visualization_interface") - @pytest.mark.parametrize("comp", ["X", "Y", "z", "norm"]) # lowercase intentional + @pytest.mark.parametrize( + "comp", ["X", "Y", "z", "norm", "all"] + ) # lowercase intentional def test_disp_plot(mapdl, static_solve, comp): - assert ( - mapdl.post_processing.plot_nodal_displacement( - comp, smooth_shading=True, cmap=PyMAPDL_cmap + if comp == "all": + context = pytest.raises( + ValueError, match='"ALL" not allowed in this context' + ) + else: + context = NullContext() + + with context: + assert ( + mapdl.post_processing.plot_nodal_displacement( + comp, smooth_shading=True, cmap=PyMAPDL_cmap + ) + is None ) - is None - ) @staticmethod @requires("ansys-tools-visualization_interface") @@ -234,7 +260,7 @@ def test_element_selection(mapdl, static_solve): # TODO: add valid result @staticmethod - @pytest.mark.parametrize("comp", ["X", "Y", "z"]) # lowercase intentional + @pytest.mark.parametrize("comp", ["X", "Y", "z", "all"]) # lowercase intentional def test_rot(mapdl, static_solve, comp): from_grpc = mapdl.post_processing.nodal_rotation(comp) @@ -249,9 +275,17 @@ def test_rot(mapdl, static_solve, comp): @staticmethod @requires("ansys-tools-visualization_interface") - @pytest.mark.parametrize("comp", ["X", "Y", "z"]) # lowercase intentional + @pytest.mark.parametrize("comp", ["X", "Y", "z", "all"]) # lowercase intentional def test_plot_rot(mapdl, static_solve, comp): - assert mapdl.post_processing.plot_nodal_rotation(comp) is None + if comp == "all": + context = pytest.raises( + ValueError, match='"ALL" not allowed in this context' + ) + else: + context = NullContext() + + with context: + assert mapdl.post_processing.plot_nodal_rotation(comp) is None # TODO: add valid result @staticmethod @@ -597,7 +631,7 @@ def test_plot_nodal_elastic_eqv_strain(mapdl, static_solve): ) @staticmethod - @pytest.mark.parametrize("comp", ["X", "Y", "z"]) # lowercase intentional + @pytest.mark.parametrize("comp", ["X", "Y", "z", "all"]) # lowercase intentional def test_elem_disp(mapdl, static_solve, comp): mapdl.post1(mute=True) mapdl.set(1, 1, mute=True) @@ -607,8 +641,18 @@ def test_elem_disp(mapdl, static_solve, comp): # use pretab to get the data table_name = "values" - mapdl.etable(table_name, "U", comp, mute=True) - arr = np.genfromtxt(mapdl.pretab(table_name).splitlines()[1:])[:, 1] + if comp != "all": + mapdl.etable(table_name, "U", comp, mute=True) + arr = np.genfromtxt(mapdl.pretab(table_name).splitlines()[1:])[:, 1] + else: + arr = [] + for direction in ["x", "y", "z"]: + mapdl.etable(table_name, "U", direction, mute=True) + arr.append( + np.genfromtxt(mapdl.pretab(table_name).splitlines()[1:])[:, 1] + ) + arr = np.array(arr).T + assert np.allclose(arr, disp_from_grpc) @staticmethod @@ -640,15 +684,26 @@ def test_elem_disp_norm(mapdl, static_solve): assert np.allclose(norm_disp, disp_from_grpc) @staticmethod - @pytest.mark.parametrize("comp", ["X", "Y", "Z", "NORM"]) + @pytest.mark.parametrize("comp", ["X", "Y", "Z", "NORM", "all"]) @requires("ansys-tools-visualization_interface") def test_elem_disp_plot(mapdl, static_solve, comp): mapdl.post1(mute=True) mapdl.set(1, 1, mute=True) - assert mapdl.post_processing.plot_element_displacement(comp) is None + + if comp == "all": + context = pytest.raises( + ValueError, match='"ALL" not allowed in this context' + ) + else: + context = NullContext() + + with context: + assert mapdl.post_processing.plot_element_displacement(comp) is None + + STRESS_TYPES.extend([1, 2, 3]) @staticmethod - @pytest.mark.parametrize("component", STRESS_TYPES[::3]) + @pytest.mark.parametrize("component", STRESS_TYPES) @pytest.mark.parametrize("option", ["min", "max", "avg"]) def test_element_stress(mapdl, static_solve, component, option): mapdl.post1(mute=True) @@ -656,7 +711,7 @@ def test_element_stress(mapdl, static_solve, component, option): stress = mapdl.post_processing.element_stress(component, option) # use pretab to get the data - table_name = "values" + component + table_name = "values" + str(component) mapdl.etable(table_name, "S", component, option=option, mute=True) from_pretab = np.genfromtxt(mapdl.pretab(table_name).splitlines()[1:])[:, 1] assert np.allclose(stress, from_pretab) @@ -1141,6 +1196,16 @@ def contact_solve(mapdl): mapdl.set("last") mapdl.mute = False + @staticmethod + def test_time(mapdl, contact_solve): + assert mapdl.post_processing.time == 1 + + @staticmethod + def test_freq(mapdl, contact_solve): + # same as post_processing.time + assert mapdl.post_processing.freq == 1 + assert mapdl.post_processing.time == mapdl.post_processing.freq + @staticmethod def test_nodal_contact_friction_stress(mapdl, contact_solve): # Format tables. @@ -1300,76 +1365,164 @@ def test_exited(mapdl): ############################################################################### -# @pytest.mark.parametrize('comp', COMPONENT_STRESS_TYPE) -# def test_nodal_thermal_component_strain(mapdl, thermal_solve, comp): -# index = COMPONENT_STRESS_TYPE.index(comp) -# mapdl.prnsol('EPPL', 'COMP', mute=True) # run twice to clear out warning -# data = np.genfromtxt(mapdl.prnsol('EPPL', 'COMP').splitlines()[1:]) -# nnum_ans = data[:, 0].astype(np.int32) -# data_ans = data[:, index + 1] -# data = mapdl.post_processing.nodal_thermal_component_strain(comp) -# data = data[np.in1d(mapdl.mesh.nnum, nnum_ans)] +class Test_thermal_solve: -# assert np.allclose(data_ans, data) + @staticmethod + @pytest.fixture(scope="class") + def thermal_solve(mapdl): + mapdl.mute = True + mapdl.finish() + mapdl.clear() + mapdl.prep7() + mapdl.et(1, "PLANE223", 11, 1) # COUPLE-FIELD ELEMENT TYPE, WEAK COUPLING + mapdl.et(2, "CONTA175", 1) # CONTACT ELEMENT TYPE + mapdl.et(3, "TARGE169") # TARGET ELEMENT TYPE + mapdl.mp("EX", 1, 10e6) # YOUNG'S MODULUS + mapdl.mp("KXX", 1, 250) # CONDUCTIVITY + mapdl.mp("ALPX", 1, 12e-6) # THERMAL EXPANSION COEFFICIENT + mapdl.mp("PRXY", "", 0.3) + mapdl.r(2, "", "", -1000, -0.005) + mapdl.rmore("", "", "", "", "", -100) + mapdl.rmore("", 100) + mapdl.rmore() + mapdl.rmore(0.01) + + # SET UP FINITE ELEMENT MODEL + mapdl.n(1) + mapdl.n(2, 0.4) + mapdl.n(3, "(0.4+0.0035)") + mapdl.n(4, "(0.9+0.0035)") + mapdl.ngen(2, 4, 1, 4, 1, "", 0.1) + mapdl.e(1, 2, 6, 5) # PLANE223 ELEMENTS + mapdl.e(3, 4, 8, 7) + mapdl.type(2) # CONTACT ELEMENTS + mapdl.real(2) + mapdl.e(2) + mapdl.e(6) + mapdl.type(3) # TARGET ELEMENTS + mapdl.real(2) + mapdl.nsel("S", "NODE", "", 3, 7, 4) + mapdl.esln() + mapdl.esurf() + mapdl.allsel() -# @requires("ansys-tools-visualization_interface") -# def test_plot_nodal_thermal_component_strain(mapdl, thermal_solve): -# assert mapdl.post_processing.plot_nodal_thermal_component_strain('x') is None + # APPLY INITIAL BOUNDARY CONDITIONS + mapdl.d(1, "UY", "", "", 4, 1) + mapdl.d(1, "UX", "", "", 5, 4) + mapdl.d(4, "UX", "", "", 8, 4) + mapdl.tref(100) + mapdl.eresx("YES") + mapdl.finish() + mapdl.slashsolu() + mapdl.nlgeom("ON") # LARGE DEFLECTION EFFECTS TURNED ON + mapdl.d(1, "TEMP", 500, "", 5, 4) + mapdl.d(3, "TEMP", 100, "", 4) + mapdl.d(7, "TEMP", 100, "", 8) + mapdl.solve() # FIRST LOAD STEP -# @pytest.mark.parametrize('comp', PRINCIPAL_TYPE) -# def test_nodal_thermal_principal_strain(mapdl, thermal_solve, comp): -# from_grpc = mapdl.post_processing.nodal_thermal_principal_strain(comp) + mapdl.solution() + mapdl.allsel() + mapdl.outres("all", "all") + mapdl.solve() + mapdl.mute = False -# index = PRINCIPAL_TYPE.index(comp) -# mapdl.prnsol('EPPL', 'PRIN') # flush to ignore warning -# arr = np.genfromtxt(mapdl.prnsol('EPPL', 'PRIN').splitlines()[1:]) -# nnum_ans = arr[:, 0] -# from_prns = arr[:, index + 1] + mapdl.save("thermal_solve") + mapdl.finish() -# # grpc includes all nodes. ignore the ones not included in prnsol -# from_grpc = from_grpc[np.in1d(mapdl.mesh.nnum, nnum_ans)] + @staticmethod + @pytest.fixture() + def resume(mapdl, thermal_solve): + mapdl.solution() + mapdl.resume("thermal_solve") -# assert np.allclose(from_grpc, from_prns) + mapdl.post1() + mapdl.allsel() + mapdl.set("last") + mapdl.header("OFF", "OFF", "OFF", "OFF", "OFF", "OFF") + nsigfig = 10 + mapdl.format("", "E", nsigfig + 9, nsigfig) + mapdl.page(1e9, "", -1, 240) + + @staticmethod + @pytest.mark.parametrize("comp", COMPONENT_STRESS_TYPE) + def test_nodal_thermal_component_strain(mapdl, resume, comp): + + index = COMPONENT_STRESS_TYPE.index(comp) + mapdl.prnsol("EPTH", "COMP", mute=True) # run twice to clear out warning -# @requires("ansys-tools-visualization_interface") -# def test_plot_nodal_thermal_principal_strain(mapdl, thermal_solve): -# assert mapdl.post_processing.plot_nodal_thermal_principal_strain(1) is None + data = np.genfromtxt(mapdl.prnsol("EPTH", "COMP").splitlines()[1:]) + nnum_ans = data[:, 0].astype(np.int32) + data_ans = data[:, index + 1] + data = mapdl.post_processing.nodal_thermal_component_strain(comp) + data = data[np.in1d(mapdl.mesh.nnum, nnum_ans)] + + assert np.allclose(data_ans, data) + + @staticmethod + @requires("ansys-tools-visualization_interface") + def test_plot_nodal_thermal_component_strain(mapdl, resume): + assert mapdl.post_processing.plot_nodal_thermal_component_strain("x") is None + + @staticmethod + @pytest.mark.parametrize("comp", PRINCIPAL_TYPE) + def test_nodal_thermal_principal_strain(mapdl, resume, comp): + from_grpc = mapdl.post_processing.nodal_thermal_principal_strain(comp) + + index = PRINCIPAL_TYPE.index(comp) + mapdl.prnsol("EPTH", "PRIN") # flush to ignore warning + arr = np.genfromtxt(mapdl.prnsol("EPTH", "PRIN").splitlines()[1:]) + nnum_ans = arr[:, 0] + from_prns = arr[:, index + 1] + # grpc includes all nodes. ignore the ones not included in prnsol + from_grpc = from_grpc[np.in1d(mapdl.mesh.nnum, nnum_ans)] -# def test_nodal_thermal_strain_intensity(mapdl, thermal_solve): -# mapdl.prnsol('EPPL', 'PRIN', mute=True) # run twice to clear out warning -# data = np.genfromtxt(mapdl.prnsol('EPPL', 'PRIN').splitlines()[1:]) -# nnum_ans = data[:, 0].astype(np.int32) -# sint_ans = data[:, -2] -# sint = mapdl.post_processing.nodal_thermal_strain_intensity() + assert np.allclose(from_grpc, from_prns) -# sint_aligned = sint[np.in1d(mapdl.mesh.nnum, nnum_ans)] -# assert np.allclose(sint_ans, sint_aligned) + @staticmethod + @requires("ansys-tools-visualization_interface") + def test_plot_nodal_thermal_principal_strain(mapdl, resume): + assert mapdl.post_processing.plot_nodal_thermal_principal_strain(1) is None + @staticmethod + def test_nodal_thermal_strain_intensity(mapdl, resume): + mapdl.prnsol("EPTH", "PRIN", mute=True) # run twice to clear out warning + data = np.genfromtxt(mapdl.prnsol("EPTH", "PRIN").splitlines()[1:]) + nnum_ans = data[:, 0].astype(np.int32) + sint_ans = data[:, -2] + sint = mapdl.post_processing.nodal_thermal_strain_intensity() -# @requires("ansys-tools-visualization_interface") -# def test_plot_nodal_thermal_strain_intensity(mapdl, thermal_solve): -# assert mapdl.post_processing.plot_nodal_thermal_strain_intensity() is None + sint_aligned = sint[np.in1d(mapdl.mesh.nnum, nnum_ans)] + assert np.allclose(sint_ans, sint_aligned) + @staticmethod + @requires("ansys-tools-visualization_interface") + def test_plot_nodal_thermal_strain_intensity(mapdl, resume): + assert mapdl.post_processing.plot_nodal_thermal_strain_intensity() is None -# def test_nodal_thermal_eqv_strain(mapdl, thermal_solve): -# mapdl.prnsol('EPPL', 'PRIN', mute=True) # run twice to clear out warning -# data = np.genfromtxt(mapdl.prnsol('EPPL', 'PRIN').splitlines()[1:]) -# nnum_ans = data[:, 0].astype(np.int32) -# seqv_ans = data[:, -1] -# seqv = mapdl.post_processing.nodal_thermal_eqv_strain() + @staticmethod + def test_nodal_thermal_eqv_strain(mapdl, resume): + mapdl.prnsol("EPTH", "PRIN", mute=True) # run twice to clear out warning + data = np.genfromtxt(mapdl.prnsol("EPTH", "PRIN").splitlines()[1:]) + nnum_ans = data[:, 0].astype(np.int32) + seqv_ans = data[:, -1] + seqv = mapdl.post_processing.nodal_thermal_eqv_strain() -# seqv_aligned = seqv[np.in1d(mapdl.mesh.nnum, nnum_ans)] -# assert np.allclose(seqv_ans, seqv_aligned) + seqv_aligned = seqv[np.in1d(mapdl.mesh.nnum, nnum_ans)] + assert np.allclose(seqv_ans, seqv_aligned) + @staticmethod + @requires("ansys-tools-visualization_interface") + def test_plot_nodal_thermal_eqv_strain(mapdl, resume): + assert ( + mapdl.post_processing.plot_nodal_thermal_eqv_strain(smooth_shading=True) + is None + ) -# @requires("ansys-tools-visualization_interface") -# def test_plot_nodal_thermal_eqv_strain(mapdl, thermal_solve): -# assert mapdl.post_processing.plot_nodal_thermal_eqv_strain(smooth_shading=True) is None ###############################################################################