ansys / pydpf-core

Data Processing Framework - Python Core
http://dpf.docs.pyansys.com/
MIT License
67 stars 23 forks source link

DpfPlotter.add_field does not handle shell layers #1435

Open aukselis-c1connections opened 6 months ago

aukselis-c1connections commented 6 months ago

Before submitting the issue

Description of the bug

I have an LS-DYNA results database with membrane elements that have x, y, xy output for stresses. I would like to calculate the von misses stress from the stress results on these elements for all time steps and then take a maximum envelope of the calculated results over all time steps for each node/element. When I use min_max_over_time_by_entity operator do that for me, the results cannot be plotted with the following error:

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Cell In[19], [line 8](vscode-notebook-cell:?execution_count=19&line=8)
      [4](vscode-notebook-cell:?execution_count=19&line=4) eqv = ops.invariant.von_mises_eqv_fc(stress_op)
      [6](vscode-notebook-cell:?execution_count=19&line=6) max_eqv = ops.min_max.min_max_over_time_by_entity(eqv).outputs.max()
----> [8](vscode-notebook-cell:?execution_count=19&line=8) max_eqv.plot(show_edges=False, show_displacement=True)

File [c:\Users\USER\miniconda3\envs\py39\lib\site-packages\ansys\dpf\core\fields_container.py:507](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/fields_container.py:507), in FieldsContainer.plot(self, label_space, **kwargs)
    [505](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/fields_container.py:505) fields = self.get_fields(label_space=label_space)
    [506](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/fields_container.py:506) for f in fields:
--> [507](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/fields_container.py:507)     plt.add_field(field=f, **kwargs)
    [508](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/fields_container.py:508) plt.show_figure(**kwargs)

File [c:\Users\USER\miniconda3\envs\py39\lib\site-packages\ansys\dpf\core\plotter.py:623](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:623), in DpfPlotter.add_field(self, field, meshed_region, show_max, show_min, label_text_size, label_point_size, deform_by, scale_factor, **kwargs)
    [573](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:573) def add_field(
    [574](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:574)     self,
    [575](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:575)     field,
   (...)
    [583](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:583)     **kwargs,
    [584](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:584) ):
    [585](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:585)     """Add a field containing data to the plotter.
    [586](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:586) 
    [587](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:587)     A meshed_region to plot on can be added.
   (...)
    [621](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:621) 
    [622](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:622)     """
--> [623](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:623)     self._internal_plotter.add_field(
    [624](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:624)         field=field,
    [625](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:625)         meshed_region=meshed_region,
    [626](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:626)         show_max=show_max,
    [627](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:627)         show_min=show_min,
    [628](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:628)         label_text_size=label_text_size,
    [629](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:629)         label_point_size=label_point_size,
    [630](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:630)         deform_by=deform_by,
    [631](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:631)         scale_factor=scale_factor,
    [632](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:632)         as_linear=True,
    [633](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:633)         **kwargs,
    [634](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:634)     )

File [c:\Users\USER\miniconda3\envs\py39\lib\site-packages\ansys\dpf\core\plotter.py:263](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:263), in _PyVistaPlotter.add_field(self, field, meshed_region, show_max, show_min, label_text_size, label_point_size, deform_by, scale_factor, scale_factor_legend, as_linear, **kwargs)
    [261](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:261) if location != locations.overall:
    [262](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:262)     ind, mask = mesh_location.map_scoping(field.scoping)
--> [263](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:263)     overall_data[ind] = field.data[mask]
    [264](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:264) else:
    [265](file:///C:/Users/USER/miniconda3/envs/py39/lib/site-packages/ansys/dpf/core/plotter.py:265)     overall_data[:] = field.data[0]

IndexError: boolean index did not match indexed array along dimension 0; dimension is 6132 but corresponding boolean dimension is 2044

Steps To Reproduce

Here is the output I get when I print the model after loading the results.

DPF Model
------------------------------
Unknown analysis
Unit system: NMM: mm, ton, N, s, mV, mA, degC
Physics Type: Unknown
Available results:
     -  global_kinetic_energy: TimeFreq_steps Global Kinetic Energy
     -  global_internal_energy: TimeFreq_steps Global Internal Energy
     -  global_total_energy: TimeFreq_steps Global Total Energy
     -  global_velocity: TimeFreq_steps Global Velocity
     -  initial_coordinates: Nodal Initial Coordinates
     -  coordinates: Nodal Coordinates
     -  velocity: Nodal Velocity      
     -  acceleration: Nodal Acceleration
     -  stress: Elemental Stress      
     -  stress_von_mises: Elemental Stress Von Mises
     -  plastic_strain_eqv: Elemental Plastic Strain Eqv
     -  thickness: Elemental Thickness
     -  shell_x_membrane_resultant: Elemental Shell X Membrane Resultant
     -  shell_y_membrane_resultant: Elemental Shell Y Membrane Resultant
     -  shell_xy_membrane_resultant: Elemental Shell Xy Membrane Resultant
     -  shell_x_bending_resultant: Elemental Shell X Bending Resultant
     -  shell_y_bending_resultant: Elemental Shell Y Bending Resultant
     -  shell_xy_bending_resultant: Elemental Shell Xy Bending Resultant
     -  shell_x_shear_resultant: Elemental Shell X Shear Resultant
     -  shell_y_shear_resultant: Elemental Shell Y Shear Resultant
     -  displacement: Nodal Displacement
------------------------------
DPF  Meshed Region: 
  2146 nodes 
  2044 elements 
  Unit: mm 
  With shell (2D) elements
------------------------------
DPF  Time/Freq Support: 
  Number of sets: 27862 
Cumulative     Time (s)       LoadStep       Substep         
1              0.000000       1              1               
2              0.000001       2              1               
3              0.000002       3              1               
4              0.000003       4              1               
5              0.000004       5              1    
...
27861          0.027864       27861          1               
27862          0.027864       27862          1               

I then use these commands to achieve what I want.

stress = model.results.stress
stress_op = stress.on_all_time_freqs()
eqv = ops.invariant.von_mises_eqv_fc(stress_op)
max_eqv = ops.min_max.min_max_over_time_by_entity(eqv).outputs.max()
max_eqv.plot(show_edges=False, show_displacement=True)

The same procedure with solid elements works without issue.

Is this a bug or I am doing something wrong.

Which Operating System causes the issue?

Windows

Which DPF/Ansys version are you using?

Ansys 2024 R1

Which Python version causes the issue?

3.9

Installed packages

Package Version Editable project location


aiohttp 3.8.5 aiosignal 1.3.1 amqp 5.1.1 ansys-api-mapdl 0.5.1 ansys-api-platform-instancemanagement 1.0.0b3 ansys-dpf-core 0.11.0 ansys-dpf-post 0.5.0 ansys-mapdl-core 0.65.0 ansys-mapdl-reader 0.52.16 ansys-platform-instancemanagement 1.1.1 ansys-tools-path 0.2.6 appdirs 1.4.4 asgiref 3.7.2 asttokens 2.2.1 async-timeout 4.0.3 attrs 23.1.0 backcall 0.2.0 billiard 4.1.0 black 23.3.0 cachetools 5.3.1 cad-to-shapely 0.3.1 celery 5.3.4 certifi 2023.5.7 charset-normalizer 3.1.0 click 8.1.7 click-didyoumean 0.3.0 click-plugins 1.1.1 click-repl 0.3.0 codecov 2.1.13 colorama 0.4.6 colorcet 3.0.1 comm 0.1.3 contourpy 1.1.0 coverage 7.2.7 cssbeautifier 1.14.9 cycler 0.11.0 databind.core 4.4.0 databind.json 4.4.0 debugpy 1.6.7 decorator 5.1.1 Deprecated 1.2.14 Django 4.2.5 django-advanced-filters 2.0.0 django-debug-toolbar 4.2.0 django-json-widget 1.1.1 django-ratelimit-backend 2.0 django-turnstile 0.1.0 djlint 1.34.0 dnspython 2.4.2 docopt 0.6.2 docspec 2.2.1 docspec-python 2.2.1 docstring-parser 0.11 EditorConfig 0.12.3 et-xmlfile 1.1.0 eventlet 0.33.3 exceptiongroup 1.1.1 executing 1.2.0 ezdxf 1.1.3 fastjsonschema 2.19.0 fonttools 4.40.0 frozenlist 1.4.0 future 0.18.3 geomdl 5.3.1 google-api-core 2.11.1 google-api-python-client 2.91.0 google-auth 2.21.0 google-auth-httplib2 0.1.0 googleapis-common-protos 1.59.1 greenlet 3.0.1 grpcio 1.56.0 html-tag-names 0.1.2 html-void-elements 0.1.0 httplib2 0.22.0 idna 3.4 imageio 2.28.0 imageio-ffmpeg 0.4.9 importlib-metadata 6.7.0 importlib-resources 5.12.0 iniconfig 2.0.0 ipykernel 6.23.3 ipython 8.14.0 ipywidgets 8.1.0 jedi 0.18.2 Jinja2 3.1.2 joblib 1.3.1 jsbeautifier 1.14.9 json5 0.9.14 jsonschema 4.20.0 jsonschema-specifications 2023.11.2 jupyter_client 8.3.0 jupyter_core 5.3.1 jupyterlab-widgets 3.0.8 kiwisolver 1.4.4 kombu 5.3.2 latex2mathml 3.76.0 llvmlite 0.41.1 lxml 4.9.3 Markdown 3.4.4 markdown-alerts 0.1 markdown-it-py 3.0.0 MarkupSafe 2.1.3 matplotlib 3.8.2 matplotlib-inline 0.1.6 mdurl 0.1.2 meshio 5.3.4 Metatools 0.1.1 more-itertools 10.1.0 mpmath 1.3.0 msgpack-python 0.5.6 multidict 6.0.4 mypy-extensions 1.0.0 nbformat 5.9.2 nest-asyncio 1.5.6 nr-date 2.0.0 nr-stream 1.1.5 nr.util 0.8.12 numba 0.58.1 numpy 1.25.0 openpyxl 3.1.2 packaging 23.1 pandas 2.0.3 param 1.13.0 parso 0.8.3 pathspec 0.11.1 pickleshare 0.7.5 Pillow 9.5.0 pip 23.1.2 pipreqs 0.4.13 platformdirs 3.8.0 plotext 5.2.8 plotly 5.18.0 pluggy 1.2.0 pooch 1.7.0 prompt-toolkit 3.0.38 protobuf 3.20.3 protoc-gen-swagger 0.1.0 psutil 5.9.8 psycopg2 2.9.7 pure-eval 0.2.2 pyansys-tools-versioning 0.4.0 pyasn1 0.5.1 pyasn1-modules 0.3.0 pyct 0.5.0 pydoc-markdown 4.8.2 Pygments 2.15.1 pyiges 0.3.0 pyparsing 3.1.1 pytest 7.4.0 pytest-cov 4.1.0 python-dateutil 2.8.2 python-decouple 3.8 pytz 2023.3 pyvista 0.43.3 pywin32 306 PyYAML 6.0 pyzmq 25.1.0 redis 5.0.1 referencing 0.31.1 regex 2023.8.8 repoze.lru 0.7 requests 2.31.0 rhino-shapley-interop 0.0.4 rhino3dm 8.0.0b3 rich 13.7.0 Routes 2.5.1 rpds-py 0.13.2 rsa 4.9 scikit-learn 1.3.0 scipy 1.10.1 scooby 0.9.2 sectionproperties 3.1.2 setuptools 69.1.0 shapely 2.0.2 simplejson 3.19.2 six 1.16.0 sqlparse 0.4.4 stack-data 0.6.2 sympy 1.12 tenacity 8.2.3 threadpoolctl 3.1.0 tomli 2.0.1 tomli_w 1.0.0 tornado 6.3.2 tqdm 4.65.0 traitlets 5.9.0 trame 3.5.2 trame-client 2.16.1 trame-plotly 3.0.1 trame-server 2.17.2 trame-vtk 2.5.8 trame-vuetify 2.3.1 triangle 20230923 typeapi 2.1.1 typing_extensions 4.7.0 tzdata 2023.3 uritemplate 4.1.1 urllib3 1.26.18 vine 5.0.0 vtk 9.2.6 watchdog 3.0.0 wcwidth 0.2.6 wheel 0.38.4 widgetsnbextension 4.0.8 wrapt 1.15.0 wslink 1.12.4 XlsxWriter 3.1.4 xlwings 0.30.11 yapf 0.40.1 yarg 0.1.9 yarl 1.9.2 zipp 3.17.0

PProfizi commented 6 months ago

Hi @aukselis-c1connections, could you please share what the field obtained looks like? With a print(max_eqv)

aukselis-c1connections commented 6 months ago

Hi @PProfizi,

Sure here it is:

DPF  Fields Container
  with 1 field(s)
  defined on labels: unknown 

  with:
  - field 0 {unknown:  1} with Elemental location, 1 components and 2044 entities.
aukselis-c1connections commented 6 months ago

I am uploading a reduced output file where the issue is present. Perhaps it can help to debug. d3part.zip

PProfizi commented 6 months ago

Hi @aukselis-c1connections I was able to reproduce the error. I'll look into resolving it.

PProfizi commented 6 months ago

Hi @aukselis-c1connections, I found out the culprit is the FieldsContainer.plot method. Since the final object you want to plot is a FieldsContainer containing only a single field, what you can do is plot this field with: max_eqv[0].plot() This worked on my end: image

What you can do to improve the plot is set the Field.unit and the Field.name.

I'll keep investigating why the FieldsContainer.plot() failed in your case.

PProfizi commented 6 months ago

Hi @aukselis-c1connections I now know what the original issue is. When requesting eqv, what you get are scalar fields but with 3 values per element instead of one. One for each shell layer. There is an issue in how FieldsContainer.plot handles layered results. I'll keep looking into it.

What you can do for now is use ansys.dpf.core.operators.utility.change_shell_layers to pick a layer to plot:

eqv = ops.utility.change_shell_layers(fields_container=eqv, e_shell_layer=1)

or use Field.plot as indicated above. A third option is to request a specific layer from the start when using result operators such as stress by using the shell_layer argument.

aukselis-c1connections commented 6 months ago

Hi @PProfizi,

This seems to work. Thanks! But indeed it should not return an error by default, it would be nice if this gets fixed. I am pretty sure I will not remember the workaround in a couple of months :)