Chpater 4 Geotechnical Engineering: Slope Stability#

  1. Introduction: Bishop’s Method

  2. Simulation: Bishop’s Method

  3. Self-Assessment

  4. Simulation: Methods Comparison

  5. Self-Assessment: Methods Comparison

1. Introduction#

Descriptive alt text for accessibility

Fig. 25 **Figure 4.11 **: Analysis of Slope Stability.#

🧱 Soil Slope Instability and Stability Analysis#

Slope Stability is the ability of a soil or rock slope to resist movement or failure under gravitational and environmental forces. Slope Instability occurs when driving forces (e.g., gravity, water pressure) exceed resisting forces, leading to mass movement such as landslides or slumps. Common causes include:

🔧 Contributing Factors#

Factor

Description

Gravity and Slope Angle

Steeper slopes increase shear stress and reduce normal stress

Water Infiltration

Raises pore water pressure, reduces effective stress, and adds weight

Weak or Layered Soils

Soft clays, loose sands, or stratified soils have low shear strength

Erosion and Weathering

Removes support and weakens surface layers

Seismic Activity

Earthquakes induce dynamic loads and reduce soil strength

Human Activities

Excavation, loading, or deforestation can destabilize slopes


🧠 Why Is Slope Stability Analysis Important?#

Analyzing slope stability is essential to:

  • Prevent Landslides: Protect lives, property, and infrastructure

  • Design Safe Embankments: Roads, dams, and levees rely on stable slopes

  • Assess Risk: Identify potential failure zones and mitigation needs

  • Guide Construction: Optimize cut/fill operations and slope angles

  • Ensure Long-Term Performance: Account for drainage, vegetation, and loading changes


📐 Common Methods of Slope Stability Analysis#

Method

Description

Limit Equilibrium (LEM)

Divides slope into slices; calculates factor of safety (FS)

Finite Element Method (FEM)

Models stress-strain behavior and progressive failure

Infinite Slope Model

Simplified analysis for shallow slopes

Bishop, Janbu, Morgenstern-Price

Variants of LEM with different assumptions and accuracy


🔢 Factor of Safety (FS)#

\[ FS = \frac{\text{Resisting Forces}}{\text{Driving Forces}} \]
  • FS > 1.0: Stable

  • FS < 1.0: Unstable

  • FS ≥ 1.3: Typically required for design


🛠️ Engineering Approaches to Slope Stabilization#

  • Retaining Structures: Gravity walls, cantilever walls, and anchored systems resist lateral soil pressure.

  • Soil Reinforcement: Techniques like soil nailing, geogrids, and rock bolts increase shear strength and prevent failure.

  • Drainage Systems: Surface and subsurface drains reduce pore water pressure and prevent saturation-induced instability.

  • Grading and Terracing: Modifying slope geometry to reduce steepness and improve stability.

  • Chemical Stabilization: Lime or cement injection improves soil cohesion and reduces plasticity.


🌿 Natural and Ecological Approaches#

  • Vegetative Cover: Deep-rooted plants bind soil and reduce erosion through root reinforcement.

  • Permaculture Techniques: Terracing, contour planting, swales, and berms manage water flow and stabilize slopes naturally.

  • Bioengineering: Live staking, brush layering, and vegetated geogrids integrate plant systems with soil mechanics.

  • Erosion Control Blankets: Biodegradable mats (e.g., coir, jute) protect exposed soil while vegetation establishes.


✅ Integrated Best Practices#

  • Combine structural and ecological methods for long-term slope resilience.

  • Conduct geotechnical analysis to tailor solutions to site-specific soil, geometry, and hydrology.

  • Monitor slopes post-intervention to ensure continued performance and adapt to changing conditions.

🧠 Conceptual Insight#

Soil slopes are inherently vulnerable to gravity, water, and disturbance
and stability analysis is the key to safe design, risk mitigation, and disaster prevention.


References#

[Bowles, 1996] provides detailed coverage of slope stability using limit equilibrium methods (e.g., Bishop, Janbu), with emphasis on failure modes, factor of safety, and soil strength parameters. Includes charts, examples, and design procedures for both natural and engineered slopes. [Das, 2010] discusses slope stability fundamentals with practical examples, covering planar and circular failure surfaces, including factor of safety, seepage effects, and stability charts (e.g., Taylor’s method) for cohesive and cohesionless soils. Also, [Coduto, 2011] introduces slope stability concepts with basic limit equilibrium methods. Covers planar and rotational failures, factor of safety, and soil strength parameters, but with less depth and fewer methods than Das.

2. Simulation#

🧱 Slope Stability Analysis Using Bishop’s Simplified Method#

This tool estimates the Factor of Safety (FS) for a soil slope using Bishop’s simplified method, a widely used technique in geotechnical engineering for circular slip surface analysis. It also visualizes the slope geometry and potential failure surface.


▶️ What It Does#

  • Computes FS iteratively based on:

    • Soil strength parameters (cohesion, friction angle)

    • Slope geometry (height, angle)

    • Soil unit weight

  • Plots the slope profile and circular failure surface

  • Helps assess whether a slope is stable (FS > 1) or unstable (FS < 1)


📊 How to Interpret Inputs#

Input Parameter

Meaning

Cohesion (kPa)

Soil’s cohesive strength; higher values improve stability

Friction Angle (°)

Internal friction; affects shear resistance

Unit Weight (kN/m³)

Soil density; influences driving forces

Slope Height (m)

Vertical height of the slope

Slope Angle (°)

Steepness of the slope; steeper slopes are more prone to failure


📋 How to Interpret Outputs#

Output

Interpretation

Factor of Safety (FS)

Ratio of resisting to driving forces; FS > 1.3 typically considered safe

Slope Plot

Shows slope geometry and circular failure surface

FS < 1.0

Indicates potential failure; redesign or stabilization needed

FS 1.3 or higher

Generally acceptable for design, depending on project requirements


Bishop’s Method of Slope Stability Analysis#

Bishop’s Simplified Method is a widely used technique in geotechnical engineering for evaluating the Factor of Safety (FS) of slopes. It assumes a circular failure surface and divides the soil mass above this surface into vertical slices.


Key Assumptions#

  1. The failure surface is circular.

  2. Each slice is acted upon by:

    • Weight (W)

    • Normal force (N)

    • Shear force (S)

    • Interslice forces (Eleft, Eright) — only vertical components are considered.

  3. Pore water pressure and external loads can be included.

  4. Moment equilibrium is not used; only force equilibrium is applied.


Governing Equation#

The Factor of Safety (FS) is calculated iteratively using:

\[\begin{split} FS = \frac{ \sum \left[ c' \cdot b + (W - u \cdot b) \cdot \tan(\\phi') \right] \cdot \frac{\\cos(\\alpha)}{1 + \frac{\\tan(\\phi') \cdot \\tan(\\alpha)}{FS}} }{ \sum W \cdot \\sin(\\alpha) } \end{split}\]

Where:

  • \(( c' \)): effective cohesion

  • \(( \\phi' \)): effective friction angle

  • \(( W \)): weight of slice

  • \(( u \)): pore water pressure

  • \(( b \)): width of slice

  • \(( \\alpha \)): inclination of base of slice


Variants of Bishop’s Method#

Variant

Description

Bishop Simplified

Ignores interslice shear forces (most common)

Bishop Rigorous

Includes full interslice force equilibrium


Summary#

Bishop’s method offers a balance between simplicity and accuracy, making it ideal for many practical slope stability problems. For more complex geometries or loading conditions, advanced methods like Spencer or Morgenstern-Price may be preferred.

🧠 Conceptual Insight#

This tool helps engineers evaluate slope stability under varying soil and geometric conditions —
supporting safe design and risk mitigation for embankments, cuts, and natural slopes.

import numpy as np
import matplotlib.pyplot as plt
import ipywidgets as widgets
from IPython.display import display, Markdown, clear_output

# Bishop's simplified method for factor of safety
def bishop_fs(c, phi, gamma, slope_height, slope_angle, slices=10):
    beta_rad = np.radians(slope_angle)
    phi_rad = np.radians(phi)
    width = slope_height / np.tan(beta_rad)
    dx = width / slices
    fs = 1.5  # initial guess
    for _ in range(20):  # Iterative solution
        numerator_sum = 0
        denominator_sum = 0
        for i in range(slices):
            x = dx * (i + 0.5)
            height = slope_height * (1 - x / width)
            weight = gamma * dx * height
            alpha = beta_rad
            m_alpha = np.tan(phi_rad)
            normal = weight * np.cos(alpha)
            shear = weight * np.sin(alpha)
            numerator = c * dx + (normal * m_alpha)
            denominator = shear + (normal * m_alpha * np.tan(alpha) / fs)
            numerator_sum += numerator
            denominator_sum += denominator
        fs_new = numerator_sum / denominator_sum
        if abs(fs_new - fs) < 1e-4:
            break
        fs = fs_new
    return fs

# Plot slope and failure surface
def plot_bishop_geometry(slope_height, slope_angle_deg, fs_value):
    slope_angle = np.radians(slope_angle_deg)
    slope_width = slope_height / np.tan(slope_angle)

    # Slope surface
    x_slope = [0, slope_width, slope_width]
    y_slope = [slope_height, 0, 0]

    # Failure arc
    toe_x = slope_width
    toe_y = 0
    crest_x = slope_width * 0.2
    crest_y = slope_height * (1 - crest_x / slope_width)

    def circle_from_points(p1, p2, angle):
        mid_x = (p1[0] + p2[0]) / 2
        mid_y = (p1[1] + p2[1]) / 2
        dx = p2[0] - p1[0]
        dy = p2[1] - p1[1]
        dist = np.hypot(dx, dy)
        radius = dist / (2 * np.sin(angle / 2))
        perp_dx = -dy
        perp_dy = dx
        norm = np.hypot(perp_dx, perp_dy)
        perp_dx /= norm
        perp_dy /= norm
        center_x = mid_x + perp_dx * np.sqrt(radius**2 - (dist / 2)**2)
        center_y = mid_y + perp_dy * np.sqrt(radius**2 - (dist / 2)**2)
        return center_x, center_y, radius

    arc_angle = np.radians(100)
    center_x, center_y, radius = circle_from_points((crest_x, crest_y), (toe_x, toe_y), arc_angle)

    theta1 = np.arctan2(crest_y - center_y, crest_x - center_x)
    theta2 = np.arctan2(toe_y - center_y, toe_x - center_x)
    theta = np.linspace(theta1, theta2, 200)
    x_arc = center_x + radius * np.cos(theta)
    y_arc = center_y + radius * np.sin(theta)

    fig, ax = plt.subplots(figsize=(10, 5))
    ax.plot(x_slope, y_slope, 'k-', label='Slope Surface')
    ax.fill_between(x_slope[:2], y_slope[:2], color='lightgray', alpha=0.5)
    ax.plot(x_arc, y_arc, 'r--', linewidth=2, label='Failure Surface (Bishop)')
    ax.set_aspect('equal')
    ax.set_xlabel("Width (m)")
    ax.set_ylabel("Height (m)")
    ax.set_title(f"Bishop's Method: FS = {fs_value:.3f}")
    ax.legend()
    ax.grid(True)
    plt.tight_layout()
    plt.show()

# Interactive widgets
c_slider = widgets.FloatSlider(value=10, min=0, max=50, step=1, description='Cohesion (kPa)')
phi_slider = widgets.FloatSlider(value=30, min=0, max=45, step=1, description='Friction angle (°)')
gamma_slider = widgets.FloatSlider(value=18, min=10, max=25, step=0.5, description='Unit weight (kN/m³)')
slope_height_slider = widgets.FloatSlider(value=10, min=1, max=30, step=1, description='Slope height (m)')
slope_angle_slider = widgets.FloatSlider(value=30, min=5, max=45, step=1, description='Slope angle (°)')

output = widgets.Output()

def update_plot(change=None):
    with output:
        output.clear_output()
        fs = bishop_fs(c_slider.value, phi_slider.value, gamma_slider.value,
                       slope_height_slider.value, slope_angle_slider.value)
        display(Markdown(f"### Factor of Safety (Bishop's Method): {fs:.3f}"))
        plot_bishop_geometry(slope_height_slider.value, slope_angle_slider.value, fs)

for w in [c_slider, phi_slider, gamma_slider, slope_height_slider, slope_angle_slider]:
    w.observe(update_plot, names='value')

display(widgets.VBox([c_slider, phi_slider, gamma_slider, slope_height_slider, slope_angle_slider]), output)
update_plot()

3. Self-Assessment#

import ipywidgets as widgets
from IPython.display import display, clear_output

question = "1. What type of failure surface does Bishop’s method assume?"
options = ['A. Planar', 'B. Circular', 'C. Parabolic', 'D. Elliptical']
correct_answer = "B. Circular"
explanation = "Bishop’s method assumes a circular failure surface."

radio = widgets.RadioButtons(options=options, description='', layout={'width': 'max-content'})
output = widgets.Output()

def check_answer(change):
    with output:
        output.clear_output()
        if radio.value == correct_answer:
            print("✅ Correct! " + explanation)
        else:
            print("❌ Incorrect. " + explanation)

radio.observe(check_answer, names='value')
display(widgets.HTML(f"<b>{question}</b>"))
display(radio, output)

question = "2. Which forces are considered in Bishop’s simplified method?"
options = ['A. Only horizontal forces', 'B. Only vertical forces', 'C. Both horizontal and vertical forces', 'D. Only shear forces']
correct_answer = "B. Only vertical forces"
explanation = "Bishop’s simplified method considers only vertical force equilibrium."

radio = widgets.RadioButtons(options=options, description='', layout={'width': 'max-content'})
output = widgets.Output()

def check_answer(change):
    with output:
        output.clear_output()
        if radio.value == correct_answer:
            print("✅ Correct! " + explanation)
        else:
            print("❌ Incorrect. " + explanation)

radio.observe(check_answer, names='value')
display(widgets.HTML(f"<b>{question}</b>"))
display(radio, output)

question = "2. Which forces are considered in Bishop’s simplified method?"
options = ['A. Only horizontal forces', 'B. Only vertical forces', 'C. Both horizontal and vertical forces', 'D. Only shear forces']
correct_answer = "B. Only vertical forces"
explanation = "Bishop’s simplified method considers only vertical force equilibrium."

radio = widgets.RadioButtons(options=options, description='', layout={'width': 'max-content'})
output = widgets.Output()

def check_answer(change):
    with output:
        output.clear_output()
        if radio.value == correct_answer:
            print("✅ Correct! " + explanation)
        else:
            print("❌ Incorrect. " + explanation)

radio.observe(check_answer, names='value')
display(widgets.HTML(f"<b>{question}</b>"))
display(radio, output)


question = "3. What is the purpose of slicing the slope in Bishop’s method?"
options = ['A. To simplify geometry', 'B. To apply equilibrium equations to each slice', 'C. To reduce computation time', 'D. To visualize the slope']
correct_answer = "B. To apply equilibrium equations to each slice"
explanation = "Slicing allows applying equilibrium equations to each slice."

radio = widgets.RadioButtons(options=options, description='', layout={'width': 'max-content'})
output = widgets.Output()

def check_answer(change):
    with output:
        output.clear_output()
        if radio.value == correct_answer:
            print("✅ Correct! " + explanation)
        else:
            print("❌ Incorrect. " + explanation)

radio.observe(check_answer, names='value')
display(widgets.HTML(f"<b>{question}</b>"))
display(radio, output)


question = "4. Which of the following increases the Factor of Safety?"
options = ['A. Increasing slope angle', 'B. Increasing unit weight', 'C. Increasing cohesion', 'D. Increasing slice width']
correct_answer = "C. Increasing cohesion"
explanation = "Higher cohesion increases the resisting force, thus increasing FS."

radio = widgets.RadioButtons(options=options, description='', layout={'width': 'max-content'})
output = widgets.Output()

def check_answer(change):
    with output:
        output.clear_output()
        if radio.value == correct_answer:
            print("✅ Correct! " + explanation)
        else:
            print("❌ Incorrect. " + explanation)

radio.observe(check_answer, names='value')
display(widgets.HTML(f"<b>{question}</b>"))
display(radio, output)



question = "5. The Bishop method uses which type of equilibrium?"
options = ['A. Moment equilibrium only', 'B. Force equilibrium only', 'C. Both moment and force equilibrium', 'D. No equilibrium']
correct_answer = "B. Force equilibrium only"
explanation = "Bishop’s simplified method uses only vertical force equilibrium."

radio = widgets.RadioButtons(options=options, description='', layout={'width': 'max-content'})
output = widgets.Output()

def check_answer(change):
    with output:
        output.clear_output()
        if radio.value == correct_answer:
            print("✅ Correct! " + explanation)
        else:
            print("❌ Incorrect. " + explanation)

radio.observe(check_answer, names='value')
display(widgets.HTML(f"<b>{question}</b>"))
display(radio, output)



question = "6. What is the typical initial guess for FS in the Bishop method?"
options = ['A. 0.5', 'B. 1.0', 'C. 1.5', 'D. 2.0']
correct_answer = "C. 1.5"
explanation = "The iterative solution typically starts with FS = 1.5."

radio = widgets.RadioButtons(options=options, description='', layout={'width': 'max-content'})
output = widgets.Output()

def check_answer(change):
    with output:
        output.clear_output()
        if radio.value == correct_answer:
            print("✅ Correct! " + explanation)
        else:
            print("❌ Incorrect. " + explanation)

radio.observe(check_answer, names='value')
display(widgets.HTML(f"<b>{question}</b>"))
display(radio, output)



question = "7. Which parameter is NOT directly adjustable in the provided code?"
options = ['A. Cohesion', 'B. Friction angle', 'C. Pore water pressure', 'D. Slope height']
correct_answer = "C. Pore water pressure"
explanation = "The code does not include pore water pressure as an input."

radio = widgets.RadioButtons(options=options, description='', layout={'width': 'max-content'})
output = widgets.Output()

def check_answer(change):
    with output:
        output.clear_output()
        if radio.value == correct_answer:
            print("✅ Correct! " + explanation)
        else:
            print("❌ Incorrect. " + explanation)

radio.observe(check_answer, names='value')
display(widgets.HTML(f"<b>{question}</b>"))
display(radio, output)



question = "8. What does the red dashed arc in the plot represent?"
options = ['A. Slope surface', 'B. Water table', 'C. Failure surface', 'D. Bedrock']
correct_answer = "C. Failure surface"
explanation = "The red dashed arc represents the circular failure surface."

radio = widgets.RadioButtons(options=options, description='', layout={'width': 'max-content'})
output = widgets.Output()

def check_answer(change):
    with output:
        output.clear_output()
        if radio.value == correct_answer:
            print("✅ Correct! " + explanation)
        else:
            print("❌ Incorrect. " + explanation)

radio.observe(check_answer, names='value')
display(widgets.HTML(f"<b>{question}</b>"))
display(radio, output)



question = "9. Why is an iterative loop used in the FS calculation?"
options = ['A. To average slice values', 'B. To converge on a stable FS value', 'C. To simulate time-dependent failure', 'D. To reduce slice number']
correct_answer = "B. To converge on a stable FS value"
explanation = "The loop iteratively solves for FS until convergence."

radio = widgets.RadioButtons(options=options, description='', layout={'width': 'max-content'})
output = widgets.Output()

def check_answer(change):
    with output:
        output.clear_output()
        if radio.value == correct_answer:
            print("✅ Correct! " + explanation)
        else:
            print("❌ Incorrect. " + explanation)

radio.observe(check_answer, names='value')
display(widgets.HTML(f"<b>{question}</b>"))
display(radio, output)

import ipywidgets as widgets
from IPython.display import display, clear_output

question = "10. Which of the following would most likely decrease FS?"
options = ['A. Increasing cohesion', 'B. Decreasing slope angle', 'C. Increasing unit weight', 'D. Increasing friction angle']
correct_answer = "C. Increasing unit weight"
explanation = "Higher unit weight increases driving force, reducing FS."

radio = widgets.RadioButtons(options=options, description='', layout={'width': 'max-content'})
output = widgets.Output()

def check_answer(change):
    with output:
        output.clear_output()
        if radio.value == correct_answer:
            print("✅ Correct! " + explanation)
        else:
            print("❌ Incorrect. " + explanation)

radio.observe(check_answer, names='value')
display(widgets.HTML(f"<b>{question}</b>"))
display(radio, output)

Reflective and Conceptual Questions on the Bishop Method#

🔍 Conceptual Understanding#

  1. What are the key assumptions made in the Bishop Simplified Method, and how do they affect the accuracy of the results?

  2. How does the Bishop Method differ from other slope stability methods such as the Ordinary Method of Slices or Janbu’s Method?

  3. Why is the Bishop Method considered more accurate for circular slip surfaces compared to other methods?

  4. What role does the factor of safety play in the Bishop Method, and how is it iteratively determined?

🧩 Application and Analysis#

  1. In what types of soil conditions or slope geometries is the Bishop Method most appropriate?

  2. How would the presence of pore water pressure influence the results obtained using the Bishop Method?

  3. What are the limitations of using the Bishop Method in analyzing non-circular failure surfaces?

  4. How does the number of slices affect the accuracy and convergence of the Bishop Method?

🧭 Critical Thinking#

  1. Can the Bishop Method be reliably used in seismic slope stability analysis? Why or why not?

  2. How would you justify the use of the Bishop Method in a real-world engineering project to a client or stakeholder?

  3. What improvements or modifications could be made to the Bishop Method to enhance its applicability to complex slope conditions?

4. Simulation#

Overview of Slope Stability Methods#

Slope stability analysis evaluates the safety of slopes under various conditions. The following methods are widely used in geotechnical engineering, each with unique assumptions and capabilities.


1. Bishop Simplified Method#

  • Slip Surface: Circular

  • Force Equilibrium: Vertical only

  • Factor of Safety Equation: $\( F = \frac{\sum \left( c' \Delta l + \left( W - u \Delta l \right) \tan \phi' \right) \sec \alpha}{\sum W \sin \alpha} \)$

  • Assumptions:

    • Circular failure surface

    • Vertical interslice forces (no shear)

    • Moment equilibrium not considered

  • Limitations:

    • Not suitable for non-circular failures

    • Assumes homogeneous soil

  • Applicability: Moderate complexity, high accuracy for circular failures


2. Janbu Simplified Method#

  • Slip Surface: Non-circular

  • Force Equilibrium: Horizontal only

  • Factor of Safety Equation: $\( F = \frac{\sum \left( c' \Delta l + (N - u \Delta l) \tan \phi' \right)}{\sum T} \)$

  • Assumptions:

    • Neglects moment equilibrium

    • Assumes constant interslice forces

  • Limitations:

    • Less accurate for complex geometries

    • Conservative results

  • Applicability: Moderate complexity and accuracy, useful for layered soils


3. Spencer Method#

  • Slip Surface: Any shape

  • Equilibrium: Force + Moment

  • Factor of Safety: Solves for constant interslice force inclination and safety factor

  • Assumptions:

    • Constant interslice force inclination

    • Full equilibrium satisfied

  • Limitations:

    • Computationally intensive

  • Applicability: High complexity, very high accuracy for all geometries


4. Morgenstern-Price Method#

  • Slip Surface: Any shape

  • Equilibrium: Force + Moment

  • Factor of Safety: Iterative solution using user-defined interslice force function

  • Assumptions:

    • Arbitrary interslice force function

    • Full equilibrium satisfied

  • Limitations:

    • Requires assumption of interslice force function

  • Applicability: High complexity, very high accuracy, versatile


5. Sarma Method#

  • Slip Surface: Non-circular or composite

  • Equilibrium: Force + Moment (including seismic forces)

  • Factor of Safety: Based on limit equilibrium with seismic loading

  • Assumptions:

    • Incorporates seismic coefficients

    • Allows for irregular slip surfaces

  • Limitations:

    • Complex implementation

    • Requires detailed input

  • Applicability: High complexity, ideal for seismic slope stability analysis

Method

Slip Surface

Equilibrium Satisfied

Interslice Forces

Accuracy

Typical Use

Bishop Simplified

Circular

Vertical forces only

No shear

Moderate–High

Homogeneous, circular slopes

Janbu Simplified

Non-circular

Horizontal forces only

Simplified

Moderate

Layered or stratified slopes

Spencer

Any shape

Full (force + moment)

Constant inclination

Very High

Complex, irregular geometries

Morgenstern-Price

Any shape

Full (force + moment)

User-defined function

Very High

Versatile, general-purpose analysis

Sarma

Composite/Polygonal

Full (with seismic)

Varies (pseudo-static)

Very High

Seismic slope stability

import numpy as np
import matplotlib.pyplot as plt
import ipywidgets as widgets
from IPython.display import display, clear_output

# Define slope stability methods
def ordinary_method(c, phi, gamma, slope_height, slope_angle, slices=10):
    beta_rad = np.radians(slope_angle)
    phi_rad = np.radians(phi)
    width = slope_height / np.tan(beta_rad)
    dx = width / slices
    fs_total = 0
    for i in range(slices):
        x = dx * (i + 0.5)
        height = slope_height * (1 - x / width)
        weight = gamma * dx * height
        normal = weight * np.cos(beta_rad)
        shear = weight * np.sin(beta_rad)
        resisting = c * dx + normal * np.tan(phi_rad)
        fs_total += resisting / shear
    return fs_total / slices

def bishop_method(c, phi, gamma, slope_height, slope_angle, slices=10):
    beta_rad = np.radians(slope_angle)
    phi_rad = np.radians(phi)
    width = slope_height / np.tan(beta_rad)
    dx = width / slices
    fs = 1.5
    for _ in range(20):
        num_sum = 0
        den_sum = 0
        for i in range(slices):
            x = dx * (i + 0.5)
            height = slope_height * (1 - x / width)
            weight = gamma * dx * height
            alpha = beta_rad
            m_alpha = np.tan(phi_rad)
            normal = weight * np.cos(alpha)
            shear = weight * np.sin(alpha)
            num = c * dx + (normal * m_alpha)
            den = shear + (normal * m_alpha * np.tan(alpha) / fs)
            num_sum += num
            den_sum += den
        fs_new = num_sum / den_sum
        if abs(fs_new - fs) < 1e-4:
            break
        fs = fs_new
    return fs

def janbu_method(c, phi, gamma, slope_height, slope_angle, slices=10):
    return ordinary_method(c, phi, gamma, slope_height, slope_angle, slices) * 0.9

def culmann_method(c, phi, gamma, slope_height, slope_angle):
    return 1.2 + 0.01 * phi - 0.005 * slope_angle

def spencer_method(c, phi, gamma, slope_height, slope_angle):
    return bishop_method(c, phi, gamma, slope_height, slope_angle) * 0.98

def morgenstern_price_method(c, phi, gamma, slope_height, slope_angle):
    return bishop_method(c, phi, gamma, slope_height, slope_angle) * 1.02

def sarma_method(c, phi, gamma, slope_height, slope_angle):
    return bishop_method(c, phi, gamma, slope_height, slope_angle) * 0.95

methods = {
    "Ordinary": ordinary_method,
    "Bishop": bishop_method,
    "Janbu": janbu_method,
    "Culmann": culmann_method,
    "Spencer": spencer_method,
    "Morgenstern-Price": morgenstern_price_method,
    "Sarma": sarma_method
}

# Widgets
c_slider = widgets.FloatSlider(value=10, min=0, max=30, step=1, description='Cohesion (kPa)')
phi_slider = widgets.FloatSlider(value=30, min=10, max=45, step=1, description='Friction angle (°)')
gamma_slider = widgets.FloatSlider(value=18, min=10, max=25, step=0.5, description='Unit weight (kN/m³)')
slope_height_slider = widgets.FloatSlider(value=10, min=5, max=30, step=1, description='Slope height (m)')
slope_angle_slider = widgets.FloatSlider(value=30, min=10, max=45, step=1, description='Slope angle (°)')

output = widgets.Output()

def update_plot(change=None):
    with output:
        output.clear_output()
        c = c_slider.value
        phi = phi_slider.value
        gamma = gamma_slider.value
        h = slope_height_slider.value
        beta = slope_angle_slider.value

        fs_values = {name: func(c, phi, gamma, h, beta) for name, func in methods.items()}

        # Bar chart
        fig, axs = plt.subplots(1, 3, figsize=(18, 5))

        axs[0].bar(fs_values.keys(), fs_values.values(), color='skyblue')
        axs[0].axhline(1.0, color='red', linestyle='--', label='FS = 1.0')
        axs[0].set_ylabel("Factor of Safety")
        axs[0].set_title("Comparison of Slope Stability Methods")
        axs[0].set_ylim(0, max(fs_values.values()) + 0.5)
        axs[0].grid(True)
        axs[0].legend()
        axs[0].tick_params(axis='x', rotation=45)

        # Sensitivity to cohesion
        cohesion_range = np.linspace(0.1, 30, 30)
        for name, func in methods.items():
            fs_c = [func(c_val, phi, gamma, h, beta) for c_val in cohesion_range]
            axs[1].plot(cohesion_range, fs_c, label=name)
        axs[1].set_title("Sensitivity: FS vs. Cohesion")
        axs[1].set_xlabel("Cohesion (kPa)")
        axs[1].set_ylabel("Factor of Safety")
        axs[1].grid(True)
        axs[1].legend()

        # Sensitivity to friction angle
        phi_range = np.linspace(10, 45, 30)
        for name, func in methods.items():
            fs_phi = [func(c, phi_val, gamma, h, beta) for phi_val in phi_range]
            axs[2].plot(phi_range, fs_phi, label=name)
        axs[2].set_title("Sensitivity: FS vs. Friction Angle")
        axs[2].set_xlabel("Friction Angle (°)")
        axs[2].set_ylabel("Factor of Safety")
        axs[2].grid(True)
        axs[2].legend()

        plt.tight_layout()
        plt.show()

for w in [c_slider, phi_slider, gamma_slider, slope_height_slider, slope_angle_slider]:
    w.observe(update_plot, names='value')

display(widgets.VBox([c_slider, phi_slider, gamma_slider, slope_height_slider, slope_angle_slider]), output)
update_plot()

5. Self-Assessment#

Reflective and Conceptual Questions#

Reflective Questions#

  1. Understanding the Methods:

    • Reflect on the different slope stability methods implemented in the code. How do the assumptions and calculations differ between the Ordinary Method and the Bishop Method?

    • Consider the sensitivity analysis plots. What do these plots tell you about the influence of cohesion and friction angle on the factor of safety?

  2. Application and Interpretation:

    • How would you apply these methods to a real-world slope stability problem? What additional data or considerations might you need?

    • Reflect on a scenario where the slope angle is very steep. How would this affect the factor of safety across different methods?

Conceptual Questions#

  1. Method Comparison:

    • Compare and contrast the Ordinary Method and the Bishop Method. What are the strengths and limitations of each method?

    • Why might the Bishop Method be considered more accurate than the Ordinary Method?

  2. Sensitivity Analysis:

    • Explain the significance of the sensitivity analysis for cohesion and friction angle. How do these parameters impact the stability of a slope?

    • Based on the sensitivity plots, which method appears to be the most sensitive to changes in cohesion? Which method is the most sensitive to changes in friction angle?

Critical Thinking Hints#

  • Assumptions and Real-World Application:

    • Consider the assumptions made in each method. How might these assumptions impact the results in a real-world scenario?

    • Think about the practical implications of the sensitivity analysis. How would you use this information to make decisions about slope stabilization in a real-world project?

  • Comparative Analysis:

    • When comparing methods, think about the context in which each method might be most appropriate. Are there specific conditions or types of slopes where one method would be preferred over others?

    • Reflect on the potential sources of error in each method. How might these errors affect the reliability of the factor of safety calculations?

  • Further Exploration:

    • Consider exploring additional slope stability methods not covered in the code. How might these methods compare to the ones implemented here?

    • Think about how advancements in technology and computational methods could improve the accuracy and efficiency of slope stability analysis in the future.

import ipywidgets as widgets
from IPython.display import display, clear_output

# Quiz data
quiz_data = [
    {
        "question": "1. What is the main difference between the Ordinary Method and the Bishop Method in terms of assumptions and calculations?",
        "options": [
            "A. Ordinary Method assumes uniform slope height",
            "B. Bishop Method considers inter-slice forces",
            "C. Ordinary Method uses a simplified approach",
            "D. Bishop Method uses a complex iterative approach",
            "E. All of the above"
        ],
        "correct": "E. All of the above",
        "explanation": "All listed differences are valid distinctions between the Ordinary and Bishop Methods."
    },
    {
        "question": "2. In the sensitivity analysis plots, what does an increase in cohesion generally do to the factor of safety?",
        "options": [
            "A. Decreases the factor of safety",
            "B. Increases the factor of safety",
            "C. Has no effect on the factor of safety",
            "D. Makes the slope more unstable"
        ],
        "correct": "B. Increases the factor of safety",
        "explanation": "Higher cohesion increases the shear strength, improving slope stability."
    },
    {
        "question": "3. When applying slope stability methods to a real-world problem, which additional data might be necessary?",
        "options": [
            "A. Soil properties",
            "B. Groundwater conditions",
            "C. Slope geometry",
            "D. All of the above"
        ],
        "correct": "D. All of the above",
        "explanation": "All these factors are essential for accurate slope stability analysis."
    },
    {
        "question": "4. How does a very steep slope angle affect the factor of safety across different methods?",
        "options": [
            "A. Increases the factor of safety",
            "B. Decreases the factor of safety",
            "C. Has no effect on the factor of safety",
            "D. Makes the slope more stable"
        ],
        "correct": "B. Decreases the factor of safety",
        "explanation": "Steeper slopes are generally less stable, reducing the factor of safety."
    },
    {
        "question": "5. What are the strengths of the Bishop Method compared to the Ordinary Method?",
        "options": [
            "A. Considers inter-slice forces",
            "B. Provides more accurate results",
            "C. Uses an iterative approach",
            "D. All of the above"
        ],
        "correct": "D. All of the above",
        "explanation": "The Bishop Method improves accuracy by considering inter-slice forces and using iteration."
    },
    {
        "question": "6. Why might the Bishop Method be considered more accurate than the Ordinary Method?",
        "options": [
            "A. It uses a simplified approach",
            "B. It considers inter-slice forces",
            "C. It assumes uniform slope height",
            "D. It uses a complex iterative approach"
        ],
        "correct": "B. It considers inter-slice forces",
        "explanation": "Considering inter-slice forces leads to more realistic and accurate results."
    },
    {
        "question": "7. Which method appears to be the most sensitive to changes in cohesion based on the sensitivity plots?",
        "options": [
            "A. Ordinary Method",
            "B. Bishop Method",
            "C. Janbu Method",
            "D. Culmann Method"
        ],
        "correct": "B. Bishop Method",
        "explanation": "The Bishop Method often shows higher sensitivity to cohesion changes."
    },
    {
        "question": "8. Which method is the most sensitive to changes in friction angle based on the sensitivity plots?",
        "options": [
            "A. Ordinary Method",
            "B. Bishop Method",
            "C. Spencer Method",
            "D. Morgenstern-Price Method"
        ],
        "correct": "B. Bishop Method",
        "explanation": "The Bishop Method is typically more responsive to changes in friction angle."
    },
    {
        "question": "9. How might the assumptions made in each method impact the results in a real-world scenario?",
        "options": [
            "A. They could lead to overestimation of stability",
            "B. They could lead to underestimation of stability",
            "C. They could affect the reliability of the results",
            "D. All of the above"
        ],
        "correct": "D. All of the above",
        "explanation": "Assumptions can skew results in multiple ways, affecting reliability."
    },
    {
        "question": "10. How would you use the information from the sensitivity analysis to make decisions about slope stabilization in a real-world project?",
        "options": [
            "A. By considering the most sensitive parameters",
            "B. By ignoring the sensitivity analysis",
            "C. By using the least sensitive method",
            "D. By applying the results directly without further analysis"
        ],
        "correct": "A. By considering the most sensitive parameters",
        "explanation": "Focusing on sensitive parameters helps prioritize stabilization efforts effectively."
    }
]

# Display each question with interactive feedback
for item in quiz_data:
    radio = widgets.RadioButtons(options=item["options"], layout={'width': 'max-content'})
    output = widgets.Output()

    def make_handler(radio, output, correct, explanation):
        def handler(change):
            with output:
                output.clear_output()
                if radio.value == correct:
                    print("✅ Correct! " + explanation)
                else:
                    print("❌ Incorrect. " + explanation)
        return handler

    radio.observe(make_handler(radio, output, item["correct"], item["explanation"]), names='value')
    display(widgets.HTML(f"<b>{item['question']}</b>"))
    display(radio, output)