| | | Output splitted fields containter
diff --git a/src/ansys/dpf/core/operators/math/modal_damping_ratio.py b/src/ansys/dpf/core/operators/math/modal_damping_ratio.py
index be69df2b19c..95f262dd8f9 100644
--- a/src/ansys/dpf/core/operators/math/modal_damping_ratio.py
+++ b/src/ansys/dpf/core/operators/math/modal_damping_ratio.py
@@ -17,6 +17,7 @@
if TYPE_CHECKING:
from ansys.dpf.core.field import Field
+ from ansys.dpf.core.time_freq_support import TimeFreqSupport
class modal_damping_ratio(Operator):
@@ -36,7 +37,7 @@ class modal_damping_ratio(Operator):
Inputs
------
- natural_freq:
+ natural_freq: Field or TimeFreqSupport
input vector expects natural frequencies.
const_ratio: float, optional
constant modal damping ratio
@@ -60,7 +61,7 @@ class modal_damping_ratio(Operator):
>>> op = dpf.operators.math.modal_damping_ratio()
>>> # Make input connections
- >>> my_natural_freq = dpf.()
+ >>> my_natural_freq = dpf.Field()
>>> op.inputs.natural_freq.connect(my_natural_freq)
>>> my_const_ratio = float()
>>> op.inputs.const_ratio.connect(my_const_ratio)
@@ -132,7 +133,7 @@ def _spec() -> Specification:
map_input_pin_spec={
0: PinSpecification(
name="natural_freq",
- type_names=["vector "],
+ type_names=["vector", "field", "time_freq_support"],
optional=False,
document=r"""input vector expects natural frequencies.""",
),
@@ -224,7 +225,7 @@ class InputsModalDampingRatio(_Inputs):
--------
>>> from ansys.dpf import core as dpf
>>> op = dpf.operators.math.modal_damping_ratio()
- >>> my_natural_freq = dpf.()
+ >>> my_natural_freq = dpf.Field()
>>> op.inputs.natural_freq.connect(my_natural_freq)
>>> my_const_ratio = float()
>>> op.inputs.const_ratio.connect(my_const_ratio)
@@ -238,7 +239,7 @@ class InputsModalDampingRatio(_Inputs):
def __init__(self, op: Operator):
super().__init__(modal_damping_ratio._spec().inputs, op)
- self._natural_freq: Input = Input(
+ self._natural_freq: Input[Field | TimeFreqSupport] = Input(
modal_damping_ratio._spec().input_pin(0), 0, op, -1
)
self._inputs.append(self._natural_freq)
@@ -260,7 +261,7 @@ def __init__(self, op: Operator):
self._inputs.append(self._k_coefficient)
@property
- def natural_freq(self) -> Input:
+ def natural_freq(self) -> Input[Field | TimeFreqSupport]:
r"""Allows to connect natural_freq input to the operator.
input vector expects natural frequencies.
diff --git a/src/ansys/dpf/core/operators/result/__init__.py b/src/ansys/dpf/core/operators/result/__init__.py
index a98e6a24fc8..64a0fade3c4 100644
--- a/src/ansys/dpf/core/operators/result/__init__.py
+++ b/src/ansys/dpf/core/operators/result/__init__.py
@@ -217,7 +217,6 @@
from .magnetic_vector_potential import magnetic_vector_potential
from .mapdl_material_properties import mapdl_material_properties
from .mapdl_section import mapdl_section
-from .mapdl_split_on_facet_indices import mapdl_split_on_facet_indices
from .mapdl_split_to_acmo_facet_indices import mapdl_split_to_acmo_facet_indices
from .mass_flow_rate import mass_flow_rate
from .mass_fraction import mass_fraction
diff --git a/src/ansys/dpf/core/operators/result/mapdl_split_on_facet_indices.py b/src/ansys/dpf/core/operators/result/mapdl_split_on_facet_indices.py
deleted file mode 100644
index 0fd5b92f6c2..00000000000
--- a/src/ansys/dpf/core/operators/result/mapdl_split_on_facet_indices.py
+++ /dev/null
@@ -1,443 +0,0 @@
-"""
-mapdl_split_on_facet_indices
-
-Autogenerated DPF operator classes.
-"""
-
-from __future__ import annotations
-from typing import TYPE_CHECKING
-
-from warnings import warn
-from ansys.dpf.core.dpf_operator import Operator
-from ansys.dpf.core.inputs import Input, _Inputs
-from ansys.dpf.core.outputs import Output, _Outputs
-from ansys.dpf.core.operators.specification import PinSpecification, Specification
-from ansys.dpf.core.config import Config
-from ansys.dpf.core.server_types import AnyServerType
-
-if TYPE_CHECKING:
- from ansys.dpf.core.fields_container import FieldsContainer
- from ansys.dpf.core.meshed_region import MeshedRegion
- from ansys.dpf.core.property_field import PropertyField
- from ansys.dpf.core.scoping import Scoping
-
-
-class mapdl_split_on_facet_indices(Operator):
- r"""Splits each Field in a FieldsContainer defined on the skin elements of a
- mesh according to the local facets indices of its corresponding solid
- element. The output FieldsContainer retains the original labels and adds
- a ‘facet’ label, which indicates at which facet of the solid mesh was
- the original skin element located. The facet ids are according to MAPDL
- convention. The scoping of the output Fields reflects the element
- indices in the solid mesh.
-
-
- Inputs
- ------
- fields_container: FieldsContainer
- Fields container to split, with generic number of labels (e.g. time, zone, complex...). Fields may have Elemental or ElementalNodal location; scoping ids are skin element ids.
- property_field_new_elements_to_old: PropertyField
- This property field provides, for each new face element ID (in the scoping), the corresponding 3D volume element index (in the data) it has been extracted from. The 3D volume element ID can be found with the element scoping of the input mesh.
- facet_indices: PropertyField
- This property field gives, for each new face element ID (in the scoping), the corresponding face index on the source 3D volume element. The 3D volume element can be extracted from the previous output.
- volume_mesh: MeshedRegion
- The solid support.
- degenerated_tets: Scoping, optional
- Elemental scoping of tet elements. If connected, the tets in the scoping are treated as degenerated tets (SOLID185), and the rest as non-degenerated tets (SOLID285). Pins 185 and 285 are mutually exclusionary (they cannot be connected at the same time), and if none of them is connected, all tets are treated as non-degenerated (SOLID285).
- non_degenerated_tets: Scoping, optional
- Elemental scoping of tet elements. If connected, the tets in the scoping are treated as non-degenerated tets (SOLID285), and the rest as degenerated tets (SOLID185). Pins 185 and 285 are mutually exclusionary (they cannot be connected at the same time), and if none of them is connected, all tets are treated as non-degenerated (SOLID285).
-
- Outputs
- -------
- fields_container: FieldsContainer
- Output splitted fields containter
-
- Examples
- --------
- >>> from ansys.dpf import core as dpf
-
- >>> # Instantiate operator
- >>> op = dpf.operators.result.mapdl_split_on_facet_indices()
-
- >>> # Make input connections
- >>> my_fields_container = dpf.FieldsContainer()
- >>> op.inputs.fields_container.connect(my_fields_container)
- >>> my_property_field_new_elements_to_old = dpf.PropertyField()
- >>> op.inputs.property_field_new_elements_to_old.connect(my_property_field_new_elements_to_old)
- >>> my_facet_indices = dpf.PropertyField()
- >>> op.inputs.facet_indices.connect(my_facet_indices)
- >>> my_volume_mesh = dpf.MeshedRegion()
- >>> op.inputs.volume_mesh.connect(my_volume_mesh)
- >>> my_degenerated_tets = dpf.Scoping()
- >>> op.inputs.degenerated_tets.connect(my_degenerated_tets)
- >>> my_non_degenerated_tets = dpf.Scoping()
- >>> op.inputs.non_degenerated_tets.connect(my_non_degenerated_tets)
-
- >>> # Instantiate operator and connect inputs in one line
- >>> op = dpf.operators.result.mapdl_split_on_facet_indices(
- ... fields_container=my_fields_container,
- ... property_field_new_elements_to_old=my_property_field_new_elements_to_old,
- ... facet_indices=my_facet_indices,
- ... volume_mesh=my_volume_mesh,
- ... degenerated_tets=my_degenerated_tets,
- ... non_degenerated_tets=my_non_degenerated_tets,
- ... )
-
- >>> # Get output data
- >>> result_fields_container = op.outputs.fields_container()
- """
-
- def __init__(
- self,
- fields_container=None,
- property_field_new_elements_to_old=None,
- facet_indices=None,
- volume_mesh=None,
- degenerated_tets=None,
- non_degenerated_tets=None,
- config=None,
- server=None,
- ):
- super().__init__(
- name="mapdl::split_on_facet_indices",
- config=config,
- server=server,
- inputs_type=InputsMapdlSplitOnFacetIndices,
- outputs_type=OutputsMapdlSplitOnFacetIndices,
- )
- if fields_container is not None:
- self.inputs.fields_container.connect(fields_container)
- if property_field_new_elements_to_old is not None:
- self.inputs.property_field_new_elements_to_old.connect(
- property_field_new_elements_to_old
- )
- if facet_indices is not None:
- self.inputs.facet_indices.connect(facet_indices)
- if volume_mesh is not None:
- self.inputs.volume_mesh.connect(volume_mesh)
- if degenerated_tets is not None:
- self.inputs.degenerated_tets.connect(degenerated_tets)
- if non_degenerated_tets is not None:
- self.inputs.non_degenerated_tets.connect(non_degenerated_tets)
-
- @staticmethod
- def _spec() -> Specification:
- description = r"""Splits each Field in a FieldsContainer defined on the skin elements of a
-mesh according to the local facets indices of its corresponding solid
-element. The output FieldsContainer retains the original labels and adds
-a ‘facet’ label, which indicates at which facet of the solid mesh was
-the original skin element located. The facet ids are according to MAPDL
-convention. The scoping of the output Fields reflects the element
-indices in the solid mesh.
-"""
- spec = Specification(
- description=description,
- map_input_pin_spec={
- 0: PinSpecification(
- name="fields_container",
- type_names=["fields_container"],
- optional=False,
- document=r"""Fields container to split, with generic number of labels (e.g. time, zone, complex...). Fields may have Elemental or ElementalNodal location; scoping ids are skin element ids.""",
- ),
- 1: PinSpecification(
- name="property_field_new_elements_to_old",
- type_names=["property_field"],
- optional=False,
- document=r"""This property field provides, for each new face element ID (in the scoping), the corresponding 3D volume element index (in the data) it has been extracted from. The 3D volume element ID can be found with the element scoping of the input mesh.""",
- ),
- 2: PinSpecification(
- name="facet_indices",
- type_names=["property_field"],
- optional=False,
- document=r"""This property field gives, for each new face element ID (in the scoping), the corresponding face index on the source 3D volume element. The 3D volume element can be extracted from the previous output.""",
- ),
- 3: PinSpecification(
- name="volume_mesh",
- type_names=["abstract_meshed_region"],
- optional=False,
- document=r"""The solid support.""",
- ),
- 185: PinSpecification(
- name="degenerated_tets",
- type_names=["scoping"],
- optional=True,
- document=r"""Elemental scoping of tet elements. If connected, the tets in the scoping are treated as degenerated tets (SOLID185), and the rest as non-degenerated tets (SOLID285). Pins 185 and 285 are mutually exclusionary (they cannot be connected at the same time), and if none of them is connected, all tets are treated as non-degenerated (SOLID285).""",
- ),
- 285: PinSpecification(
- name="non_degenerated_tets",
- type_names=["scoping"],
- optional=True,
- document=r"""Elemental scoping of tet elements. If connected, the tets in the scoping are treated as non-degenerated tets (SOLID285), and the rest as degenerated tets (SOLID185). Pins 185 and 285 are mutually exclusionary (they cannot be connected at the same time), and if none of them is connected, all tets are treated as non-degenerated (SOLID285).""",
- ),
- },
- map_output_pin_spec={
- 0: PinSpecification(
- name="fields_container",
- type_names=["fields_container"],
- optional=False,
- document=r"""Output splitted fields containter""",
- ),
- },
- )
- return spec
-
- @staticmethod
- def default_config(server: AnyServerType = None) -> Config:
- """Returns the default config of the operator.
-
- This config can then be changed to the user needs and be used to
- instantiate the operator. The Configuration allows to customize
- how the operation will be processed by the operator.
-
- Parameters
- ----------
- server:
- Server with channel connected to the remote or local instance. When
- ``None``, attempts to use the global server.
-
- Returns
- -------
- config:
- A new Config instance equivalent to the default config for this operator.
- """
- return Operator.default_config(
- name="mapdl::split_on_facet_indices", server=server
- )
-
- @property
- def inputs(self) -> InputsMapdlSplitOnFacetIndices:
- """Enables to connect inputs to the operator
-
- Returns
- --------
- inputs:
- An instance of InputsMapdlSplitOnFacetIndices.
- """
- return self._inputs
-
- @property
- def outputs(self) -> OutputsMapdlSplitOnFacetIndices:
- """Enables to get outputs of the operator by evaluating it
-
- Returns
- --------
- outputs:
- An instance of OutputsMapdlSplitOnFacetIndices.
- """
- return self._outputs
-
-
-class InputsMapdlSplitOnFacetIndices(_Inputs):
- """Intermediate class used to connect user inputs to
- mapdl_split_on_facet_indices operator.
-
- Examples
- --------
- >>> from ansys.dpf import core as dpf
- >>> op = dpf.operators.result.mapdl_split_on_facet_indices()
- >>> my_fields_container = dpf.FieldsContainer()
- >>> op.inputs.fields_container.connect(my_fields_container)
- >>> my_property_field_new_elements_to_old = dpf.PropertyField()
- >>> op.inputs.property_field_new_elements_to_old.connect(my_property_field_new_elements_to_old)
- >>> my_facet_indices = dpf.PropertyField()
- >>> op.inputs.facet_indices.connect(my_facet_indices)
- >>> my_volume_mesh = dpf.MeshedRegion()
- >>> op.inputs.volume_mesh.connect(my_volume_mesh)
- >>> my_degenerated_tets = dpf.Scoping()
- >>> op.inputs.degenerated_tets.connect(my_degenerated_tets)
- >>> my_non_degenerated_tets = dpf.Scoping()
- >>> op.inputs.non_degenerated_tets.connect(my_non_degenerated_tets)
- """
-
- def __init__(self, op: Operator):
- super().__init__(mapdl_split_on_facet_indices._spec().inputs, op)
- self._fields_container: Input[FieldsContainer] = Input(
- mapdl_split_on_facet_indices._spec().input_pin(0), 0, op, -1
- )
- self._inputs.append(self._fields_container)
- self._property_field_new_elements_to_old: Input[PropertyField] = Input(
- mapdl_split_on_facet_indices._spec().input_pin(1), 1, op, -1
- )
- self._inputs.append(self._property_field_new_elements_to_old)
- self._facet_indices: Input[PropertyField] = Input(
- mapdl_split_on_facet_indices._spec().input_pin(2), 2, op, -1
- )
- self._inputs.append(self._facet_indices)
- self._volume_mesh: Input[MeshedRegion] = Input(
- mapdl_split_on_facet_indices._spec().input_pin(3), 3, op, -1
- )
- self._inputs.append(self._volume_mesh)
- self._degenerated_tets: Input[Scoping] = Input(
- mapdl_split_on_facet_indices._spec().input_pin(185), 185, op, -1
- )
- self._inputs.append(self._degenerated_tets)
- self._non_degenerated_tets: Input[Scoping] = Input(
- mapdl_split_on_facet_indices._spec().input_pin(285), 285, op, -1
- )
- self._inputs.append(self._non_degenerated_tets)
-
- @property
- def fields_container(self) -> Input[FieldsContainer]:
- r"""Allows to connect fields_container input to the operator.
-
- Fields container to split, with generic number of labels (e.g. time, zone, complex...). Fields may have Elemental or ElementalNodal location; scoping ids are skin element ids.
-
- Returns
- -------
- input:
- An Input instance for this pin.
-
- Examples
- --------
- >>> from ansys.dpf import core as dpf
- >>> op = dpf.operators.result.mapdl_split_on_facet_indices()
- >>> op.inputs.fields_container.connect(my_fields_container)
- >>> # or
- >>> op.inputs.fields_container(my_fields_container)
- """
- return self._fields_container
-
- @property
- def property_field_new_elements_to_old(self) -> Input[PropertyField]:
- r"""Allows to connect property_field_new_elements_to_old input to the operator.
-
- This property field provides, for each new face element ID (in the scoping), the corresponding 3D volume element index (in the data) it has been extracted from. The 3D volume element ID can be found with the element scoping of the input mesh.
-
- Returns
- -------
- input:
- An Input instance for this pin.
-
- Examples
- --------
- >>> from ansys.dpf import core as dpf
- >>> op = dpf.operators.result.mapdl_split_on_facet_indices()
- >>> op.inputs.property_field_new_elements_to_old.connect(my_property_field_new_elements_to_old)
- >>> # or
- >>> op.inputs.property_field_new_elements_to_old(my_property_field_new_elements_to_old)
- """
- return self._property_field_new_elements_to_old
-
- @property
- def facet_indices(self) -> Input[PropertyField]:
- r"""Allows to connect facet_indices input to the operator.
-
- This property field gives, for each new face element ID (in the scoping), the corresponding face index on the source 3D volume element. The 3D volume element can be extracted from the previous output.
-
- Returns
- -------
- input:
- An Input instance for this pin.
-
- Examples
- --------
- >>> from ansys.dpf import core as dpf
- >>> op = dpf.operators.result.mapdl_split_on_facet_indices()
- >>> op.inputs.facet_indices.connect(my_facet_indices)
- >>> # or
- >>> op.inputs.facet_indices(my_facet_indices)
- """
- return self._facet_indices
-
- @property
- def volume_mesh(self) -> Input[MeshedRegion]:
- r"""Allows to connect volume_mesh input to the operator.
-
- The solid support.
-
- Returns
- -------
- input:
- An Input instance for this pin.
-
- Examples
- --------
- >>> from ansys.dpf import core as dpf
- >>> op = dpf.operators.result.mapdl_split_on_facet_indices()
- >>> op.inputs.volume_mesh.connect(my_volume_mesh)
- >>> # or
- >>> op.inputs.volume_mesh(my_volume_mesh)
- """
- return self._volume_mesh
-
- @property
- def degenerated_tets(self) -> Input[Scoping]:
- r"""Allows to connect degenerated_tets input to the operator.
-
- Elemental scoping of tet elements. If connected, the tets in the scoping are treated as degenerated tets (SOLID185), and the rest as non-degenerated tets (SOLID285). Pins 185 and 285 are mutually exclusionary (they cannot be connected at the same time), and if none of them is connected, all tets are treated as non-degenerated (SOLID285).
-
- Returns
- -------
- input:
- An Input instance for this pin.
-
- Examples
- --------
- >>> from ansys.dpf import core as dpf
- >>> op = dpf.operators.result.mapdl_split_on_facet_indices()
- >>> op.inputs.degenerated_tets.connect(my_degenerated_tets)
- >>> # or
- >>> op.inputs.degenerated_tets(my_degenerated_tets)
- """
- return self._degenerated_tets
-
- @property
- def non_degenerated_tets(self) -> Input[Scoping]:
- r"""Allows to connect non_degenerated_tets input to the operator.
-
- Elemental scoping of tet elements. If connected, the tets in the scoping are treated as non-degenerated tets (SOLID285), and the rest as degenerated tets (SOLID185). Pins 185 and 285 are mutually exclusionary (they cannot be connected at the same time), and if none of them is connected, all tets are treated as non-degenerated (SOLID285).
-
- Returns
- -------
- input:
- An Input instance for this pin.
-
- Examples
- --------
- >>> from ansys.dpf import core as dpf
- >>> op = dpf.operators.result.mapdl_split_on_facet_indices()
- >>> op.inputs.non_degenerated_tets.connect(my_non_degenerated_tets)
- >>> # or
- >>> op.inputs.non_degenerated_tets(my_non_degenerated_tets)
- """
- return self._non_degenerated_tets
-
-
-class OutputsMapdlSplitOnFacetIndices(_Outputs):
- """Intermediate class used to get outputs from
- mapdl_split_on_facet_indices operator.
-
- Examples
- --------
- >>> from ansys.dpf import core as dpf
- >>> op = dpf.operators.result.mapdl_split_on_facet_indices()
- >>> # Connect inputs : op.inputs. ...
- >>> result_fields_container = op.outputs.fields_container()
- """
-
- def __init__(self, op: Operator):
- super().__init__(mapdl_split_on_facet_indices._spec().outputs, op)
- self._fields_container: Output[FieldsContainer] = Output(
- mapdl_split_on_facet_indices._spec().output_pin(0), 0, op
- )
- self._outputs.append(self._fields_container)
-
- @property
- def fields_container(self) -> Output[FieldsContainer]:
- r"""Allows to get fields_container output of the operator
-
- Output splitted fields containter
-
- Returns
- -------
- output:
- An Output instance for this pin.
-
- Examples
- --------
- >>> from ansys.dpf import core as dpf
- >>> op = dpf.operators.result.mapdl_split_on_facet_indices()
- >>> # Get the output from op.outputs. ...
- >>> result_fields_container = op.outputs.fields_container()
- """
- return self._fields_container
diff --git a/src/ansys/dpf/core/operators/utility/__init__.py b/src/ansys/dpf/core/operators/utility/__init__.py
index 73eb3c36ef8..0d71a4509c5 100644
--- a/src/ansys/dpf/core/operators/utility/__init__.py
+++ b/src/ansys/dpf/core/operators/utility/__init__.py
@@ -83,6 +83,7 @@
from .split_in_for_each_range import split_in_for_each_range
from .strain_from_voigt import strain_from_voigt
from .strain_from_voigt_fc import strain_from_voigt_fc
+from .transpose_fields_container import transpose_fields_container
from .txt_file_to_dpf import txt_file_to_dpf
from .unitary_field import unitary_field
from .weighted_merge_fields_by_label import weighted_merge_fields_by_label
diff --git a/src/ansys/dpf/core/operators/utility/transpose_fields_container.py b/src/ansys/dpf/core/operators/utility/transpose_fields_container.py
new file mode 100644
index 00000000000..22ed1da9f81
--- /dev/null
+++ b/src/ansys/dpf/core/operators/utility/transpose_fields_container.py
@@ -0,0 +1,293 @@
+"""
+transpose_fields_container
+
+Autogenerated DPF operator classes.
+"""
+
+from __future__ import annotations
+from typing import TYPE_CHECKING
+
+from warnings import warn
+from ansys.dpf.core.dpf_operator import Operator
+from ansys.dpf.core.inputs import Input, _Inputs
+from ansys.dpf.core.outputs import Output, _Outputs
+from ansys.dpf.core.operators.specification import PinSpecification, Specification
+from ansys.dpf.core.config import Config
+from ansys.dpf.core.server_types import AnyServerType
+
+if TYPE_CHECKING:
+ from ansys.dpf.core.fields_container import FieldsContainer
+
+
+class transpose_fields_container(Operator):
+ r"""Transposes a fields container so that the fields’ scoping becomes the
+ container’s scoping and a chosen label (default: time) becomes the
+ fields’ scoping.
+
+ Input layout (example with time label, 2 body labels, 3 nodes): FC
+ labels: [time, body] Field 0: {time:1, body:1} -> scoping {n1, n2, n3},
+ data […] Field 1: {time:1, body:2} -> scoping {n4, n5}, data […] Field
+ 2: {time:2, body:1} -> scoping {n1, n2, n3}, data […] Field 3: {time:2,
+ body:2} -> scoping {n4, n5}, data […]
+
+ Output layout (transposed on time): FC labels: [Nodal, body] Field 0:
+ {Nodal:n1, body:1} -> scoping {t1, t2}, data [gathered from fields 0,2]
+ Field 1: {Nodal:n2, body:1} -> scoping {t1, t2}, data [gathered from
+ fields 0,2] Field 1: {Nodal:n3, body:1} -> scoping {t1, t2}, data
+ [gathered from fields 0,2] Field 2: {Nodal:n4, body:2} -> scoping {t1,
+ t2}, data [gathered from fields 1,3] Field 3: {Nodal:n5, body:2} ->
+ scoping {t1, t2}, data [gathered from fields 1,3] …
+
+ Each output field gathers one entity’s data across all values of the
+ transposed label from the input fields that share the same
+ non-transposed labels. All input fields sharing a labelspace where only
+ the transposed label changes must have the same scoping and location.
+
+
+ Inputs
+ ------
+ fields_container: FieldsContainer
+ It is assumed that the fields container consists of fields having the same scoping.
+ label: str, optional
+ fields container label to use as fields label (default is time)
+
+ Outputs
+ -------
+ fields_container: FieldsContainer
+
+ Examples
+ --------
+ >>> from ansys.dpf import core as dpf
+
+ >>> # Instantiate operator
+ >>> op = dpf.operators.utility.transpose_fields_container()
+
+ >>> # Make input connections
+ >>> my_fields_container = dpf.FieldsContainer()
+ >>> op.inputs.fields_container.connect(my_fields_container)
+ >>> my_label = str()
+ >>> op.inputs.label.connect(my_label)
+
+ >>> # Instantiate operator and connect inputs in one line
+ >>> op = dpf.operators.utility.transpose_fields_container(
+ ... fields_container=my_fields_container,
+ ... label=my_label,
+ ... )
+
+ >>> # Get output data
+ >>> result_fields_container = op.outputs.fields_container()
+ """
+
+ def __init__(self, fields_container=None, label=None, config=None, server=None):
+ super().__init__(
+ name="transpose_fields_container",
+ config=config,
+ server=server,
+ inputs_type=InputsTransposeFieldsContainer,
+ outputs_type=OutputsTransposeFieldsContainer,
+ )
+ if fields_container is not None:
+ self.inputs.fields_container.connect(fields_container)
+ if label is not None:
+ self.inputs.label.connect(label)
+
+ @staticmethod
+ def _spec() -> Specification:
+ description = r"""Transposes a fields container so that the fields’ scoping becomes the
+container’s scoping and a chosen label (default: time) becomes the
+fields’ scoping.
+
+Input layout (example with time label, 2 body labels, 3 nodes): FC
+labels: [time, body] Field 0: {time:1, body:1} -> scoping {n1, n2, n3},
+data […] Field 1: {time:1, body:2} -> scoping {n4, n5}, data […] Field
+2: {time:2, body:1} -> scoping {n1, n2, n3}, data […] Field 3: {time:2,
+body:2} -> scoping {n4, n5}, data […]
+
+Output layout (transposed on time): FC labels: [Nodal, body] Field 0:
+{Nodal:n1, body:1} -> scoping {t1, t2}, data [gathered from fields 0,2]
+Field 1: {Nodal:n2, body:1} -> scoping {t1, t2}, data [gathered from
+fields 0,2] Field 1: {Nodal:n3, body:1} -> scoping {t1, t2}, data
+[gathered from fields 0,2] Field 2: {Nodal:n4, body:2} -> scoping {t1,
+t2}, data [gathered from fields 1,3] Field 3: {Nodal:n5, body:2} ->
+scoping {t1, t2}, data [gathered from fields 1,3] …
+
+Each output field gathers one entity’s data across all values of the
+transposed label from the input fields that share the same
+non-transposed labels. All input fields sharing a labelspace where only
+the transposed label changes must have the same scoping and location.
+"""
+ spec = Specification(
+ description=description,
+ map_input_pin_spec={
+ 0: PinSpecification(
+ name="fields_container",
+ type_names=["fields_container"],
+ optional=False,
+ document=r"""It is assumed that the fields container consists of fields having the same scoping.""",
+ ),
+ 1: PinSpecification(
+ name="label",
+ type_names=["string"],
+ optional=True,
+ document=r"""fields container label to use as fields label (default is time)""",
+ ),
+ },
+ map_output_pin_spec={
+ 0: PinSpecification(
+ name="fields_container",
+ type_names=["fields_container"],
+ optional=False,
+ document=r"""""",
+ ),
+ },
+ )
+ return spec
+
+ @staticmethod
+ def default_config(server: AnyServerType = None) -> Config:
+ """Returns the default config of the operator.
+
+ This config can then be changed to the user needs and be used to
+ instantiate the operator. The Configuration allows to customize
+ how the operation will be processed by the operator.
+
+ Parameters
+ ----------
+ server:
+ Server with channel connected to the remote or local instance. When
+ ``None``, attempts to use the global server.
+
+ Returns
+ -------
+ config:
+ A new Config instance equivalent to the default config for this operator.
+ """
+ return Operator.default_config(name="transpose_fields_container", server=server)
+
+ @property
+ def inputs(self) -> InputsTransposeFieldsContainer:
+ """Enables to connect inputs to the operator
+
+ Returns
+ --------
+ inputs:
+ An instance of InputsTransposeFieldsContainer.
+ """
+ return self._inputs
+
+ @property
+ def outputs(self) -> OutputsTransposeFieldsContainer:
+ """Enables to get outputs of the operator by evaluating it
+
+ Returns
+ --------
+ outputs:
+ An instance of OutputsTransposeFieldsContainer.
+ """
+ return self._outputs
+
+
+class InputsTransposeFieldsContainer(_Inputs):
+ """Intermediate class used to connect user inputs to
+ transpose_fields_container operator.
+
+ Examples
+ --------
+ >>> from ansys.dpf import core as dpf
+ >>> op = dpf.operators.utility.transpose_fields_container()
+ >>> my_fields_container = dpf.FieldsContainer()
+ >>> op.inputs.fields_container.connect(my_fields_container)
+ >>> my_label = str()
+ >>> op.inputs.label.connect(my_label)
+ """
+
+ def __init__(self, op: Operator):
+ super().__init__(transpose_fields_container._spec().inputs, op)
+ self._fields_container: Input[FieldsContainer] = Input(
+ transpose_fields_container._spec().input_pin(0), 0, op, -1
+ )
+ self._inputs.append(self._fields_container)
+ self._label: Input[str] = Input(
+ transpose_fields_container._spec().input_pin(1), 1, op, -1
+ )
+ self._inputs.append(self._label)
+
+ @property
+ def fields_container(self) -> Input[FieldsContainer]:
+ r"""Allows to connect fields_container input to the operator.
+
+ It is assumed that the fields container consists of fields having the same scoping.
+
+ Returns
+ -------
+ input:
+ An Input instance for this pin.
+
+ Examples
+ --------
+ >>> from ansys.dpf import core as dpf
+ >>> op = dpf.operators.utility.transpose_fields_container()
+ >>> op.inputs.fields_container.connect(my_fields_container)
+ >>> # or
+ >>> op.inputs.fields_container(my_fields_container)
+ """
+ return self._fields_container
+
+ @property
+ def label(self) -> Input[str]:
+ r"""Allows to connect label input to the operator.
+
+ fields container label to use as fields label (default is time)
+
+ Returns
+ -------
+ input:
+ An Input instance for this pin.
+
+ Examples
+ --------
+ >>> from ansys.dpf import core as dpf
+ >>> op = dpf.operators.utility.transpose_fields_container()
+ >>> op.inputs.label.connect(my_label)
+ >>> # or
+ >>> op.inputs.label(my_label)
+ """
+ return self._label
+
+
+class OutputsTransposeFieldsContainer(_Outputs):
+ """Intermediate class used to get outputs from
+ transpose_fields_container operator.
+
+ Examples
+ --------
+ >>> from ansys.dpf import core as dpf
+ >>> op = dpf.operators.utility.transpose_fields_container()
+ >>> # Connect inputs : op.inputs. ...
+ >>> result_fields_container = op.outputs.fields_container()
+ """
+
+ def __init__(self, op: Operator):
+ super().__init__(transpose_fields_container._spec().outputs, op)
+ self._fields_container: Output[FieldsContainer] = Output(
+ transpose_fields_container._spec().output_pin(0), 0, op
+ )
+ self._outputs.append(self._fields_container)
+
+ @property
+ def fields_container(self) -> Output[FieldsContainer]:
+ r"""Allows to get fields_container output of the operator
+
+ Returns
+ -------
+ output:
+ An Output instance for this pin.
+
+ Examples
+ --------
+ >>> from ansys.dpf import core as dpf
+ >>> op = dpf.operators.utility.transpose_fields_container()
+ >>> # Get the output from op.outputs. ...
+ >>> result_fields_container = op.outputs.fields_container()
+ """
+ return self._fields_container
diff --git a/src/ansys/dpf/gatebin/Ans.Dpf.GrpcClient.dll b/src/ansys/dpf/gatebin/Ans.Dpf.GrpcClient.dll
index 4f2723e6eabf080f8ecfba132b6e43f8ecd6767b..a7e1626a40dce31bcfc406c48cdf1e057c0d3533 100644
GIT binary patch
delta 74118
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 |