[17]:
%matplotlib inline
%load_ext autoreload
%autoreload 2
The autoreload extension is already loaded. To reload it, use:
  %reload_ext autoreload
[18]:
import math
import numpy as np
import matplotlib.pyplot as plt

from helpr.api import CrackEvolutionAnalysis
from helpr.physics.pipe import Pipe
from helpr.physics.crack_initiation import DefectSpecification
from helpr.physics.environment import EnvironmentSpecification
from helpr.physics.material import MaterialSpecification
from helpr.physics.stress_state import InternalAxialHoopStress
from helpr.physics.crack_growth import CrackGrowth, get_design_curve
from helpr.physics.life_assessment import LifeAssessment
from helpr.physics.fracture import calculate_failure_assessment

from helpr.utilities.unit_conversion import convert_psi_to_mpa, convert_in_to_m
from helpr.utilities.plots import generate_pipe_life_assessment_plot
from helpr.utilities.postprocessing import calc_pipe_life_criteria, report_single_pipe_life_criteria_results, report_single_cycle_evolution

from probabilistic.capabilities.uncertainty_definitions import DeterministicCharacterization

Single Deterministic Pipeline Lifetime Evaluation

Problem Specification

  • Geometry

[19]:
pipe_outer_diameter = convert_in_to_m(36)  # 36 inch outer diameter
wall_thickness = convert_in_to_m(0.406)    # 0.406 inch wall thickness
  • Material Properties

[20]:
yield_strength = convert_psi_to_mpa(52_000)      # material yield strength of 52_000 psi
fracture_resistance = 55                     # fracture resistance (toughness) MPa m1/2
  • Operating Conditions

[21]:
max_pressure = convert_psi_to_mpa(840)   # maximum pressure during oscillation MPa
min_pressure = convert_psi_to_mpa(638)   # minimum pressure during oscillation (or R = 0.75)
temperature = 293                         # K -> temperature of gas degrees C
volume_fraction_h2 = 1                      # % mole fraction H2 in natural gas blend
  • Initial Crack Dimensions

[22]:
flaw_depth = 25      # flaw 25% through pipe thickness
flaw_length = convert_in_to_m(1.575)   # width of initial crack/flaw, m
  • Physics Modeling Choices

[23]:
stress_intensity_method = 'anderson'  # Stress intensity factor method used
surface = 'inside'

Modular Analysis

  • Create Pipe Object

[24]:
pipe_module = Pipe(outer_diameter=pipe_outer_diameter,
                   wall_thickness=wall_thickness)
  • Specify Pipe Material Properties

[25]:
material_module = MaterialSpecification(yield_strength=yield_strength,
                                        fracture_resistance=fracture_resistance)
  • Specify Defect

[26]:
defect_module = DefectSpecification(flaw_depth=flaw_depth,
                                    flaw_length=flaw_length,
                                    surface=surface)
  • Specify Pipe Gaseous Environment

[27]:
environment_module = EnvironmentSpecification(max_pressure=max_pressure,
                                              min_pressure=min_pressure,
                                              temperature=temperature,
                                              volume_fraction_h2=volume_fraction_h2)
  • Determine Stress Environment on Pipe

[28]:
stress_module = InternalAxialHoopStress(pipe=pipe_module,
                                        environment=environment_module,
                                        material=material_module,
                                        defect=defect_module,
                                        stress_intensity_method=stress_intensity_method)
/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 ' +
  • Specify Crack Growth Model

[29]:
crack_growth_module = CrackGrowth(environment=environment_module,
                                  growth_model_specification={'model_name': 'code_case_2938'})
  • Evolve Cracks Over Cycles to Failure

[30]:
pipe_evaluation = LifeAssessment(pipe_specification=pipe_module,
                                 stress_state=stress_module,
                                 crack_growth=crack_growth_module,
                                 delta_c_rule='proportional')
load_cycling = pipe_evaluation.calc_life_assessment(max_cycles=math.inf, cycle_step=None)
  • Postprocess QoIs (life criteria)

[31]:
input_parameter_values = {'flaw_depth': [flaw_depth],
                          'max_pressure': [max_pressure],
                          'min_pressure': [min_pressure],
                          'temperature': [temperature],
                          'volume_fraction_h2': [volume_fraction_h2],
                          'outer_diameter': [pipe_outer_diameter],
                          'wall_thickness': [wall_thickness],
                          'yield_strength': [yield_strength],
                          'fracture_resistance': [fracture_resistance],
                          'flaw_length': [flaw_length]}

calculate_failure_assessment(input_parameter_values,
                             [load_cycling],
                             [stress_module],
                             fad_type='simple')

life_criteria = calc_pipe_life_criteria(cycle_results=load_cycling,
                                        pipe=pipe_module,
                                        material=material_module)
  • Plot QoI

[32]:
specific_life_criteria_result = report_single_pipe_life_criteria_results(life_criteria, pipe_index=0)
specific_load_cycling = report_single_cycle_evolution(load_cycling, pipe_index=0)
generate_pipe_life_assessment_plot(specific_load_cycling, specific_life_criteria_result, pipe_name='Test Pipe')
plt.savefig('./Figures/deterministic_crack_growth.png', format='png', dpi=300)
              Cycles to a(crit)  Cycles to 25% a(crit)  Cycles to 1/2 Nc  \
Total cycles        5669.412446               1.000000       2834.706223
a/t                    0.333509               0.083377          0.270803

              Cycles to FAD line
Total cycles         4872.658604
a/t                     0.302642
_images/demo_deterministic_32_1.png

Interact with Modular Analysis Through API

  • Specify Problem, Initiate Crack, and Evolve Crack to Failure

[33]:
analysis = CrackEvolutionAnalysis(outer_diameter=DeterministicCharacterization(name='outer_diameter', value=pipe_outer_diameter),
                                  wall_thickness=DeterministicCharacterization(name='wall_thickness', value=wall_thickness),
                                  flaw_depth=DeterministicCharacterization(name='flaw_depth', value=flaw_depth),
                                  max_pressure=DeterministicCharacterization(name='max_pressure', value=max_pressure),
                                  min_pressure=DeterministicCharacterization(name='min_pressure', value=min_pressure),
                                  temperature=DeterministicCharacterization(name='temperature', value=temperature),
                                  volume_fraction_h2=DeterministicCharacterization(name='volume_fraction_h2', value=volume_fraction_h2),
                                  yield_strength=DeterministicCharacterization(name='yield_strength', value=yield_strength),
                                  fracture_resistance=DeterministicCharacterization(name='fracture_resistance', value=fracture_resistance),
                                  flaw_length=DeterministicCharacterization(name='flaw_length', value=flaw_length),
                                  stress_intensity_method=stress_intensity_method,
                                  surface=surface,
                                  fad_type='simple',
                                  cycle_step=1)
analysis.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 ' +
  • Postprocess and Plot QoI

[34]:
analysis.postprocess_single_crack_results()
_, _ = analysis.get_design_curve_plot()
plt.savefig('./Figures/deterministic_crack_growth_rate.png', format='png', dpi=300)

_, _ = analysis.assemble_failure_assessment_diagram()
              Cycles to a(crit)  Cycles to 25% a(crit)  Cycles to 1/2 Nc  \
Total cycles        5702.066633               1.000000       2851.033316
a/t                    0.333509               0.083377          0.270839

              Cycles to FAD line
Total cycles         4898.324240
a/t                     0.302642
_images/demo_deterministic_37_1.png
_images/demo_deterministic_37_2.png
_images/demo_deterministic_37_3.png
[35]:
analysis.save_results()
[35]:
'Results/date_30_03_2026_time_16_31/'