Skip to content

Instantly share code, notes, and snippets.

@flare9x
Last active March 21, 2024 14:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save flare9x/b0b8995cac0680d4791075110e717155 to your computer and use it in GitHub Desktop.
Save flare9x/b0b8995cac0680d4791075110e717155 to your computer and use it in GitHub Desktop.
ASME Section VIII – Division 1 - Appendix 13
# ASME VIII 2017
# 13-4 DESIGN OF VESSELS OF NONCIRCULAR CROSS SECTION
# Figure 13-2(a) Vessels of Rectangular Cross Section
# Selection = Sketch (1)
#--- Begin single script - validate calculations against example problem
# ASME PTB-4-2013 - Example Problem - Header Box Data
# Material = SA516, Grade 70 (S)
S = 20000
# Design Conditions = 900 psig@350 F(P)
P = 400
# Inside Length (Short Side) = 10.625 in (H)
H = 7.125
# Inside Length (Long Side) = 126.0 in (h)
h = 9.25
# Overall Vessel Length = 346.38 + 8 in (Lv)
Lv = 40.0
# Thickness (Short Side) = 1.625 in (t1)
t1 = 1.0
# Thickness (Long Side) = 1.625 in (t2)
t2 = 1.0
# Thickness (End Plate) = 1.625 in (t5)
t5 = .75
# Corrosion Allowance = 0.125 in (CA)
CA = .125
# Weld Joint Efficiency (Corner Joint) = (E = 1.0) # 100% UT + Spot RT
E = 1.0
# Tube Outside Diameter = 1.0000 in
do = 1.0
# Tube Pitch = 2.3910 in
p = 2.3910
# Paragraph 13-5 – Calculate the equation constants.
h = h + 2*CA
H = H +2*(CA)
t1 = t1 - CA
t2 = t2 - CA
t5 = t5 - CA
t = t1 # Plates same t
# The design equations in this paragraph
# are based on vessels in which the ratio of the length of the vessel to the long side or short side
# lengths (aspect ratio) is greater than four. These equations are conservatively applicable to vessels
# of aspect ratio less than four. Vessels with aspect ratios less than four may be designed in
# accordance with the provisions of U-2(g).
if (Lv/h > 4) {
print("Satisfied")
} else if (Lv/h < 4) {
print("Not Satisifed")
}
# Paragraph 13-5 – Calculate the equation constants.
b = 1.0
c = t / 2 # The sign of ci is positive. The sign of co is negative
I1 = b*(t1^3) / 12
I2 = b*(t2^3) / 12
a = H/h
K = (I2/I1)*a
# Paragraph 13-7(a) – Calculate the membrane and membrane plus bending stresses.
# The membrane stress on the short side plate, Equation (1):
Sm_eq1 = (P * h) / (2*t1)
# The membrane stress on the long side plate, Equation (2):
# 13-6 LIGAMENT EFFICIENCY OF MULTIDIAMETER HOLES IN PLATES
# In calculations made according to this Appendix for the
# case of a plate with uniform diameter holes, the ligament
# efficiency factors em and eb for membrane and bending
# stresses, respectively, are considered to be the same.
em = (p - do) / p
eb = em
Sm_eq2 = (P * H) / (2 * t2 * em)
# The bending stress at Location N, short side plate, Equation (3):
SbN_eq3 = ((P*+c) / (12*I1)) * (-1.5 * (H)^2 + (h)^2*((1 + (a)^2 * K) / (1+K)))
SbN_eq3i = -SbN_eq3 # Inside is negative
SbN_eq3o = SbN_eq3 # Outside is positive
# The bending stress at Location Q, short side plate, Equation (4):
SbQ_eq4 = ((P * h^2 * c) / (12 * I1)) * ((1 + a^2 * K) / (1 + K))
SbQ_eq4i = SbQ_eq4 # Inside is positive
SbQ_eq4o = -SbQ_eq4 # Outside is negative
# The bending stress at Location M, long side plate, Equation (5):
SbM_eq5 = ((P * h^2 * c) / (12 * I2 * eb)) * (-1.5+(1+a^2*K) / (1 + K))
SbM_eq5i = SbM_eq5 # Inside is negative
SbM_eq5o = abs(SbM_eq5) # Outside is positive
# The bending stress at Location Q, long side plate, Equation (6):
SbQ_eq6 = (((P * h^2 * c) / (12 * I2)) * ((1 + a^2 * K) / (1 + K)))
SbQ_eq6i = SbQ_eq6 # Inside is positive
SbQ_eq6o = -SbQ_eq6 # Outside is negative
# Paragraphs 13-4(b), 13-4(c), and 13-7, Equations (7) through (10) – Acceptance Criteria:
if (Sm_eq1 <= (S * E)) {
cat("Short Side Membrane Stress",Sm_eq1,"psig is below Allowable Stress (S * E)", S*E,"psig")
}
# Short side plate at Location N, Membrane + Bending Stress:
N_totali = Sm_eq1 + SbN_eq3i
N_totalo = Sm_eq1 + SbN_eq3o
if (N_totali <= 1.5 * (S * E)) {
cat("Short Side Membrane + Bending Stress at location N (inside)",N_totali,"psig is below Allowable Stress 1.5*(S * E)", 1.5*(S*E),"psig")
}
if (N_totalo <= 1.5 * (S * E)) {
cat("Short Side Membrane + Bending Stress at location N (outside)",N_totalo,"psig is below Allowable Stress 1.5*(S * E)", 1.5*(S*E),"psig")
}
# Short side plate at Location Q, Membrane + Bending Stress:
Q_totali = Sm_eq1 + SbQ_eq4i
Q_totalo = Sm_eq1 + SbQ_eq4o
if (Q_totali <= 1.5 * (S * E)) {
cat("Short Side Membrane + Bending Stress at location Q (inside)",Q_totali,"psig is below Allowable Stress 1.5*(S * E)", 1.5*(S*E),"psig")
}
if (Q_totalo <= 1.5 * (S * E)) {
cat("Short Side Membrane + Bending Stress at location Q (outside)",Q_totalo,"psig is below Allowable Stress 1.5*(S * E)", 1.5*(S*E),"psig")
}
# Long side plate, Membrane Stress:
if (Sm_eq2 <= (S * E)) {
cat("Short Side Membrane Stress",Sm_eq2,"psig is below Allowable Stress (S * E)", S*E,"psig")
}
# Long side plate at Location M, Membrane + Bending Stress:
M_totali = Sm_eq2 + SbM_eq5i
M_totalo = Sm_eq2 + SbM_eq5o
if (M_totali <= 1.5 * (S * E)) {
cat("True - Long Side Membrane + Bending Stress at location M (inside)",M_totali,"psig is below Allowable Stress 1.5*(S * E)", 1.5*(S*E),"psig")
} else if (M_totali > 1.5 * (S * E)) {
cat("Flase - Long Side Membrane + Bending Stress at location M (inside)",M_totali,"psig is above Allowable Stress 1.5*(S * E)", 1.5*(S*E),"psig")
}
if (M_totalo <= 1.5 * (S * E)) {
cat("True - Long Side Membrane + Bending Stress at location M (outside)",M_totalo,"psig is below Allowable Stress 1.5*(S * E)", 1.5*(S*E),"psig")
} else if (M_totalo > 1.5 * (S * E)) {
cat("False - Long Side Membrane + Bending Stress at location M (outside)",M_totalo,"psig is above Allowable Stress 1.5*(S * E)", 1.5*(S*E),"psig")
}
# Long side plate at Location Q, Membrane + Bending Stress:
Q_totali = Sm_eq2 + SbQ_eq6i
Q_totalo = Sm_eq2 + SbQ_eq6o
if (Q_totali <= 1.5 * (S * E)) {
cat("True - Long Side Membrane + Bending Stress at location Q (inside)",Q_totali,"psig is below Allowable Stress 1.5*(S * E)", 1.5*(S*E),"psig")
} else if (Q_totali > 1.5 * (S * E)) {
cat("Flase - Long Side Membrane + Bending Stress at location Q (inside)",Q_totali,"psig is above Allowable Stress 1.5*(S * E)", 1.5*(S*E),"psig")
}
if (Q_totalo <= 1.5 * (S * E)) {
cat("True - Long Side Membrane + Bending Stress at location Q (outside)",Q_totalo,"psig is below Allowable Stress 1.5*(S * E)", 1.5*(S*E),"psig")
} else if (Q_totalo > 1.5 * (S * E)) {
cat("False - Long Side Membrane + Bending Stress at location Q (outside)",Q_totalo,"psig is above Allowable Stress 1.5*(S * E)", 1.5*(S*E),"psig")
}
#--- End single script
#--- Begin iterative script
# Iterate to find the failure thickness's
S = 20000
P = 400
H = 7.125
h = 9.25
Lv = 40.0
t1 = 1.0
t2 = 1.0
t5 = .75
CA = .125
E = 1.0
do = 1.0
p = 2.3910
# Substitute t1 and t2 for a range of thickness
t1 = seq(from=0.01,to=3.05,by=0.05)
t2 = seq(from=0.01,to=3.05,by=0.05)
# Establish this appendix can be used
if (Lv/h > 4) {
print("Satisfied")
} else if (Lv/h < 4) {
print("Not Satisifed")
}
# Iterate through varying t1 and t2 thickness to find failure points
# Initialize output
output = data.frame(short_side_membrane_stress = numeric(0), short_side_membrane_plus_bending_stress_at_location_N_inside = numeric(0), short_side_membrane_plus_bending_stress_at_location_N_outside = numeric(0),
short_side_membrane_plus_bending_stress_at_location_Q_inside = numeric(0), short_side_membrane_plus_bending_stress_at_location_Q_outside = numeric(0),
long_side_membrane_stress = numeric(0),long_side_membrane_plus_bending_stress_at_location_M_inside = numeric(0),long_side_membrane_plus_bending_stress_at_location_M_outside = numeric(0),
long_side_membrane_plus_bending_stress_at_location_Q_inside = numeric(0), long_side_membrane_plus_bending_stress_at_location_Q_outside = numeric(0),t1_thickness = numeric(0),t2_thickness = numeric(0), all_pass = numeric(0))
for (i in 1:length(t1)) {
# Paragraph 13-5 – Calculate the equation constants.
b = 1.0
c = t1[i] / 2 # The sign of ci is positive. The sign of co is negative
I1 = b*(t1[i]^3) / 12
I2 = b*(t2[i]^3) / 12
a = H/h
K = (I2/I1)*a
# Paragraph 13-7(a) – Calculate the membrane and membrane plus bending stresses.
# The membrane stress on the short side plate, Equation (1):
Sm_eq1 = (P * h) / (2*t1[i])
# The membrane stress on the long side plate, Equation (2):
em = (p - do) / p
eb = em
Sm_eq2 = (P * H) / (2 * t2[i] * em)
# The bending stress at Location N, short side plate, Equation (3):
SbN_eq3 = ((P*+c) / (12*I1)) * (-1.5 * (H)^2 + (h)^2*((1 + (a)^2 * K) / (1+K)))
SbN_eq3i = -SbN_eq3 # Inside is negative - compression
SbN_eq3o = SbN_eq3 # Outside is positive + positive
# The bending stress at Location Q, short side plate, Equation (4):
SbQ_eq4 = ((P * h^2 * c) / (12 * I1)) * ((1 + a^2 * K) / (1 + K))
SbQ_eq4i = SbQ_eq4 # Inside is positive + positive
SbQ_eq4o = -SbQ_eq4 # Outside is negative - compression
# The bending stress at Location M, long side plate, Equation (5):
SbM_eq5 = ((P * h^2 * c) / (12 * I2 * eb)) * (-1.5+(1+a^2*K) / (1 + K))
SbM_eq5i = SbM_eq5 # Inside is negative - compression
SbM_eq5o = abs(SbM_eq5) # Outside is positive + positive
# The bending stress at Location Q, long side plate, Equation (6):
SbQ_eq6 = (((P * h^2 * c) / (12 * I2)) * ((1 + a^2 * K) / (1 + K)))
SbQ_eq6i = SbQ_eq6 # Inside is positive + positive
SbQ_eq6o = -SbQ_eq6 # Outside is negative - compression
# Paragraphs 13-4(b), 13-4(c), and 13-7, Equations (7) through (10) – Acceptance Criteria:
# 1 = true, 0 = false
if (Sm_eq1 <= (S * E)) {
short_side_membrane_stress = 1
} else if (Sm_eq1 > (S * E)) {
short_side_membrane_stress = 0
}
# Short side plate at Location N, Membrane + Bending Stress:
N_totali = Sm_eq1 + SbN_eq3i
N_totalo = Sm_eq1 + SbN_eq3o
if (N_totali <= 1.5 * (S * E)) {
short_side_membrane_plus_bending_stress_at_location_N_inside = 1
} else if (N_totali > 1.5 * (S * E)) {
short_side_membrane_plus_bending_stress_at_location_N_inside = 0
}
if (N_totalo <= 1.5 * (S * E)) {
short_side_membrane_plus_bending_stress_at_location_N_outside = 1
} else if (N_totalo > 1.5 * (S * E)) {
short_side_membrane_plus_bending_stress_at_location_N_outside = 0
}
# Short side plate at Location Q, Membrane + Bending Stress:
Q_totali = Sm_eq1 + SbQ_eq4i
Q_totalo = Sm_eq1 + SbQ_eq4o
if (Q_totali <= 1.5 * (S * E)) {
short_side_membrane_plus_bending_stress_at_location_Q_inside = 1
} else if (Q_totali > 1.5 * (S * E)) {
short_side_membrane_plus_bending_stress_at_location_Q_inside = 0
}
if (Q_totalo <= 1.5 * (S * E)) {
short_side_membrane_plus_bending_stress_at_location_Q_outside = 1
} else if (Q_totalo > 1.5 * (S * E)) {
short_side_membrane_plus_bending_stress_at_location_Q_outside = 0
}
# Long side plate, Membrane Stress:
if (Sm_eq2 <= (S * E)) {
long_side_membrane_stress = 1
} else if (Sm_eq2 > (S * E)) {
long_side_membrane_stress = 0
}
# Long side plate at Location M, Membrane + Bending Stress:
M_totali = Sm_eq2 + SbM_eq5i
M_totalo = Sm_eq2 + SbM_eq5o
if (M_totali <= 1.5 * (S * E)) {
long_side_membrane_plus_bending_stress_at_location_M_inside = 1
} else if (M_totali > 1.5 * (S * E)) {
long_side_membrane_plus_bending_stress_at_location_M_inside = 0
}
if (M_totalo <= 1.5 * (S * E)) {
long_side_membrane_plus_bending_stress_at_location_M_outside = 1
} else if (M_totalo > 1.5 * (S * E)) {
long_side_membrane_plus_bending_stress_at_location_M_outside = 0
}
# Long side plate at Location Q, Membrane + Bending Stress:
Q_totali = Sm_eq2 + SbQ_eq6i
Q_totalo = Sm_eq2 + SbQ_eq6o
if (Q_totali <= 1.5 * (S * E)) {
long_side_membrane_plus_bending_stress_at_location_Q_inside = 1
} else if (Q_totali > 1.5 * (S * E)) {
long_side_membrane_plus_bending_stress_at_location_Q_inside = 0
}
if (Q_totalo <= 1.5 * (S * E)) {
long_side_membrane_plus_bending_stress_at_location_Q_outside = 1
} else if (Q_totalo > 1.5 * (S * E)) {
long_side_membrane_plus_bending_stress_at_location_Q_outside = 0
}
t1_thickness = t1[i]
t2_thickness = t2[i]
# For varying t1,t2 check if Stresses at N,M and Q (inside and outside) Pass
test_all_pass = sum(short_side_membrane_stress,short_side_membrane_plus_bending_stress_at_location_N_inside,short_side_membrane_plus_bending_stress_at_location_N_outside,
short_side_membrane_plus_bending_stress_at_location_Q_inside,short_side_membrane_plus_bending_stress_at_location_Q_outside,long_side_membrane_stress,
long_side_membrane_plus_bending_stress_at_location_M_inside,long_side_membrane_plus_bending_stress_at_location_M_outside,long_side_membrane_plus_bending_stress_at_location_Q_inside,
long_side_membrane_plus_bending_stress_at_location_Q_outside)
if(test_all_pass == 10) {
all_pass = 1
} else if (test_all_pass != 10) {
all_pass = 0
}
temp_row = data.frame(short_side_membrane_stress,short_side_membrane_plus_bending_stress_at_location_N_inside,short_side_membrane_plus_bending_stress_at_location_N_outside,
short_side_membrane_plus_bending_stress_at_location_Q_inside,short_side_membrane_plus_bending_stress_at_location_Q_outside,long_side_membrane_stress,
long_side_membrane_plus_bending_stress_at_location_M_inside,long_side_membrane_plus_bending_stress_at_location_M_outside,long_side_membrane_plus_bending_stress_at_location_Q_inside,
long_side_membrane_plus_bending_stress_at_location_Q_outside,t1_thickness,t2_thickness,all_pass)
output = rbind(output,temp_row)
} # end
# Find first passing thickness (tmin)
for (i in 2:nrow(output)) {
if(output$all_pass[i-1] == 0 & output$all_pass[i] == 1) {
tmin = max(output$t1_thickness[i],output$t2_thickness[i])
}
}
cat("Resulting Pressure Tmin = ",tmin)
# plot data
t = output$t1_thickness
index = 1:nrow(output)
plot(x = index,y = t, xlab = "No.", ylab = "t", main = "Thickness Needed For Stresses At Location N, M and Q To All Pass", cex.main=1.0,axes = FALSE,col = ifelse(t < tmin,'red','green'), pch = 19 )
axis(side = 1, at = 1:length(t),labels = 1:length(t), las =1,cex.axis=.7,tck = 0, lty = 2, col = "grey")
axis(side = 2, at = seq(from=0.01,to=3.05,by=0.05),labels = seq(from=0.01,to=3.05,by=0.05), las =0,cex.axis=.7,tck = 0, lty = 2)
box()
abline(h=tmin)
text(13, 1.0, expression("Tmin = 0.86"), col = "black")
text(25, .7, expression("Thickness = Fail"), col = "red")
text(55, 2.0, expression("Thickness = Pass"), col = "green")
#--- End iterative script
@alagrana
Copy link

Hello flare9x. Do you have a user manual of it?. Looks very interesting !

@gargtarang
Copy link

Hello flare9x. Do you have a user manual of it?. Looks very interesting !
ASME Section VIII Div 1 Mandatory Appendix 13

@joe-mcnamera
Copy link

how do i run this?

@flare9x
Copy link
Author

flare9x commented Nov 18, 2022

its written for R. There's a single script for a given plate thickness - what the stresses are, end line 157. There is another script that at a specified plate dimension, will iterate over a 'range' of plate thickness's and check that the stresses induced are within code allowable stress - that output is saved in a dataframe and the plot at the bottom will show this result as well. Run script in R, RStudio.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment