Life time Calculation¶
This Notebook shows a general calculation stream for a nominal and local stress reliability approach.
Stress derivation¶
First we read in different time signals (coming from a test bench or a vehicle measurement e.g.).
- Import the time series into a pandas Data Frame
- Resample the time series if necessary
- Filter the time series with a bandpass filter if necessary
- Edititing time series using Running Statistics methods
- Rainflow Calculation
- Mean stress correction
- Multiplication with repeating factor of every manoveur
Damage Calculation¶
- Select the damage calculation method (Miner elementary, Miner-Haibach, …)
- Calculate the damage for every load level and the damage sum
- Calculate the failure probability with or w/o field scatter
Local stress approach¶
- Load the FE mesh
- Apply the load history to the FE mesh
- Calculate the damage
[1]:
import numpy as np
import pandas as pd
from pylife.stress.histogram import *
import pylife.stress.timesignal as ts
from pylife.stress.rainflow import *
import pylife.stress.equistress
import pylife.strength.meanstress
from pylife.strength import miner
from pylife.strength import sn_curve
from pylife.strength.miner import MinerElementar, MinerHaibach
from pylife.strength import failure_probability as fp
import pylife.vmap
import pyvista as pv
from pylife.materialdata.woehler.diagrams.woehler_curve_diagrams import WoehlerCurveDiagrams
import pylife.mesh.meshplot
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib as mpl
from scipy.stats import norm
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
import io
from IPython.display import HTML
import base64
# mpl.style.use('seaborn')
# mpl.style.use('seaborn-notebook')
mpl.style.use('bmh')
%matplotlib inline
pv.set_plot_theme('document')
pv.set_jupyter_backend('ipygany')
---------------------------------------------------------------------------
NoSectionError Traceback (most recent call last)
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/theano/configparser.py:238, in TheanoConfigParser.fetch_val_for_key(self, key, delete_key)
237 try:
--> 238 return self._theano_cfg.get(section, option)
239 except InterpolationError:
File ~/.pyenv/versions/3.8.6/lib/python3.8/configparser.py:781, in RawConfigParser.get(self, section, option, raw, vars, fallback)
780 try:
--> 781 d = self._unify_values(section, vars)
782 except NoSectionError:
File ~/.pyenv/versions/3.8.6/lib/python3.8/configparser.py:1149, in RawConfigParser._unify_values(self, section, vars)
1148 if section != self.default_section:
-> 1149 raise NoSectionError(section) from None
1150 # Update with the entry specific variables
NoSectionError: No section: 'blas'
During handling of the above exception, another exception occurred:
KeyError Traceback (most recent call last)
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/theano/configparser.py:354, in ConfigParam.__get__(self, cls, type_, delete_key)
353 try:
--> 354 val_str = cls.fetch_val_for_key(self.name, delete_key=delete_key)
355 self.is_default = False
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/theano/configparser.py:242, in TheanoConfigParser.fetch_val_for_key(self, key, delete_key)
241 except (NoOptionError, NoSectionError):
--> 242 raise KeyError(key)
KeyError: 'blas__ldflags'
During handling of the above exception, another exception occurred:
AttributeError Traceback (most recent call last)
Cell In [1], line 18
14 import pylife.vmap
16 import pyvista as pv
---> 18 from pylife.materialdata.woehler.diagrams.woehler_curve_diagrams import WoehlerCurveDiagrams
20 import pylife.mesh.meshplot
21 import matplotlib.pyplot as plt
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/pylife/materialdata/woehler/__init__.py:26
24 from .analyzers.probit import Probit
25 from .analyzers.maxlike import MaxLikeInf, MaxLikeFull
---> 26 from .analyzers.bayesian import Bayesian
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/pylife/materialdata/woehler/analyzers/bayesian.py:22
20 import numpy as np
21 import pandas as pd
---> 22 import theano.tensor as tt
23 import pymc3 as pm
25 from .elementary import Elementary
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/theano/__init__.py:83
75 # This is the api version for ops that generate C code. External ops
76 # might need manual changes if this number goes up. An undefined
77 # __api_version__ can be understood to mean api version 0.
78 #
79 # This number is not tied to the release version and should change
80 # very rarely.
81 __api_version__ = 1
---> 83 from theano import scalar, tensor
84 from theano.compile import (
85 In,
86 Mode,
(...)
93 shared,
94 )
95 from theano.compile.function import function, function_dump
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/theano/tensor/__init__.py:20
9 from theano.compile import SpecifyShape, specify_shape
10 from theano.gradient import (
11 Lop,
12 Rop,
(...)
18 verify_grad,
19 )
---> 20 from theano.tensor import nnet # used for softmax, sigmoid, etc.
21 from theano.tensor import sharedvar # adds shared-variable constructors
22 from theano.tensor import (
23 blas,
24 blas_c,
(...)
29 xlogx,
30 )
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/theano/tensor/nnet/__init__.py:3
1 import warnings
----> 3 from . import opt
4 from .abstract_conv import conv2d as abstract_conv2d
5 from .abstract_conv import conv2d_grad_wrt_inputs, conv3d, separable_conv2d
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/theano/tensor/nnet/opt.py:32
24 from theano.tensor.nnet.blocksparse import (
25 SparseBlockGemv,
26 SparseBlockOuter,
27 sparse_block_gemv_inplace,
28 sparse_block_outer_inplace,
29 )
31 # Cpu implementation
---> 32 from theano.tensor.nnet.conv import ConvOp, conv2d
33 from theano.tensor.nnet.corr import CorrMM, CorrMM_gradInputs, CorrMM_gradWeights
34 from theano.tensor.nnet.corr3d import Corr3dMM, Corr3dMMGradInputs, Corr3dMMGradWeights
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/theano/tensor/nnet/conv.py:20
18 from theano.graph.basic import Apply
19 from theano.graph.op import OpenMPOp
---> 20 from theano.tensor import blas
21 from theano.tensor.basic import (
22 NotScalarConstantError,
23 as_tensor_variable,
24 get_scalar_constant_value,
25 patternbroadcast,
26 )
27 from theano.tensor.nnet.abstract_conv import get_conv_output_shape, get_conv_shape_1axis
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/theano/tensor/blas.py:163
161 from theano.scalar import bool as bool_t
162 from theano.tensor import basic as tt
--> 163 from theano.tensor.blas_headers import blas_header_text, blas_header_version
164 from theano.tensor.opt import in2out, local_dimshuffle_lift
165 from theano.tensor.type import values_eq_approx_remove_inf_nan
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/theano/tensor/blas_headers.py:1016
997 header += textwrap.dedent(
998 """\
999 static float sdot_(int* Nx, float* x, int* Sx, float* y, int* Sy)
(...)
1010 """
1011 )
1013 return header + blas_code
-> 1016 if not config.blas__ldflags:
1017 _logger.warning("Using NumPy C-API based implementation for BLAS functions.")
1020 def mkl_threads_text():
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/theano/configparser.py:358, in ConfigParam.__get__(self, cls, type_, delete_key)
356 except KeyError:
357 if callable(self.default):
--> 358 val_str = self.default()
359 else:
360 val_str = self.default
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/theano/link/c/cmodule.py:2621, in default_blas_ldflags()
2617 try:
2618 if hasattr(numpy.distutils, "__config__") and numpy.distutils.__config__:
2619 # If the old private interface is available use it as it
2620 # don't print information to the user.
-> 2621 blas_info = numpy.distutils.__config__.blas_opt_info
2622 else:
2623 # We do this import only here, as in some setup, if we
2624 # just import theano and exit, with the import at global
(...)
2630 # This happen with Python 2.7.3 |EPD 7.3-1 and numpy 1.8.1
2631 # isort: off
2632 import numpy.distutils.system_info # noqa
AttributeError: module 'numpy.distutils.__config__' has no attribute 'blas_opt_info'
Time series signal¶
import, filtering and so on. You can import your own signal with
- pd.read_csv()
- pd.read_excel()
- scipy.io.loadmat() for matlab files
and so on
[2]:
t = np.linspace(0,60,60*2048)
files = ['wn','sine']
wn = pd.DataFrame(index = t, columns = ['sensor_1'], data = 120*np.random.randn(len(t)))
sine = pd.DataFrame(index = t, columns = ['sensor_1'], data = 80*np.sin(2*np.pi*50*t))
input_data = [wn,sine]
[3]:
# input_data = []
# for upload in files:
# data_akt = pd.read_csv(data_loc + upload, sep = ",")
# if len(data_akt.columns) == 1:
# print ('please use "," as seperator next time')
# data_akt = pd.read_csv(data_loc + upload, sep = ";")
# input_data.append(data_akt)
# print(upload + " imported succesfully")
Resampling¶
[4]:
f_resample = widgets.FloatText(value = 1024,min=1,max=100e3,step=1,
description='Resampling frequency [Hz]',
disabled=False,readout=True,readout_format='d')
display(f_resample)
# select time column
# timeColumn = widgets.Dropdown(options = data_akt.columns)
# display(timeColumn)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [4], line 1
----> 1 f_resample = widgets.FloatText(value = 1024,min=1,max=100e3,step=1,
2 description='Resampling frequency [Hz]',
3 disabled=False,readout=True,readout_format='d')
4 display(f_resample)
5 # select time column
6 # timeColumn = widgets.Dropdown(options = data_akt.columns)
7 # display(timeColumn)
NameError: name 'widgets' is not defined
[5]:
meas_resample = []
for file_act in input_data:
# file_act = file_act.set_index(timeColumn.value)
meas_resample.append(ts.TimeSignalPrep(file_act).resample_acc(f_resample.value))
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [5], line 4
1 meas_resample = []
2 for file_act in input_data:
3 # file_act = file_act.set_index(timeColumn.value)
----> 4 meas_resample.append(ts.TimeSignalPrep(file_act).resample_acc(f_resample.value))
NameError: name 'f_resample' is not defined
[6]:
print("select channel to plot")
plotChan = widgets.Dropdown(options = file_act.columns)
display(plotChan)
select channel to plot
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [6], line 2
1 print("select channel to plot")
----> 2 plotChan = widgets.Dropdown(options = file_act.columns)
3 display(plotChan)
NameError: name 'widgets' is not defined
[7]:
fig, ax = plt.subplots(len(meas_resample))
fig.suptitle('Resampled input data')
ii = 0
for df_act in meas_resample:
if len(meas_resample) == 1:
ax.plot(df_act.index, df_act[plotChan.value])
else:
ax[ii].plot(df_act.index, df_act[plotChan.value])
ii += 1
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [7], line 1
----> 1 fig, ax = plt.subplots(len(meas_resample))
2 fig.suptitle('Resampled input data')
3 ii = 0
NameError: name 'plt' is not defined
Filtering¶
[8]:
f_min = widgets.FloatText(value = 5,description='min frequency [Hz]',disabled=False)
f_max = widgets.FloatText(value = 100,description='max frequency [Hz]',disabled=False)
display(f_min)
display(f_max)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [8], line 1
----> 1 f_min = widgets.FloatText(value = 5,description='min frequency [Hz]',disabled=False)
2 f_max = widgets.FloatText(value = 100,description='max frequency [Hz]',disabled=False)
3 display(f_min)
NameError: name 'widgets' is not defined
[9]:
bandpass = []
for df_act in meas_resample:
bandpassDF = pd.DataFrame(index = df_act.index)
for col_act in df_act.columns:
bandpassDF[col_act] = ts.TimeSignalPrep(df_act[col_act]).butter_bandpass(f_min.value,f_max.value,f_resample.value,5)
bandpass.append(bandpassDF)
display(bandpassDF)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [9], line 7
5 bandpassDF[col_act] = ts.TimeSignalPrep(df_act[col_act]).butter_bandpass(f_min.value,f_max.value,f_resample.value,5)
6 bandpass.append(bandpassDF)
----> 7 display(bandpassDF)
NameError: name 'bandpassDF' is not defined
Running statistics¶
[10]:
print("select channel to for running stats")
runChan = widgets.Dropdown(options = df_act.columns)
display(runChan)
print(" Running statistics method")
method_choice = widgets.Dropdown(options = ['rms','max','min','abs'])
display(method_choice)
paraRunStats = ['window_length', 'buffer_overlap', 'limit']
values = [800,0.1,0.015]
child = [widgets.FloatText(description=name) for name in paraRunStats]
tab = widgets.Tab()
tab.children = child
for i in range(len(child)):
tab.set_title(i, paraRunStats[i])
tab.children[i].value = values[i]
tab
select channel to for running stats
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [10], line 2
1 print("select channel to for running stats")
----> 2 runChan = widgets.Dropdown(options = df_act.columns)
3 display(runChan)
4 print(" Running statistics method")
NameError: name 'widgets' is not defined
[11]:
""" Running statistics to drop out zero values """
cleaned = []
for df_act in bandpass:
cleaned_df = ts.TimeSignalPrep(df_act).running_stats_filt(
col = runChan.value,
window_length = int(tab.children[0].value),
buffer_overlap = int(tab.children[1].value),
limit = tab.children[2].value,
method = method_choice.value)
cleaned.append(cleaned_df)
# display(cleaned_df)
[12]:
print("select channel to plot")
plotChan = widgets.Dropdown(options = file_act.columns)
display(plotChan)
select channel to plot
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [12], line 2
1 print("select channel to plot")
----> 2 plotChan = widgets.Dropdown(options = file_act.columns)
3 display(plotChan)
NameError: name 'widgets' is not defined
[13]:
fig, ax = plt.subplots(len(meas_resample))
fig.suptitle('Cleaned input data')
for i, df_act in enumerate(cleaned):
if len(meas_resample) == 1:
ax.plot(df_act.index, df_act[plotChan.value])
else:
ax[i].plot(df_act.index, df_act[plotChan.value])
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [13], line 1
----> 1 fig, ax = plt.subplots(len(meas_resample))
2 fig.suptitle('Cleaned input data')
3 for i, df_act in enumerate(cleaned):
NameError: name 'plt' is not defined
Rainflow¶
[14]:
rfcChan = widgets.Dropdown(options = df_act.columns)
display(rfcChan)
binwidget = widgets.IntSlider(value = 64, min=1, max=1024, step=1,description='Bins:')
display(binwidget)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [14], line 1
----> 1 rfcChan = widgets.Dropdown(options = df_act.columns)
2 display(rfcChan)
3 binwidget = widgets.IntSlider(value = 64, min=1, max=1024, step=1,description='Bins:')
NameError: name 'widgets' is not defined
[15]:
rainflow = []
for df_act in cleaned:
rfc = RainflowCounterFKM().process(df_act[rfcChan.value].values)
rfm = rfc.get_rainflow_matrix_frame(binwidget.value)
rainflow.append(rfm)
[16]:
colormap = cm.ScalarMappable()
cmap = cm.get_cmap('PuRd')
# fig, ax = plt.subplots(2,len(rainflow))
fig = plt.figure(figsize = (8,11))
fig.suptitle('Rainflow of Channel ' + rfcChan.value)
for i, rf_act in enumerate(rainflow):
# 2D
ax = fig.add_subplot(3,2,2*(i+1)-1)
froms = rf_act.index.get_level_values('from').mid
tos = rf_act.index.get_level_values('to').mid
counts = np.flipud((rf_act.values.reshape(rf_act.index.levshape).T))#.ravel()
ax.set_xlabel('From')
ax.set_ylabel('To')
ax.imshow(np.log10(counts), extent=[froms.min(), froms.max(), tos.min(), tos.max()])
# 3D
ax = fig.add_subplot(3,2,2*(i+1), projection='3d')
bottom = np.zeros_like(counts.ravel())
width = rf_act.index.get_level_values('from').length.min()
depth = rf_act.index.get_level_values('to').length.min()
max_height = np.max(counts.ravel()) # get range of colorbars
min_height = np.min(counts.ravel())
rgba = [cmap((k-min_height)/max_height) for k in counts.ravel()]
ax.set_xlabel('From')
ax.set_ylabel('To')
ax.set_zlabel('Count')
ax.bar3d(froms.ravel(), tos.ravel(), bottom, width, depth, counts.ravel(), shade=True, color=rgba, zsort='average')
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [16], line 1
----> 1 colormap = cm.ScalarMappable()
2 cmap = cm.get_cmap('PuRd')
3 # fig, ax = plt.subplots(2,len(rainflow))
NameError: name 'cm' is not defined
Meanstress transformation¶
[17]:
meanstress_para = ['M', 'M2', 'R_Goal']
values = [0.3,0.2,-1]
child = [widgets.FloatText(description=name) for name in meanstress_para]
tab_mean = widgets.Tab()
tab_mean.children = child
for i in range(len(child)):
tab_mean.set_title(i, meanstress_para[i])
tab_mean.children[i].value = values[i]
tab_mean
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [17], line 3
1 meanstress_para = ['M', 'M2', 'R_Goal']
2 values = [0.3,0.2,-1]
----> 3 child = [widgets.FloatText(description=name) for name in meanstress_para]
4 tab_mean = widgets.Tab()
5 tab_mean.children = child
Cell In [17], line 3, in <listcomp>(.0)
1 meanstress_para = ['M', 'M2', 'R_Goal']
2 values = [0.3,0.2,-1]
----> 3 child = [widgets.FloatText(description=name) for name in meanstress_para]
4 tab_mean = widgets.Tab()
5 tab_mean.children = child
NameError: name 'widgets' is not defined
[18]:
transformed = []
for rf_act in rainflow:
transformed.append(rf_act.meanstress_hist.FKM_goodman(pd.Series({'M': tab_mean.children[0].value,
'M2': tab_mean.children[1].value})
, R_goal = tab_mean.children[2].value))
Repeating factor¶
[19]:
child = [widgets.FloatText(description=name) for name in files]
tab_repeat = widgets.Tab()
tab_repeat.children = child
for i in range(len(child)):
tab_repeat.set_title(i, files[i])
tab_repeat.children[i].value = int(50/(i+1))
tab_repeat
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [19], line 1
----> 1 child = [widgets.FloatText(description=name) for name in files]
2 tab_repeat = widgets.Tab()
3 tab_repeat.children = child
Cell In [19], line 1, in <listcomp>(.0)
----> 1 child = [widgets.FloatText(description=name) for name in files]
2 tab_repeat = widgets.Tab()
3 tab_repeat.children = child
NameError: name 'widgets' is not defined
[20]:
for ii in range(len(files)):
transformed[ii] = transformed[ii]*tab_repeat.children[ii].value
range_only_total = combine_hist(transformed,method = "sum")
display(range_only_total)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Cell In [20], line 2
1 for ii in range(len(files)):
----> 2 transformed[ii] = transformed[ii]*tab_repeat.children[ii].value
3 range_only_total = combine_hist(transformed,method = "sum")
4 display(range_only_total)
IndexError: list index out of range
[21]:
fig, ax = plt.subplots(nrows=1, ncols=2,figsize=(10, 5))
# plot total
amplitude = range_only_total.index.get_level_values('range').left.values[::-1]/2
cycles = range_only_total.values[::-1].ravel()
ax[0].step(cycles,amplitude,c = "black",linewidth = 3, label = "total")
ax[1].step(np.cumsum(cycles),amplitude,c = "black",linewidth = 3, label = "total")
ii = 0
for range_only in transformed:
amplitude = range_only.index.get_level_values('range').mid.values[::-1]/2
cycles = range_only.values[::-1].ravel()
ax[0].step(cycles,amplitude,label = files [ii])
ax[1].step(np.cumsum(cycles),amplitude,label = files [ii])
ii += 1
ax[0].set_title('Count')
ax[1].set_title('Cumulated sum count')
ax[1].legend()
for ai in ax:
ai.xaxis.grid(True)
ai.set_xlabel('count')
ai.set_ylabel('amplitude of ' + rfcChan.value)
ai.set_ylim((0,max(amplitude)))
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [21], line 1
----> 1 fig, ax = plt.subplots(nrows=1, ncols=2,figsize=(10, 5))
2 # plot total
3 amplitude = range_only_total.index.get_level_values('range').left.values[::-1]/2
NameError: name 'plt' is not defined
Nominal stress approach¶
Material parameters¶
You can create your own material data from Woeler tests using the Notebook woehler_analyzer
[22]:
mat = pd.Series(index = ['k_1', 'ND_50', 'SD_50', '1/TN', '1/TS'],
data = [8, 1.5e+06, 1.5e+02, 12, 1.1])
display(mat)
k_1 8.0
ND_50 1500000.0
SD_50 150.0
1/TN 12.0
1/TS 1.1
dtype: float64
Damage Calculation¶
[23]:
SNmethod = widgets.Dropdown(options = ['Miner Elementar','Miner Haibach','Miner original'])
display(SNmethod)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [23], line 1
----> 1 SNmethod = widgets.Dropdown(options = ['Miner Elementar','Miner Haibach','Miner original'])
2 display(SNmethod)
NameError: name 'widgets' is not defined
[24]:
damage_calc = sn_curve.FiniteLifeCurve(**mat.drop(['1/TN','1/TS']))
damage = damage_calc.calc_damage(range_only_total,method = 'original')
# display(damage)
print("\033[5m Total Damage of channel %s: %.2e \033[0m" % (rfcChan.value,damage.sum()))
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [24], line 2
1 damage_calc = sn_curve.FiniteLifeCurve(**mat.drop(['1/TN','1/TS']))
----> 2 damage = damage_calc.calc_damage(range_only_total,method = 'original')
3 # display(damage)
4 print("\033[5m Total Damage of channel %s: %.2e \033[0m" % (rfcChan.value,damage.sum()))
NameError: name 'range_only_total' is not defined
[25]:
SRI = mat['SD_50']*(mat['ND_50']**(1/mat['k_1']))
# Plotting
diagdata = WoehlerCurveDiagrams(mat, fatigue_data = None, analyzer = None,
y_min=2, y_max=SRI, x_min=1e1, x_max=1e12, ax = None)
diagdata.plot_fitted_curve( k_2=15)
plt.step(np.cumsum(cycles),2*amplitude)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [25], line 3
1 SRI = mat['SD_50']*(mat['ND_50']**(1/mat['k_1']))
2 # Plotting
----> 3 diagdata = WoehlerCurveDiagrams(mat, fatigue_data = None, analyzer = None,
4 y_min=2, y_max=SRI, x_min=1e1, x_max=1e12, ax = None)
5 diagdata.plot_fitted_curve( k_2=15)
6 plt.step(np.cumsum(cycles),2*amplitude)
NameError: name 'WoehlerCurveDiagrams' is not defined
Failure Probaility¶
Without field scatter¶
[26]:
D50 = 0.05
d = damage.sum()
di = np.logspace(np.log10(1e-1*d),np.log10(1e3*d),1000).flatten()
std = np.log10(mat['1/TN'])/2.5631031311
failprob = fp.FailureProbability(D50,std).pf_simple_load(di)
#print(failprob)
fig, ax = plt.subplots()
ax.semilogx(di, failprob, label='cdf')
ax.vlines(d, max(failprob), fp.FailureProbability(D50,std).pf_simple_load(d))
#
plt.xlabel("Damage")
plt.ylabel("cdf")
plt.title("Failure probability = %.2e" %fp.FailureProbability(D50,std).pf_simple_load(d))
plt.ylim(0,max(failprob))
plt.xlim(min(di),max(di))
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [26], line 2
1 D50 = 0.05
----> 2 d = damage.sum()
3 di = np.logspace(np.log10(1e-1*d),np.log10(1e3*d),1000).flatten()
4 std = np.log10(mat['1/TN'])/2.5631031311
NameError: name 'damage' is not defined
With field scatter¶
[27]:
field_std = 0.35
fig, ax = plt.subplots()
# plot pdf of material
mat_pdf = norm.pdf(np.log10(di), loc=np.log10(D50), scale=std)
ax.semilogx(di, mat_pdf, label='pdf_mat')
# plot pdf of load
field_pdf = norm.pdf(np.log10(di), loc=np.log10(d), scale=field_std)
ax.semilogx(di, field_pdf, label='pdf_load',color = 'r')
plt.xlabel("Damage")
plt.ylabel("pdf")
plt.title("Failure probability = %.2e" %fp.FailureProbability(D50,std).pf_norm_load(d,field_std))
plt.legend()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [27], line 2
1 field_std = 0.35
----> 2 fig, ax = plt.subplots()
3 # plot pdf of material
4 mat_pdf = norm.pdf(np.log10(di), loc=np.log10(D50), scale=std)
NameError: name 'plt' is not defined
FE based failure probability calculation¶
FE Data¶
[28]:
vm_mesh = pylife.vmap.VMAPImport("plate_with_hole.vmap")
pyLife_mesh = (vm_mesh.make_mesh('1', 'STATE-2')
.join_coordinates()
.join_variable('STRESS_CAUCHY')
.join_variable('DISPLACEMENT')
.to_frame())
pyLife_mesh.sample(10)
[28]:
x | y | z | S11 | S22 | S33 | S12 | S13 | S23 | dx | dy | dz | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
element_id | node_id | ||||||||||||
2348 | 2529 | -12.898024 | 5.043483 | 0.0 | 31.530674 | 2.548773 | 0.0 | 15.299500 | 0.0 | 0.0 | -0.005355 | -2.683275e-05 | 0.0 |
4375 | 4495 | -12.949039 | -6.678593 | 0.0 | 43.582188 | 1.339038 | 0.0 | -12.696354 | 0.0 | 0.0 | -0.005050 | 8.312715e-05 | 0.0 |
152 | 5456 | 11.613465 | 8.801641 | 0.0 | 71.453232 | -0.010022 | 0.0 | -1.659853 | 0.0 | 0.0 | 0.003944 | -4.149746e-04 | 0.0 |
7 | 4943 | 6.531105 | 4.282071 | 0.0 | 7.892305 | -8.635008 | 0.0 | 1.650274 | 0.0 | 0.0 | 0.004573 | -1.685894e-03 | 0.0 |
617 | 819 | 6.382044 | 4.971782 | 0.0 | 24.553560 | -7.306720 | 0.0 | -4.594051 | 0.0 | 0.0 | 0.004121 | -1.815735e-03 | 0.0 |
381 | 6246 | 8.700279 | 6.144556 | 0.0 | 49.453789 | -6.915460 | 0.0 | -8.297787 | 0.0 | 0.0 | 0.003934 | -8.298817e-04 | 0.0 |
3729 | 12898 | -5.862029 | -4.604344 | 0.0 | 9.270004 | -1.616697 | 0.0 | -0.216634 | 0.0 | 0.0 | -0.004689 | 1.961728e-03 | 0.0 |
4638 | 4591 | -14.018771 | -6.163092 | 0.0 | 37.169250 | 2.586217 | 0.0 | -12.849130 | 0.0 | 0.0 | -0.005351 | 2.429623e-05 | 0.0 |
2954 | 10846 | 11.770742 | -0.774989 | 0.0 | 4.559637 | 0.088149 | 0.0 | 4.189425 | 0.0 | 0.0 | 0.005776 | 3.926224e-06 | 0.0 |
1742 | 192 | -8.303333 | 0.000000 | 0.0 | -8.103550 | -53.486710 | 0.0 | 2.622392 | 0.0 | 0.0 | -0.006014 | 8.659753e-38 | 0.0 |
[29]:
# Equivalent stress range
pyLife_mesh['mises'] = 2*pyLife_mesh.equistress.mises()
# Scaling with amplitude
pyLife_mesh['mises'] = 2*pyLife_mesh['mises']/pyLife_mesh['mises'].max()
ampl_fe = pd.DataFrame(data = amplitude, columns = ["ampl"] ,index =cycles)
s_vm_scaled = pd.DataFrame(data = ampl_fe.values*pyLife_mesh['mises'].transpose().values,index = ampl_fe.index,columns = pyLife_mesh['mises'].index)
display(s_vm_scaled)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [29], line 5
3 # Scaling with amplitude
4 pyLife_mesh['mises'] = 2*pyLife_mesh['mises']/pyLife_mesh['mises'].max()
----> 5 ampl_fe = pd.DataFrame(data = amplitude, columns = ["ampl"] ,index =cycles)
6 s_vm_scaled = pd.DataFrame(data = ampl_fe.values*pyLife_mesh['mises'].transpose().values,index = ampl_fe.index,columns = pyLife_mesh['mises'].index)
7 display(s_vm_scaled)
NameError: name 'amplitude' is not defined
Damage Calculation¶
[30]:
N = damage_calc.calc_N(s_vm_scaled,ignore_limits = True)
d_mesh_cycle = 1/(N.div(N.index.values, axis = 'index'))
#np.sum(data_act[range_mid > sn_curve_parameters["sigma_ak"]].values/N)
d_mesh = d_mesh_cycle.sum()
display(d_mesh)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [30], line 1
----> 1 N = damage_calc.calc_N(s_vm_scaled,ignore_limits = True)
2 d_mesh_cycle = 1/(N.div(N.index.values, axis = 'index'))
3 #np.sum(data_act[range_mid > sn_curve_parameters["sigma_ak"]].values/N)
NameError: name 's_vm_scaled' is not defined
[31]:
pyLife_mesh = pyLife_mesh.join(pd.DataFrame(data = d_mesh,columns = ['d']))
display(pyLife_mesh)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [31], line 1
----> 1 pyLife_mesh = pyLife_mesh.join(pd.DataFrame(data = d_mesh,columns = ['d']))
2 display(pyLife_mesh)
NameError: name 'd_mesh' is not defined
[32]:
# plotting using pyvista
pyLife_nodes = pyLife_mesh.groupby('node_id').mean()
mesh = pv.PolyData(pyLife_nodes[['x', 'y', 'z']].values)
mesh.point_arrays["d"] = pyLife_nodes["d"].values
mesh.plot(scalars="d",log_scale = True)
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/pandas/core/indexes/base.py:3803, in Index.get_loc(self, key, method, tolerance)
3802 try:
-> 3803 return self._engine.get_loc(casted_key)
3804 except KeyError as err:
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/pandas/_libs/index.pyx:138, in pandas._libs.index.IndexEngine.get_loc()
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/pandas/_libs/index.pyx:165, in pandas._libs.index.IndexEngine.get_loc()
File pandas/_libs/hashtable_class_helper.pxi:5745, in pandas._libs.hashtable.PyObjectHashTable.get_item()
File pandas/_libs/hashtable_class_helper.pxi:5753, in pandas._libs.hashtable.PyObjectHashTable.get_item()
KeyError: 'd'
The above exception was the direct cause of the following exception:
KeyError Traceback (most recent call last)
Cell In [32], line 4
2 pyLife_nodes = pyLife_mesh.groupby('node_id').mean()
3 mesh = pv.PolyData(pyLife_nodes[['x', 'y', 'z']].values)
----> 4 mesh.point_arrays["d"] = pyLife_nodes["d"].values
5 mesh.plot(scalars="d",log_scale = True)
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/pandas/core/frame.py:3804, in DataFrame.__getitem__(self, key)
3802 if self.columns.nlevels > 1:
3803 return self._getitem_multilevel(key)
-> 3804 indexer = self.columns.get_loc(key)
3805 if is_integer(indexer):
3806 indexer = [indexer]
File ~/checkouts/readthedocs.org/user_builds/pylife/envs/1.1.4/lib/python3.8/site-packages/pandas/core/indexes/base.py:3805, in Index.get_loc(self, key, method, tolerance)
3803 return self._engine.get_loc(casted_key)
3804 except KeyError as err:
-> 3805 raise KeyError(key) from err
3806 except TypeError:
3807 # If we have a listlike key, _check_indexing_error will raise
3808 # InvalidIndexError. Otherwise we fall through and re-raise
3809 # the TypeError.
3810 self._check_indexing_error(key)
KeyError: 'd'
[33]:
print("Maximal damage sum: %f" % d_mesh.max())
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [33], line 1
----> 1 print("Maximal damage sum: %f" % d_mesh.max())
NameError: name 'd_mesh' is not defined