Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix combination of skin extraction with scoping #673

Merged
merged 34 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
441c44e
Fix combination of skin extraction with scoping
janvonrickenbach Jul 30, 2024
d681a5b
Don't export skin scoping separately
janvonrickenbach Jul 31, 2024
431c7fd
Simplify logic with forward operators
janvonrickenbach Aug 5, 2024
8ab7fe2
Fix problem with forward operator
janvonrickenbach Aug 6, 2024
75087b1
Remove view of selection workflow
janvonrickenbach Aug 6, 2024
2962315
Fix server assignment for forwarding operators
janvonrickenbach Aug 6, 2024
2a15039
Update test assertions
janvonrickenbach Aug 6, 2024
13cb6fd
Cleanup
janvonrickenbach Aug 6, 2024
e524c62
Run pre commit on all files
janvonrickenbach Aug 6, 2024
7e74ba1
Add new tests that checks the exact values of on the skin
janvonrickenbach Aug 8, 2024
a875ac9
Add tests for principal and equivalent results
janvonrickenbach Aug 8, 2024
460996e
Add tests for displacement
janvonrickenbach Aug 13, 2024
7a278d4
Simplify test code
janvonrickenbach Aug 13, 2024
78cc56a
Cleanup
janvonrickenbach Aug 13, 2024
48211c3
Cleanup and more comments
janvonrickenbach Aug 14, 2024
37c9a40
Fix some tests
janvonrickenbach Aug 14, 2024
831abbf
Fix some tests
janvonrickenbach Aug 14, 2024
a1dd1cb
Fix some tests
janvonrickenbach Aug 14, 2024
5381f06
Fix some tests
janvonrickenbach Aug 14, 2024
37f6ba8
Fix some tests
janvonrickenbach Aug 14, 2024
2aeb1b9
Add cyclic tests
janvonrickenbach Aug 14, 2024
b590bfc
Add tests for cyclic simulations
janvonrickenbach Aug 14, 2024
dc5a97b
Merge branch 'master' into jvonrick/fix_skin_extraction_with_selection
janvonrickenbach Aug 14, 2024
5424196
Fix checks for server version
janvonrickenbach Aug 15, 2024
a2d792f
Merge remote-tracking branch 'origin/jvonrick/fix_skin_extraction_wit…
janvonrickenbach Aug 15, 2024
67ff7eb
New workflow is only supported for server versions 8_0 and higher
janvonrickenbach Aug 15, 2024
084af72
Fix check for server version
janvonrickenbach Aug 15, 2024
f007436
Skip tests for older server versions
janvonrickenbach Aug 15, 2024
4686a92
Fix result comparison for older version
janvonrickenbach Aug 15, 2024
aefadc3
Fix getting the solid mesh element ids for older versions
janvonrickenbach Aug 15, 2024
bbc2d4f
Add tests for more complicated skin geometries
janvonrickenbach Aug 22, 2024
1545e62
Small cosmetic improvements
janvonrickenbach Aug 26, 2024
085dfaa
Adapt to backend changes: solid to skin mapping operator now propagat…
janvonrickenbach Aug 27, 2024
dae7b64
Skip principal strain tests for server version before 9.0
janvonrickenbach Aug 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/ansys/dpf/post/harmonic_mechanical_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ def _get_result_workflow(
equivalent_op = self._model.operator(name="eqv_fc")
wf.add_operator(operator=equivalent_op)
# If a strain result, change the location now
# TBD: Why do we put the the equivalent operator
# before the averaging operator for strain results?
Comment on lines +128 to +129
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @janvonrickenbach,
If I remember correctly, it should be because this is what is done in the Mechanical workflow.

Copy link
Contributor Author

@janvonrickenbach janvonrickenbach Aug 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is also what Camille mentioned. I will add a note in the upcomping refactoring PR.

if (
average_op is not None
and category == ResultCategory.equivalent
Expand Down
68 changes: 49 additions & 19 deletions src/ansys/dpf/post/selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
class _WfNames:
data_sources = "data_sources"
scoping = "scoping"
skin_input_mesh = "skin_input_mesh"
final_scoping = "final_scoping"
scoping_a = "scoping_a"
scoping_b = "scoping_b"
Expand Down Expand Up @@ -404,9 +405,24 @@ def select_skin(
be returned by the Operator ``operators.metadata.is_cyclic``. Used to get the skin
on the expanded mesh.
"""
op = operators.mesh.skin(server=self._server)
self._selection.add_operator(op)
mesh_input = op.inputs.mesh

def connect_any(operator_input, input_value):
# Workaround to connect any inputs: see
# https://github.com/ansys/pydpf-core/issues/1670
operator_input._operator().connect(operator_input._pin, input_value)

skin_operator = operators.mesh.skin(server=self._server)
self._selection.add_operator(skin_operator)

initial_mesh_fwd_op = operators.utility.forward(server=self._server)
self._selection.set_input_name(
_WfNames.initial_mesh, initial_mesh_fwd_op.inputs.any
)
self._selection.add_operator(initial_mesh_fwd_op)

skin_operator_input_mesh_fwd_op = operators.utility.forward(server=self._server)
connect_any(skin_operator_input_mesh_fwd_op.inputs.any, initial_mesh_fwd_op)
self._selection.add_operator(skin_operator_input_mesh_fwd_op)

if _is_model_cyclic(is_model_cyclic):
mesh_provider_cyc = operators.mesh.mesh_provider()
Expand Down Expand Up @@ -436,13 +452,11 @@ def select_skin(
server=self._server,
)
self._selection.add_operator(mesh_by_scop_op)
op.inputs.mesh.connect(mesh_by_scop_op)
skin_operator_input_mesh_fwd_op.inputs.any(mesh_by_scop_op)
else:
op.inputs.mesh.connect(mesh_provider_cyc)
self._selection.set_input_name(
_WfNames.initial_mesh, mesh_provider_cyc, 100
) # hack
mesh_input = None
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why mesh_input was set to None here. It is checked on line 459, but I just replaced this checked with a not _is_model_cyclic check.

skin_operator_input_mesh_fwd_op.inputs.any(mesh_provider_cyc)

mesh_provider_cyc.connect(100, initial_mesh_fwd_op.outputs.any)

elif elements is not None:
if not isinstance(elements, Scoping):
Expand All @@ -453,34 +467,50 @@ def select_skin(
scoping=elements, server=self._server
)
self._selection.add_operator(mesh_by_scop_op)
mesh_input = mesh_by_scop_op.inputs.mesh
op.inputs.mesh.connect(mesh_by_scop_op)
skin_operator_input_mesh_fwd_op.inputs.any(mesh_by_scop_op.outputs.mesh)
connect_any(mesh_by_scop_op.inputs.mesh, initial_mesh_fwd_op.outputs.any)

if mesh_input is not None:
self._selection.set_input_name(_WfNames.initial_mesh, mesh_input)
if not _is_model_cyclic(is_model_cyclic):
if location == result_native_location:
self._selection.set_output_name(_WfNames.mesh, op.outputs.mesh)
self._selection.set_output_name(_WfNames.skin, op.outputs.mesh)
self._selection.set_output_name(
_WfNames.mesh, skin_operator.outputs.mesh
)

self._selection.set_output_name(_WfNames.skin, skin_operator.outputs.mesh)
if location == locations.nodal and result_native_location == locations.nodal:
self._selection.set_output_name(
_WfNames.scoping, op.outputs.nodes_mesh_scoping
_WfNames.scoping, skin_operator.outputs.nodes_mesh_scoping
)

elif not _is_model_cyclic(is_model_cyclic) and (
result_native_location == locations.elemental
or result_native_location == locations.elemental_nodal
):
transpose_op = operators.scoping.transpose(
mesh_scoping=op.outputs.nodes_mesh_scoping, server=self._server
mesh_scoping=skin_operator.outputs.nodes_mesh_scoping,
server=self._server,
)
self._selection.add_operator(transpose_op)
self._selection.set_input_name(
_WfNames.initial_mesh, transpose_op.inputs.meshed_region
connect_any(
transpose_op.inputs.meshed_region, initial_mesh_fwd_op.outputs.any
)
self._selection.set_output_name(
_WfNames.scoping, transpose_op.outputs.mesh_scoping_as_scoping
)

connect_any(
skin_operator.inputs.mesh, skin_operator_input_mesh_fwd_op.outputs.any
)

# Provide the input mesh from which a skin was generated
# This is useful because the skin_mesh contains the mapping of
# skin elements to the original mesh element indices, which is used
# by the solid_to_skin_fc operator. The skin_input_mesh can be passed
# to the solid_to_skin_fc operator to ensure that the mapping is correct.
self._selection.set_output_name(
_WfNames.skin_input_mesh, skin_operator_input_mesh_fwd_op.outputs.any
)

def select_with_scoping(self, scoping: Scoping):
"""Directly sets the scoping as the spatial selection.

Expand Down
16 changes: 14 additions & 2 deletions src/ansys/dpf/post/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ def split_mesh_by_properties(
List[elemental_properties],
Dict[elemental_properties, Union[int, List[int]]],
],
) -> Meshes:
) -> Union[Mesh, Meshes, None]:
"""Splits the simulation Mesh according to properties and returns it as Meshes.

Parameters
Expand Down Expand Up @@ -1021,12 +1021,24 @@ def _create_averaging_operator(
) # To keep for retro-compatibility
else:
inpt = first_average_op.inputs.mesh

if self._model._server.meet_version("8.0"):
# solid mesh_input only supported for server version
# 8.0 and up
average_wf.set_input_name(
_WfNames.skin_input_mesh, first_average_op.inputs.solid_mesh
)
average_wf.set_input_name(_WfNames.skin, inpt)
average_wf.connect_with(
selection.spatial_selection._selection,
output_input_names={_WfNames.skin: _WfNames.skin},
)

average_wf.connect_with(
selection.spatial_selection._selection,
output_input_names={_WfNames.skin_input_mesh: _WfNames.skin_input_mesh},
)

if location == locations.nodal:
average_op = self._model.operator(name="to_nodal_fc")
elif location == locations.elemental:
Expand All @@ -1035,6 +1047,6 @@ def _create_averaging_operator(
average_op.connect(0, forward, 0)
else:
first_average_op = average_op

# Todo: returns None if location is ElementalNodal and skin is active
if first_average_op is not None and average_op is not None:
return (first_average_op, average_op)
7 changes: 7 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
pytest as a sesson fixture
"""
import os
import pathlib
import re

from ansys.dpf.core.check_version import get_server_version, meets_version
Expand Down Expand Up @@ -44,6 +45,12 @@ def get_lighting():
running_docker = os.environ.get("DPF_DOCKER", False)


def save_screenshot(dataframe, suffix=""):
"""Save a screenshot of a dataframe plot, with the current test name."""
test_path = pathlib.Path(os.environ.get("PYTEST_CURRENT_TEST"))
dataframe.plot(screenshot=f"{'_'.join(test_path.name.split('::'))}_{suffix}.jpeg")


def resolve_test_file(basename, additional_path=""):
"""Resolves a test file's full path based on the base name and the
environment.
Expand Down
Loading
Loading