diff --git a/src/ansys/dpf/post/__init__.py b/src/ansys/dpf/post/__init__.py index 0457b016e..4a4ad3284 100644 --- a/src/ansys/dpf/post/__init__.py +++ b/src/ansys/dpf/post/__init__.py @@ -14,7 +14,7 @@ """ import ansys.dpf.core as core -from ansys.dpf.core.common import locations +from ansys.dpf.core.common import locations # noqa: F401 try: import importlib.metadata as importlib_metadata @@ -23,6 +23,7 @@ from ansys.dpf.post import mesh, selection, tools from ansys.dpf.post.common import Grouping as grouping +from ansys.dpf.post.dataframe import DataFrame # noqa: F401 from ansys.dpf.post.dpf_path import create_path_on_coordinates from ansys.dpf.post.misc import Report from ansys.dpf.post.post_utility import ( diff --git a/src/ansys/dpf/post/data_object.py b/src/ansys/dpf/post/data_object.py deleted file mode 100644 index 74d9aa738..000000000 --- a/src/ansys/dpf/post/data_object.py +++ /dev/null @@ -1,133 +0,0 @@ -"""Module containing the ``DataObject`` class.""" -from ansys.dpf.post.errors import PandasImportError - - -class DataObject: - """Exposes the fields container generated by a result provider.""" - - def __init__(self, fields_container=None, server=None, index=None, columns=None): - """Wrap a FieldsContainer within a DataObject. - - Parameters - ---------- - fields_container: - :class:`ansys.dpf.core.fields_container.FieldsContainer`to wrap. - server: - DPF server to use. - index: - Index to use. - columns: - Columns to use. - """ - self._fc = fields_container - if columns is not None: - self._columns = columns - - if index is not None: - self._index = index - - # super().__init__(fields_container._internal_obj, server) - - def __len__(self): - """Return the length of the DataObject.""" - return len(self._fc) - - def __min__(self, **kwargs): - """Return the minimum of the data.""" - return self.as_array().min() - - def __max__(self, **kwargs): - """Return the maximum of the data.""" - return self.as_array().max() - - def max(self, **kwargs): - """Return the maximum of the data.""" - return float(self.as_array().max()) - - def min(self, **kwargs): - """Return the minimum of the data.""" - return float(self.as_array().min()) - - def as_data_frame(self, columns=None, **kwargs): - """Returns the data from the field container as a Pandas data_frame. - - Parameters - ---------- - columns : - Columns description. - - Returns - ------- - class:`pandas.core.frame.DataFrame` - - Examples - -------- - >>> import pandas as pd - >>> from ansys.dpf import post - >>> from ansys.dpf.post import examples - >>> simulation = post.load_simulation(examples.multishells_rst) - >>> # Export the displacements vector field at step 1 as a DataFrame - >>> displacement = simulation.displacement(load_steps=[1], node_ids=[1, 2, 3]) - >>> df = displacement.as_data_frame() - >>> print(df) - UX UY UZ - 1 0.398320 -13.797378 -0.163767 - 2 0.233114 -13.797652 -0.153190 - 3 0.367542 -13.808151 -0.163739 - >>> print(df.name) - displacement_1.s - - """ - try: - import pandas as pd - except ModuleNotFoundError: - raise PandasImportError - - if not columns: - columns = self._columns - # The wrapped FieldsContainer should only contain one Field - if len(self) > 1: - raise NotImplementedError( - "This function requires for the DataObject to contain only" - "one data entity." - ) - df = pd.DataFrame(self.as_array(), columns=columns, index=self._index) - df.name = self._fc[-1].name - return df - - def as_array(self): - """Return the DataObject as a NumPy array. - - Returns - ------- - class:`pandas.core.frame.DataFrame` - - Examples - -------- - >>> import pandas as pd - >>> from ansys.dpf import post - >>> from ansys.dpf.post import examples - >>> simulation = post.load_simulation(examples.multishells_rst) - >>> # Export the displacements vector field at step 1 as a DataFrame - >>> displacement = simulation.displacement(load_steps=[1], node_ids=[1, 2, 3]) - >>> arr = displacement.as_array() - >>> print(arr) - [[ 0.39831985 -13.79737819 -0.16376683] - [ 0.23311378 -13.79765179 -0.15318972] - [ 0.36754181 -13.80815135 -0.16373945]] - - """ - return self._fc[-1].data - - def plot(self, **kwargs): - """Plot the result.""" - self._fc[-1].plot(**kwargs) - - def animate(self, **kwargs): - """Animate the result. - - Returns - ------- - The interactive plotter object used for animation. - """ - return self._fc.animate(**kwargs) diff --git a/src/ansys/dpf/post/dataframe.py b/src/ansys/dpf/post/dataframe.py new file mode 100644 index 000000000..75dd665ef --- /dev/null +++ b/src/ansys/dpf/post/dataframe.py @@ -0,0 +1,663 @@ +"""Module containing the ``DataFrame`` class.""" +from __future__ import annotations + +import itertools +from os import PathLike +from typing import List, Union +import warnings + +import ansys.dpf.core as dpf +from ansys.dpf.core.dpf_array import DPFArray + +from ansys.dpf.post import locations +from ansys.dpf.post.index import ( + CompIndex, + FrequencyIndex, + Index, + LabelIndex, + MeshIndex, + MultiIndex, + ResultsIndex, + SetIndex, + TimeIndex, +) + +display_width = 80 +display_max_colwidth = 10 +display_max_lines = 6 + + +class DataFrame: + """A DataFrame style API to manipulate DPF data.""" + + def __init__( + self, + data: dpf.FieldsContainer, + index: Union[MultiIndex, Index, List[int]], + columns: Union[MultiIndex, Index, List[str], None] = None, + ): + """Creates a DPF DataFrame based on the given input data. + + Parameters + ---------- + data: + Data to use. + index: + Row indexing (labels) to use. + columns: + Column indexing (labels) to use. + """ + self._index = index + if isinstance(data, dpf.FieldsContainer): + self._fc = data + # if index is None: + # raise NotImplementedError("Creation from FieldsContainer without index " + # "is not yet supported") + # # self._index = Index( + # # name=location_to_label[data[0].location], values=None + # # ) + else: + raise ValueError( + f"Input data type '{type(data)}' is not a valid data type for DataFrame creation." + ) + if columns is not None: + self._columns = columns + else: + self._columns = None + + # if parent_simulation is not None: + # self._parent_simulation = weakref.ref(parent_simulation) + + self._str = None + self._last_display_width = display_width + self._last_display_max_colwidth = display_max_colwidth + + @property + def columns(self): + """Returns the column labels of the DataFrame.""" + if self._columns is None: + indexes = [ResultsIndex(values=[self._fc[0].name.split("_")])] + indexes.extend( + [ + LabelIndex(name=label, values=self._fc.get_label_scoping(label).ids) + for label in self._fc.labels + ] + ) + self._columns = MultiIndex(indexes=indexes) + return self._columns + + @property + def index(self) -> Union[MultiIndex, Index]: + """Returns the Index or MultiIndex for the rows of the DataFrame.""" + return self._index + + @property + def axes(self) -> List[str]: + """Returns a list of the axes of the DataFrame with the row Index and the column Index.""" + names = self.index.names + names.extend(self.columns.names) + return names + + @property + def results_index(self) -> Union[ResultsIndex, None]: + """Returns the available ResultsIndex is present.""" + results_index = self.columns.results_index + if results_index is None: + results_index = self.index.results_index + return results_index + + @property + def mesh_index(self) -> Union[MeshIndex, None]: + """Returns the available MeshIndex is present.""" + mesh_index = self.columns.mesh_index + if mesh_index is None: + mesh_index = self.index.mesh_index + return mesh_index + + @property + def labels(self) -> List[str]: + """Returns a list of the names of available ResultsIndex indexes.""" + names = [index.name for index in self.index if isinstance(index, LabelIndex)] + names.extend( + [index.name for index in self.columns if isinstance(index, LabelIndex)] + ) + return names + + @property + def _core_object(self): + """Returns the underlying PyDPF-Core class:`ansys.dpf.core.FieldsContainer` object.""" + return self._fc + + def select(self, **kwargs) -> DataFrame: + """Returns a new DataFrame based on selection criteria (value-based). + + Parameters + ---------- + **kwargs: + This function accepts as argument any of the Index names available associated with a + value or a list of values. + For example, if 'time' is an available class:`Index ` + of the class:`DataFrame ` `df`, then you can select the time 1 + by using `df.select(time=1)`. + One can get the list of available axes using + :func:`DataFrame.axes `. + + Returns + ------- + A DataFrame of the selected values. + + """ + # Check for invalid arguments + axes = self.axes + for argument in kwargs.keys(): + if argument not in axes: + raise ValueError( + f"The DataFrame has no axis {argument}, cannot select it. " + f"Available axes are: {axes}." + ) + if "set_id" in kwargs.keys(): + kwargs["time"] = kwargs["set_id"] + # Initiate a workflow + server = self._fc._server + wf = dpf.Workflow(server=server) + wf.progress_bar = False + input_fc = self._fc + fc = self._fc + out = None + + # Initiate future DataFrame indexes with those from initial DataFrame + mesh_index = None + comp_index = None + for index in self.index: + if isinstance(index, MeshIndex): + mesh_index = index + if isinstance(index, CompIndex): + comp_index = index + location = self._fc[0].location + results_index = self.results_index + + # Treat selection on a label + if any([label in kwargs.keys() for label in self._fc.labels]): + fc = dpf.FieldsContainer() + fc.labels = self._fc.labels + for i, field in enumerate(self._fc): + label_space = self._fc.get_label_space(i) + for key in label_space.keys(): + if not isinstance(kwargs[key], list): + kwargs[key] = [kwargs[key]] + if label_space[key] in kwargs[key]: + fc.add_field(label_space=label_space, field=field) + input_fc = fc + + # # Treat selection on components + if "comp" in kwargs.keys(): + from ansys.dpf.post.simulation import component_label_to_index + + comp_to_extract = kwargs["comp"] + if not isinstance(comp_to_extract, list): + comp_to_extract = [comp_to_extract] + component_indexes = [component_label_to_index[c] for c in comp_to_extract] + selector_fc = dpf.operators.logic.component_selector_fc( + fields_container=input_fc, + component_number=component_indexes, + server=server, + ) + out = selector_fc.outputs.fields_container + comp_index = CompIndex(values=comp_to_extract) + + # Treat selection on DataFrame.index (rescope) + if isinstance(self.index, MeshIndex): + mesh_index_name = self.index.name + else: + mesh_index_name = self.index.mesh_index.name + if ( + mesh_index_name in kwargs.keys() + and mesh_index.location != locations.elemental_nodal + ): + if "node" in mesh_index_name: + node_ids = kwargs[mesh_index_name] + if not isinstance(node_ids, (DPFArray, list)): + node_ids = [node_ids] + mesh_scoping = dpf.mesh_scoping_factory.nodal_scoping( + node_ids=node_ids, + server=server, + ) + elif "element" in mesh_index_name: + element_ids = kwargs[mesh_index_name] + if not isinstance(element_ids, list): + element_ids = [element_ids] + mesh_scoping = dpf.mesh_scoping_factory.elemental_scoping( + element_ids=element_ids, + server=server, + ) + else: + raise NotImplementedError( + f"Selection on a DataFrame with index " + f"'{mesh_index_name}' is not yet supported" + ) + rescope_fc = dpf.operators.scoping.rescope_fc( + fields_container=input_fc, + mesh_scoping=mesh_scoping, + server=server, + ) + out = rescope_fc.outputs.fields_container + mesh_index = MeshIndex(location=location, values=mesh_scoping.ids) + elif ( + mesh_index_name in kwargs.keys() + and mesh_index.location == locations.elemental_nodal + ): + raise NotImplementedError( + f"Element selection on a DataFrame with elemental nodal results " + f"is not yet supported" + ) + + if out is not None: + wf.set_output_name("out", out) + fc = wf.get_output("out", dpf.FieldsContainer) + + row_indexes = [mesh_index] + if comp_index is not None: + row_indexes.append(comp_index) + row_index = MultiIndex( + indexes=row_indexes, + ) + + column_indexes = [ + results_index, + SetIndex(values=fc.get_available_ids_for_label("time")), + ] + label_indexes = [] + for label in fc.labels: + if label not in ["time"]: + column_indexes.append( + LabelIndex(name=label, values=fc.get_available_ids_for_label(label)) + ) + column_indexes.extend(label_indexes) + column_index = MultiIndex(indexes=column_indexes) + + return DataFrame( + data=fc, + columns=column_index, + index=row_index, + ) + + def iselect(self, **kwargs) -> DataFrame: + """Returns a new DataFrame based on selection criteria (index-based). + + Parameters + ---------- + **kwargs: + This function accepts as argument any of the Index names available associated with a + value or a list of values. + For example, if 'time' is an available class:`Index ` + of the class:`DataFrame ` `df`, then you can select the first + `time` value by using `df.select(time=0)`. + One can get the list of available axes using + :func:`DataFrame.axes `. + + Returns + ------- + A DataFrame of the selected values. + + """ + # Check for invalid arguments + axes = self.axes + for argument in kwargs.keys(): + if argument not in axes: + raise ValueError( + f"The DataFrame has no axis {argument}, cannot select it. " + f"Available axes are: {axes}." + ) + for label in kwargs.keys(): + indices = kwargs[label] + if label in self.index.names: + ids = getattr(self.index, label).values[indices] + else: + ids = getattr(self.columns, label).values[indices] + if isinstance(ids, DPFArray): + ids = ids.tolist() + kwargs[label] = ids + return self.select(**kwargs) + + def __len__(self): + """Return the length of the DataFrame.""" + return len(self.index) + + def __str__(self) -> str: + """String representation of the DataFrame.""" + if ( + (self._str is None) + or (self._last_display_width != display_width) + or (self._last_display_max_colwidth != display_max_colwidth) + ): + self._update_str(width=display_width, max_colwidth=display_max_colwidth) + self._last_display_width = display_width + self._last_display_max_colwidth = display_max_colwidth + return self._str + + def _update_str(self, width: int, max_colwidth: int): + """Updates the DataFrame string representation using given display options. + + The string representation is limited to five lines, meaning any DataFrame with more than + five rows will be truncated and only the five first rows are displayed. + + Parameters + ---------- + width: + Number of characters to use for the total width. + max_colwidth: + Maximum number of characters to use for each column. + """ + lines = [] + empty = " " * max_colwidth + truncated = "...".rjust(max_colwidth) + max_n_col = width // max_colwidth + max_n_rows = display_max_lines + # Create lines with row labels and values + num_column_indexes = len(self.columns) + num_rows_indexes = len(self.index) + n_max_value_col = max_n_col - num_rows_indexes + column_headers = [] + for column_index in self.columns: + column_headers.append( + empty * (num_rows_indexes - 1) + column_index.name.rjust(max_colwidth) + ) + lines.extend(column_headers) + + row_headers = "".join( + [row_index.name.rjust(max_colwidth) for row_index in self.index] + ) + lines.append(row_headers) + entity_ids = [] + # Create combinations for rows + num_mesh_entities_to_ask = max_n_rows + lists = [] + entity_ids = None + for index in self.index: + if isinstance(index, MeshIndex): + if index._values is not None: + values = index.values + entity_ids = values + else: + values = self._first_n_ids_first_field(num_mesh_entities_to_ask) + elif isinstance(index, CompIndex): + values = index.values + else: + values = index.values + lists.append(values) + row_combinations = [p for p in itertools.product(*lists)] + + # Add row headers for the first combinations (max_n_rows) + previous_combination = [None] * len(lists) + for combination in row_combinations[:max_n_rows]: + line = "".join( + [ + str(combination[i]).rjust(max_colwidth) + if combination[i] != previous_combination[i] + else empty + for i in range(len(combination)) + ] + ) + previous_combination = combination + lines.append(line) + + # Create combinations for columns + num_mesh_entities_to_ask = max_n_rows + entity_ids = None + lists = [] + time_position = 1 + complex_position = None + comp_values = None + for position, index in enumerate(self.columns): + if isinstance(index, MeshIndex): + if index._values is not None: + values = index.values + entity_ids = values + else: + values = self._first_n_ids_first_field(num_mesh_entities_to_ask) + elif isinstance(index, CompIndex): + values = index.values + comp_values = values + elif isinstance(index, (FrequencyIndex, TimeIndex)): + values = index.values + time_position = position + else: + values = index.values + if index.name == "complex": + complex_position = position + lists.append(values) + combinations = [p for p in itertools.product(*lists)] + + def flatten(arr): + new_arr = [] + for item in arr: + if isinstance(item, list): + new_arr.extend(flatten(item)) + else: + new_arr.append(item) + return new_arr + + def treat_elemental_nodal(treat_lines, pos, n_comp, n_ent, n_lines): + # Update row headers + elem_headers = treat_lines[pos : pos + n_comp] + new_elem_headers = [] + for i_ent in range(1, n_ent + 1): + for header in elem_headers: + new_elem_header = [ + header[:max_colwidth] + + header[max_colwidth + 4 :] + + f" ({i_ent})" + ] + # elem_header_i.extend(elem_headers[1:]) + new_elem_headers.extend(new_elem_header) + treat_lines = treat_lines[:pos] + new_elem_headers + treat_lines[pos:] + return treat_lines[:n_lines] + + # Query data by selecting a sub-dataframe + + # Add text for the first n_max_value_col columns + previous_combination = [None] * len(lists) + for i_c, combination in enumerate(combinations[:n_max_value_col]): + to_append = [ + str(combination[i]).rjust(max_colwidth) + if combination[i] != previous_combination[i] + else empty + for i in range(len(combination)) + ] + to_append.append(empty) + # Get data in the FieldsContainer for those positions + # Create label_space from combination + label_space = {"time": combination[time_position]} + if complex_position is not None: + label_space["complex"] = combination[complex_position] + fields = self._fc.get_fields(label_space=label_space) + values = [] + if entity_ids is None: + for field in fields: + array_values = [] + position = len(column_headers) + 1 + for k in list(range(num_mesh_entities_to_ask)): + try: + values_list = field.get_entity_data(k).tolist() + except Exception as e: + values_list = [[None] * len(comp_values)] + num_entities = len(values_list) + if isinstance(values_list[0], list): + num_components = len(values_list[0]) + else: + num_components = 1 + current_number_lines = len(lines) + # Detect number of nodes when elemental nodal and update headers to + # repeat for each node (do not print their ID for now) + if ( + i_c == 0 + and field.location == locations.elemental_nodal + and len(values_list) != 0 + ): + lines = treat_elemental_nodal( + lines, + position, + num_components, + num_entities, + current_number_lines, + ) + position += num_entities * num_components + array_values.append(values_list) + if position >= current_number_lines: + break + if array_values: + array_values = flatten(array_values) + values.extend(array_values) + else: + array_values = [] + position = len(column_headers) + 1 + for entity_id in entity_ids: + for field in fields: + try: + values_list = field.get_entity_data_by_id( + entity_id + ).tolist() + except Exception as e: + values_list = [[None] * len(comp_values)] + num_entities = len(values_list) + num_components = len(values_list[0]) + current_number_lines = len(lines) + # Detect number of nodes when elemental nodal and update headers to + # repeat for each node (do not print their ID for now) + if ( + i_c == 0 + and field.location == locations.elemental_nodal + and len(values_list) != 0 + ): + lines = treat_elemental_nodal( + lines, + position, + num_components, + num_entities, + current_number_lines, + ) + position += num_entities * num_components + array_values.append(array_values) + if position >= current_number_lines: + break + if array_values: + array_values = flatten(array_values) + values.extend(array_values) + + # take_comp_map = [True] * len(values) + # if comp_values is not None: + + value_strings = [] + for value in values[: len(lines) - (num_column_indexes + 1)]: + if value is not None: + value_string = f"{value:.{max_colwidth - 8}e}".rjust(max_colwidth) + else: + value_string = empty + value_strings.append(value_string) + to_append.extend(value_strings) + previous_combination = combination + # print(to_append) + # print(len(to_append)) + # print(len(lines)) + for i in range(len(lines)): + lines[i] = lines[i] + to_append[i] + + txt = "\n" + "".join([line + "\n" for line in lines]) + self._str = txt + + def _first_n_ids_first_field(self, n: int): + """Return the n first entity IDs of the first field in the underlying FieldsContainer.""" + return self._fc[0].scoping.ids[:n] + + def __repr__(self): + """Representation of the DataFrame.""" + return f"DataFrame" + + def plot(self, **kwargs): + """Plot the result. + + Parameters + ---------- + **kwargs: + This function accepts as argument any of the Index names available associated with a + single value. + For example, if 'set_ids' is an available class:`Index ` + of the class:`DataFrame ` `df`, then you can plot the data at + `set_id` 1 by using `df.plot(set_ids=1)`. + One can get the list of available axes using + :func:`DataFrame.axes `. + + Returns + ------- + The interactive plotter object used for plotting. + + """ + if kwargs != {}: + # Check for invalid arguments + axes = self.axes + for argument in kwargs.keys(): + if argument not in axes: + raise ValueError( + f"The DataFrame has no axis {argument}, cannot plot it. " + f"Available axes are: {axes}." + ) + # Construct the associated label_space + fc = self.select(**kwargs)._fc + else: + # If no kwarg was given, construct a default label_space + fc = self._fc + labels = fc.labels + if "time" in labels: + label = "time" + value = fc.get_available_ids_for_label(label)[-1] + label_space = {label: value} + elif "frequencies" in labels: + label = "frequencies" + value = fc.get_available_ids_for_label(label)[0] + label_space = {label: value} + else: + label_space = fc.get_label_space(0) + label_space = label_space + field = fc.get_field(label_space_or_index=label_space) + return field.plot(text=str(label_space), **kwargs) + + def animate( + self, + save_as: Union[PathLike, None] = None, + deform: bool = False, + scale_factor: Union[List[float], float, None] = None, + **kwargs, + ): + """Animate the result. + + Parameters + ---------- + save_as : Path of file to save the animation to. Defaults to None. Can be of any format + supported by pyvista.Plotter.write_frame (.gif, .mp4, ...). + deform : + Whether to plot the deformed mesh. + scale_factor : float, list, optional + Scale factor to apply when warping the mesh. Defaults to 1.0. Can be a list to make + scaling frequency-dependent. + + Returns + ------- + The interactive plotter object used for animation. + """ + deform_by = None + if deform: + try: + simulation = self._parent_simulation() + deform_by = simulation._model.results.displacement.on_time_scoping( + self._fc.get_time_scoping() + ) + except Exception as e: + warnings.warn( + UserWarning( + "Displacement result unavailable, " + f"unable to animate on the deformed mesh:\n{e}" + ) + ) + return self._fc.animate( + save_as=save_as, deform_by=deform_by, scale_factor=scale_factor, **kwargs + ) diff --git a/src/ansys/dpf/post/examples/__init__.py b/src/ansys/dpf/post/examples/__init__.py index 049ef4768..530963530 100644 --- a/src/ansys/dpf/post/examples/__init__.py +++ b/src/ansys/dpf/post/examples/__init__.py @@ -8,6 +8,7 @@ download_all_kinds_of_complexity_modal, download_transient_result, electric_therm, + find_multishells_rst, msup_transient, multishells_rst, simple_bar, diff --git a/src/ansys/dpf/post/harmonic_mechanical_simulation.py b/src/ansys/dpf/post/harmonic_mechanical_simulation.py index d32e61e88..36f15860d 100644 --- a/src/ansys/dpf/post/harmonic_mechanical_simulation.py +++ b/src/ansys/dpf/post/harmonic_mechanical_simulation.py @@ -4,7 +4,15 @@ from ansys.dpf import core from ansys.dpf.post import locations -from ansys.dpf.post.data_object import DataObject +from ansys.dpf.post.dataframe import DataFrame +from ansys.dpf.post.index import ( + CompIndex, + LabelIndex, + MeshIndex, + MultiIndex, + ResultsIndex, + SetIndex, +) from ansys.dpf.post.selection import Selection from ansys.dpf.post.simulation import MechanicalSimulation, ResultCategory @@ -31,7 +39,7 @@ def _get_result( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -87,7 +95,7 @@ def _get_result( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ # Build the targeted spatial and time scoping @@ -128,23 +136,9 @@ def _get_result( location=location, ) - # Build the list of requested results - if category in [ResultCategory.scalar, ResultCategory.equivalent]: - # A scalar or equivalent result has no components - to_extract = None - columns = [base_name] - elif category in [ResultCategory.vector, ResultCategory.matrix]: - # A matrix or vector result can have components selected - to_extract, columns = self._build_components_from_components( - base_name=base_name, category=category, components=components - ) - elif category == ResultCategory.principal: - # A principal type of result can have components selected - to_extract, columns = self._build_components_from_principal( - base_name=base_name, components=components - ) - else: - raise ValueError(f"'{category}' is not a valid category value.") + comp, to_extract, columns = self._create_components( + base_name, category, components + ) # Initialize a workflow wf = core.Workflow(server=self._model._server) @@ -282,11 +276,35 @@ def _get_result( message=f"Returned Dataframe with columns {columns} is empty.", category=UserWarning, ) + comp_index = None + if comp is not None: + comp_index = CompIndex(values=comp) + row_indexes = [MeshIndex(location=location, fc=fc)] + if comp_index is not None: + row_indexes.append(comp_index) + column_indexes = [ + ResultsIndex(values=[base_name]), + SetIndex(values=fc.get_available_ids_for_label("time")), + ] + label_indexes = [] + for label in fc.labels: + if label not in ["time"]: + label_indexes.append( + LabelIndex(name=label, values=fc.get_available_ids_for_label(label)) + ) + + column_indexes.extend(label_indexes) + column_index = MultiIndex(indexes=column_indexes) + + row_index = MultiIndex( + indexes=row_indexes, + ) + # Return the result wrapped in a DPF_Dataframe - return DataObject( - fields_container=fc, - columns=columns, - index=wf.get_output("scoping", core.types.scoping).ids, + return DataFrame( + data=fc, + columns=column_index, + index=row_index, ) def displacement( @@ -305,7 +323,7 @@ def displacement( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract displacement results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -345,7 +363,7 @@ def displacement( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -382,7 +400,7 @@ def velocity( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract velocity results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -422,7 +440,7 @@ def velocity( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -459,7 +477,7 @@ def acceleration( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract acceleration results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -499,7 +517,7 @@ def acceleration( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -534,7 +552,7 @@ def stress( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -580,7 +598,7 @@ def stress( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -612,7 +630,7 @@ def stress_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -648,7 +666,7 @@ def stress_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -681,7 +699,7 @@ def stress_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -719,7 +737,7 @@ def stress_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -753,7 +771,7 @@ def stress_principal( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal principal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -798,7 +816,7 @@ def stress_principal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -830,7 +848,7 @@ def stress_principal_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental principal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -865,7 +883,7 @@ def stress_principal_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -898,7 +916,7 @@ def stress_principal_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal principal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -935,7 +953,7 @@ def stress_principal_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -968,7 +986,7 @@ def stress_eqv_von_mises( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal equivalent Von Mises stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1011,7 +1029,7 @@ def stress_eqv_von_mises( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1042,7 +1060,7 @@ def stress_eqv_von_mises_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental equivalent Von Mises stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1075,7 +1093,7 @@ def stress_eqv_von_mises_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1107,7 +1125,7 @@ def stress_eqv_von_mises_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal equivalent Von Mises stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1142,7 +1160,7 @@ def stress_eqv_von_mises_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1176,7 +1194,7 @@ def elastic_strain( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1222,7 +1240,7 @@ def elastic_strain( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1255,7 +1273,7 @@ def elastic_strain_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1293,7 +1311,7 @@ def elastic_strain_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1325,7 +1343,7 @@ def elastic_strain_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1361,7 +1379,7 @@ def elastic_strain_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1395,7 +1413,7 @@ def elastic_strain_principal( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal principal elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1440,7 +1458,7 @@ def elastic_strain_principal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1473,7 +1491,7 @@ def elastic_strain_principal_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal principal elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1510,7 +1528,7 @@ def elastic_strain_principal_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1542,7 +1560,7 @@ def elastic_strain_principal_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental principal elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1577,7 +1595,7 @@ def elastic_strain_principal_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1610,7 +1628,7 @@ def elastic_strain_eqv_von_mises( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal equivalent Von Mises elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1653,7 +1671,7 @@ def elastic_strain_eqv_von_mises( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1684,7 +1702,7 @@ def elastic_strain_eqv_von_mises_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental equivalent Von Mises elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1717,7 +1735,7 @@ def elastic_strain_eqv_von_mises_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1749,7 +1767,7 @@ def elastic_strain_eqv_von_mises_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal equivalent Von Mises elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1784,7 +1802,7 @@ def elastic_strain_eqv_von_mises_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1818,7 +1836,7 @@ def reaction_force( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract reaction force results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1858,7 +1876,7 @@ def reaction_force( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1890,7 +1908,7 @@ def elemental_volume( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental volume results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1923,7 +1941,7 @@ def elemental_volume( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1954,7 +1972,7 @@ def elemental_mass( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental mass results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -1987,7 +2005,7 @@ def elemental_mass( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2022,7 +2040,7 @@ def element_nodal_forces( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract element nodal forces results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -2070,7 +2088,7 @@ def element_nodal_forces( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2105,7 +2123,7 @@ def element_nodal_forces_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract element nodal forces nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -2145,7 +2163,7 @@ def element_nodal_forces_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2179,7 +2197,7 @@ def element_nodal_forces_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract element nodal forces elemental results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -2217,7 +2235,7 @@ def element_nodal_forces_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2252,7 +2270,7 @@ def nodal_force( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal force results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -2292,7 +2310,7 @@ def nodal_force( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2327,7 +2345,7 @@ def nodal_moment( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal moment results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -2367,7 +2385,7 @@ def nodal_moment( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2399,7 +2417,7 @@ def element_centroids( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract element centroids results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -2432,7 +2450,7 @@ def element_centroids( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2463,7 +2481,7 @@ def thickness( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract element thickness results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -2496,7 +2514,7 @@ def thickness( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2529,7 +2547,7 @@ def element_orientations( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal element orientations results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -2572,7 +2590,7 @@ def element_orientations( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2603,7 +2621,7 @@ def element_orientations_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental element orientations results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -2636,7 +2654,7 @@ def element_orientations_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2668,7 +2686,7 @@ def element_orientations_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal element orientations results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `load_steps` are mutually @@ -2703,7 +2721,7 @@ def element_orientations_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( diff --git a/src/ansys/dpf/post/index.py b/src/ansys/dpf/post/index.py new file mode 100644 index 000000000..68d939a32 --- /dev/null +++ b/src/ansys/dpf/post/index.py @@ -0,0 +1,309 @@ +"""Module containing the ``Index`` class.""" +from abc import ABC +from typing import List, Union +import weakref + +import ansys.dpf.core as dpf + +from ansys.dpf import post + +location_to_label = { + dpf.locations.nodal: "node", + dpf.locations.elemental: "element", + dpf.locations.elemental_nodal: "element", + dpf.locations.overall: "overall", + dpf.locations.time_freq_step: "step", + dpf.locations.time_freq: "set", +} + + +class Index(ABC): + """A Pandas style API to manipulate indexes.""" + + def __init__( + self, + name: str, + values: Union[List, None] = None, + scoping: Union[dpf.Scoping, None] = None, + ): + """Creates an Index object to use in a DataFrame. + + Parameters + ---------- + name: + Name of the Index. + values: + Values taken by the Index. + scoping: + Scoping corresponding to this index to keep a weak reference. + """ + self._name = name.replace(" ", "_") + self._values = values + self._dtype = None + self._len = None + self._scoping_ref = None + # if scoping is None and values is None: + # raise ValueError("Arguments 'values' and 'scoping' cannot both be None.") + if scoping is not None: + self._scoping_ref = weakref.ref(scoping) + if values is not None: + self._dtype = type(values[0]) + self._str = None + + def __repr__(self): + """Representation of the Index.""" + return f'Index' + + def __str__(self): + """String representation of the Index.""" + return ( + f'Index "{self._name}" with ' + f"{len(self._values) if self._values is not None else 'uncounted'} " + f"values of {self._dtype if self._dtype is not None else 'undetermined'} type" + ) + + def __len__(self): + """Returns the length of the index.""" + if self._len is not None: + return self._len + if self._scoping_ref is not None: + return self._scoping_ref().size + if self.values is not None: + self._len = len(self.values) + return self._len + else: + return None + + @property + def name(self): + """Returns the name of the Index.""" + return self._name + + @property + def values(self): + """Returns the values of the Index.""" + if self._values is None: + self._evaluate_values() + return self._values + + def _evaluate_values(self): + """Evaluates the values of the Index.""" + if self._scoping_ref is not None: + self._values = self._scoping_ref().ids + + +class MeshIndex(Index): + """Index class specific to mesh entities.""" + + def __init__( + self, + location: Union[post.locations, str], + values: Union[List[int], None] = None, + scoping: Union[dpf.Scoping, None] = None, + fc: Union[dpf.FieldsContainer, None] = None, + ): + """Initiate this class.""" + name = location_to_label[location] + self.location = location + if fc is None and values is None and scoping is None: + raise ValueError( + "Arguments 'values', 'scoping' and 'fc' cannot all be None." + ) + if fc is not None: + self._fc = weakref.ref(fc) + super().__init__(name=name, values=values, scoping=scoping) + + def __repr__(self): + """Representation of the MeshIndex.""" + return f'MeshIndex' + + def _evaluate_values(self): + """Evaluates the values of the MeshIndex.""" + if self._scoping_ref is not None: + self._values = self._scoping_ref().ids + else: + # Merge the fields container scoping + fc = self._fc() + if fc is not None: + scopings = dpf.operators.utility.extract_scoping( + field_or_fields_container=fc + ).outputs.mesh_scoping_as_scopings_container + merge_op = dpf.operators.utility.merge_scopings(scopings=scopings) + self._values = merge_op.eval().ids + else: + raise AttributeError( + "The FieldsContainer affiliated to the MeshIndex is no longer " + "available. Cannot evaluate Index.values." + ) + + +class ResultsIndex(Index): + """Index class specific to results.""" + + def __init__( + self, + values: List[str], + ): + """Initiate this class.""" + super().__init__(name="results", values=values, scoping=None) + + def __repr__(self): + """Representation of the Index.""" + return f"ResultIndex<{self.values}>" + + +class LabelIndex(Index): + """Index class specific to labels.""" + + def __init__( + self, + name: str, + values: Union[List, None] = None, + scoping: Union[dpf.Scoping, None] = None, + ): + """Initiate this class.""" + super().__init__(name=name, values=values, scoping=scoping) + + +class TimeIndex(Index): + """Index class specific to time.""" + + def __init__( + self, + values: Union[List, None] = None, + scoping: Union[dpf.Scoping, None] = None, + ): + """Initiate this class.""" + super().__init__(name="time", values=values, scoping=scoping) + + +class ModeIndex(Index): + """Index class specific to modes.""" + + def __init__( + self, + values: Union[List, None] = None, + scoping: Union[dpf.Scoping, None] = None, + ): + """Initiate this class.""" + super().__init__(name="mode", values=values, scoping=scoping) + + +class FrequencyIndex(Index): + """Index class specific to frequency.""" + + def __init__( + self, + values: Union[List, None] = None, + scoping: Union[dpf.Scoping, None] = None, + ): + """Initiate this class.""" + super().__init__(name="frequency", values=values, scoping=scoping) + + +class SetIndex(Index): + """Index class specific to set_id.""" + + def __init__( + self, + values: Union[List, None] = None, + scoping: Union[dpf.Scoping, None] = None, + ): + """Initiate this class.""" + super().__init__(name="set_id", values=values, scoping=scoping) + + +class CompIndex(Index): + """Index class specific to components.""" + + def __init__( + self, + values: Union[List, None] = None, + ): + """Initiate this class.""" + super().__init__(name="comp", values=values) + + +class MultiIndex: + """A Pandas style API to manipulate multi-indexes.""" + + def __init__( + self, + indexes: List[Index], + ): + """Creates a MultiIndex from several Index objects. + + Parameters + ---------- + indexes: + Ordered list of class:`ansys.dpf.post.index.Index` objects. + """ + self._indexes = indexes + # self._labels = [] + # self._label_names = None + # self._result_names = None + for i, index in enumerate(self._indexes): + setattr(self, index.name, index) + + # @property + # def labels(self): + # """Returns the list of label Index objects.""" + # return self._labels + # + # @property + # def results(self): + # """Returns the Index of available results.""" + # return self._results + + def __repr__(self): + """Representation of the Index.""" + return f"MultiIndex<{self._indexes}>" + + # def __str__(self): + # """String representation of the Index.""" + # txt = f"MultiIndex with {len(self)} Label Index objects:\n" + # for index in self._indexes: + # txt += str(index) + "\n" + # # txt += f"and a ResultsIndex of size {len(self.results)}" + # return txt + + def __len__(self): + """Returns the number of Index objects in the MultiIndex.""" + return len(self._indexes) + + def __getitem__(self, item): + """Get an Index in the MultiIndex.""" + return self._indexes[item] + + @property + def names(self): + """Returns a list with the name of each Index.""" + return [index.name for index in self._indexes] + + @property + def results_index(self) -> Union[ResultsIndex, None]: + """Returns the available ResultsIndex is present.""" + for index in self._indexes: + if isinstance(index, ResultsIndex): + return index + return None + + @property + def mesh_index(self) -> Union[MeshIndex, None]: + """Returns the available ResultsIndex is present.""" + for index in self._indexes: + if isinstance(index, MeshIndex): + return index + return None + + # @property + # def label_names(self): + # """Returns a list with the name of each label Index.""" + # if self._label_names is None: + # self._label_names = [index.name for index in self._indexes] + # return + # + # @property + # def result_names(self): + # """Returns a list with the available results.""" + # return self.results.values diff --git a/src/ansys/dpf/post/mesh.py b/src/ansys/dpf/post/mesh.py index 2670ea260..548ea0518 100644 --- a/src/ansys/dpf/post/mesh.py +++ b/src/ansys/dpf/post/mesh.py @@ -1,4 +1,5 @@ """Module containing the ``Mesh`` class.""" +from typing import List from ansys.dpf.core import MeshedRegion @@ -10,7 +11,26 @@ def __init__(self, meshed_region: MeshedRegion): """Initialize this class.""" self._meshed_region = meshed_region + def __str__(self): + """String representation of this class.""" + return str(self._meshed_region).replace("Meshed Region", "Mesh") + @property - def available_named_selections(self): - """Returns the available named selection of the mesh.""" + def available_named_selections(self) -> List[str]: + """Returns the available named selections of the mesh.""" return self._meshed_region.available_named_selections + + @property + def node_ids(self) -> List[int]: + """Returns the list of node IDs in the mesh.""" + return self._meshed_region.nodes.scoping.ids + + @property + def element_ids(self) -> List[int]: + """Returns the list of element IDs in the mesh.""" + return self._meshed_region.elements.scoping.ids + + @property + def _core_object(self): + """Returns the underlying PyDPF-Core class:`ansys.dpf.core.MeshedRegion` object.""" + return self._meshed_region diff --git a/src/ansys/dpf/post/modal_mechanical_simulation.py b/src/ansys/dpf/post/modal_mechanical_simulation.py index 609e2cac7..d40efaece 100644 --- a/src/ansys/dpf/post/modal_mechanical_simulation.py +++ b/src/ansys/dpf/post/modal_mechanical_simulation.py @@ -1,10 +1,9 @@ """Module containing the ``ModalMechanicalSimulation`` class.""" from typing import List, Union -import warnings from ansys.dpf import core from ansys.dpf.post import locations -from ansys.dpf.post.data_object import DataObject +from ansys.dpf.post.dataframe import DataFrame from ansys.dpf.post.selection import Selection from ansys.dpf.post.simulation import MechanicalSimulation, ResultCategory @@ -27,7 +26,7 @@ def _get_result( modes: Union[int, List[int], None] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -76,7 +75,7 @@ def _get_result( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ # Build the targeted spatial and time scoping @@ -107,23 +106,9 @@ def _get_result( location=location, ) - # Build the list of requested results - if category in [ResultCategory.scalar, ResultCategory.equivalent]: - # A scalar or equivalent result has no components - to_extract = None - columns = [base_name] - elif category in [ResultCategory.vector, ResultCategory.matrix]: - # A matrix or vector result can have components selected - to_extract, columns = self._build_components_from_components( - base_name=base_name, category=category, components=components - ) - elif category == ResultCategory.principal: - # A principal type of result can have components selected - to_extract, columns = self._build_components_from_principal( - base_name=base_name, components=components - ) - else: - raise ValueError(f"'{category}' is not a valid category value.") + comp, to_extract, columns = self._create_components( + base_name, category, components + ) # Initialize a workflow wf = core.Workflow(server=self._model._server) @@ -227,18 +212,7 @@ def _get_result( # Evaluate the workflow fc = wf.get_output("out", core.types.fields_container) - # Test for empty results - if (len(fc) == 0) or all([len(f) == 0 for f in fc]): - warnings.warn( - message=f"Returned Dataframe with columns {columns} is empty.", - category=UserWarning, - ) - # Return the result wrapped in a DPF_Dataframe - return DataObject( - fields_container=fc, - columns=columns, - index=wf.get_output("scoping", core.types.scoping).ids, - ) + return self._create_dataframe(fc, location, columns, comp, base_name) def displacement( self, @@ -252,7 +226,7 @@ def displacement( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract displacement results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -290,7 +264,7 @@ def displacement( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -321,7 +295,7 @@ def stress( location: Union[locations, str] = locations.elemental_nodal, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -365,7 +339,7 @@ def stress( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -393,7 +367,7 @@ def stress_elemental( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -427,7 +401,7 @@ def stress_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -456,7 +430,7 @@ def stress_nodal( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract nodal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -492,7 +466,7 @@ def stress_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -522,7 +496,7 @@ def stress_principal( location: Union[locations, str] = locations.elemental_nodal, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal principal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -565,7 +539,7 @@ def stress_principal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -593,7 +567,7 @@ def stress_principal_elemental( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental principal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -626,7 +600,7 @@ def stress_principal_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -655,7 +629,7 @@ def stress_principal_nodal( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract nodal principal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -690,7 +664,7 @@ def stress_principal_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -719,7 +693,7 @@ def stress_eqv_von_mises( location: Union[locations, str] = locations.elemental_nodal, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal equivalent Von Mises stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -760,7 +734,7 @@ def stress_eqv_von_mises( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -787,7 +761,7 @@ def stress_eqv_von_mises_elemental( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental equivalent Von Mises stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -818,7 +792,7 @@ def stress_eqv_von_mises_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -846,7 +820,7 @@ def stress_eqv_von_mises_nodal( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract nodal equivalent Von Mises stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -879,7 +853,7 @@ def stress_eqv_von_mises_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -909,7 +883,7 @@ def elastic_strain( location: Union[locations, str] = locations.elemental_nodal, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -953,7 +927,7 @@ def elastic_strain( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -982,7 +956,7 @@ def elastic_strain_nodal( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1018,7 +992,7 @@ def elastic_strain_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1046,7 +1020,7 @@ def elastic_strain_elemental( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1080,7 +1054,7 @@ def elastic_strain_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1110,7 +1084,7 @@ def elastic_strain_principal( location: Union[locations, str] = locations.elemental_nodal, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal principal elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1153,7 +1127,7 @@ def elastic_strain_principal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1182,7 +1156,7 @@ def elastic_strain_principal_nodal( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract nodal principal elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1217,7 +1191,7 @@ def elastic_strain_principal_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1245,7 +1219,7 @@ def elastic_strain_principal_elemental( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental principal elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1278,7 +1252,7 @@ def elastic_strain_principal_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1307,7 +1281,7 @@ def elastic_strain_eqv_von_mises( location: Union[locations, str] = locations.elemental_nodal, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal equivalent Von Mises elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1348,7 +1322,7 @@ def elastic_strain_eqv_von_mises( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1375,7 +1349,7 @@ def elastic_strain_eqv_von_mises_elemental( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental equivalent Von Mises elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1406,7 +1380,7 @@ def elastic_strain_eqv_von_mises_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1434,7 +1408,7 @@ def elastic_strain_eqv_von_mises_nodal( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract nodal equivalent Von Mises elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1467,7 +1441,7 @@ def elastic_strain_eqv_von_mises_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1496,7 +1470,7 @@ def plastic_state_variable( location: Union[locations, str] = locations.elemental_nodal, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal plastic state variable results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1537,7 +1511,7 @@ def plastic_state_variable( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1564,7 +1538,7 @@ def plastic_state_variable_elemental( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental plastic state variable results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1595,7 +1569,7 @@ def plastic_state_variable_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1623,7 +1597,7 @@ def plastic_state_variable_nodal( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract nodal plastic state variable results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1656,7 +1630,7 @@ def plastic_state_variable_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1686,7 +1660,7 @@ def plastic_strain( location: Union[locations, str] = locations.elemental_nodal, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1730,7 +1704,7 @@ def plastic_strain( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1759,7 +1733,7 @@ def plastic_strain_nodal( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract nodal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1795,7 +1769,7 @@ def plastic_strain_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1823,7 +1797,7 @@ def plastic_strain_elemental( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1857,7 +1831,7 @@ def plastic_strain_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1887,7 +1861,7 @@ def plastic_strain_principal( location: Union[locations, str] = locations.elemental_nodal, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal principal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1930,7 +1904,7 @@ def plastic_strain_principal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1959,7 +1933,7 @@ def plastic_strain_principal_nodal( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract nodal principal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -1994,7 +1968,7 @@ def plastic_strain_principal_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2022,7 +1996,7 @@ def plastic_strain_principal_elemental( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental principal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2055,7 +2029,7 @@ def plastic_strain_principal_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2084,7 +2058,7 @@ def plastic_strain_eqv( location: Union[locations, str] = locations.elemental_nodal, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal equivalent plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2125,7 +2099,7 @@ def plastic_strain_eqv( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2153,7 +2127,7 @@ def plastic_strain_eqv_nodal( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract nodal equivalent plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2186,7 +2160,7 @@ def plastic_strain_eqv_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2213,7 +2187,7 @@ def plastic_strain_eqv_elemental( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental equivalent plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2244,7 +2218,7 @@ def plastic_strain_eqv_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2274,7 +2248,7 @@ def reaction_force( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract reaction force results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2312,7 +2286,7 @@ def reaction_force( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2340,7 +2314,7 @@ def elemental_volume( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental volume results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2371,7 +2345,7 @@ def elemental_volume( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2398,7 +2372,7 @@ def elemental_mass( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental mass results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2429,7 +2403,7 @@ def elemental_mass( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2456,7 +2430,7 @@ def element_centroids( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract element centroids results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2487,7 +2461,7 @@ def element_centroids( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2514,7 +2488,7 @@ def thickness( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract element thickness results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2545,7 +2519,7 @@ def thickness( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2574,7 +2548,7 @@ def element_orientations( location: Union[locations, str] = locations.elemental_nodal, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal element orientations results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2615,7 +2589,7 @@ def element_orientations( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2642,7 +2616,7 @@ def element_orientations_elemental( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract elemental element orientations results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2673,7 +2647,7 @@ def element_orientations_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2701,7 +2675,7 @@ def element_orientations_nodal( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract nodal element orientations results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2734,7 +2708,7 @@ def element_orientations_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2763,7 +2737,7 @@ def hydrostatic_pressure( location: Union[locations, str] = locations.elemental_nodal, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract hydrostatic pressure element nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2804,7 +2778,7 @@ def hydrostatic_pressure( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2832,7 +2806,7 @@ def hydrostatic_pressure_nodal( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract hydrostatic pressure nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2865,7 +2839,7 @@ def hydrostatic_pressure_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2892,7 +2866,7 @@ def hydrostatic_pressure_elemental( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract hydrostatic pressure elemental results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -2923,7 +2897,7 @@ def hydrostatic_pressure_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2954,7 +2928,7 @@ def element_nodal_forces( location: Union[locations, str] = locations.elemental_nodal, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract element nodal forces results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -3000,7 +2974,7 @@ def element_nodal_forces( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3031,7 +3005,7 @@ def element_nodal_forces_nodal( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract element nodal forces nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -3069,7 +3043,7 @@ def element_nodal_forces_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3099,7 +3073,7 @@ def element_nodal_forces_elemental( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract element nodal forces elemental results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -3135,7 +3109,7 @@ def element_nodal_forces_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3166,7 +3140,7 @@ def nodal_force( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract nodal force results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -3204,7 +3178,7 @@ def nodal_force( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3235,7 +3209,7 @@ def nodal_moment( selection: Union[Selection, None] = None, set_ids: Union[int, List[int], None] = None, all_sets: bool = False, - ) -> DataObject: + ) -> DataFrame: """Extract nodal moment results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `frequencies`, and `modes` are mutually @@ -3273,7 +3247,7 @@ def nodal_moment( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( diff --git a/src/ansys/dpf/post/simulation.py b/src/ansys/dpf/post/simulation.py index 717cee511..63a65810d 100644 --- a/src/ansys/dpf/post/simulation.py +++ b/src/ansys/dpf/post/simulation.py @@ -4,16 +4,48 @@ from os import PathLike import re from typing import List, Tuple, Union +import warnings import ansys.dpf.core as dpf -from ansys.dpf.core import DataSources, Model +from ansys.dpf.core import DataSources, Model, TimeFreqSupport from ansys.dpf.core.plotter import DpfPlotter import numpy as np from ansys.dpf.post import locations +from ansys.dpf.post.dataframe import DataFrame +from ansys.dpf.post.index import ( + CompIndex, + LabelIndex, + MeshIndex, + MultiIndex, + ResultsIndex, + SetIndex, +) from ansys.dpf.post.mesh import Mesh from ansys.dpf.post.selection import Selection +component_label_to_index = { + "1": 0, + "2": 1, + "3": 2, + "4": 3, + "5": 4, + "6": 5, + "X": 0, + "Y": 1, + "Z": 2, + "XX": 0, + "YY": 1, + "ZZ": 2, + "XY": 3, + "YZ": 4, + "XZ": 5, +} + +vector_component_names = ["X", "Y", "Z"] +matrix_component_names = ["XX", "YY", "ZZ", "XY", "YZ", "XZ"] +principal_names = ["1", "2", "3"] + class ResultCategory(Enum): """Enum for available result categories.""" @@ -28,23 +60,9 @@ class ResultCategory(Enum): class Simulation(ABC): """Base class of all PyDPF-Post simulation types.""" - _component_to_id = { - "1": 0, - "2": 1, - "3": 2, - "4": 3, - "5": 4, - "6": 5, - "X": 0, - "Y": 1, - "Z": 2, - "XY": 3, - "YZ": 4, - "XZ": 5, - } - - _component_names = ["X", "Y", "Z", "XX", "XY", "YZ"] - _principal_names = ["1", "2", "3"] + _vector_component_names = vector_component_names + _matrix_component_names = matrix_component_names + _principal_names = principal_names def __init__(self, data_sources: DataSources, model: Model): """Initialize the simulation using a ``dpf.core.Model`` object.""" @@ -62,6 +80,10 @@ def __init__(self, data_sources: DataSources, model: Model): } self._time_freq_precision = None + def release_streams(self): + """Release the streams to data files if any is active.""" + self._model.metadata.release_streams() + @property def results(self) -> List[str]: r"""Available results. @@ -96,37 +118,37 @@ def geometries(self): """ return self._geometries - @property - def boundary_conditions(self): - """List of boundary conditions in the simulation. - - Returns a list of boundary_condition objects. - - Examples - -------- - >>> from ansys.dpf import post - >>> from ansys.dpf.post import examples - >>> simulation = post.load_simulation(examples.static_rst) - >>> print(simulation.boundary_conditions) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS - [] - """ - return self._boundary_conditions - - @property - def loads(self): - """List of loads in the simulation. - - Returns a list of load objects. - - Examples - -------- - >>> from ansys.dpf import post - >>> from ansys.dpf.post import examples - >>> simulation = post.load_simulation(examples.static_rst) - >>> print(simulation.loads) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS - [] - """ - return self._loads + # @property + # def boundary_conditions(self): + # """List of boundary conditions in the simulation. + # + # Returns a list of boundary_condition objects. + # + # Examples + # -------- + # >>> from ansys.dpf import post + # >>> from ansys.dpf.post import examples + # >>> simulation = post.load_simulation(examples.static_rst) + # >>> print(simulation.boundary_conditions) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS + # [] + # """ + # return self._boundary_conditions + + # @property + # def loads(self): + # """List of loads in the simulation. + # + # Returns a list of load objects. + # + # Examples + # -------- + # >>> from ansys.dpf import post + # >>> from ansys.dpf.post import examples + # >>> simulation = post.load_simulation(examples.static_rst) + # >>> print(simulation.loads) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS + # [] + # """ + # return self._loads @property def mesh(self) -> Mesh: @@ -140,7 +162,11 @@ def mesh(self) -> Mesh: >>> from ansys.dpf.post import examples >>> simulation = post.load_simulation(examples.static_rst) >>> print(simulation.mesh) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS - + DPF Mesh: + 81 nodes + 8 elements + Unit: m + With solid (3D) elements """ if self._mesh is None: self._mesh = Mesh(self._model.metadata.meshed_region) @@ -281,10 +307,15 @@ def _get_time_freq_precision(self): return self._time_freq_precision @property - def time_freq_support(self): + def time_freq_support(self) -> TimeFreqSupport: """Description of the temporal/frequency analysis of the model.""" return self._time_frequencies + @property + def set_ids(self) -> List: + """Returns the list of set IDs available in the simulation.""" + return list(range(1, self.time_freq_support.n_sets + 1)) + @property def units(self): """Returns the current time/frequency and distance units used.""" @@ -302,7 +333,19 @@ def __str__(self): txt += self._model.__str__() return txt - def _build_components_from_components(self, base_name, category, components): + def _build_components_for_vector(self, base_name, components): + out, columns = self._build_components( + base_name, components, self._vector_component_names + ) + return out, columns + + def _build_components_for_matrix(self, base_name, components): + out, columns = self._build_components( + base_name, components, self._matrix_component_names + ) + return out, columns + + def _build_components(self, base_name, components, component_names): # Create operator internal names based on components out = [] if components is None: @@ -321,47 +364,44 @@ def _build_components_from_components(self, base_name, category, components): ) if isinstance(comp, int): comp = str(comp) - if comp not in self._component_to_id.keys(): + if comp not in component_label_to_index.keys(): raise ValueError( f"Component {comp} is not valid. Please use one of: " - f"{list(self._component_to_id.keys())}." + f"{list(component_label_to_index.keys())}." ) - out.append(self._component_to_id[comp]) + out.append(component_label_to_index[comp]) # Take unique values and build names list - if out is not None: - out = list(set(out)) - if out is None and category == ResultCategory.vector: - columns = [base_name + comp for comp in self._component_names[:3]] - elif out is None and category == ResultCategory.matrix: - columns = [base_name + comp for comp in self._component_names] + if out is None: + columns = [base_name + comp for comp in component_names] else: - columns = [base_name + self._component_names[i] for i in out] + out = list(set(out)) + columns = [base_name + component_names[i] for i in out] return out, columns - def _build_components_from_principal(self, base_name, components): + def _build_components_for_principal(self, base_name, components): # Create operator internal names based on principal components out = [] if components is None: - out = None - else: - if isinstance(components, int) or isinstance(components, str): - components = [components] - if not isinstance(components, list): + components = [1] + + if isinstance(components, int) or isinstance(components, str): + components = [components] + if not isinstance(components, list): + raise ValueError( + "Argument 'components' must be an int, a str, or a list of either." + ) + for comp in components: + if not (isinstance(comp, str) or isinstance(comp, int)): raise ValueError( - "Argument 'components' must be an int, a str, or a list of either." + "Argument 'components' can only contain integers and/or strings." ) - for comp in components: - if not (isinstance(comp, str) or isinstance(comp, int)): - raise ValueError( - "Argument 'components' can only contain integers and/or strings." - ) - if str(comp) not in self._principal_names: - raise ValueError( - "A principal component ID must be one of: " - f"{self._principal_names}." - ) - out.append(int(comp) - 1) + if str(comp) not in self._principal_names: + raise ValueError( + "A principal component ID must be one of: " + f"{self._principal_names}." + ) + out.append(int(comp) - 1) # Take unique values if out is not None: @@ -387,6 +427,79 @@ def _build_result_operator( op.connect(9, location) return op + def _create_components(self, base_name, category, components): + comp = None + # Build the list of requested results + if category in [ResultCategory.scalar, ResultCategory.equivalent]: + # A scalar or equivalent result has no components + to_extract = None + columns = [base_name] + elif category == ResultCategory.vector: + # A vector result can have components selected + to_extract, columns = self._build_components_for_vector( + base_name=base_name, components=components + ) + if to_extract is not None: + comp = [self._vector_component_names[i] for i in to_extract] + else: + comp = self._vector_component_names + elif category == ResultCategory.matrix: + # A vector result can have components selected + to_extract, columns = self._build_components_for_matrix( + base_name=base_name, components=components + ) + if to_extract is not None: + comp = [self._matrix_component_names[i] for i in to_extract] + else: + comp = self._matrix_component_names + elif category == ResultCategory.principal: + # A principal type of result can have components selected + to_extract, columns = self._build_components_for_principal( + base_name=base_name, components=components + ) + comp = [self._principal_names[i] for i in to_extract] + else: + raise ValueError(f"'{category}' is not a valid category value.") + return comp, to_extract, columns + + def _create_dataframe(self, fc, location, columns, comp, base_name): + # Test for empty results + if (len(fc) == 0) or all([len(f) == 0 for f in fc]): + warnings.warn( + message=f"Returned Dataframe with columns {columns} is empty.", + category=UserWarning, + ) + comp_index = None + if comp is not None: + comp_index = CompIndex(values=comp) + row_indexes = [MeshIndex(location=location, fc=fc)] + if comp_index is not None: + row_indexes.append(comp_index) + column_indexes = [ + ResultsIndex(values=[base_name]), + SetIndex(values=fc.get_available_ids_for_label("time")), + ] + label_indexes = [] + for label in fc.labels: + if label not in ["time"]: + label_indexes.append( + LabelIndex(name=label, values=fc.get_available_ids_for_label(label)) + ) + + column_indexes.extend(label_indexes) + column_index = MultiIndex(indexes=column_indexes) + + row_index = MultiIndex( + indexes=row_indexes, + ) + + # Return the result wrapped in a DPF_Dataframe + return DataFrame( + data=fc, + columns=column_index, + index=row_index, + ) + class MechanicalSimulation(Simulation, ABC): """Base class for mechanical type simulations. @@ -432,12 +545,12 @@ def _build_selection( # Create the SpatialSelection if named_selections: selection.select_named_selection(named_selection=named_selections) - elif element_ids: + elif element_ids is not None: if location == locations.nodal: selection.select_nodes_of_elements(elements=element_ids, mesh=self.mesh) else: selection.select_elements(elements=element_ids) - elif node_ids: + elif node_ids is not None: if location != locations.nodal: raise ValueError( "Argument 'node_ids' can only be used if 'location' " diff --git a/src/ansys/dpf/post/static_mechanical_simulation.py b/src/ansys/dpf/post/static_mechanical_simulation.py index c4d9c237e..865161032 100644 --- a/src/ansys/dpf/post/static_mechanical_simulation.py +++ b/src/ansys/dpf/post/static_mechanical_simulation.py @@ -1,10 +1,9 @@ """Module containing the ``StaticMechanicalSimulation`` class.""" from typing import List, Tuple, Union -import warnings from ansys.dpf import core from ansys.dpf.post import locations -from ansys.dpf.post.data_object import DataObject +from ansys.dpf.post.dataframe import DataFrame from ansys.dpf.post.selection import Selection from ansys.dpf.post.simulation import MechanicalSimulation, ResultCategory @@ -29,7 +28,7 @@ def _get_result( node_ids: Union[List[int], None] = None, element_ids: Union[List[int], None] = None, named_selections: Union[List[str], str, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -80,7 +79,7 @@ def _get_result( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ # Build the targeted time scoping @@ -109,23 +108,9 @@ def _get_result( location=location, ) - # Build the list of requested results - if category in [ResultCategory.scalar, ResultCategory.equivalent]: - # A scalar or equivalent result has no components - to_extract = None - columns = [base_name] - elif category in [ResultCategory.vector, ResultCategory.matrix]: - # A matrix or vector result can have components selected - to_extract, columns = self._build_components_from_components( - base_name=base_name, category=category, components=components - ) - elif category == ResultCategory.principal: - # A principal type of result can have components selected - to_extract, columns = self._build_components_from_principal( - base_name=base_name, components=components - ) - else: - raise ValueError(f"'{category}' is not a valid category value.") + comp, to_extract, columns = self._create_components( + base_name, category, components + ) # Initialize a workflow wf = core.Workflow(server=self._model._server) @@ -218,29 +203,12 @@ def _get_result( wf.add_operator(operator=norm_op) out = norm_op.outputs.fields_container - extract_scoping = self._model.operator(name="extract_scoping") - extract_scoping.connect(0, out) - merge_scopings = self._model.operator(name="merge::scoping") - merge_scopings.connect(0, extract_scoping.outputs.mesh_scoping_as_scoping) - wf.set_output_name("scoping", merge_scopings.outputs.merged_scoping) - # Set the workflow output wf.set_output_name("out", out) # Evaluate the workflow fc = wf.get_output("out", core.types.fields_container) - # Test for empty results - if (len(fc) == 0) or all([len(f) == 0 for f in fc]): - warnings.warn( - message=f"Returned Dataframe with columns {columns} is empty.", - category=UserWarning, - ) - # Return the result wrapped in a DPF_Dataframe - return DataObject( - fields_container=fc, - columns=columns, - index=wf.get_output("scoping", core.types.scoping).ids, - ) + return self._create_dataframe(fc, location, columns, comp, base_name) def displacement( self, @@ -256,7 +224,7 @@ def displacement( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract displacement results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -296,7 +264,7 @@ def displacement( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -329,7 +297,7 @@ def stress( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -375,7 +343,7 @@ def stress( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -405,7 +373,7 @@ def stress_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -441,7 +409,7 @@ def stress_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -472,7 +440,7 @@ def stress_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -510,7 +478,7 @@ def stress_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -542,7 +510,7 @@ def stress_principal( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal principal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -588,7 +556,7 @@ def stress_principal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -618,7 +586,7 @@ def stress_principal_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental principal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -653,7 +621,7 @@ def stress_principal_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -684,7 +652,7 @@ def stress_principal_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal principal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -721,7 +689,7 @@ def stress_principal_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -752,7 +720,7 @@ def stress_eqv_von_mises( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal equivalent Von Mises stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -795,7 +763,7 @@ def stress_eqv_von_mises( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -824,7 +792,7 @@ def stress_eqv_von_mises_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental equivalent Von Mises stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -857,7 +825,7 @@ def stress_eqv_von_mises_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -887,7 +855,7 @@ def stress_eqv_von_mises_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal equivalent Von Mises stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -922,7 +890,7 @@ def stress_eqv_von_mises_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -954,7 +922,7 @@ def elastic_strain( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1000,7 +968,7 @@ def elastic_strain( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1031,7 +999,7 @@ def elastic_strain_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1069,7 +1037,7 @@ def elastic_strain_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1099,7 +1067,7 @@ def elastic_strain_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1135,7 +1103,7 @@ def elastic_strain_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1167,7 +1135,7 @@ def elastic_strain_principal( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal principal elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1212,7 +1180,7 @@ def elastic_strain_principal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1243,7 +1211,7 @@ def elastic_strain_principal_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal principal elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1280,7 +1248,7 @@ def elastic_strain_principal_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1310,7 +1278,7 @@ def elastic_strain_principal_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental principal elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1345,7 +1313,7 @@ def elastic_strain_principal_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1376,7 +1344,7 @@ def elastic_strain_eqv_von_mises( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal equivalent Von Mises elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1419,7 +1387,7 @@ def elastic_strain_eqv_von_mises( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1448,7 +1416,7 @@ def elastic_strain_eqv_von_mises_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental equivalent Von Mises elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1481,7 +1449,7 @@ def elastic_strain_eqv_von_mises_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1511,7 +1479,7 @@ def elastic_strain_eqv_von_mises_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal equivalent Von Mises elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1546,7 +1514,7 @@ def elastic_strain_eqv_von_mises_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1577,7 +1545,7 @@ def plastic_state_variable( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal plastic state variable results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1620,7 +1588,7 @@ def plastic_state_variable( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1649,7 +1617,7 @@ def plastic_state_variable_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental plastic state variable results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1682,7 +1650,7 @@ def plastic_state_variable_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1712,7 +1680,7 @@ def plastic_state_variable_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal plastic state variable results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1747,7 +1715,7 @@ def plastic_state_variable_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1779,7 +1747,7 @@ def plastic_strain( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1825,7 +1793,7 @@ def plastic_strain( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1856,7 +1824,7 @@ def plastic_strain_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1894,7 +1862,7 @@ def plastic_strain_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1924,7 +1892,7 @@ def plastic_strain_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1960,7 +1928,7 @@ def plastic_strain_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1992,7 +1960,7 @@ def plastic_strain_principal( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal principal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2037,7 +2005,7 @@ def plastic_strain_principal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2068,7 +2036,7 @@ def plastic_strain_principal_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal principal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2105,7 +2073,7 @@ def plastic_strain_principal_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2135,7 +2103,7 @@ def plastic_strain_principal_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental principal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2170,7 +2138,7 @@ def plastic_strain_principal_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2201,7 +2169,7 @@ def plastic_strain_eqv( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal equivalent plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2244,7 +2212,7 @@ def plastic_strain_eqv( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2274,7 +2242,7 @@ def plastic_strain_eqv_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal equivalent plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2309,7 +2277,7 @@ def plastic_strain_eqv_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2338,7 +2306,7 @@ def plastic_strain_eqv_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental equivalent plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2371,7 +2339,7 @@ def plastic_strain_eqv_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2403,7 +2371,7 @@ def creep_strain( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal creep strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2449,7 +2417,7 @@ def creep_strain( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2480,7 +2448,7 @@ def creep_strain_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal creep strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2518,7 +2486,7 @@ def creep_strain_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2548,7 +2516,7 @@ def creep_strain_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental creep strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2584,7 +2552,7 @@ def creep_strain_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2616,7 +2584,7 @@ def creep_strain_principal( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal principal creep strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2661,7 +2629,7 @@ def creep_strain_principal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2692,7 +2660,7 @@ def creep_strain_principal_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal principal creep strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2729,7 +2697,7 @@ def creep_strain_principal_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2759,7 +2727,7 @@ def creep_strain_principal_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental principal creep strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2794,7 +2762,7 @@ def creep_strain_principal_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2825,7 +2793,7 @@ def creep_strain_eqv( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal equivalent creep strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2868,7 +2836,7 @@ def creep_strain_eqv( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2898,7 +2866,7 @@ def creep_strain_equivalent_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal equivalent creep strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2933,7 +2901,7 @@ def creep_strain_equivalent_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2962,7 +2930,7 @@ def creep_strain_equivalent_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental equivalent creep strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2995,7 +2963,7 @@ def creep_strain_equivalent_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3027,7 +2995,7 @@ def reaction_force( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract reaction force results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3067,7 +3035,7 @@ def reaction_force( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3098,7 +3066,7 @@ def elemental_volume( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental volume results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3133,7 +3101,7 @@ def elemental_volume( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3162,7 +3130,7 @@ def elemental_mass( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental mass results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3195,7 +3163,7 @@ def elemental_mass( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3224,7 +3192,7 @@ def elemental_heat_generation( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental heat generation results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3257,7 +3225,7 @@ def elemental_heat_generation( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3286,7 +3254,7 @@ def element_centroids( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract element centroids results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3319,7 +3287,7 @@ def element_centroids( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3348,7 +3316,7 @@ def thickness( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract element thickness results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3381,7 +3349,7 @@ def thickness( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3412,7 +3380,7 @@ def element_orientations( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal element orientations results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3455,7 +3423,7 @@ def element_orientations( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3484,7 +3452,7 @@ def element_orientations_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental element orientations results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3517,7 +3485,7 @@ def element_orientations_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3547,7 +3515,7 @@ def element_orientations_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal element orientations results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3582,7 +3550,7 @@ def element_orientations_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3611,7 +3579,7 @@ def stiffness_matrix_energy( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract stiffness matrix energy results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3644,7 +3612,7 @@ def stiffness_matrix_energy( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3673,7 +3641,7 @@ def artificial_hourglass_energy( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract artificial hourglass energy results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3706,7 +3674,7 @@ def artificial_hourglass_energy( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3735,7 +3703,7 @@ def thermal_dissipation_energy( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract thermal dissipation energy results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3768,7 +3736,7 @@ def thermal_dissipation_energy( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3797,7 +3765,7 @@ def kinetic_energy( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract kinetic energy results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3830,7 +3798,7 @@ def kinetic_energy( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3861,7 +3829,7 @@ def hydrostatic_pressure( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract hydrostatic pressure element nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3896,7 +3864,7 @@ def hydrostatic_pressure( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3926,7 +3894,7 @@ def hydrostatic_pressure_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract hydrostatic pressure nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3961,7 +3929,7 @@ def hydrostatic_pressure_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3990,7 +3958,7 @@ def hydrostatic_pressure_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract hydrostatic pressure elemental results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -4023,7 +3991,7 @@ def hydrostatic_pressure_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -4054,7 +4022,7 @@ def structural_temperature( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract structural temperature element nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -4097,7 +4065,7 @@ def structural_temperature( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -4127,7 +4095,7 @@ def structural_temperature_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract structural temperature nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -4162,7 +4130,7 @@ def structural_temperature_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -4191,7 +4159,7 @@ def structural_temperature_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract structural temperature elemental results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -4224,7 +4192,7 @@ def structural_temperature_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -4257,7 +4225,7 @@ def element_nodal_forces( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract element nodal forces results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -4305,7 +4273,7 @@ def element_nodal_forces( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -4338,7 +4306,7 @@ def element_nodal_forces_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract element nodal forces nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -4378,7 +4346,7 @@ def element_nodal_forces_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -4410,7 +4378,7 @@ def element_nodal_forces_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract element nodal forces elemental results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -4448,7 +4416,7 @@ def element_nodal_forces_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -4481,7 +4449,7 @@ def nodal_force( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal force results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -4521,7 +4489,7 @@ def nodal_force( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -4554,7 +4522,7 @@ def nodal_moment( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal moment results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -4594,7 +4562,7 @@ def nodal_moment( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( diff --git a/src/ansys/dpf/post/transient_mechanical_simulation.py b/src/ansys/dpf/post/transient_mechanical_simulation.py index 86f3a7cd1..9b5d36f4e 100644 --- a/src/ansys/dpf/post/transient_mechanical_simulation.py +++ b/src/ansys/dpf/post/transient_mechanical_simulation.py @@ -1,10 +1,9 @@ """Module containing the ``TransientMechanicalSimulation`` class.""" from typing import List, Tuple, Union -import warnings from ansys.dpf import core from ansys.dpf.post import locations -from ansys.dpf.post.data_object import DataObject +from ansys.dpf.post.dataframe import DataFrame from ansys.dpf.post.selection import Selection from ansys.dpf.post.simulation import MechanicalSimulation, ResultCategory @@ -29,7 +28,7 @@ def _get_result( node_ids: Union[List[int], None] = None, element_ids: Union[List[int], None] = None, named_selections: Union[List[str], str, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -81,7 +80,7 @@ def _get_result( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ # Build the targeted time scoping @@ -110,23 +109,9 @@ def _get_result( location=location, ) - # Build the list of requested results - if category in [ResultCategory.scalar, ResultCategory.equivalent]: - # A scalar or equivalent result has no components - to_extract = None - columns = [base_name] - elif category in [ResultCategory.vector, ResultCategory.matrix]: - # A matrix or vector result can have components selected - to_extract, columns = self._build_components_from_components( - base_name=base_name, category=category, components=components - ) - elif category == ResultCategory.principal: - # A principal type of result can have components selected - to_extract, columns = self._build_components_from_principal( - base_name=base_name, components=components - ) - else: - raise ValueError(f"'{category}' is not a valid category value.") + comp, to_extract, columns = self._create_components( + base_name, category, components + ) # Initialize a workflow wf = core.Workflow(server=self._model._server) @@ -234,18 +219,7 @@ def _get_result( # Evaluate the workflow fc = wf.get_output("out", core.types.fields_container) - # Test for empty results - if (len(fc) == 0) or all([len(f) == 0 for f in fc]): - warnings.warn( - message=f"Returned Dataframe with columns {columns} is empty.", - category=UserWarning, - ) - # Return the result wrapped in a DPF_Dataframe - return DataObject( - fields_container=fc, - columns=columns, - index=wf.get_output("scoping", core.types.scoping).ids, - ) + return self._create_dataframe(fc, location, columns, comp, base_name) def displacement( self, @@ -261,7 +235,7 @@ def displacement( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract displacement results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -301,7 +275,7 @@ def displacement( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -334,7 +308,7 @@ def velocity( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract velocity results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -374,7 +348,7 @@ def velocity( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -407,7 +381,7 @@ def acceleration( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract acceleration results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -447,7 +421,7 @@ def acceleration( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -480,7 +454,7 @@ def stress( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -526,7 +500,7 @@ def stress( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -556,7 +530,7 @@ def stress_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -592,7 +566,7 @@ def stress_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -623,7 +597,7 @@ def stress_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -661,7 +635,7 @@ def stress_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -693,7 +667,7 @@ def stress_principal( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal principal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -738,7 +712,7 @@ def stress_principal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -768,7 +742,7 @@ def stress_principal_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental principal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -803,7 +777,7 @@ def stress_principal_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -834,7 +808,7 @@ def stress_principal_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal principal stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -871,7 +845,7 @@ def stress_principal_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -902,7 +876,7 @@ def stress_eqv_von_mises( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal equivalent Von Mises stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -945,7 +919,7 @@ def stress_eqv_von_mises( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -974,7 +948,7 @@ def stress_eqv_von_mises_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental equivalent Von Mises stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1007,7 +981,7 @@ def stress_eqv_von_mises_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1037,7 +1011,7 @@ def stress_eqv_von_mises_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal equivalent Von Mises stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1072,7 +1046,7 @@ def stress_eqv_von_mises_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1104,7 +1078,7 @@ def elastic_strain( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1150,7 +1124,7 @@ def elastic_strain( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1181,7 +1155,7 @@ def elastic_strain_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1219,7 +1193,7 @@ def elastic_strain_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1249,7 +1223,7 @@ def elastic_strain_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract stress results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1285,7 +1259,7 @@ def elastic_strain_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1317,7 +1291,7 @@ def elastic_strain_principal( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal principal elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1362,7 +1336,7 @@ def elastic_strain_principal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1393,7 +1367,7 @@ def elastic_strain_principal_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal principal elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1430,7 +1404,7 @@ def elastic_strain_principal_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1460,7 +1434,7 @@ def elastic_strain_principal_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental principal elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1495,7 +1469,7 @@ def elastic_strain_principal_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1526,7 +1500,7 @@ def elastic_strain_eqv_von_mises( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal equivalent Von Mises elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1569,7 +1543,7 @@ def elastic_strain_eqv_von_mises( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1598,7 +1572,7 @@ def elastic_strain_eqv_von_mises_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental equivalent Von Mises elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1631,7 +1605,7 @@ def elastic_strain_eqv_von_mises_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1661,7 +1635,7 @@ def elastic_strain_eqv_von_mises_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal equivalent Von Mises elastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1696,7 +1670,7 @@ def elastic_strain_eqv_von_mises_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1727,7 +1701,7 @@ def plastic_state_variable( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal plastic state variable results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1770,7 +1744,7 @@ def plastic_state_variable( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1799,7 +1773,7 @@ def plastic_state_variable_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental plastic state variable results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1832,7 +1806,7 @@ def plastic_state_variable_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1862,7 +1836,7 @@ def plastic_state_variable_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal plastic state variable results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1897,7 +1871,7 @@ def plastic_state_variable_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -1929,7 +1903,7 @@ def plastic_strain( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -1975,7 +1949,7 @@ def plastic_strain( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2006,7 +1980,7 @@ def plastic_strain_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2044,7 +2018,7 @@ def plastic_strain_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2074,7 +2048,7 @@ def plastic_strain_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2110,7 +2084,7 @@ def plastic_strain_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2142,7 +2116,7 @@ def plastic_strain_principal( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal principal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2187,7 +2161,7 @@ def plastic_strain_principal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2218,7 +2192,7 @@ def plastic_strain_principal_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal principal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2255,7 +2229,7 @@ def plastic_strain_principal_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2285,7 +2259,7 @@ def plastic_strain_principal_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental principal plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2320,7 +2294,7 @@ def plastic_strain_principal_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2351,7 +2325,7 @@ def plastic_strain_eqv( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal equivalent plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2394,7 +2368,7 @@ def plastic_strain_eqv( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2424,7 +2398,7 @@ def plastic_strain_eqv_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal equivalent plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2459,7 +2433,7 @@ def plastic_strain_eqv_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2488,7 +2462,7 @@ def plastic_strain_eqv_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental equivalent plastic strain results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2521,7 +2495,7 @@ def plastic_strain_eqv_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2553,7 +2527,7 @@ def reaction_force( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract reaction force results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2593,7 +2567,7 @@ def reaction_force( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2623,7 +2597,7 @@ def elemental_volume( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental volume results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2656,7 +2630,7 @@ def elemental_volume( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2685,7 +2659,7 @@ def elemental_mass( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental mass results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2718,7 +2692,7 @@ def elemental_mass( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2747,7 +2721,7 @@ def elemental_heat_generation( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental heat generation results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2780,7 +2754,7 @@ def elemental_heat_generation( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2809,7 +2783,7 @@ def element_centroids( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract element centroids results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2842,7 +2816,7 @@ def element_centroids( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2871,7 +2845,7 @@ def thickness( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract element thickness results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2904,7 +2878,7 @@ def thickness( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -2935,7 +2909,7 @@ def element_orientations( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract elemental nodal element orientations results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -2978,7 +2952,7 @@ def element_orientations( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3007,7 +2981,7 @@ def element_orientations_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract elemental element orientations results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3040,7 +3014,7 @@ def element_orientations_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3070,7 +3044,7 @@ def element_orientations_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal element orientations results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3105,7 +3079,7 @@ def element_orientations_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3134,7 +3108,7 @@ def artificial_hourglass_energy( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract artificial hourglass energy results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3167,7 +3141,7 @@ def artificial_hourglass_energy( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3196,7 +3170,7 @@ def thermal_dissipation_energy( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract thermal dissipation energy results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3229,7 +3203,7 @@ def thermal_dissipation_energy( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3258,7 +3232,7 @@ def kinetic_energy( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract kinetic energy results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3291,7 +3265,7 @@ def kinetic_energy( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3322,7 +3296,7 @@ def hydrostatic_pressure( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract hydrostatic pressure element nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3365,7 +3339,7 @@ def hydrostatic_pressure( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3395,7 +3369,7 @@ def hydrostatic_pressure_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract hydrostatic pressure nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3430,7 +3404,7 @@ def hydrostatic_pressure_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3459,7 +3433,7 @@ def hydrostatic_pressure_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract hydrostatic pressure elemental results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3492,7 +3466,7 @@ def hydrostatic_pressure_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3523,7 +3497,7 @@ def structural_temperature( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract structural temperature element nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3566,7 +3540,7 @@ def structural_temperature( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3596,7 +3570,7 @@ def structural_temperature_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract structural temperature nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3631,7 +3605,7 @@ def structural_temperature_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3660,7 +3634,7 @@ def structural_temperature_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract structural temperature elemental results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3693,7 +3667,7 @@ def structural_temperature_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3726,7 +3700,7 @@ def element_nodal_forces( named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, location: Union[locations, str] = locations.elemental_nodal, - ) -> DataObject: + ) -> DataFrame: """Extract element nodal forces results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3774,7 +3748,7 @@ def element_nodal_forces( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3807,7 +3781,7 @@ def element_nodal_forces_nodal( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract element nodal forces nodal results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3847,7 +3821,7 @@ def element_nodal_forces_nodal( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3879,7 +3853,7 @@ def element_nodal_forces_elemental( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract element nodal forces elemental results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3917,7 +3891,7 @@ def element_nodal_forces_elemental( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -3950,7 +3924,7 @@ def nodal_force( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal force results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -3990,7 +3964,7 @@ def nodal_force( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( @@ -4023,7 +3997,7 @@ def nodal_moment( ] = None, named_selections: Union[List[str], str, None] = None, selection: Union[Selection, None] = None, - ) -> DataObject: + ) -> DataFrame: """Extract nodal moment results from the simulation. Arguments `selection`, `set_ids`, `all_sets`, `times`, and `load_steps` are mutually @@ -4063,7 +4037,7 @@ def nodal_moment( Returns ------- - Returns a :class:`ansys.dpf.post.data_object.DataObject` instance. + Returns a :class:`ansys.dpf.post.data_object.DataFrame` instance. """ return self._get_result( diff --git a/tests/conftest.py b/tests/conftest.py index dfb96dc6a..fd6c8eeeb 100755 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -82,6 +82,12 @@ def simple_bar(): return examples.simple_bar +@pytest.fixture() +def multishells(): + """Resolve the path of the "multishells.rst" result file.""" + return examples.find_multishells_rst() + + @pytest.fixture() def transient_rst(): """Resolve the path of the "transient.rst" result file.""" diff --git a/tests/test_dataframe.py b/tests/test_dataframe.py new file mode 100644 index 000000000..54c075383 --- /dev/null +++ b/tests/test_dataframe.py @@ -0,0 +1,167 @@ +import ansys.dpf.core as core +import pytest +from pytest import fixture + +from ansys.dpf import post +from ansys.dpf.post.index import ( + CompIndex, + LabelIndex, + MeshIndex, + MultiIndex, + ResultsIndex, +) +from ansys.dpf.post.static_mechanical_simulation import StaticMechanicalSimulation +from ansys.dpf.post.transient_mechanical_simulation import TransientMechanicalSimulation + + +@fixture +def df(static_rst): + simulation = StaticMechanicalSimulation(static_rst) + return simulation.displacement() + + +def test_dataframe_core_object(df): + assert isinstance(df._core_object, core.FieldsContainer) + assert len(df._core_object) == 1 + + +def test_dataframe_from_fields_container(simple_bar): + model = core.Model(simple_bar) + fc = model.results.displacement().eval() + column_indexes = [ + LabelIndex(name=label, values=fc.get_available_ids_for_label(label)) + for label in fc.labels + ] + column_indexes.append(ResultsIndex(values=["U"])) + column_index = MultiIndex(indexes=column_indexes) + + row_indexes = [ + MeshIndex(location=post.locations.nodal, fc=fc), + CompIndex(values=["X", "Y", "Z"]), + ] + row_index = MultiIndex(indexes=row_indexes) + + df = post.DataFrame( + data=fc, + columns=column_index, + index=row_index, + ) + assert df.axes == ["node", "comp", "time", "results"] + + +def test_dataframe_from_error(): + fc = [1, 2, 3] + with pytest.raises(ValueError, match="not a valid data type"): + _ = post.DataFrame(data=fc, index=[1, 2]) + + +# def test_dataframe_len(multishells, transient_rst): +# # Case of one set with two nodal fields +# model = core.Model(multishells) +# fc = model.results.stress.on_all_time_freqs.on_location("Nodal").eval() +# df = post.DataFrame(data=fc) +# assert len(df) == 2 +# # Case of several sets with one field per set +# model = core.Model(transient_rst) +# fc = model.results.displacement.on_all_time_freqs.eval() +# df = post.DataFrame(data=fc) +# assert len(df) == 35 + + +def test_dataframe_columns(df): + columns = df.columns + print(repr(columns)) + print(columns) + + +def test_dataframe_index(df): + index = df.index + print(repr(index)) + print(index) + + +def test_dataframe_select_raise(df, transient_rst): + with pytest.raises(ValueError, match="has no axis"): + df.select(toto=1) + + with pytest.raises(NotImplementedError, match="Element selection"): + simulation = TransientMechanicalSimulation(transient_rst) + df = simulation.stress() + _ = df.select(element=391) + + +def test_dataframe_select(df): + # print(df) + df2 = df.select(node=[1, 2], set_id=1, comp="X") + assert all(df2.mesh_index.values == [1, 2]) + assert df2.index.comp.values == ["X"] + assert df2.columns.set_id.values == [1] + # print(df2) + + +def test_dataframe_iselect(df): + df2 = df.iselect(node=[0, 1], set_id=0, comp=0) + assert all(df2.mesh_index.values == [1, 26]) + assert df2.index.comp.values == ["X"] + assert df2.columns.set_id.values == [1] + # print(df2) + + +def test_dataframe_plot(df): + df.plot(set_id=1, node=[1, 2, 3, 4, 5, 6, 7, 8, 9]) + + +def test_dataframe_repr(df): + ref = ( + "DataFrame>, " + "Index>]>, columns=MultiIndex<[ResultIndex<['U']>, " + "Index>]>>" + ) + assert repr(df) == ref + + +def test_dataframe_str(transient_rst): + simulation = TransientMechanicalSimulation(transient_rst) + df = simulation.displacement(all_sets=True) + print(df) + ref = """ + results U + set_id 1 2 3 4 5 6 + node comp + 525 X 0.00e+00 4.85e-05 2.30e-04 6.51e-04 1.48e-03 2.93e-03 + Y 0.00e+00 2.87e-04 1.14e-03 2.54e-03 4.41e-03 6.59e-03 + Z 0.00e+00 -1.26e-10 -4.34e-10 -8.29e-10 -1.15e-09 -1.39e-09 + 534 X 0.00e+00 6.55e-06 1.05e-04 5.30e-04 1.67e-03 4.02e-03 + Y 0.00e+00 6.27e-04 2.51e-03 5.62e-03 9.86e-03 1.50e-02 + Z 0.00e+00 -3.20e-10 -1.10e-09 -2.13e-09 -2.94e-09 -3.57e-09 +""" # noqa: W291 + assert str(df) == ref + df = simulation.stress() + print(df) + print(df._fc[0].get_entity_data_by_id(391)) + ref = """ + results S + set_id 35 + element comp + 391 XX (1) -3.28e+05 + YY (1) 1.36e+06 + ZZ (1) 1.49e+08 + XY (1) -4.89e+06 + YZ (1) 1.43e+07 + XZ (1) 1.65e+07 +""" # noqa: W291 + assert str(df) == ref + df2 = df.select(comp="YY") + print(df2) + ref = """ + results S + set_id 35 + element comp + 391 YY (1) 1.36e+06 + 391 YY (2) 1.29e+06 + 391 YY (3) -3.53e+07 + 391 YY (4) -2.72e+07 + 391 YY (5) 2.83e+07 + 391 YY (6) 5.26e+06 +""" # noqa: W291 + assert str(df2) == ref diff --git a/tests/test_mesh.py b/tests/test_mesh.py new file mode 100644 index 000000000..aa4d6852e --- /dev/null +++ b/tests/test_mesh.py @@ -0,0 +1,42 @@ +import ansys.dpf.core as core +import numpy as np +from pytest import fixture + +from ansys.dpf.post.static_mechanical_simulation import StaticMechanicalSimulation + + +@fixture +def mesh(static_rst): + simulation = StaticMechanicalSimulation(static_rst) + return simulation.mesh + + +def test_mesh_core_object(mesh): + assert isinstance(mesh._core_object, core.MeshedRegion) + assert mesh._core_object.nodes.n_nodes == 81 + + +def test_mesh_node_ids(mesh): + n_ids = mesh.node_ids + assert len(n_ids) == 81 + assert all([isinstance(i, (int, np.integer)) for i in n_ids]) + + +def test_mesh_element_ids(mesh): + e_ids = mesh.element_ids + assert len(e_ids) == 8 + assert all([isinstance(i, (int, np.integer)) for i in e_ids]) + + +def test_mesh_available_named_selections(mesh): + ns = mesh.available_named_selections + assert len(ns) == 1 + assert all([isinstance(n, str) for n in ns]) + + +def test_mesh_str(mesh): + txt = str(mesh) + assert ( + txt + == "DPF Mesh: \n 81 nodes \n 8 elements \n Unit: m \n With solid (3D) elements" + ) diff --git a/tests/test_simulation.py b/tests/test_simulation.py index f824d2e8f..7f386e1ae 100644 --- a/tests/test_simulation.py +++ b/tests/test_simulation.py @@ -41,14 +41,14 @@ def test_simulation_geometries(static_simulation): assert geometries == [] -def test_simulation_boundary_conditions(static_simulation): - boundary_conditions = static_simulation.boundary_conditions - assert boundary_conditions == [] - - -def test_simulation_loads(static_simulation): - loads = static_simulation.loads - assert loads == [] +# def test_simulation_boundary_conditions(static_simulation): +# boundary_conditions = static_simulation.boundary_conditions +# assert boundary_conditions == [] +# +# +# def test_simulation_loads(static_simulation): +# loads = static_simulation.loads +# assert loads == [] def test_simulation_mesh(static_simulation):