Skip to content

Commit 459d231

Browse files
germa89akaszynski
andcommitted
Fix/lsread to non interactive (#1384)
* Adding LSREAD to non-allowed interactive cmd Also wrapping LSREAD in non-interactive context manager. * Adding unit test. * Updating docs and docstring. * Double checking unit test. * Missing in. * add example; improve test * Fixing unit test * fixing unit test Co-authored-by: Alex Kaszynski <[email protected]>
1 parent 4ff2c76 commit 459d231

File tree

7 files changed

+316
-26
lines changed

7 files changed

+316
-26
lines changed

doc/source/user_guide/mapdl.rst

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -828,17 +828,20 @@ These commands are detailed in Table-2_.
828828

829829
**Table 2. Non-interactive only commands.**
830830

831-
+---------------+-------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
832-
| | Interactive | Non-interactive | Direct Run | Notes |
833-
+===============+=========================+==================================+======================================================================================================================+=====================================================================================================+
834-
| * ``*CREATE`` | |:x:| Not available | |:heavy_check_mark:| Available | |:heavy_minus_sign:| Only in :attr:`Mapdl.non_interactive <ansys.mapdl.core.Mapdl.non_interactive>` | It is recommended to create Python functions instead. |
835-
+---------------+-------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
836-
| * ``CFOPEN`` | |:x:| Not available | |:heavy_check_mark:| Available | |:heavy_minus_sign:| Only in :attr:`Mapdl.non_interactive <ansys.mapdl.core.Mapdl.non_interactive>` | It is recommended to use Python functions such as ``open``. |
837-
+---------------+-------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
838-
| * ``CFCLOSE`` | |:x:| Not available | |:heavy_check_mark:| Available | |:heavy_minus_sign:| Only in :attr:`Mapdl.non_interactive <ansys.mapdl.core.Mapdl.non_interactive>` | It is recommended to use Python functions such as ``open``. |
839-
+---------------+-------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
840-
| * ``*VWRITE`` | |:x:| Not available | |:heavy_check_mark:| Available | |:heavy_minus_sign:| Only in :attr:`Mapdl.non_interactive <ansys.mapdl.core.Mapdl.non_interactive>` | If you are working in a local session, it is recommended you use Python function such as ``open``. |
841-
+---------------+-------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
831+
+---------------+---------------------------------------------------------------------------------------------------------------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
832+
| | Interactive | Non-interactive | Direct Run | Notes |
833+
+===============+=================================================================================================================================+==================================+======================================================================================================================+=====================================================================================================+
834+
| * ``*CREATE`` | |:x:| Not available | |:heavy_check_mark:| Available | |:heavy_minus_sign:| Only in :attr:`Mapdl.non_interactive <ansys.mapdl.core.Mapdl.non_interactive>` | It is recommended to create Python functions instead. |
835+
+---------------+---------------------------------------------------------------------------------------------------------------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
836+
| * ``CFOPEN`` | |:x:| Not available | |:heavy_check_mark:| Available | |:heavy_minus_sign:| Only in :attr:`Mapdl.non_interactive <ansys.mapdl.core.Mapdl.non_interactive>` | It is recommended to use Python functions such as ``open``. |
837+
+---------------+---------------------------------------------------------------------------------------------------------------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
838+
| * ``CFCLOSE`` | |:x:| Not available | |:heavy_check_mark:| Available | |:heavy_minus_sign:| Only in :attr:`Mapdl.non_interactive <ansys.mapdl.core.Mapdl.non_interactive>` | It is recommended to use Python functions such as ``open``. |
839+
+---------------+---------------------------------------------------------------------------------------------------------------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
840+
| * ``*VWRITE`` | |:x:| Not available | |:heavy_check_mark:| Available | |:heavy_minus_sign:| Only in :attr:`Mapdl.non_interactive <ansys.mapdl.core.Mapdl.non_interactive>` | If you are working in a local session, it is recommended you use Python function such as ``open``. |
841+
+---------------+---------------------------------------------------------------------------------------------------------------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
842+
| * ``LSWRITE`` | |:heavy_check_mark:| Available (Internally running in :attr:`Mapdl.non_interactive <ansys.mapdl.core.Mapdl.non_interactive>`) | |:heavy_check_mark:| Available | |:heavy_minus_sign:| Only in :attr:`Mapdl.non_interactive <ansys.mapdl.core.Mapdl.non_interactive>` | |
843+
+---------------+---------------------------------------------------------------------------------------------------------------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
844+
842845

843846

844847

src/ansys/mapdl/core/_commands/solution/load_step_operations.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ def lsdele(self, lsmin="", lsmax="", lsinc="", **kwargs):
6060
def lsread(self, lsnum="", **kwargs):
6161
"""Reads load and load step option data into the database.
6262
63+
.. warning:: This command can only run in non-interactive mode.
64+
Please visit `Unsupported "Interactive" Commands
65+
<https://mapdl.docs.pyansys.com/user_guide/mapdl.html#unsupported-interactive-commands>`_
66+
for further information.
67+
6368
APDL Command: LSREAD
6469
6570
Parameters
@@ -83,6 +88,62 @@ def lsread(self, lsnum="", **kwargs):
8388
existing SFGRAD specification.
8489
8590
This command is also valid in PREP7.
91+
92+
Examples
93+
--------
94+
Demonstrate writing out load steps using :func:`lswrite
95+
<ansys.mapdl.core.Mapdl.lswrite> and reading them back in using
96+
``lsread``.
97+
98+
>>> from ansys.mapdl.core import launch_mapdl
99+
>>> mapdl = launch_mapdl()
100+
>>> mapdl.clear()
101+
>>> mapdl.prep7()
102+
103+
Build a 5 x 5 flat plate out of shell181 elements.
104+
105+
>>> mapdl.rectng(0, 5, 0, 5)
106+
>>> mapdl.et(1, 'SHELL181')
107+
>>> mapdl.mp('ex', 1, 10.0e5)
108+
>>> mapdl.sectype(1, 'shell')
109+
>>> mapdl.secdata(0.1) # 0.1 thick
110+
>>> mapdl.esize(1)
111+
>>> mapdl.amesh('all')
112+
113+
Fix the four corners
114+
115+
>>> mapdl.d('node(0,0,0)', 'all')
116+
>>> mapdl.d('node(0,5,0)', 'all')
117+
>>> mapdl.d('node(5,5,0)', 'all')
118+
>>> mapdl.d('node(5,0,0)', 'all')
119+
120+
Enter the solution routine and define a force at (2,2,0).
121+
122+
>>> mapdl.slashsolu()
123+
>>> mapdl.antype('static')
124+
>>> mapdl.f('node(2,2,0)', 'fz', -10)
125+
126+
Write load out as load step 1 and delete all loads and displacements.
127+
128+
>>> mapdl.lswrite(1)
129+
>>> mapdl.fdele('all', 'all')
130+
>>> mapdl.ddele('all', 'all')
131+
132+
Read back in the loads and list them.
133+
134+
>>> mapdl.lsread(1)
135+
>>> mapdl.flist()
136+
LIST NODAL FORCES FOR SELECTED NODES 1 TO 36 BY 1
137+
CURRENTLY SELECTED NODAL LOAD SET= FX FY FZ MX MY MZ
138+
139+
*** MAPDL - ENGINEERING ANALYSIS SYSTEM RELEASE 2022 R2 22.2 ***
140+
Ansys Mechanical Enterprise
141+
00000000 VERSION=LINUX x64 10:15:14 AUG 22, 2022 CP= 0.561
142+
143+
NODE LABEL REAL IMAG
144+
26 FZ -10.0000000 0.00000000
145+
146+
86147
"""
87148
command = f"LSREAD,{lsnum}"
88149
return self.run(command, **kwargs)

src/ansys/mapdl/core/errors.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ def __init__(self, msg=""):
6161
RuntimeError.__init__(self, msg)
6262

6363

64+
class MapdlCommandIgnoredError(RuntimeError):
65+
"""Raised when MAPDL ignores a command."""
66+
67+
def __init__(self, msg=""):
68+
RuntimeError.__init__(self, msg)
69+
70+
6471
class MapdlExitedError(RuntimeError):
6572
"""Raised when MAPDL has exited"""
6673

src/ansys/mapdl/core/mapdl.py

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@
2828
StringWithLiteralRepr,
2929
inject_docs,
3030
)
31-
from ansys.mapdl.core.errors import MapdlInvalidRoutineError, MapdlRuntimeError
31+
from ansys.mapdl.core.errors import (
32+
MapdlCommandIgnoredError,
33+
MapdlInvalidRoutineError,
34+
MapdlRuntimeError,
35+
)
3236
from ansys.mapdl.core.inline_functions import Query
3337
from ansys.mapdl.core.misc import (
3438
Information,
@@ -77,6 +81,7 @@
7781
"*IF": "Use a python ``if`` or run as non_interactive",
7882
"CMAT": "Run `CMAT` as ``non_interactive``.",
7983
"*REP": "Run '*REPEAT' in ``non_interactive``.",
84+
"LSRE": "Run 'LSREAD' in ``non_interactive``.",
8085
}
8186

8287
## Soft-invalid commands
@@ -2646,6 +2651,11 @@ def run(self, command, write_to_log=True, mute=None, **kwargs) -> str:
26462651
text += "\n\nIgnore these messages by setting allow_ignore=True"
26472652
raise MapdlInvalidRoutineError(text)
26482653

2654+
if "command is ignored" in text:
2655+
if not self.allow_ignore:
2656+
text += "\n\nIgnore these messages by setting allow_ignore=True"
2657+
raise MapdlCommandIgnoredError(text)
2658+
26492659
# flag errors
26502660
if "*** ERROR ***" in self._response and not self._ignore_errors:
26512661
self._raise_output_errors(self._response)
@@ -3601,3 +3611,71 @@ def _raise_output_errors(self, response):
36013611
raise MapdlRuntimeError(
36023612
f"\n\nError in instance {self.name}\n\n" + error_message
36033613
)
3614+
3615+
@wraps(Commands.lsread)
3616+
def lsread(self, *args, **kwargs):
3617+
"""Wraps the ``LSREAD`` which does not work in interactive mode."""
3618+
self._log.debug("Forcing 'LSREAD' to run in non-interactive mode.")
3619+
with self.non_interactive:
3620+
super().lsread(*args, **kwargs)
3621+
return self._response.strip()
3622+
3623+
@wraps(Commands.lsread)
3624+
def lsread(self, *args, **kwargs):
3625+
"""Wraps the ``LSREAD`` which does not work in interactive mode."""
3626+
self._log.debug("Forcing 'LSREAD' to run in non-interactive mode.")
3627+
with self.non_interactive:
3628+
super().lsread(*args, **kwargs)
3629+
return self._response.strip()
3630+
3631+
def file(self, fname="", ext="", **kwargs):
3632+
"""Specifies the data file where results are to be found.
3633+
3634+
APDL Command: FILE
3635+
3636+
Parameters
3637+
----------
3638+
fname : str
3639+
File name and directory path (248 characters maximum, including the
3640+
characters needed for the directory path). An unspecified
3641+
directory path defaults to the working directory; in this case, you
3642+
can use all 248 characters for the file name.
3643+
3644+
ext : str, default: "rst"
3645+
Filename extension (eight-character maximum). If ``fname`` has an
3646+
extension this is ignored.
3647+
3648+
Notes
3649+
-----
3650+
Specifies the Ansys data file where the results are to be found for
3651+
postprocessing.
3652+
3653+
Examples
3654+
--------
3655+
Load a result file that is outside of the current working directory.
3656+
3657+
>>> from ansys.mapdl.core import launch_mapdl
3658+
>>> mapdl = launch_mapdl()
3659+
>>> mapdl.post1()
3660+
>>> mapdl.file('/tmp/file.rst')
3661+
3662+
"""
3663+
# MAPDL always adds the "rst" extension onto the name, even if already
3664+
# has one, so here we simply reconstruct it.
3665+
filename = pathlib.Path(fname + ext)
3666+
3667+
if not filename.exists():
3668+
# potential that the user is relying on the default "rst"
3669+
filename_rst = filename.parent / (filename.name + ".rst")
3670+
if not filename_rst.exists():
3671+
raise FileNotFoundError(f"Unable to locate {filename}")
3672+
3673+
return self._file(filename, **kwargs)
3674+
3675+
def _file(self, filename, **kwargs):
3676+
"""Run the MAPDL ``file`` command with a proper filename."""
3677+
filename = pathlib.Path(filename)
3678+
ext = filename.suffix
3679+
fname = str(filename).replace(ext, "")
3680+
ext = ext.replace(".", "")
3681+
return self.run(f"FILE,{fname},{ext}", **kwargs)

tests/conftest.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ def query(mapdl, cleared):
377377

378378
@pytest.fixture
379379
def solved_box(mapdl, cleared):
380+
mapdl.mute = True # improve stability
380381
mapdl.prep7()
381382
mapdl.et(1, "SOLID5")
382383
mapdl.block(0, 10, 0, 20, 0, 30)
@@ -399,6 +400,8 @@ def solved_box(mapdl, cleared):
399400
mapdl.antype("STATIC")
400401
mapdl.solve()
401402
mapdl.finish()
403+
mapdl.mute = False
404+
402405
q = mapdl.queries
403406
return q, get_details_of_nodes(mapdl)
404407

0 commit comments

Comments
 (0)