Mohr circle for strains#
Β© 2022 Exneyder A. Montoya-Araque, Daniel F. Ruiz and Universidad EAFIT.
This notebook can be interactively run in Google - Colab.
This notebook was developed following the theory presented in Ch. 1 - Book Mohr Circles, Stress Paths and Geotechnics (2nd Ed.) by Parry [2014].
Required modules and global setup for plots#
import ast
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from ipywidgets import widgets as wgt
from IPython import get_ipython
from IPython.display import display
if 'google.colab' in str(get_ipython()):
print('Running on CoLab. Installing the required modules...')
from subprocess import run
# run('pip install ipympl', shell=True);
from google.colab import output
output.enable_custom_widget_manager()
# Figures setup
# %matplotlib widget
mpl.rcParams.update({
"font.family": "serif",
"font.serif": ["Computer Modern Roman", "cmr", "cmr10", "DejaVu Serif"], # or
"mathtext.fontset": "cm", # Use Computer Modern fonts for math
"axes.formatter.use_mathtext": True, # Use mathtext for axis labels
"axes.unicode_minus": False, # Use standard minus sign instead of a unicode character
})
Funciones#
def get_strain_state(π_xx, π_yy, π_xy):
c = 0.5 * (π_xx + π_yy)
r = np.sqrt((π_xx - c) ** 2 + π_xy**2)
π_1 = r * np.cos(0) + c
π_3 = r * np.cos(np.pi) + c
strain_state = {
"π_1": π_1,
"π_3": π_3,
"π_xx": π_xx,
"π_yy": π_yy,
"π_xy": π_xy,
"π_vol": (π_1 + π_3),
"0.5*πΎ_max": r,
"r": r,
"c": c
}
return strain_state
def get_xy_from_angle(angle, r, c):
x, y = r * np.cos(2*np.deg2rad(angle)) + c, r * np.sin(2*np.deg2rad(angle))
return x, y
def plot_mohr_circle(π_xx, π_yy, π_xy, plot_pole=False, plot_plane=False, π=10,
xlim=None, ylim=None, **kwargs):
strain_state = get_strain_state(π_xx, π_yy, π_xy)
pole = (π_xx, -1 * π_xy)
angles4circ = np.linspace(0, 2 * np.pi, 200)
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=kwargs.get('figsize'))
ax.plot(strain_state['r'] * np.cos(angles4circ) + strain_state['c'],
strain_state['r'] * np.sin(angles4circ), c="k") # Mohr circle
ax.axhline(y=0, c="k")
params = {'ls': "", "fillstyle": 'none', "markeredgewidth": 2, "ms": 7}
label = ("$\\varepsilon_{xx}=$" + f"{π_xx:.2f}" + ",\n$\\varepsilon_{xy}=$" + f"{π_xy:.2f}")
ax.plot(π_xx, π_xy, c="C3", marker="s", label=label, **params) # π_xx, π_xy
label = ("$\\varepsilon_{yy}=$" + f"{π_yy:.2f}" + ",\n$\\varepsilon_{yx}=$" + f"{π_xy:.2f}")
ax.plot(π_yy, -1 * π_xy, c="C4", marker="s", label=label, **params) # π_yy, (-)π_xy
ax.plot(strain_state['c'], 0, ls="", c="k", marker=(8, 2, 0), ms=10) # Mean strain (center)
label = "$0.5\\gamma_\mathrm{max}=$" + f"{strain_state['r']:.2f}" # Max shear str (radius)
ax.plot(strain_state['c'], strain_state['r'], c="C2", marker='v', label=label, **params)
label = "$\\varepsilon_{1}=$" + f"{strain_state['π_1']:.2f}" # epsilon_1
ax.plot(strain_state['π_1'], 0, c="C0", marker= "o", label=label, **params)
label = "$\\varepsilon_{3}=$" + f"{strain_state['π_3']:.2f}" # epsilon_3
ax.plot(strain_state['π_3'], 0, c="C1", marker= "o", label=label, **params)
if plot_pole: # Pole and stress on a plane
ax.axvline(x=pole[0], c="C3", ls="-", lw=1.25)
ax.axhline(y=pole[1], c="C4", ls="-", lw=1.25)
ax.plot(*pole, ls="", c="k", marker=".", fillstyle='full', ms=7,
label=f"$P\ ({pole[0]:.2f}, {pole[1]:.2f})$")
if plot_plane:
π½ = 0.5 * np.degrees(np.arctan2(2 * π_xy, π_yy - π_xx))
π = -(π + π½)
π_dir, π_shr = get_xy_from_angle(π, strain_state['r'], strain_state['c'])
ax.plot((strain_state['c'], π_yy, π_xx), (0, -π_xy, -π_xy), c="k", ls="--",
lw=1.25, label="Plane $\\varepsilon_y$")
label=f"Plane at $\\omega={π:.1f}$" + \
"$^{\\circ}\\circlearrowright$\nfrom Plane $\\varepsilon_y$"
ax.plot((π_dir, pole[0]), (π_shr, pole[1]), c="C5", ls="--", lw=1.25, label=label)
label = f"Plane at $2\\omega={2*π:.1f}$" + \
"$^{\\circ}\\circlearrowright$\nfrom Plane $\\varepsilon_y$"
ax.plot((π_dir, strain_state['c']), (π_shr, 0), c="C6", ls="--", lw=1.25, label=label)
label = ("Strains on the plane\n" + "$\\varepsilon=$" + f"{π_dir:.2f}"
+ ", $0.5\\gamma=$" + f"{π_shr:.2f}")
ax.plot(π_dir, π_shr, ls="", c="k", marker=".", label=label)
ax.legend(loc="center left", bbox_to_anchor=(1, 0.5))
ax.grid(True, ls="--")
ax.spines["bottom"].set_linewidth(1.5)
ax.spines["left"].set_linewidth(1.5)
ax.set_aspect("equal", anchor=None)
ax.set(
xlabel="Direct strain, $\\varepsilon$",
ylabel="Shear strain, $0.5\\gamma$",
xlim=xlim,
ylim=ylim
)
return strain_state
def plot_zero_ext_comp_lines(πΏπ_h, πΏπ_v, plot_plane=False, π=10, xlim=None,
ylim=None, **kwargs):
πΏπ_1, πΏπ_3 = max(πΏπ_h, πΏπ_v), min(πΏπ_h, πΏπ_v) # Principal strains
def getlbl(πΏπ):
lb = 'h' if πΏπ == πΏπ_h else 'v'
return '$\\delta\\varepsilon_\\mathrm{'+lb+'}=$'
strain_state = get_strain_state(πΏπ_1, πΏπ_3, 0)
angles4circ = np.linspace(0, 2 * np.pi, 200)
pole = (πΏπ_h, 0)
π = np.rad2deg(np.arcsin(-strain_state['c'] / (strain_state['r'])))
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=kwargs.get('figsize'))
ax.plot(strain_state['r'] * np.cos(angles4circ) + strain_state['c'],
strain_state['r'] * np.sin(angles4circ), c="k") # Mohr circle
params = {'ls': "", "fillstyle": 'none', "markeredgewidth": 1.75, "ms": 7}
label = ("$\\delta\\varepsilon_1=$" + getlbl(πΏπ_1) + f"{πΏπ_1:.2f}")
ax.plot(πΏπ_1, 0, c="C0", marker="o", label=label, **params) # πΏπ_1
label = ("$\delta\\varepsilon_3=$" + getlbl(πΏπ_3) + f"{πΏπ_3:.2f}")
ax.plot(πΏπ_3, 0, c="C1", marker="o", label=label, **params) # πΏπ_3
ax.plot(strain_state['c'], 0, ls="", c="k", marker=(8, 2, 0), ms=10) # Mean strain (center)
label = "$0.5\\delta\\gamma_\mathrm{max}=$" + f"{strain_state['r']:.2f}" # Max shear str (radius)
ax.plot(strain_state['c'], strain_state['r'], c="C2", marker='v', label=label, **params)
label = "$0.5\\delta\\varepsilon_\\mathrm{vol}=" + f"{strain_state['c']:.3f}$" + \
f"\n$\\hookrightarrow \\psi={π:.1f}$" + "$^{\circ}$"
ax.plot((strain_state['c'], 0), (0, 0), c="grey", ls="-", lw=3, label=label) # πΏv/2)
# Zero extension lines
π½ = 0.5 * np.degrees(np.arctan2(0, πΏπ_v - πΏπ_h))
π_zero = np.rad2deg(0.5 * np.arccos(-strain_state['c'] / strain_state['r']))
π_dir, π_shr = get_xy_from_angle(π_zero, strain_state['r'], strain_state['c'])
ax.plot((π_dir, πΏπ_h, π_dir), (π_shr, 0, -π_shr), c="k", ls="--", lw=1.25,
label="Zero direct strain planes\n($\\delta\\varepsilon=0$)")
π_dir, π_shr = get_xy_from_angle(π_zero-90, strain_state['r'], strain_state['c'])
ax.plot((π_dir, πΏπ_h, π_dir), (π_shr, 0, -π_shr), c="k", ls="-", lw=1.25,
label="Zero extension lines")
# Arbitrary plane
if plot_plane:
ax.plot((πΏπ_v, πΏπ_h), (0, 0), c="C3", ls="--", lw=1.25,
label="Plane $\\delta\\varepsilon_\\mathrm{v}$")
π = -(π + π½)
π_dir, π_shr = get_xy_from_angle(π, strain_state['r'], strain_state['c'])
label=f"Plane at $\\omega={π:.1f}$" + \
"$^{\circ}\\circlearrowright$\nfrom Plane $\\delta\\varepsilon_1$"
ax.plot((π_dir, pole[0]), (π_shr, pole[1]), c="C4", ls="--", lw=1.25, label=label)
label = f"Plane at $2\\omega={2*π:.1f}$" + \
"$^{\circ}\\circlearrowright$\nfrom Plane $\\delta\\varepsilon_\\mathrm{v}$"
ax.plot((π_dir, strain_state['c']), (π_shr, 0), c="C5", ls="--", lw=1.25, label=label)
label = ("Strains on the plane\n" + "$\\varepsilon=$" + f"{π_dir:.2f}"
+ ", $0.5\\gamma=$" + f"{π_shr:.2f}")
ax.plot(π_dir, π_shr, ls="", c="k", marker="o", fillstyle='none', label=label)
ax.plot(*pole, ls="", c="k", marker=".", fillstyle='full', ms=7, # Pole
label=f"$P\ ({pole[0]:.2f}, {pole[1]:.2f})$")
# Plot settings
ax.legend(loc="center left", bbox_to_anchor=(1, 0.5))
ax.grid(True, ls="--")
ax.spines["bottom"].set_linewidth(1.5)
ax.spines["left"].set_linewidth(1.5)
ax.set_aspect("equal", anchor=None)
ax.set(xlabel="$\\delta\\varepsilon$", ylabel="$\\delta0.5\delta\\gamma$",
xlim=xlim, ylim=ylim)
return
Ejemplo bΓ‘sico del Circulo de Mohr#
# plot_mohr_circle(π_xx=30, π_yy=20, π_xy=10)
plot_mohr_circle(π_xx=-0.01, π_yy=0.2, π_xy=-0.2, plot_pole=True)
{'π_1': 0.3208871399615304,
'π_3': -0.13088713996153037,
'π_xx': -0.01,
'π_yy': 0.2,
'π_xy': -0.2,
'π_vol': 0.19000000000000003,
'0.5*πΎ_max': 0.22588713996153037,
'r': 0.22588713996153037,
'c': 0.095}

s, l = {'description_width': '60px'}, wgt.Layout(width='400px')
s_env, l_env = {'description_width': '60px'}, wgt.Layout(width='190px')
controls = {
'Ξ΅_xx': wgt.FloatSlider(value=-0.1, min=-1, max=1, description="π_xx", style=s, layout=l),
'Ξ΅_yy': wgt.FloatSlider(value=0.2, min=-1, max=1, description="π_yy", style=s, layout=l),
'Ξ΅_xy': wgt.FloatSlider(value=-0.2, min=-1, max=1, description="π_xy", style=s, layout=l),
'plot_pole': wgt.Checkbox(value=False, description="Plot pole?", style=s, layout=l),
'plot_plane': wgt.Checkbox(value=False, description="Plot a plane? β ", style=s_env, layout=wgt.Layout(width='180px')),
'Ο': wgt.FloatSlider(value=10, min=0, max=180, step=0.2, description="π", style={'description_width': '10px'}, layout=wgt.Layout(width='220px')),
'xlim': wgt.FloatRangeSlider(value=[-.3, .5], min=-1, max=1, step=.5, description='x-axis:', readout_format='.0f', style=s, layout=l),
'ylim': wgt.FloatRangeSlider(value=[-.3, .3], min=-1, max=1, step=.5, description='y-axis:', readout_format='.0f', style=s, layout=l),
'static_fig': wgt.Checkbox(value=True, description='Non-vector image (improve widget performance)', disabled=False, style=s, layout=l)
}
c_all = list(controls.values())
c_pln = [wgt.HBox(c_all[4:6])]
c = c_all[:4] + c_pln + c_all[6:]
fig = wgt.interactive_output(plot_mohr_circle, controls)
wgt.HBox((wgt.VBox(c), fig), layout=wgt.Layout(align_items='center'))
Lineas de cero extensiΓ³n en el cΓrculo de Mohr#
plot_zero_ext_comp_lines(πΏπ_h=-0.16, πΏπ_v=0.094, plot_plane=True, π=25)
plot_zero_ext_comp_lines(πΏπ_h=0.16, πΏπ_v=-0.094, plot_plane=True, π=25)
plot_zero_ext_comp_lines(πΏπ_h=-0.094, πΏπ_v=0.16, plot_plane=True, π=25)



s, l = {'description_width': '60px'}, wgt.Layout(width='400px')
s_env, l_env = {'description_width': '60px'}, wgt.Layout(width='190px')
controls = {
'δΡ_h': wgt.FloatSlider(value=-0.16, min=-1, max=1, step=.0001, description="πΏπ_h", readout_format='.4f', style=s, layout=l),
'δΡ_v': wgt.FloatSlider(value=0.0942, min=-1, max=1, step=.0001, description="πΏπ_v", readout_format='.4f', style=s, layout=l),
'plot_plane': wgt.Checkbox(value=False, description="Plot a plane? β ", style=s_env, layout=wgt.Layout(width='180px')),
'Ο': wgt.FloatSlider(value=10, min=0, max=180, step=1, description="π", style={'description_width': '10px'}, layout=wgt.Layout(width='220px')),
'xlim': wgt.FloatRangeSlider(value=[-.2, .2], min=-1, max=1, step=.02, description='x-axis:', readout_format='.2f', style=s, layout=l),
'ylim': wgt.FloatRangeSlider(value=[-.15, .15], min=-1, max=1, step=.02, description='y-axis:', readout_format='.2f', style=s, layout=l),
'static_fig': wgt.Checkbox(value=True, description='Non-vector image (improve widget performance)', disabled=False, style=s, layout=l)
}
c_all = list(controls.values())
c_pln = [wgt.HBox(c_all[2:4])]
c = c_all[:2] + c_pln + c_all[4:]
fig = wgt.interactive_output(plot_zero_ext_comp_lines, controls)
wgt.HBox((wgt.VBox(c), fig), layout=wgt.Layout(align_items='center'))