Skip to content

Commit

Permalink
CommandOutput improvements (#1554)
Browse files Browse the repository at this point in the history
* Allow magicwords definition when instantiating CommandListingOutput class

Fix a bug that omitted the last number on the listing.

Added unit tests

* Wraping ``set,list`` with the command output listing class

Adding unit test

* Exposing ``set`` in post_processing using ``mapdl.set("list")``

* Updating docs

* Improving docs

* Fixing lathe issue.

* making sure were the argument is a string

* Fixing table references

* Fixing unit test

* Exposing 'columns_names'.

Adding unit tests

* Fixing building issue.

* Renaming method set to step

* Reseting cache
  • Loading branch information
germa89 authored Oct 24, 2022
1 parent 4ecf526 commit 87f54fe
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 38 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ env:
# You should go up in number, if you go down (or repeat a previous value)
# you might end up reusing a previous cache if it haven't been deleted already.
# It applies 7 days retention policy by default.
RESET_PIP_CACHE: 1
RESET_EXAMPLES_CACHE: 1
RESET_DOC_BUILD_CACHE: 1
RESET_AUTOSUMMARY_CACHE: 1
RESET_PIP_CACHE: 2
RESET_EXAMPLES_CACHE: 2
RESET_DOC_BUILD_CACHE: 2
RESET_AUTOSUMMARY_CACHE: 2

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down
59 changes: 33 additions & 26 deletions doc/source/user_guide/post.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,32 +37,39 @@ These commands are listed in Table-1_.

**Table 1. Commands with extra processing methods in the output.**

+----------------+---------------------------------------------------------------------------------------------------+----------------------------------------------------------+
| Category | Extra Methods Available | Mapdl Commands |
+================+===================================================================================================+==========================================================+
| **Listing** | * :func:`to_list() <ansys.mapdl.core.commands.CommandListingOutput.to_list>` | * :func:`prcint() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | * :func:`to_array() <ansys.mapdl.core.commands.CommandListingOutput.to_array>` | * :func:`prenergy() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | * :func:`to_dataframe() <ansys.mapdl.core.commands.CommandListingOutput.to_dataframe>` | * :func:`prerr() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`presol() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`pretab() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`print() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`priter() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`prjsol() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`prnld() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`prnsol() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`prorb() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`prpath() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`prrfor() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`prrsol() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`prsect() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`prvect() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`stat() <ansys.mapdl.core.mapdl._MapdlCore>` |
| | | * :func:`swlist() <ansys.mapdl.core.mapdl._MapdlCore>` |
+----------------+---------------------------------------------------------------------------------------------------+----------------------------------------------------------+
| **Boundary** | * :func:`to_list() <ansys.mapdl.core.commands.BoundaryConditionsListingOutput.to_list>` | * :func:`dlist() <ansys.mapdl.core.mapdl._MapdlCore>` |
| **Conditions** | * :func:`to_dataframe() <ansys.mapdl.core.commands.BoundaryConditionsListingOutput.to_dataframe>` | * :func:`flist() <ansys.mapdl.core.mapdl._MapdlCore>` |
| **Listing** | | |
+----------------+---------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+----------------+---------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
| Category | Extra Methods Available | Mapdl Commands |
+================+===================================================================================================+==========================================================================+
| **Listing** | * :class:`cmd.to_list() <ansys.mapdl.core.commands.CommandListingOutput>` | **Results Listing** |
| | * :class:`cmd.to_array() <ansys.mapdl.core.commands.CommandListingOutput>` | |
| | * :class:`cmd.to_dataframe() <ansys.mapdl.core.commands.CommandListingOutput>` | * :func:`Mapdl.prcint() <ansys.mapdl.core.Mapdl.prcint>` |
| | | * :func:`Mapdl.prenergy() <ansys.mapdl.core.Mapdl.prenergy>` |
| | | * :func:`Mapdl.prerr() <ansys.mapdl.core.Mapdl.prerr>` |
| | | * :func:`Mapdl.presol() <ansys.mapdl.core.Mapdl.presol>` |
| | | * :func:`Mapdl.pretab() <ansys.mapdl.core.Mapdl.pretab>` |
| | | * :func:`Mapdl.print() <ansys.mapdl.core.Mapdl.print>` |
| | | * :func:`Mapdl.priter() <ansys.mapdl.core.Mapdl.priter>` |
| | | * :func:`Mapdl.prjsol() <ansys.mapdl.core.Mapdl.prjsol>` |
| | | * :func:`Mapdl.prnld() <ansys.mapdl.core.Mapdl.prnld>` |
| | | * :func:`Mapdl.prnsol() <ansys.mapdl.core.Mapdl.prnsol>` |
| | | * :func:`Mapdl.prorb() <ansys.mapdl.core.Mapdl.prorb>` |
| | | * :func:`Mapdl.prpath() <ansys.mapdl.core.Mapdl.prpath>` |
| | | * :func:`Mapdl.prrfor() <ansys.mapdl.core.Mapdl.prrfor>` |
| | | * :func:`Mapdl.prrsol() <ansys.mapdl.core.Mapdl.prrsol>` |
| | | * :func:`Mapdl.prsect() <ansys.mapdl.core.Mapdl.prsect>` |
| | | * :func:`Mapdl.prvect() <ansys.mapdl.core.Mapdl.prvect>` |
| | | * :func:`Mapdl.stat() <ansys.mapdl.core.Mapdl.stat>` |
| | | * :func:`Mapdl.swlist() <ansys.mapdl.core.Mapdl.swlist>` |
| | | |
| | | **Other Listing** |
| | | |
| | | * :func:`Mapdl.set("LIST") <ansys.mapdl.core.Mapdl.set>` |
| | | |
+----------------+---------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
| **Boundary** | * :func:`cmd.to_list() <ansys.mapdl.core.commands.BoundaryConditionsListingOutput>` | * :func:`Mapdl.dlist() <ansys.mapdl.core.Mapdl.dlist>` |
| **Conditions** | * :func:`cmd.to_dataframe() <ansys.mapdl.core.commands.BoundaryConditionsListingOutput>` | * :func:`Mapdl.flist() <ansys.mapdl.core.Mapdl.flist>` |
| **Listing** | | |
+----------------+---------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------+

Here's a simple example demonstrating the the usage:

Expand Down
4 changes: 4 additions & 0 deletions src/ansys/mapdl/core/_commands/post1_/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,10 @@ def set(
LIST - Scan the results file and list a summary of each load step. (KIMG, TIME,
ANGLE, and NSET are ignored.)
.. versionchanged:: 0.64
From version 0.64 you can use the methods ``to_list`` and
``to_array`` on the object returning from ``mapdl.set("list")``.
sbstep
Substep number (within Lstep). Defaults to the last substep of the
load step (except in a buckling or modal analysis). For a buckling
Expand Down
31 changes: 23 additions & 8 deletions src/ansys/mapdl/core/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@

# compiled regular expressions used for parsing tablular outputs
REG_LETTERS = re.compile(r"[a-df-zA-DF-Z]+") # all except E or e
REG_FLOAT_INT = re.compile(r"[+-]?[0-9]*[.]?[0-9]+[Ee]?[+-]?[0-9]+|\s[0-9]+\s")
REG_FLOAT_INT = re.compile(
r"[+-]?[0-9]*[.]?[0-9]*[Ee]?[+-]?[0-9]+|\s[0-9]+\s"
) # match number groups
BC_REGREP = re.compile(
r"^\s*([0-9]+)\s*([A-Za-z]+)\s*([0-9]*[.]?[0-9]+)\s+([0-9]*[.]?[0-9]+)"
)
Expand Down Expand Up @@ -490,20 +492,30 @@ class CommandListingOutput(CommandOutput):
a list of lists, a Numpy array or a Pandas DataFrame.
"""

def __new__(cls, content, cmd=None, magicwords=None, columns_names=None):
obj = super().__new__(cls, content)
obj._cmd = cmd
obj._magicwords = magicwords
obj._columns_names = columns_names
return obj

def __init__(self, *args, **kwargs):
self._cache = None

def _is_data_start(self, line, magicword=None):
def _is_data_start(self, line, magicwords=None):
"""Check if line is the start of a data group."""
if not magicword:
magicword = GROUP_DATA_START
if not magicwords:
if self._magicwords:
magicwords = self._magicwords
else:
magicwords = GROUP_DATA_START

# Checking if we are supplying a custom start function.
if self.custom_data_start(line) is not None:
return self.custom_data_start(line)

if line.split():
if line.split()[0] in magicword or self.custom_data_start(line):
if line.split()[0] in magicwords or self.custom_data_start(line):
return True
return False

Expand Down Expand Up @@ -569,7 +581,7 @@ def _get_body(self, trail_header=None):
body = body[:i]
return body

def _get_data_group_indexes(self, body, magicword=None):
def _get_data_group_indexes(self, body, magicwords=None):
"""Return the indexes of the start and end of the data groups."""
if "*****ANSYS VERIFICATION RUN ONLY*****" in str(self[:1000]):
shift = 2
Expand All @@ -580,7 +592,7 @@ def _get_data_group_indexes(self, body, magicword=None):
start_idxs = [
ind
for ind, each in enumerate(body)
if self._is_data_start(each, magicword=magicword)
if self._is_data_start(each, magicwords=magicwords)
]
end_idxs = [
ind - shift for ind, each in enumerate(body) if self._is_empty_line(each)
Expand All @@ -602,6 +614,9 @@ def get_columns(self):
List of strings
"""
if self._columns_names:
return self._columns_names

body = self._get_body()
pairs = list(self._get_data_group_indexes(body))
try:
Expand All @@ -621,7 +636,7 @@ def _parse_table(self):
parsed_lines = []
for line in self.splitlines():
# exclude any line containing characters [A-Z] except for E
if line and not REG_LETTERS.search(line):
if line.strip() and not REG_LETTERS.search(line):
items = REG_FLOAT_INT.findall(line)
if items:
parsed_lines.append(items)
Expand Down
38 changes: 38 additions & 0 deletions src/ansys/mapdl/core/mapdl.py
Original file line number Diff line number Diff line change
Expand Up @@ -3799,3 +3799,41 @@ def use(self, *args, **kwargs):
# Updating arg since the path is not needed anymore.
args = (base_name, args[1:])
return super().use(*args, **kwargs)

@wraps(Commands.set)
def set(
self,
lstep="",
sbstep="",
fact="",
kimg="",
time="",
angle="",
nset="",
order="",
**kwargs,
):
"""Wraps SET to return a Command listing"""
output = super().set(
lstep, sbstep, fact, kimg, time, angle, nset, order, **kwargs
)

if (
isinstance(lstep, str)
and lstep.upper() == "LIST"
and not sbstep
and not fact
):
return CommandListingOutput(
output,
magicwords=["SET", "TIME/FREQ"],
columns_names=[
"SET",
"TIME/FREQ",
"LOAD STEP",
"SUBSTEP",
"CUMULATIVE",
],
)
else:
return output
16 changes: 16 additions & 0 deletions src/ansys/mapdl/core/post.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,22 @@ def sub_step(self) -> int:
"""
return int(self._mapdl.get_value("ACTIVE", item1="SET", it1num="SBST"))

@property
def step(self) -> int:
"""Current step number
Examples
--------
>>> mapdl.post1()
>>> mapdl.set(1, 2)
>>> mapdl.post_processing.set
2
"""
sets = self._mapdl.set("LIST").to_array()
ldstep = self.load_step
substep = self.sub_step
return sets[(sets[:, 2] == ldstep) & (sets[:, 3] == substep)][0, 0]

@property
def time(self) -> float:
"""Time associated with current result in the database.
Expand Down
37 changes: 37 additions & 0 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,26 @@
"kcmplx": 1,
}


set_list_0 = """***** INDEX OF DATA SETS ON RESULTS FILE *****
SET TIME/FREQ LOAD STEP SUBSTEP CUMULATIVE
1 0.20000 1 1 3
2 0.40000 1 2 5
3 0.70000 1 3 7
4 1.0000 1 4 9"""

set_list_1 = """***** INDEX OF DATA SETS ON RESULTS FILE *****
SET TIME/FREQ LOAD STEP SUBSTEP CUMULATIVE
1 0.10000E-02 1 10 10
2 0.20000E-02 2 1 11
3 0.30000E-02 2 2 12
4 0.40000E-02 2 3 13
5 0.50000E-02 2 4 14
6 0.60000E-02 2 5 15
"""

PRNSOL_OUT = """PRINT F REACTION SOLUTIONS PER NODE
1 0.1287512532E+008 0.4266737217E+007
2 -0.1512012179E+007 0.2247558576E+007
Expand Down Expand Up @@ -659,6 +679,23 @@ def test_string_with_literal():
assert len(output.split()) == 2


@pytest.mark.parametrize("output,last_element", [(set_list_0, 9), (set_list_1, 15)])
def test_magicwords(output, last_element):
magicwords = ["SET"]
obj = CommandListingOutput(
output,
magicwords=magicwords,
columns_names=["SET", "TIME/FREQ", "LOAD STEP", "SUBSTEP", "CUMULATIVE"],
)

assert obj.to_list() is not None
assert obj.to_array() is not None
assert obj.to_dataframe() is not None

arr = obj.to_array()
assert arr[-1, -1] == last_element


def test_nlist_to_array(mapdl, beam_solve):
# This kinternal include the internal points, so it matches the
# number of nodes with midside nodes.
Expand Down
15 changes: 15 additions & 0 deletions tests/test_mapdl.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from pyvista.plotting import system_supports_plotting

from ansys.mapdl import core as pymapdl
from ansys.mapdl.core.commands import CommandListingOutput
from ansys.mapdl.core.errors import MapdlCommandIgnoredError, MapdlRuntimeError
from ansys.mapdl.core.launcher import get_start_instance, launch_mapdl
from ansys.mapdl.core.misc import random_string
Expand Down Expand Up @@ -1596,6 +1597,20 @@ def test_use_uploading(mapdl, cleared, tmpdir):
mapdl.use("asdf/myinexistentmacro.mac")


def test_set_list(mapdl, cube_solve):
mapdl.post1()
obj = mapdl.set("list")

assert isinstance(obj, CommandListingOutput)

assert obj.to_array() is not None
assert obj.to_array().size != 0

obj = mapdl.set("list", 1)

assert not isinstance(obj, CommandListingOutput)


def test_mode(mapdl):
assert mapdl.mode == "grpc"
assert mapdl.is_grpc
Expand Down
Loading

0 comments on commit 87f54fe

Please sign in to comment.