[1]:
%matplotlib inline
%load_ext autoreload
%autoreload 2
[2]:
import matplotlib.pyplot as plt
from helpr.api import CrackEvolutionAnalysis
from helpr.utilities.unit_conversion import convert_in_to_m, convert_psi_to_mpa
from probabilistic.capabilities.uncertainty_definitions import DeterministicCharacterization, TruncatedLognormalDistribution
Advanced User Options
Specify Common User Inputs
[3]:
# Pipe dimensions
outer_diameter = DeterministicCharacterization(name='outer_diameter', value=convert_in_to_m(36))
wall_thickness = DeterministicCharacterization(name='wall_thickness', value=convert_in_to_m(0.406))
# Gas environment
max_pressure = DeterministicCharacterization(name='max_pressure', value=convert_psi_to_mpa(840))
min_pressure = DeterministicCharacterization(name='min_pressure', value=convert_psi_to_mpa(638))
temperature = DeterministicCharacterization(name='temperature', value=293)
volume_fraction_h2 = DeterministicCharacterization(name='volume_fraction_h2', value=1)
# Pipe material properties
yield_strength = DeterministicCharacterization(name='yield_strength', value=convert_psi_to_mpa(52_000))
fracture_resistance = DeterministicCharacterization(name='fracture_resistance', value=55)
# Flaw geometry
flaw_depth = DeterministicCharacterization(name='flaw_depth', value=25)
flaw_length = DeterministicCharacterization(name='flaw_length', value=convert_in_to_m(1.575))
Varying Crack Width Growth Assumption
[4]:
# Fixed model assumptions
stress_intensity_method='api'
surface='inside'
analysis_prop = \
CrackEvolutionAnalysis(outer_diameter=outer_diameter,
wall_thickness=wall_thickness,
max_pressure=max_pressure,
min_pressure=min_pressure,
temperature=temperature,
volume_fraction_h2=volume_fraction_h2,
yield_strength=yield_strength,
fracture_resistance=fracture_resistance,
flaw_depth=flaw_depth,
flaw_length=flaw_length,
stress_intensity_method=stress_intensity_method,
surface=surface,
delta_c_rule='proportional')
analysis_prop.perform_study()
analysis_fix = CrackEvolutionAnalysis(outer_diameter=outer_diameter,
wall_thickness=wall_thickness,
max_pressure=max_pressure,
min_pressure=min_pressure,
temperature=temperature,
volume_fraction_h2=volume_fraction_h2,
yield_strength=yield_strength,
fracture_resistance=fracture_resistance,
flaw_depth=flaw_depth,
flaw_length=flaw_length,
stress_intensity_method=stress_intensity_method,
surface=surface,
delta_c_rule='fixed')
analysis_fix.perform_study()
analysis_ind = CrackEvolutionAnalysis(outer_diameter=outer_diameter,
wall_thickness=wall_thickness,
max_pressure=max_pressure,
min_pressure=min_pressure,
temperature=temperature,
volume_fraction_h2=volume_fraction_h2,
yield_strength=yield_strength,
fracture_resistance=fracture_resistance,
flaw_depth=flaw_depth,
flaw_length=flaw_length,
stress_intensity_method=stress_intensity_method,
surface=surface,
delta_c_rule='independent')
analysis_ind.perform_study()
/Users/bbschro/Development/helpr/src/helpr/utilities/postprocessing.py:363: UserWarning: Kmax + Kres did not reach fracture resistance for at least one crack, setting a_crit/t = 0.8 for such cracks
wr.warn('Kmax + Kres did not reach fracture resistance for at least one crack, ' +
/Users/bbschro/Development/helpr/src/helpr/utilities/postprocessing.py:363: UserWarning: Kmax + Kres did not reach fracture resistance for at least one crack, setting a_crit/t = 0.8 for such cracks
wr.warn('Kmax + Kres did not reach fracture resistance for at least one crack, ' +
[5]:
fig, ax1 = plt.subplots(figsize=(4,4))
ax2 = ax1.twinx()
ax1.plot([], [], color='gray', linestyle='-', label='proportional')
ax1.plot([], [], color='gray', linestyle='--', label='fixed')
ax1.plot([], [], color='gray', linestyle=':', label='independent')
ax1.plot(analysis_prop.nominal_load_cycling[0]['Total cycles'],
analysis_prop.nominal_load_cycling[0]['a (m)'],
'r-')
ax2.plot(analysis_prop.nominal_load_cycling[0]['Total cycles'],
analysis_prop.nominal_load_cycling[0]['c (m)'],
'b-')
ax1.plot(analysis_fix.nominal_load_cycling[0]['Total cycles'],
analysis_fix.nominal_load_cycling[0]['a (m)'],
'r--')
ax2.plot(analysis_fix.nominal_load_cycling[0]['Total cycles'],
analysis_fix.nominal_load_cycling[0]['c (m)'],
'b--')
ax1.plot(analysis_ind.nominal_load_cycling[0]['Total cycles'],
analysis_ind.nominal_load_cycling[0]['a (m)'],
'r:')
ax2.plot(analysis_ind.nominal_load_cycling[0]['Total cycles'],
analysis_ind.nominal_load_cycling[0]['c (m)'],
'b:')
ax1.set_xlabel('Total cycles')
ax1.set_ylabel('a (m)', color='r')
ax2.set_ylabel('c (m)', color='b')
ax1.legend(loc=0, title='c growth assumption')
plt.grid(color='gray', alpha=0.3, linestyle='--')
[6]:
fig, ax1 = plt.subplots(figsize=(4,4))
ax2 = ax1.twinx()
ax1.plot([], [], color='gray', linestyle='-', label='proportional')
ax1.plot(analysis_prop.nominal_load_cycling[0]['Total cycles'],
analysis_prop.nominal_load_cycling[0]['a (m)'],
'r-')
ax2.plot(analysis_prop.nominal_load_cycling[0]['Total cycles'],
analysis_prop.nominal_load_cycling[0]['c (m)'],
'b-')
ax1.set_xlabel('Total cycles')
ax1.set_ylabel('a (m)', color='r')
ax2.set_ylabel('c (m)', color='b')
ax1.legend(loc=0, title='c growth assumption')
plt.grid(color='gray', alpha=0.3, linestyle='--')
[7]:
fig, ax1 = plt.subplots(figsize=(4,4))
ax2 = ax1.twinx()
ax1.plot([], [], color='gray', linestyle='--', label='fixed')
ax1.plot(analysis_fix.nominal_load_cycling[0]['Total cycles'],
analysis_fix.nominal_load_cycling[0]['a (m)'],
'r--')
ax2.plot(analysis_fix.nominal_load_cycling[0]['Total cycles'],
analysis_fix.nominal_load_cycling[0]['c (m)'],
'b--')
ax1.set_xlabel('Total cycles')
ax1.set_ylabel('a (m)', color='r')
ax2.set_ylabel('c (m)', color='b')
ax1.legend(loc=0, title='c growth assumption')
plt.grid(color='gray', alpha=0.3, linestyle='--')
[8]:
fig, ax1 = plt.subplots(figsize=(4,4))
ax2 = ax1.twinx()
ax1.plot([], [], color='gray', linestyle=':', label='independent')
ax1.plot(analysis_ind.nominal_load_cycling[0]['Total cycles'],
analysis_ind.nominal_load_cycling[0]['a (m)'],
'r:')
ax2.plot(analysis_ind.nominal_load_cycling[0]['Total cycles'],
analysis_ind.nominal_load_cycling[0]['c (m)'],
'b:')
ax1.set_xlabel('Total cycles')
ax1.set_ylabel('a (m)', color='r')
ax2.set_ylabel('c (m)', color='b')
ax1.legend(loc=0, title='c growth assumption')
plt.grid(color='gray', alpha=0.3, linestyle='--')
Varying Stress Intensity Factor Method
[9]:
# Fixed model assumptions
delta_c_rule='proportional'
analysis_and = CrackEvolutionAnalysis(outer_diameter=outer_diameter,
wall_thickness=wall_thickness,
max_pressure=max_pressure,
min_pressure=min_pressure,
temperature=temperature,
volume_fraction_h2=volume_fraction_h2,
yield_strength=yield_strength,
fracture_resistance=fracture_resistance,
flaw_depth=flaw_depth,
flaw_length=flaw_length,
stress_intensity_method='anderson',
surface='inside',
delta_c_rule=delta_c_rule)
analysis_and.perform_study()
analysis_api_in = CrackEvolutionAnalysis(outer_diameter=outer_diameter,
wall_thickness=wall_thickness,
max_pressure=max_pressure,
min_pressure=min_pressure,
temperature=temperature,
volume_fraction_h2=volume_fraction_h2,
yield_strength=yield_strength,
fracture_resistance=fracture_resistance,
flaw_depth=flaw_depth,
flaw_length=flaw_length,
stress_intensity_method='api',
surface='inside',
delta_c_rule=delta_c_rule)
analysis_api_in.perform_study()
analysis_api_out = CrackEvolutionAnalysis(outer_diameter=outer_diameter,
wall_thickness=wall_thickness,
max_pressure=max_pressure,
min_pressure=min_pressure,
temperature=temperature,
volume_fraction_h2=volume_fraction_h2,
yield_strength=yield_strength,
fracture_resistance=fracture_resistance,
flaw_depth=flaw_depth,
flaw_length=flaw_length,
stress_intensity_method='api',
surface='outside',
delta_c_rule=delta_c_rule)
analysis_api_out.perform_study()
/Users/bbschro/Development/helpr/src/helpr/physics/stress_state.py:521: UserWarning: Inner Radius / wall thickness exceeds bounds 5 <= R_i/t <= 20, R_i/t = 43.33497536945812, violating Anderson solution limits.
wr.warn('Inner Radius / wall thickness exceeds bounds ' +
[10]:
fig, ax1 = plt.subplots(figsize=(4,4))
ax2 = ax1.twinx()
ax1.plot([], [], color='gray', linestyle='-', label='Anderson')
ax1.plot([], [], color='gray', linestyle='--', label='API internal')
ax1.plot([], [], color='gray', linestyle=':', label='API external')
ax1.plot(analysis_and.nominal_load_cycling[0]['Total cycles'],
analysis_and.nominal_load_cycling[0]['a (m)'],
'r-')
ax2.plot(analysis_and.nominal_load_cycling[0]['Total cycles'],
analysis_and.nominal_load_cycling[0]['Kmax (MPa m^1/2)'],
'b-')
ax1.plot(analysis_api_in.nominal_load_cycling[0]['Total cycles'],
analysis_api_in.nominal_load_cycling[0]['a (m)'],
'r--')
ax2.plot(analysis_api_in.nominal_load_cycling[0]['Total cycles'],
analysis_api_in.nominal_load_cycling[0]['Kmax (MPa m^1/2)'],
'b--')
ax1.plot(analysis_api_out.nominal_load_cycling[0]['Total cycles'],
analysis_api_out.nominal_load_cycling[0]['a (m)'],
'r:')
ax2.plot(analysis_api_out.nominal_load_cycling[0]['Total cycles'],
analysis_api_out.nominal_load_cycling[0]['Kmax (MPa m^1/2)'],
'b:')
ax1.set_xlabel('Total cycles')
ax1.set_ylabel('a (m)', color='r')
ax2.set_ylabel(r'Kmax (MPa m$^{1/2}$)', color='b')
ax1.legend(loc=0, title='K Solution assumption')
plt.grid(color='gray', alpha=0.3, linestyle='--')
Compare Crack Evolution in terms of a/t vs cycles
[11]:
stress_intensity_method = 'anderson'
surface = 'inside'
delta_c_rule = 'proportional'
analysis_aovert = CrackEvolutionAnalysis(outer_diameter=outer_diameter,
wall_thickness=wall_thickness,
max_pressure=max_pressure,
min_pressure=min_pressure,
temperature=temperature,
volume_fraction_h2=volume_fraction_h2,
yield_strength=yield_strength,
fracture_resistance=fracture_resistance,
flaw_depth=flaw_depth,
flaw_length=flaw_length,
stress_intensity_method=stress_intensity_method,
surface=surface,
delta_c_rule=delta_c_rule)
analysis_aovert.perform_study()
analysis_cycles = CrackEvolutionAnalysis(outer_diameter=outer_diameter,
wall_thickness=wall_thickness,
max_pressure=max_pressure,
min_pressure=min_pressure,
temperature=temperature,
volume_fraction_h2=volume_fraction_h2,
yield_strength=yield_strength,
fracture_resistance=fracture_resistance,
flaw_depth=flaw_depth,
flaw_length=flaw_length,
stress_intensity_method=stress_intensity_method,
surface=surface,
delta_c_rule=delta_c_rule,
cycle_step=1)
analysis_cycles.perform_study()
/Users/bbschro/Development/helpr/src/helpr/physics/stress_state.py:521: UserWarning: Inner Radius / wall thickness exceeds bounds 5 <= R_i/t <= 20, R_i/t = 43.33497536945812, violating Anderson solution limits.
wr.warn('Inner Radius / wall thickness exceeds bounds ' +
[12]:
fig, ax1 = plt.subplots(figsize=(4,4))
ax1.plot(analysis_aovert.nominal_load_cycling[0]['Total cycles'],
analysis_aovert.nominal_load_cycling[0]['a/t'],
'r-', label='a/t')
ax1.plot(analysis_aovert.nominal_life_criteria['Cycles to a(crit)'][0],
analysis_aovert.nominal_life_criteria['Cycles to a(crit)'][1],
'r*')
ax1.plot(analysis_cycles.nominal_load_cycling[0]['Total cycles'],
analysis_cycles.nominal_load_cycling[0]['a/t'],
'b--', label='cycles')
ax1.plot(analysis_cycles.nominal_life_criteria['Cycles to a(crit)'][0],
analysis_cycles.nominal_life_criteria['Cycles to a(crit)'][1],
'b.')
ax1.set_xlabel('Total cycles')
ax1.set_ylabel('a/t')
ax1.legend(loc=0, title='Differential of')
plt.grid(color='gray', alpha=0.3, linestyle='--')
[13]:
flaw_depth = TruncatedLognormalDistribution(name='flaw_depth',
uncertainty_type='aleatory',
nominal_value=25,
mu=3.2,
sigma=.17,
upper_bound=80,
lower_bound=0.001) # initial flaw depth, % wall thickness
stress_intensity_method = 'anderson'
surface = 'inside'
delta_c_rule = 'proportional'
samples = 50
sample_type = 'lhs'
[14]:
%%time
analysis_aovert_prob = CrackEvolutionAnalysis(outer_diameter=outer_diameter,
wall_thickness=wall_thickness,
max_pressure=max_pressure,
min_pressure=min_pressure,
temperature=temperature,
volume_fraction_h2=volume_fraction_h2,
yield_strength=yield_strength,
fracture_resistance=fracture_resistance,
flaw_depth=flaw_depth,
flaw_length=flaw_length,
stress_intensity_method=stress_intensity_method,
surface=surface,
delta_c_rule=delta_c_rule,
aleatory_samples=samples,
sample_type=sample_type,
random_seed=1234,
max_cycles=2e4)
analysis_aovert_prob.perform_study()
CPU times: user 41.9 ms, sys: 54.8 ms, total: 96.7 ms
Wall time: 2.34 s
/Users/bbschro/Development/helpr/src/helpr/utilities/postprocessing.py:359: UserWarning: Cycles to a_crit not reached for at least one crack, setting a_crit = Nan for such cracks
wr.warn('Cycles to a_crit not reached for at least one crack, ' +
[15]:
%%time
analysis_cycles_prob = CrackEvolutionAnalysis(outer_diameter=outer_diameter,
wall_thickness=wall_thickness,
max_pressure=max_pressure,
min_pressure=min_pressure,
temperature=temperature,
volume_fraction_h2=volume_fraction_h2,
yield_strength=yield_strength,
fracture_resistance=fracture_resistance,
flaw_depth=flaw_depth,
flaw_length=flaw_length,
stress_intensity_method=stress_intensity_method,
surface=surface,
delta_c_rule=delta_c_rule,
cycle_step=1,
aleatory_samples=samples,
sample_type=sample_type,
random_seed=1234,
max_cycles=2e4)
analysis_cycles_prob.perform_study()
CPU times: user 466 ms, sys: 112 ms, total: 577 ms
Wall time: 3.4 s
[16]:
fig, ax1 = plt.subplots(figsize=(6,4))
plt.plot([], [], 'r-', label='a/t')
plt.plot([], [], 'b--', label='cycles')
for i in range(samples):
ax1.plot(analysis_aovert_prob.load_cycling[i]['Total cycles'],
analysis_aovert_prob.load_cycling[i]['a/t'],
'r-')
ax1.plot(analysis_cycles_prob.load_cycling[i]['Total cycles'],
analysis_cycles_prob.load_cycling[i]['a/t'],
'b--')
ax1.plot(analysis_aovert_prob.life_criteria['Cycles to a(crit)'][0],
analysis_aovert_prob.life_criteria['Cycles to a(crit)'][1],
'r*')
ax1.plot(analysis_cycles_prob.life_criteria['Cycles to a(crit)'][0],
analysis_cycles_prob.life_criteria['Cycles to a(crit)'][1],
'b.')
ax1.set_xlabel('Total cycles')
ax1.set_ylabel('a/t')
ax1.legend(loc=0, title='Differential of')
plt.grid(color='gray', alpha=0.3, linestyle='--')