Skip to content

Commit 48f58c0

Browse files
authored
Add example cycles_to_failure from McMunich (#591)
* Functioning cyclic_to_failure examples * Update style * Add test_examples::test_download_cycles_to_failure * Comments from Jenna Signed-off-by: paul.profizi <[email protected]> * Update title of the example * Apply suggestions from code review * Remove section separation for a visually better example * Rework formatting of the explanation paragraph * Update examples/02-modal-harmonic/06-cycles_to_failure.py * Fix formatting of the description * Fix formatting of the description * Revert "Remove section separation for a visually better example" This reverts commit 52d1b1d. * Reformat sections * Reformat * Reformat * Reformat * Reformat * Reformat * Apply suggestions from code review Signed-off-by: paul.profizi <[email protected]>
1 parent daa943f commit 48f58c0

File tree

3 files changed

+204
-34
lines changed

3 files changed

+204
-34
lines changed

ansys/dpf/core/examples/downloads.py

Lines changed: 75 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ def download_transient_result(should_upload: bool = True, server=None,
7979
return_local_path=False) -> str:
8080
"""Download an example transient result file and return the download path
8181
available server side.
82-
If the server is remote (or doesn't share the memory), the file is uploaded or made available
83-
server side.
82+
If the server is remote (or doesn't share memory), the file is uploaded or made available
83+
on the server side.
8484
8585
Examples files are downloaded to a persistent cache to avoid
8686
re-downloading the same file twice.
@@ -118,8 +118,8 @@ def download_all_kinds_of_complexity(should_upload: bool = True, server=None
118118
, return_local_path=False) -> str:
119119
"""Download an example static result and return the download path
120120
available server side.
121-
If the server is remote (or doesn't share the memory), the file is uploaded or made available
122-
server side.
121+
If the server is remote (or doesn't share memory), the file is uploaded or made available
122+
on the server side.
123123
124124
Examples files are downloaded to a persistent cache to avoid
125125
re-downloading the same file twice.
@@ -158,8 +158,8 @@ def download_all_kinds_of_complexity_modal(should_upload: bool = True, server=No
158158
return_local_path=False) -> str:
159159
"""Download an example result file from a static modal analysis and
160160
return the download path available server side.
161-
If the server is remote (or doesn't share the memory), the file is uploaded or made available
162-
server side.
161+
If the server is remote (or doesn't share memory), the file is uploaded or made available
162+
on the server side.
163163
164164
Examples files are downloaded to a persistent cache to avoid
165165
re-downloading the same file twice.
@@ -197,8 +197,8 @@ def download_all_kinds_of_complexity_modal(should_upload: bool = True, server=No
197197
def download_pontoon(should_upload: bool = True, server=None, return_local_path=False) -> str:
198198
"""Download an example result file from a static modal analsys and
199199
return the download path available server side.
200-
If the server is remote (or doesn't share the memory), the file is uploaded or made available
201-
server side.
200+
If the server is remote (or doesn't share memory), the file is uploaded or made available
201+
on the server side.
202202
203203
Examples files are downloaded to a persistent cache to avoid
204204
re-downloading the same file twice.
@@ -236,8 +236,8 @@ def download_multi_harmonic_result(should_upload: bool = True, server=None,
236236
return_local_path=False) -> str:
237237
"""Download an example multi-harmonic result file and return the
238238
download path available server side.
239-
If the server is remote (or doesn't share the memory), the file is uploaded or made available
240-
server side.
239+
If the server is remote (or doesn't share memory), the file is uploaded or made available
240+
on the server side.
241241
242242
Examples files are downloaded to a persistent cache to avoid
243243
re-downloading the same file twice.
@@ -273,10 +273,10 @@ def download_multi_harmonic_result(should_upload: bool = True, server=None,
273273

274274
def download_multi_stage_cyclic_result(should_upload: bool = True, server=None,
275275
return_local_path=False) -> str:
276-
"""Download an example multi stage result file and return the
276+
"""Download an example multi-stage result file and return the
277277
download path available server side.
278-
If the server is remote (or doesn't share the memory), the file is uploaded or made available
279-
server side.
278+
If the server is remote (or doesn't share memory), the file is uploaded or made available
279+
on the server side.
280280
281281
Examples files are downloaded to a persistent cache to avoid
282282
re-downloading the same file twice.
@@ -313,8 +313,8 @@ def download_multi_stage_cyclic_result(should_upload: bool = True, server=None,
313313
def download_sub_file(should_upload: bool = True, server=None, return_local_path=False) -> str:
314314
"""Download an example .sub result file containing matrices and return the
315315
download path available server side.
316-
If the server is remote (or doesn't share the memory), the file is uploaded or made available
317-
server side.
316+
If the server is remote (or doesn't share memory), the file is uploaded or made available
317+
on the server side.
318318
319319
Examples files are downloaded to a persistent cache to avoid
320320
re-downloading the same file twice.
@@ -352,8 +352,8 @@ def download_msup_files_to_dict(should_upload: bool = True, server=None,
352352
return_local_path=False) -> dict:
353353
"""Download all the files necessary for a msup expansion and return the
354354
download paths available server side into a dictionary extension->path.
355-
If the server is remote (or doesn't share the memory), the files are uploaded or made available
356-
server side.
355+
If the server is remote (or doesn't share memory), the file is uploaded or made available
356+
on the server side.
357357
358358
Examples files are downloaded to a persistent cache to avoid
359359
re-downloading the same file twice.
@@ -397,8 +397,8 @@ def download_distributed_files(should_upload: bool = True, server=None,
397397
return_local_path=False) -> dict:
398398
"""Download distributed rst files and return the
399399
download paths into a dictionary domain id->path.
400-
If the server is remote (or doesn't share the memory), the files are uploaded or made available
401-
server side.
400+
If the server is remote (or doesn't share memory), the file is uploaded or made available
401+
on the server side.
402402
403403
Examples files are downloaded to a persistent cache to avoid
404404
re-downloading the same file twice.
@@ -439,8 +439,8 @@ def download_distributed_files(should_upload: bool = True, server=None,
439439
def download_fluent_files(should_upload: bool = True, server=None, return_local_path=False) -> dict:
440440
"""Download the cas and dat file of a fluent analysis and return the
441441
download paths into a dictionary extension->path.
442-
If the server is remote (or doesn't share the memory), the files are uploaded or made available
443-
server side.
442+
If the server is remote (or doesn't share memory), the file is uploaded or made available
443+
on the server side.
444444
445445
Examples files are downloaded to a persistent cache to avoid
446446
re-downloading the same file twice.
@@ -481,9 +481,9 @@ def download_fluent_files(should_upload: bool = True, server=None, return_local_
481481
def download_extrapolation_3d_result(should_upload: bool = True, server=None,
482482
return_local_path=False) -> dict:
483483
"""Download example static results of reference and integrated points
484-
for extrapolation of 3d-element and return return the dictionary of 2 download paths.
485-
If the server is remote (or doesn't share the memory), the files are uploaded or made available
486-
server side.
484+
for extrapolation of 3d-element and return the dictionary of 2 download paths.
485+
If the server is remote (or doesn't share memory), the file is uploaded or made available
486+
on the server side.
487487
488488
Examples files are downloaded to a persistent cache to avoid
489489
re-downloading the same file twice.
@@ -532,8 +532,8 @@ def download_extrapolation_2d_result(should_upload: bool = True, server=None,
532532
return_local_path=False) -> dict:
533533
"""Download example static results of reference and integrated points
534534
for extrapolation of 2d-element and return the dictionary of 2 download paths.
535-
If the server is remote (or doesn't share the memory), the files are uploaded or made available
536-
server side.
535+
If the server is remote (or doesn't share memory), the file is uploaded or made available
536+
on the server side.
537537
538538
Examples files are downloaded to a persistent cache to avoid
539539
re-downloading the same file twice.
@@ -581,8 +581,8 @@ def download_extrapolation_2d_result(should_upload: bool = True, server=None,
581581
def download_hemisphere(should_upload: bool = True, server=None, return_local_path=False) -> str:
582582
"""Download an example result file from a static analysis and
583583
return the download path available server side.
584-
If the server is remote (or doesn't share the memory), the file is uploaded or made available
585-
server side.
584+
If the server is remote (or doesn't share memory), the file is uploaded or made available
585+
on the server side.
586586
587587
Examples files are downloaded to a persistent cache to avoid
588588
re-downloading the same file twice.
@@ -620,8 +620,8 @@ def download_example_asme_result(should_upload: bool = True, server=None,
620620
return_local_path=False) -> str:
621621
"""Download an example result file from a static analysis and
622622
return the download path available server side.
623-
If the server is remote (or doesn't share the memory), the file is uploaded or made available
624-
server side.
623+
If the server is remote (or doesn't share memory), the file is uploaded or made available
624+
on the server side.
625625
626626
Examples files are downloaded to a persistent cache to avoid
627627
re-downloading the same file twice.
@@ -657,8 +657,8 @@ def download_example_asme_result(should_upload: bool = True, server=None,
657657
def download_crankshaft(should_upload: bool = True, server=None, return_local_path=False) -> str:
658658
"""Download the result file of an example of a crankshaft
659659
under load and return the download path available server side.
660-
If the server is remote (or doesn't share the memory), the file is uploaded or made available
661-
server side.
660+
If the server is remote (or doesn't share memory), the file is uploaded or made available
661+
on the server side.
662662
663663
Examples files are downloaded to a persistent cache to avoid
664664
re-downloading the same file twice.
@@ -695,8 +695,8 @@ def download_crankshaft(should_upload: bool = True, server=None, return_local_pa
695695
def download_piston_rod(should_upload: bool = True, server=None, return_local_path=False) -> str:
696696
"""Download the result file of an example of a piston rod
697697
under load and return the download path available server side.
698-
If the server is remote (or doesn't share the memory), the file is uploaded or made available
699-
server side.
698+
If the server is remote (or doesn't share memory), the file is uploaded or made available
699+
on the server side.
700700
701701
Examples files are downloaded to a persistent cache to avoid
702702
re-downloading the same file twice.
@@ -846,3 +846,44 @@ def download_binout_glstat(should_upload: bool = True, server=None, return_local
846846
847847
"""
848848
return _download_file("binout", "binout_glstat", should_upload, server, return_local_path)
849+
850+
851+
def download_cycles_to_failure(should_upload: bool = True,
852+
server=None,
853+
return_local_path=False) -> str:
854+
"""Download an example result file from a cyclic analysis and
855+
return the download path.
856+
If the server is remote (or doesn't share memory), the file is uploaded or made available
857+
on the server side.
858+
859+
Examples files are downloaded to a persistent cache to avoid
860+
re-downloading the same file twice.
861+
862+
Parameters
863+
----------
864+
should_upload : bool, optional (default True)
865+
Whether the file should be uploaded server side when the server is remote.
866+
server : server.DPFServer, optional
867+
Server with channel connected to the remote or local instance. When
868+
``None``, attempts to use the global server.
869+
return_local_path: bool, optional
870+
If ``True``, the local path is returned as is, without uploading, nor searching
871+
for mounted volumes.
872+
873+
Returns
874+
-------
875+
str
876+
Path to the example file.
877+
878+
Examples
879+
--------
880+
Download an example result file and return the path of the file
881+
882+
>>> from ansys.dpf.core import examples
883+
>>> path = examples.download_cycles_to_failure()
884+
>>> path
885+
'C:/Users/user/AppData/local/temp/cycles_to_failure.rst'
886+
887+
"""
888+
return _download_file("cyclic", "cyclic_to_failure.rst",
889+
should_upload, server, return_local_path)
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
"""
2+
.. _ref_cycles_to_failure:
3+
4+
Calculate the number of cycles to fatigue failure
5+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6+
7+
This example shows how to generate and use a result file to calculate the
8+
cycles to failure result for a simple model.
9+
10+
Material data is manually imported, Structural Steel from Ansys Mechanical:
11+
12+
- Youngs Modulus (youngsSteel)
13+
- Poisson's Ratio (prxySteel)
14+
- SN curve (sn_data)
15+
16+
The first step is to generate a simple model with high stress and save the
17+
results .rst file locally to myDir (default is "C:\\\\temp").
18+
For this, we provide a short pyMAPDL script.
19+
20+
.. line-block::
21+
The second step uses PyDPF-Core to generate the cycles to failure result:
22+
The locally saved .rst file is imported and plotted.
23+
Then the von Mises stress is generated and plotted with DPF operators.
24+
The NumPy python package is then used to interpolate the cycles to failure values.
25+
The nodal von Mises equivalent stress value is used in the interpolation.
26+
(Note that the cycles to failure data must be manipulated to use NumPy interpolation)
27+
An empty field is then created and filled with the resulting cycles to failure values.
28+
The cycles to failure result is finally plotted.
29+
30+
The cycles to failure result is the (interpolated) negative of the stress result.
31+
The higher the stress result, the lower the number of cycles to failure.
32+
"""
33+
34+
from ansys.dpf import core as dpf
35+
from ansys.dpf.core import examples
36+
import numpy as np
37+
38+
###############################################################################
39+
# The first step is to generate a simple model with high stress
40+
41+
# # Material parameters from Ansys Mechanical Structural Steel
42+
youngsSteel = 200e9
43+
prxySteel = 0.3
44+
sn_data = np.empty((11, 2)) # initialize empty np matrix
45+
sn_data[:, 0] = [10, 20, 50, 100, 200, 2000, 10000, 20000, 1e5, 2e5, 1e6]
46+
sn_data[:, 1] = [3.999e9, 2.8327e9, 1.896e9, 1.413e9, 1.069e9, 4.41e8, 2.62e8, 2.14e8, 1.38e8,
47+
1.14e8, 8.62e7]
48+
49+
###############################################################################
50+
# The .rst file used is already available, but can be obtained using the short pyMAPDL code below:
51+
52+
# # ### Launch pymapdl to generate rst file in myDir
53+
# from ansys.mapdl.core import launch_mapdl
54+
# import os
55+
#
56+
#
57+
# mapdl = launch_mapdl()
58+
# mapdl.prep7()
59+
# # Model
60+
# mapdl.cylind(0.5, 0, 10, 0)
61+
# mapdl.mp("EX", 1, youngsSteel)
62+
# mapdl.mp("PRXY", 1, prxySteel)
63+
# mapdl.mshape(key=1, dimension='3d')
64+
# mapdl.et(1, "SOLID186")
65+
# mapdl.esize(0.3)
66+
# mapdl.vmesh('ALL')
67+
#
68+
# # #### Boundary Conditions: fixed constraint
69+
# mapdl.nsel(type_='S', item='LOC', comp='Z', vmin=0)
70+
# mapdl.d("all", "all")
71+
# mapdl.nsel(type_='S', item='LOC', comp='Z', vmin=10)
72+
# nnodes = mapdl.get("NumNodes", "NODE", 0, "COUNT")
73+
# mapdl.f(node="ALL", lab="fy", value=-13e6 / nnodes)
74+
# mapdl.allsel()
75+
#
76+
# # #### Solve
77+
# mapdl.run("/SOLU")
78+
# sol_output = mapdl.solve()
79+
# rst = os.path.join(mapdl.directory, 'file.rst')
80+
# mapdl.exit()
81+
# print('apdl model solved.')
82+
83+
###############################################################################
84+
# PyDPF-Core is then used to post-process the .rst file to estimate the cycles to failure.
85+
86+
# Comment the following line if solving the MAPDL problem first.
87+
rst = examples.download_cycles_to_failure()
88+
89+
# Import the result as a DPF Model object.
90+
model = dpf.Model(rst)
91+
print(model)
92+
93+
###############################################################################
94+
# Get the von mises equivalent stress, requires an operator.
95+
s_eqv_op = dpf.operators.result.stress_von_mises(data_sources=model)
96+
vm_stress_fc = s_eqv_op.eval()
97+
vm_stress_field = vm_stress_fc[0]
98+
vm_stress_field.plot(text="VM stress field")
99+
100+
###############################################################################
101+
# Use NumPy to interpolate the results.
102+
103+
# Inverse the sn_data
104+
x_values = sn_data[:, 1][::-1] # the x values are the stress ranges in ascending order
105+
y_values = sn_data[:, 0][::-1] # y values are inverted cycles to failure
106+
107+
# Interpolate cycles to failure for the VM values
108+
cycles_to_failure = np.interp(vm_stress_field.data, x_values, y_values)
109+
110+
###############################################################################
111+
# Generate a cycles_to_failure DPF Field
112+
113+
# Create an empty field
114+
cycles_to_failure_field = dpf.Field(nentities=len(vm_stress_field.scoping),
115+
nature=dpf.natures.scalar,
116+
location=dpf.locations.nodal)
117+
# Populate the field
118+
cycles_to_failure_field.scoping = vm_stress_field.scoping
119+
cycles_to_failure_field.meshed_region = vm_stress_field.meshed_region
120+
cycles_to_failure_field.data = cycles_to_failure
121+
122+
# Plot the field
123+
sargs = dict(title="cycles", fmt="%.2e")
124+
cycles_to_failure_field.plot(text="Cycles to failure", scalar_bar_args=sargs)

tests/test_examples.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ def test_download_piston_rod():
3434
assert isinstance(Model(path), Model)
3535

3636

37+
def test_download_cycles_to_failure():
38+
path = examples.download_cycles_to_failure()
39+
assert isinstance(Model(path), Model)
40+
41+
3742
list_examples = [
3843
"simple_bar",
3944
"static_rst",

0 commit comments

Comments
 (0)