Skip to content

Commit

Permalink
update evaluate_failure_criteria to support the different types of la…
Browse files Browse the repository at this point in the history
…y-up models (ACP, RST, MIXED)

Some cosmetic changes.
  • Loading branch information
roosre committed Nov 24, 2023
1 parent 28c53bd commit 1fb4700
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 11 deletions.
25 changes: 21 additions & 4 deletions doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,17 @@ to implement custom failure criteria and computation.

Provides developer installation and usage information.

The minimum set of inputs to run a post-processing for composites is the result file(s) of an

Check failure on line 49 in doc/source/index.rst

View workflow job for this annotation

GitHub Actions / vale

[vale] doc/source/index.rst#L49

[Google.OptionalPlurals] Don't use plurals in parentheses such as in 'file(s)'.
Raw output
{"message": "[Google.OptionalPlurals] Don't use plurals in parentheses such as in 'file(s)'.", "location": {"path": "doc/source/index.rst", "range": {"start": {"line": 49, "column": 81}}}, "severity": "ERROR"}
MAPDL solution and a material file (matml) which was generated by Engineering Data.

Check failure on line 50 in doc/source/index.rst

View workflow job for this annotation

GitHub Actions / vale

[vale] doc/source/index.rst#L50

[Vale.Spelling] Did you really mean 'matml'?
Raw output
{"message": "[Vale.Spelling] Did you really mean 'matml'?", "location": {"path": "doc/source/index.rst", "range": {"start": {"line": 50, "column": 37}}}, "severity": "ERROR"}
Lay-up files from ACP are optional and only required for some advanced operations. Refer to
:ref:`Limitations`.

Key features
''''''''''''

Here are some key features of PyDPF Composites:

* Post-processing of layered shell and solid elements, whether they were preprocessed by ACP or not.
* Failure criteria evaluation as shown in :ref:`Composite failure analysis <sphx_glr_examples_gallery_examples_001_failure_operator_example.py>`.
* A :class:`.SamplingPoint` class for extracting and visualizing a result over the entire thickness of a laminate as shown in
:ref:`Sampling point <sphx_glr_examples_gallery_examples_002_sampling_point_example.py>`.
Expand All @@ -65,11 +71,22 @@ Here are some key features of PyDPF Composites:

Limitations
'''''''''''
- Layered elements (section data) that have not been preprocessed with ACP are not supported.
For information on converting legacy models, see `Import of Legacy Mechanical APDL Composite Models`_
in the Ansys Help.
- Only the Mechanical APDL solver is supported.

- The following operators and features are only supported if the model was preprocessed with ACP
and if the corresponding lay-up definition file is passed to the :class:`.CompositeModel`:
- The evaluation of the failure criteria for sandwich (:class:`FaceSheetWrinklingCriterion`, :class:`ShearCrimpingCriterion`)
for solid elements. Layered shell elements are always supported.
- The computation of interlaminar normal stresses (s3) for layered shell elements.
Otherwise, s3 is zero. This also affects 3D failure criteria which use s3, such as Puck 3D.
This limitation does not affect (layered) solid elements.
- The support of variable materials and material fields. Without ACP, only the
temperature is considered for the evaluation of variable material properties.
- Global plies, ply-wise scoping, and ply-wise failure criteria. Layer-wise post-processing is

Check failure on line 84 in doc/source/index.rst

View workflow job for this annotation

GitHub Actions / vale

[vale] doc/source/index.rst#L84

[Google.LyHyphens] ' ply-' doesn't need a hyphen.
Raw output
{"message": "[Google.LyHyphens] ' ply-' doesn't need a hyphen.", "location": {"path": "doc/source/index.rst", "range": {"start": {"line": 84, "column": 40}}}, "severity": "ERROR"}
always supported thanks to the scripting
- Plotting results on the reference surface of a laminate.

Note: MAPDL models which have not been preprocessed with ACP can be converted. For more
information, see `Import of Legacy Mechanical APDL Composite Models`_ in the Ansys Help.

.. _Ansys Workbench: https://download.ansys.com/Current%20Release
.. _Import of Legacy Mechanical APDL Composite Models: https://ansyshelp.ansys.com/account/secured?returnurl=/Views/Secured/corp/v231/en/acp_ug/acp_import_legacy_APDL_comp.html
Expand Down
4 changes: 2 additions & 2 deletions examples/008_assembly_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
irf_field.plot()

# %%
# Plot IRF
# ~~~~~~~~
# Plot IRF on The Reference Surface
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot the maximum IRF on the reference surface
if version_equal_or_later(server, "8.0"):
irf_field = output_all_elements.get_field(
Expand Down
34 changes: 29 additions & 5 deletions src/ansys/dpf/composites/_composite_model_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
ElementInfo,
LayerProperty,
LayupPropertiesProvider,
LayupModelModelContextType,
add_layup_info_to_mesh,
get_element_info_provider,
)
Expand Down Expand Up @@ -177,7 +178,15 @@ def __init__(
rst_stream_provider=self._get_rst_streams_provider()
)

# self._layup_provider.outputs.layup_model_context_type.get_data() does not work because
# int32 is not supported in the Python API. See bug 946754.
# 218 is the pin of LayupModelContext
if version_equal_or_later(self._server, "8.0"):
self.layup_model_type = LayupModelModelContextType(self._layup_provider.get_output(218, int))
else:
self.layup_model_type = LayupModelModelContextType.ACP if len(composite_files.composite) > 0 else LayupModelModelContextType.NOT_AVAILABLE

if self._supports_reference_surface_operators():
self._reference_surface_and_mapping_field = _get_reference_surface_and_mapping_field(
data_sources=self.data_sources.composite, unit_system=self._unit_system
)
Expand Down Expand Up @@ -334,8 +343,6 @@ def evaluate_failure_criteria(
# is irrelevant for cases without a ply scope, we set it to False here.
write_data_for_full_element_scope = False

has_layup_provider = len(self._composite_files.composite) > 0

# configure primary scoping
scope_config = dpf.DataTree()
if time_in:
Expand Down Expand Up @@ -400,7 +407,12 @@ def evaluate_failure_criteria(
self._get_rst_streams_provider()
)
evaluate_failure_criterion_per_scope_op.inputs.mesh(self.get_mesh())
evaluate_failure_criterion_per_scope_op.inputs.has_layup_provider(has_layup_provider)
if version_equal_or_later(self._server, "8.0"):
evaluate_failure_criterion_per_scope_op.inputs.layup_model_context_type(self.layup_model_type.value)
else:
evaluate_failure_criterion_per_scope_op.inputs.has_layup_provider(
self.layup_model_type != LayupModelModelContextType.NOT_AVAILABLE
)
evaluate_failure_criterion_per_scope_op.inputs.section_data_container(
self._layup_provider.outputs.section_data_container
)
Expand All @@ -425,7 +437,8 @@ def evaluate_failure_criteria(
self.material_operators.material_support_provider.outputs
)

if has_layup_provider and write_data_for_full_element_scope:
if (self.layup_model_type != LayupModelModelContextType.NOT_AVAILABLE and
write_data_for_full_element_scope):
add_default_data_op = dpf.Operator("composite::add_default_data")
add_default_data_op.inputs.requested_element_scoping(chunking_generator.outputs)
add_default_data_op.inputs.time_id(
Expand Down Expand Up @@ -462,7 +475,7 @@ def evaluate_failure_criteria(
"No output is generated! Please check the scope (element and ply ids)."
)

if version_equal_or_later(self._server, "8.0"):
if self._supports_reference_surface_operators():
self._map_to_reference_surface_operator.inputs.min_container(
min_merger.outputs.merged_fields_container()
)
Expand Down Expand Up @@ -743,3 +756,14 @@ def _first_composite_definition_label_if_only_one(self) -> str:
f"Multiple composite definition keys exist: {self.composite_definition_labels}. "
f"Specify a key explicitly."
)

# Whether the reference surface operators are available or supported by the server
def _supports_reference_surface_operators(self):
if not version_equal_or_later(self._server, "8.0"):
return False

if (self.layup_model_type == LayupModelModelContextType.ACP or
self.layup_model_type == LayupModelModelContextType.MIXED):
return True

return False
2 changes: 2 additions & 0 deletions src/ansys/dpf/composites/layup_info/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
ElementInfo,
ElementInfoProvider,
LayupPropertiesProvider,
LayupModelModelContextType,
get_all_analysis_ply_names,
get_analysis_ply_index_to_name_map,
get_dpf_material_id_by_analyis_ply_map,
Expand All @@ -23,6 +24,7 @@
"LayerProperty",
"LayupProperty",
"LayupPropertiesProvider",
"LayupModelModelContextType",
"get_all_analysis_ply_names",
"get_analysis_ply_index_to_name_map",
"get_dpf_material_id_by_analyis_ply_map",
Expand Down
9 changes: 9 additions & 0 deletions src/ansys/dpf/composites/layup_info/_layup_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from dataclasses import dataclass
from typing import Any, Optional, Union, cast
from warnings import warn
from enum import Enum

import ansys.dpf.core as dpf
from ansys.dpf.core import DataSources, MeshedRegion, Operator, PropertyField
Expand Down Expand Up @@ -60,6 +61,14 @@ def _get_analysis_ply(mesh: MeshedRegion, name: str, skip_check: bool = False) -
return mesh.property_field(property_field_name)


# Note: must be in sync with the LayupModelContextTypeEnum in the C++ code
class LayupModelModelContextType(Enum):
NOT_AVAILABLE = 0 # no layup data
ACP = 1 # lay-up data was read from ACP
RST = 2 # lay-up data was read from RST
MIXED = 3 # lay-up data was read from RST and ACP


@dataclass(frozen=True)
class ElementInfo:
"""Provides lay-up information for an element.
Expand Down

0 comments on commit 1fb4700

Please sign in to comment.