Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CommandOutput improvements #1554

Merged
merged 15 commits into from
Oct 24, 2022
Merged
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