#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'Bruno Stuyts'
# Native Python packages
# 3rd party packages
import numpy as np
# Project imports
from groundhog.general.validation import Validator
STRESSES_POINTLOAD = {
'pointload': {'type': 'float', 'min_value': None, 'max_value': None},
'z': {'type': 'float', 'min_value': None, 'max_value': None},
'r': {'type': 'float', 'min_value': None, 'max_value': None},
'poissonsratio': {'type': 'float', 'min_value': 0.0, 'max_value': 0.5},
}
STRESSES_POINTLOAD_ERRORRETURN = {
'delta sigma z [kPa]': np.nan,
'delta sigma r [kPa]': np.nan,
'delta sigma theta [kPa]': np.nan,
'delta tau rz [kPa]': np.nan,
}
[docs]
@Validator(STRESSES_POINTLOAD, STRESSES_POINTLOAD_ERRORRETURN)
def stresses_pointload(
pointload, z, r, poissonsratio,
**kwargs):
"""
Calculates the stresses at a point below a line load according the solution proposed by Boussinesq (1885). The vertical stress increase is calculated as well as the increases in radial and tangential stress
:param pointload: Magnitude of the point load (:math:`Q`) [:math:`kN`]
:param z: Vertical distance from the surface to the point where the stresses are calculated (:math:`z`) [:math:`m`]
:param r: Radial distance from the surface to the point where the stresses are calculated (:math:`r`) [:math:`m`]
:param poissonsratio: Poisson's ratio (:math:`\\nu`) [:math:`-`] - Suggested range: 0.0 <= poissonsratio <= 0.5
.. math::
\\Delta \\sigma_z = \\frac{3Q}{2 \\pi z^2 \\left[ 1 + \\left( \\frac{r}{z} \\right)^2 \\right]^{5/2}}
\\Delta \\sigma_r = \\frac{Q}{2 \\pi} \\left( \\frac{3 r^2 z}{(r^2 + z^2)^{5/2}} - \\frac{1 - 2 \\nu}{r^2 + z^2 + z \\left( r^2 + z^2 \\right)^{1/2}}\\right)
\\Delta \\sigma_{\\theta} = \\frac{Q}{2 \\pi} \\left( 1 - 2 \\nu \\right) \\left( \\frac{z}{\\left( r^2 + z^2 \\right)^{3/2}} - \\frac{1}{r^2 + z^2 + z \\left( r^2 + z^2 \\right)^{1/2} } \\right)
\\Delta \\tau_{rz} = \\frac{3 Q}{2 \\pi} \\left[ \\frac{r z^2}{\\left( r^2 + z^2 \\right)^{5/2}} \\right]
:returns: Dictionary with the following keys:
- 'delta sigma z [kPa]': Increase in vertical normal stress (:math:`\\Delta \\sigma_z`) [:math:`kPa`]
- 'delta sigma r [kPa]': Increase in radial normal stress (:math:`\\Delta \\sigma_r`) [:math:`kPa`]
- 'delta sigma theta [kPa]': Increase in tangential normal stress (:math:`\\Delta \\sigma_{\\theta}`) [:math:`kPa`]
- 'delta tau rz [kPa]': Increase in shear stress in the rz plane (:math:`\\Delta \\tau_{rz}`) [:math:`kPa`]
.. figure:: images/stresses_pointload_1.png
:figwidth: 500.0
:width: 450.0
:align: center
Nomenclature used for point load stress calculation (Budhu, 2011)
Reference - Budhu (2011). Soil mechanics and foundation engineering
"""
_delta_sigma_z = (3 * pointload) / (
(2 * np.pi * z ** 2) *
(1 + (r / z) ** 2 ) ** (5/2) )
_delta_sigma_r = (pointload / (2 * np.pi)) * \
(
((3 * r ** 2 * z) / ((r ** 2 + z ** 2) ** (5/2))) -
(1 - 2 * poissonsratio) / (r ** 2 + z ** 2 + z * np.sqrt(r ** 2 + z ** 2))
)
_delta_sigma_theta = (pointload / (2 * np.pi)) * (1 - 2 * poissonsratio) * (
(z / ((r ** 2 + z ** 2) ** (3 / 2))) -
(1 / (r ** 2 + z ** 2 + z * np.sqrt(r ** 2 + z ** 2)))
)
_delta_tau_rz = ((3 * pointload) / (2 * np.pi)) * (
(r * z ** 2) /
((r ** 2 + z ** 2) ** (5 / 2))
)
return {
'delta sigma z [kPa]': _delta_sigma_z,
'delta sigma r [kPa]': _delta_sigma_r,
'delta sigma theta [kPa]': _delta_sigma_theta,
'delta tau rz [kPa]': _delta_tau_rz,
}
STRESSES_STRIPLOAD = {
'z': {'type': 'float', 'min_value': 0.0, 'max_value': None},
'x': {'type': 'float', 'min_value': None, 'max_value': None},
'width': {'type': 'float', 'min_value': 0.0, 'max_value': None},
'imposedstress': {'type': 'float', 'min_value': None, 'max_value': None},
'triangular': {'type': 'bool', },
}
STRESSES_STRIPLOAD_ERRORRETURN = {
'delta sigma z [kPa]': np.nan,
'delta sigma x [kPa]': np.nan,
'delta tau zx [kPa]': np.nan,
}
[docs]
@Validator(STRESSES_STRIPLOAD, STRESSES_STRIPLOAD_ERRORRETURN)
def stresses_stripload(z, x, width, imposedstress, triangular=False, **kwargs):
"""
Calculates the stress redistribution at a point in the subsoil due to a strip load with a given width, applied at the surface.
Two cases can be specified. By default, a uniform load is specified, but the stresses under a triangular load can also be calculated.
:param z: Vertical distance from the soil surface (:math:`z`) [:math:`m`] - Suggested range: z >= 0.0
:param x: Horizontal offset from the leftmost corner of the strip footing (:math:`x`) [:math:`m`]
:param width: Width of the strip footing (:math:`B`) [:math:`m`] - Suggested range: width >= 0.0
:param imposedstress: Maximum value of the imposed force per unit area (:math:`q_s`) [:math:`kN/m^2`]
:param triangular: Boolean determining whether a triangular load pattern is applied (optional, default= False)
.. math::
R_1 = \\sqrt{x^2 + z^2}
R_2 = \\sqrt{(x - B)^2 + z^2}
\\cos \\left(\\alpha + \\beta \\right) = z / R_1
\\cos \\beta = z / R_2
\\text{Uniform load}
\\Delta \\sigma_z = \\frac{q_s}{\\pi} \\left[ \\alpha + \\sin \\alpha \\cos \\left( \\alpha + 2 \\beta \\right) \\right]
\\Delta \\sigma_x = \\frac{q_s}{\\pi} \\left[ \\alpha - \\sin \\alpha \\cos \\left( \\alpha + 2 \\beta \\right) \\right]
\\Delta \\tau_{zx} = \\frac{q_s}{\\pi} \\left[ \\sin \\alpha \\sin \\left( \\alpha + 2 \\beta \\right) \\right]
\\text{Triangular load}
\\Delta \\sigma_z = \\frac{q_s}{\\pi} \\left( \\frac{x}{B} \\alpha - \\frac{1}{2} \\sin 2 \\beta \\right)
\\Delta \\sigma_x = \\frac{q_s}{\\pi} \\left( \\frac{x}{B} \\alpha - \\frac{z}{B} \\ln \\frac{R_1^2}{R_2^2} + \\frac{1}{2} \\sin 2 \\beta \\right)
\\Delta \\tau_zx = \\frac{q_s}{2 \\pi} \\left( 1 + \\cos 2 \\beta - 2 \\frac{z}{B} \\alpha \\right)
:returns: Dictionary with the following keys:
- 'delta sigma z [kPa]': Increase in vertical stress due to surface load (:math:`\\Delta \\sigma_z`) [:math:`kPa`]
- 'delta sigma x [kPa]': Increase in horizontal stress due to surface load (:math:`\\Delta \\sigma_x`) [:math:`kPa`]
- 'delta tau zx [kPa]': Increase in shear stress due to surface load (:math:`\\Delta \\tau_{zx}`) [:math:`kPa`]
.. figure:: images/stresses_stripload_1.png
:figwidth: 500.0
:width: 450.0
:align: center
Nomenclature for inputs in stress calculation due to a strip footing
Reference - Budhu (2011). Soil mechanics and foundation engineering
"""
R_1 = np.sqrt(x ** 2 + z ** 2)
R_2 = np.sqrt((x - width) ** 2 + z ** 2)
_theta1 = np.arccos(z / R_1)
_theta2 = np.arccos(z / R_2)
if x < width:
_theta2 = -_theta2
beta = _theta2
alpha = _theta1 - beta
if triangular:
# Calculation for triangular stress distribution
_delta_sigma_z = (imposedstress / np.pi) * (
(x / width) * alpha -
0.5 * np.sin(2 * beta)
)
_delta_sigma_x = (imposedstress / np.pi) * (
(x / width) * alpha -
(z / width) * np.log((R_1 ** 2) / (R_2 ** 2)) +
0.5 * np.sin(2 * beta)
)
_delta_tau_zx = (imposedstress / (2 * np.pi)) * (
1 +
np.cos(2 * beta) -
2 * (z / width) * alpha
)
else:
# Calculation for uniform stress distribution
_delta_sigma_z = (imposedstress / np.pi) * (
alpha +
np.sin(alpha) * np.cos(alpha + 2 * beta)
)
_delta_sigma_x = (imposedstress / np.pi) * (
alpha -
np.sin(alpha) * np.cos(alpha + 2 * beta)
)
_delta_tau_zx = (imposedstress / np.pi) * (
np.sin(alpha) * np.sin(alpha + 2 * beta)
)
return {
'delta sigma z [kPa]': _delta_sigma_z,
'delta sigma x [kPa]': _delta_sigma_x,
'delta tau zx [kPa]': _delta_tau_zx,
}
STRESSES_CIRCLE = {
'z': {'type': 'float', 'min_value': 0.0, 'max_value': None},
'footing_radius': {'type': 'float', 'min_value': 0.0, 'max_value': None},
'imposedstress': {'type': 'float', 'min_value': None, 'max_value': None},
'poissonsratio': {'type': 'float', 'min_value': 0.0, 'max_value': 0.5},
}
STRESSES_CIRCLE_ERRORRETURN = {
'delta sigma z [kPa]': np.nan,
'delta sigma r [kPa]': np.nan,
}
[docs]
@Validator(STRESSES_CIRCLE, STRESSES_CIRCLE_ERRORRETURN)
def stresses_circle(z, footing_radius, imposedstress, poissonsratio, **kwargs):
"""
Calculates the stress distribution below a uniformly loaded circular foundation. The stresses are calculated below the center of the circular foundation
:param z: Depth below the base of the foundation (:math:`z`) [:math:`m`] - Suggested range: z >= 0.0
:param footing_radius: Radius of the circular foundation (:math:`r_0`) [:math:`m`] - Suggested range: footing_radius >= 0.0
:param imposedstress: Applied uniform stress to the circular footing (:math:`q_s`) [:math:`kPa`]
:param poissonsratio: Poissons ratio for the soil material (:math:`\\nu`) [:math:`-`] - Suggested range: 0.0 <= poissonsratio <= 0.5
.. math::
\\Delta \\sigma_z = q_s \\left[ 1 - \\left( \\frac{1}{1 + (r_0 / z)^2} \\right)^{3/2} \\right]
\\Delta \\sigma_r = \\Delta \\sigma_{\\theta} = \\frac{q_s}{2} \\left[ (1 + 2 \\nu) - \\frac{4 (1 + \\nu)}{\\sqrt{1 + (r_0 / z)^2}} + \\frac{1}{\\left[ 1 + (r_0 / z)^2 \\right]^{3/2}} \\right]
:returns: Dictionary with the following keys:
- 'delta sigma z [kPa]': Vertical stress increase (:math:`\\Delta \\sigma_z`) [:math:`kPa`]
- 'delta sigma r [kPa]': Radial stress increase (:math:`\\Delta \\sigma_r`) [:math:`kPa`]
Reference - Budhu (2011). Soil mechanics and foundation engineering
"""
_delta_sigma_z = imposedstress * (
1 -
(1 / (1 + ((footing_radius / z) ** 2))) ** (3 / 2)
)
_delta_sigma_r = 0.5 * imposedstress * (
(1 + 2 * poissonsratio) -
(4 * (1 + poissonsratio)) / np.sqrt(1 + (footing_radius / z) ** 2) +
(1 / ((1 + ((footing_radius / z) ** 2)) ** (3 / 2)))
)
return {
'delta sigma z [kPa]': _delta_sigma_z,
'delta sigma r [kPa]': _delta_sigma_r,
}
STRESSES_RECTANGLE = {
'imposedstress': {'type': 'float', 'min_value': None, 'max_value': None},
'length': {'type': 'float', 'min_value': 0.0, 'max_value': None},
'width': {'type': 'float', 'min_value': 0.0, 'max_value': None},
'z': {'type': 'float', 'min_value': 0.0, 'max_value': None},
}
STRESSES_RECTANGLE_ERRORRETURN = {
'delta sigma z [kPa]': np.nan,
'delta sigma x [kPa]': np.nan,
'delta sigma y [kPa]': np.nan,
'delta tau zx [kPa]': np.nan,
}
[docs]
@Validator(STRESSES_RECTANGLE, STRESSES_RECTANGLE_ERRORRETURN)
def stresses_rectangle(
imposedstress, length, width, z,
**kwargs):
"""
Calculates the stresses under the corner of a uniformly loaded rectangular area. Stresses under other points can be calculated by subdividing the rectangular in smaller sub-rectangles and using superposition stresses (justified because the solution is elastic). E.g. the stresses under the center of a rectangle is calculated by subdividing the rectangle into four equal sub-areas and calculating the stress below the corner of each and summing them.
:param imposedstress: Stress applied to the uniformly loaded area (:math:`q_s`) [:math:`kPa`]
:param length: Dimension of the longest edge of the rectangle (:math:`L`) [:math:`m`] - Suggested range: length >= 0.0
:param width: Dimension of the shortest edge of the rectangle (:math:`B`) [:math:`m`] - Suggested range: width >= 0.0
:param z: Depth below the footing (:math:`z`) [:math:`m`] - Suggested range: z >= 0.0
.. math::
\\Delta \\sigma_z = \\frac{q_s}{2 \\pi} \\left[ \\tan^{-1) \\frac{L B}{z R_3} + \\frac{L B z}{R_3} \\left( \\frac{1}{R_1^2} + \\frac{1}{R_2^2} \\right) \\right]
\\Delta \\sigma_x = \\frac{q_s}{2 \\pi} \\left[ \\tan^{-1) \\frac{L B}{z R_3} - \\frac{L B z}{R_1^2 R_3} \\right]
\\Delta \\sigma_y = \\frac{q_s}{2 \\pi} \\left[ \\tan^{-1) \\frac{L B}{z R_3} - \\frac{L B z}{R_2^2 R_3} \\right]
\\Delta \\tau_{zx} = \\frac{q_s}{2 \\pi} \\left[ \\frac{B}{R_2} - \\frac{z^2 B}{R_1^2 R_3} \\right]
\\text{where}
R_1 = \\sqrt{L^2 + z^2}
R_2 = \\sqrt{B^2 + z^2}
R_3 = \\sqrt{L^2 + B^2 + z^2}
:returns: Dictionary with the following keys:
- 'delta sigma z [kPa]': Increase in vertical stress below the corner of the footing (:math:`\\Delta \\sigma_z`) [:math:`kPa`]
- 'delta sigma x [kPa]': Increase in horizontal stress in the width direction below the corner of the footing (:math:`\\Delta \\sigma_x`) [:math:`kPa`]
- 'delta sigma y [kPa]': Increase in horizontal stress in the length direction below the corner of the footing (:math:`\\Delta \\sigma_y`) [:math:`kPa`]
- 'delta tau zx [kPa]': Increase in shear stress in the zx plane below the corner of the footing (:math:`\\Delta \\tau_{zx}`) [:math:`kPa`]
.. figure:: images/stresses_rectangle_1.png
:figwidth: 500.0
:width: 450.0
:align: center
Nomenclature used for calculation of stresses below the corner of a uniformly loaded rectangle
Reference - Budhu (2011). Soil mechanics and foundation engineering
"""
R_1 = np.sqrt(length ** 2 + z ** 2)
R_2 = np.sqrt(width ** 2 + z ** 2)
R_3 = np.sqrt(length ** 2 + width ** 2 + z ** 2)
_delta_sigma_z = (imposedstress / (2 * np.pi)) * (
np.arctan((length * width) / (z * R_3)) +
((length * width * z) / R_3) * ((1 / R_1 ** 2) + (1 / (R_2 ** 2)))
)
_delta_sigma_x = (imposedstress / (2 * np.pi)) * (
np.arctan((length * width) / (z * R_3)) -
((length * width * z) / ((R_1 ** 2) * R_3))
)
_delta_sigma_y = (imposedstress / (2 * np.pi)) * (
np.arctan((length * width) / (z * R_3)) -
((length * width * z) / ((R_2 ** 2) * R_3))
)
_delta_tau_zx = (imposedstress / (2 * np.pi)) * (
(width / R_2) -
((z ** 2 * width) / (R_1 **2 * R_3))
)
return {
'delta sigma z [kPa]': _delta_sigma_z,
'delta sigma x [kPa]': _delta_sigma_x,
'delta sigma y [kPa]': _delta_sigma_y,
'delta tau zx [kPa]': _delta_tau_zx,
}