Source code for pylife.materiallaws.hookeslaw

# Copyright (c) 2019-2023 - for information on the respective copyright owner
# see the NOTICE file and/or the repository
# https://github.com/boschresearch/pylife
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

__author__ = 'Alexander Maier'
__maintainer__ = __author__

import numpy as np


class _Hookeslawcore:
    '''Parent class for the multidimensional Hooke's Law implementation. Defines the properties and checks for correct inputs'''

    def __init__(self, E, nu):
        '''Instantiate a multidimensional Hooke's Law implementation

        Parameters
        ----------

        E : float
            Young's modulus

        nu : float
            Poisson's ratio. Must be between -1 and 1./2.
        '''
        self._validateinit(nu)
        self._E = E
        self._nu = nu
        self._G = E / (2. * (1 + nu))
        self._K = E / (3. * (1 - 2 * nu))

    def _validateinit(self, nu):
        '''Validates the input of the Poisson\'s ratio
        '''
        if nu < - 1 or nu > 1./2:
            raise ValueError('Poisson\'s ratio nu is %.2f but must be -1 <= nu <= 1./2.' % nu)

    def _as_consistant_arrays(self, *args):
        '''Transforms the inputs into numpy arrays and checks the shape of the given inputs. If the shapes are note equal, a ValueError is raised
        '''
        transformed = tuple(np.asarray(arg) for arg in args)
        shape0 = transformed[0].shape
        shape = [shape0 == arg.shape for arg in transformed]
        if not all(shape):
            raise ValueError('Components\' shape is not consistent.')

        return transformed

    @property
    def E(self):
        '''Get Young's modulus'''
        return self._E

    @property
    def nu(self):
        '''Get Poisson's ratio'''
        return self._nu

    @property
    def G(self):
        '''Get the sheer modulus'''
        return self._G

    @property
    def K(self):
        '''Get the bulk modulus'''
        return self._K


[docs] class HookesLaw1d: '''Implementation of the one dimensional Hooke's Law Parameters ---------- E : float Young's modulus ''' def __init__(self, E): ''' Instantiate a one dimensional Hooke's Law implementation with a given Young's modulus Parameters ---------- E : float Young's modulus ''' self._E = E @property def E(self): '''Get Young's modulus''' return self._E
[docs] def stress(self, strain): '''Get the stress for a given elastic strain Parameters ---------- strain : array-like float The elastic strain Returns ------- strain : array-like float The resulting stress ''' return np.asarray(strain) * self._E
[docs] def strain(self, stress): '''Get the elastic strain for a given stress Parameters ---------- stress : array-like float The stress Returns ------- strain : array-like float The resulting elastic strain ''' return np.asarray(stress) / self._E
[docs] class HookesLaw2dPlaneStress(_Hookeslawcore): '''Implementation of the Hooke's Law under plane stress conditions. Parameters ---------- E : float Young's modulus nu : float Poisson's ratio. Must be between -1 and 1./2. Notes ----- A cartesian coordinate system is assumed. The stress components in 3 direction are assumed to be zero, s33 = s13 = s23 = 0.''' def __init__(self, E, nu): super().__init__(E, nu) self._Et = E self._nut = self._nu
[docs] def strain(self, s11, s22, s12): '''Get the elastic strain components for given stress components Parameters ---------- s11 : array-like float The normal stress component with basis 1-1 s22 : array-like float The normal stress component with basis 2-2 s12 : array-like float The shear stress component with basis 1-2 Returns ------- e11 : array-like float The resulting elastic normal strain component with basis 1-1 e22 : array-like float The resulting elastic normal strain component with basis 2-2 e33 : array-like float The resulting elastic normal strain component with basis 3-3 g12 : array-like float The resulting elastic engineering shear strain component with basis 1-2, (1. / 2 * g12 is the tensor component) ''' s11, s22, s12 = self._as_consistant_arrays(s11, s22, s12) e11 = 1. / self._Et * (s11 - self._nut * s22) e22 = 1. / self._Et * (s22 - self._nut * s11) e33 = - self._nu / self._E * (s11 + s22) g12 = 1. / self._G * s12 return e11, e22, e33, g12
[docs] def stress(self, e11, e22, g12): '''Get the stress components for given elastic strain components Parameters ---------- e11 : array-like float The elastic normal strain component with basis 1-1 e22 : array-like float The elastic normal strain component with basis 2-2 g12 : array-like float The elastic engineering shear strain component with basis 1-2, (1. / 2 * g12 is the tensor component) Returns ------- s11 : array-like float The resulting normal stress component with basis 1-1 s22 : array-like float The resulting normal stress component with basis 2-2 s12 : array-like float The resulting shear stress component with basis 1-2 ''' e11, e22, g12 = self._as_consistant_arrays(e11, e22, g12) factor = self._Et / (1 - np.power(self._nut, 2.)) s11 = factor * (e11 + self._nut * e22) s22 = factor * (e22 + self._nut * e11) s12 = self._G * g12 return s11, s22, s12
[docs] class HookesLaw2dPlaneStrain(HookesLaw2dPlaneStress): '''Implementation of the Hooke's Law under plane strain conditions. Parameters ---------- E : float Young's modulus nu : float Poisson's ratio. Must be between -1 and 1./2. Notes ----- A cartesian coordinate system is assumed. The strain components in 3 direction are assumed to be zero, e33 = g13 = g23 = 0. ''' def __init__(self, E, nu): super().__init__(E, nu) self._Et = self._E / (1 - np.power(self._nu, 2)) self._nut = self._nu / (1 - self._nu)
[docs] def strain(self, s11, s22, s12): '''Get the elastic strain components for given stress components Parameters ---------- s11 : array-like float The normal stress component with basis 1-1 s22 : array-like float The normal stress component with basis 2-2 s12 : array-like float The shear stress component with basis 1-2 Returns ------- e11 : array-like float The resulting elastic normal strain component with basis 1-1 e22 : array-like float The resulting elastic normal strain component with basis 2-2 g12 : array-like float The resulting elastic engineering shear strain component with basis 1-2, (1. / 2 * g12 is the tensor component) ''' e11, e22, _, g12 = super().strain(s11, s22, s12) return e11, e22, g12
[docs] def stress(self, e11, e22, g12): '''Get the stress components for given elastic strain components Parameters ---------- e11 : array-like float The elastic normal strain component with basis 1-1 e22 : array-like float The elastic normal strain component with basis 2-2 g12 : array-like float The elastic engineering shear strain component with basis 1-2, (1. / 2 * g12 is the tensor component) Returns ------- s11 : array-like float The resulting normal stress component with basis 1-1 s22 : array-like float The resulting normal stress component with basis 2-2 s33 : array-like float The resulting normal stress component with basis 3-3 s12 : array-like float The resulting shear stress component with basis 1-2 ''' s11, s22, s12 = super().stress(e11, e22, g12) s33 = self.nu * (s11 + s22) return s11, s22, s33, s12
[docs] class HookesLaw3d(_Hookeslawcore): '''Implementation of the Hooke's Law in three dimensions. Parameters ---------- E : float Young's modulus nu : float Poisson's ratio. Must be between -1 and 1./2 Notes ----- A cartesian coordinate system is assumed. ''' def __init__(self, E, nu): super().__init__(E, nu)
[docs] def strain(self, s11, s22, s33, s12, s13, s23): '''Get the elastic strain components for given stress components Parameters ---------- s11 : array-like float The resulting normal stress component with basis 1-1 s22 : array-like float The resulting normal stress component with basis 2-2 s33 : array-like float The resulting normal stress component with basis 3-3 s12 : array-like float The resulting shear stress component with basis 1-2 s13 : array-like float The resulting shear stress component with basis 1-3 s23 : array-like float The resulting shear stress component with basis 2-3 Returns ------- e11 : array-like float The resulting elastic normal strain component with basis 1-1 e22 : array-like float The resulting elastic normal strain component with basis 2-2 e33 : array-like float The resulting elastic normal strain component with basis 3-3 g12 : array-like float The resulting elastic engineering shear strain component with basis 1-2, (1. / 2 * g12 is the tensor component) g13 : array-like float The resulting elastic engineering shear strain component with basis 1-3, (1. / 2 * g13 is the tensor component) g23 : array-like float The resulting elastic engineering shear strain component with basis 2-3, (1. / 2 * g23 is the tensor component) ''' s11, s22, s33, s12, s13, s23 = self._as_consistant_arrays(s11, s22, s33, s12, s13, s23) e11 = 1 / self._E * (s11 - self._nu * (s22 + s33)) e22 = 1 / self._E * (s22 - self._nu * (s11 + s33)) e33 = 1 / self._E * (s33 - self._nu * (s11 + s22)) g12 = s12 / self._G g13 = s13 / self._G g23 = s23 / self._G return e11, e22, e33, g12, g13, g23
[docs] def stress(self, e11, e22, e33, g12, g13, g23): '''Get the stress components for given elastic strain components Parameters ---------- e11 : array-like float The elastic normal strain component with basis 1-1 e22 : array-like float The elastic normal strain component with basis 2-2 e33 : array-like float The elastic normal strain component with basis 3-3 g12 : array-like float The elastic engineering shear strain component with basis 1-2, (1. / 2 * g12 is the tensor component) g13 : array-like float The elastic engineering shear strain component with basis 1-3, (1. / 2 * g13 is the tensor component) g23 : array-like float The elastic engineering shear strain component with basis 2-3, (1. / 2 * g23 is the tensor component) Returns ------- s11 : array-like float The resulting normal stress component with basis 1-1 s22 : array-like float The resulting normal stress component with basis 2-2 s33 : array-like float The resulting normal stress component with basis 3-3 s12 : array-like float The resulting shear stress component with basis 1-2 s13 : array-like float The resulting shear stress component with basis 1-3 s23 : array-like float The resulting shear stress component with basis 2-3 ''' e11, e22, e33, g12, g13, g23 = self._as_consistant_arrays(e11, e22, e33, g12, g13, g23) factor1 = self._E / ((1 + self._nu) * (1 - 2 * self._nu)) factor2 = 1 - self._nu s11 = factor1 * (factor2 * e11 + self._nu * (e22 + e33)) s22 = factor1 * (factor2 * e22 + self._nu * (e11 + e33)) s33 = factor1 * (factor2 * e33 + self._nu * (e11 + e22)) s12 = self._G * g12 s13 = self._G * g13 s23 = self._G * g23 return s11, s22, s33, s12, s13, s23