Source code for abapy.materials

'''
Materials
=========
'''

def float_arg(arg):
  """
  Tests if an arg is float or convertible to float
  """
  try:
    arg = [float(arg)]
  except:
    pass
  return arg    
  

[docs]class VonMises(object): ''' Represents von Mises materials used for FEM simulations :param E: Young's modulus. :type E: float, list, array.array :param nu: Poisson's ratio. :type nu: float, list, array.array :param sy: Yield stress. :type sy: float, list, array.array .. note:: All inputs must have the same length or an exception will be raised. >>> from abapy.materials import VonMises >>> m = VonMises(labels='myMaterial',E=1,nu=0.45, sy=0.01) >>> print m.dump2inp() ... ''' def __init__(self, labels='mat', E = 1., nu = 0.3, sy = 0.01, dtf='d'): from array import array import numpy if type(labels) is str: labels=[labels] self.labels=labels l = len(labels) E = float_arg(E) if len(E) != l: raise Exception, 'Parameters must all have the same length' self.E=array(dtf,E) nu = float_arg(nu) if len(nu) != l: raise Exception, 'Parameters must all have the same length' self.nu=array(dtf,nu) sy = float_arg(sy) if len(sy) != l: raise Exception, 'Parameters must all have the same length' self.sy=array(dtf,sy) def __repr__(self): return '<VonMises instance: {0} samples>'.format(len(self.E))
[docs] def dump2inp(self): ''' Returns materials in INP format suitable with abaqus input files. :rtype: string ''' out = '** {0}\n'.format(self.__repr__()) pattern = '*MATERIAL, NAME={0}\n*ELASTIC\n {1}, {2}\n*PLASTIC\n {3}, 0.\n' for i in xrange(len(self.E)): out += pattern.format(self.labels[i],self.E[i],self.nu[i],self.sy[i]) return out[0:-1]
[docs]class Elastic(object): ''' Represents an istotrop linear elastic material used for FEM simulations :param E: Young's modulus. :type E: float, list, array.array :param nu: Poisson's ratio. :type nu: float, list, array.array .. note:: All inputs must have the same length or an exception will be raised. ''' def __init__(self, labels='mat', E = 1., nu = 0.3, dtf='d'): from array import array if type(labels) is str: labels=[labels] self.labels=labels l = len(labels) E = float_arg(E) if len(E) != l: raise Exception, 'Parameters must all have the same length' self.E=array(dtf,E) nu = float_arg(nu) if len(nu) != l: raise Exception, 'Parameters must all have the same length' self.nu=array(dtf,nu) def __repr__(self): return '<Elastic instance: {0} samples>'.format(len(self.E))
[docs] def dump2inp(self): ''' Returns materials in INP format suitable with abaqus input files. :rtype: string ''' out = '** {0}\n'.format(self.__repr__()) pattern = '*MATERIAL, NAME={0}\n*ELASTIC\n {1}, {2}\n' for i in xrange(len(self.E)): out += pattern.format(self.labels[i],self.E[i],self.nu[i]) return out[0:-1]
[docs]class DruckerPrager(object): ''' Represents Drucker-Prager materials used for FEM simulations :param E: Young's modulus. :type E: float, list, array.array :param nu: Poisson's ratio. :type nu: float, list, array.array :param sy: Compressive yield stress. :type sy: float, list, array.array :param beta: Friction angle in degrees. :type beta: float, list, array.array :param psi: Dilatation angle in degress. If psi = beta, the plastic flow is associated. If psi = None, the associated flow is automatically be chosen. :type psi: float, list, array.array or None :param k: tension vs. compression asymmetry. For k = 1., not asymmetry, for k=0.778 maximum possible asymmetry. :type k: float, list, array.array .. note:: All inputs must have the same length or an exception will be raised. ... ''' def __init__(self, labels='mat', E = 1., nu = 0.3, sy = 0.01, beta = 10., psi = None, k = 1., dtf='d'): from array import array if type(labels) is str: labels=[labels] self.labels=labels l = len(labels) E = float_arg(E) if len(E) != l: raise Exception, 'Parameters must all have the same length' self.E=array(dtf,E) nu = float_arg(nu) if len(nu) != l: raise Exception, 'Parameters must all have the same length' self.nu=array(dtf,nu) sy = float_arg(sy) if len(sy) != l: raise Exception, 'Parameters must all have the same length' self.sy=array(dtf,sy) beta = float_arg(beta) if len(beta) != l: raise Exception, 'Parameters must all have the same length' self.beta = array(dtf,beta) if psi == None: psi = beta psi = float_arg(psi) if len(psi) != l: raise Exception, 'Parameters must all have the same length' self.psi = array(dtf,psi) k = float_arg(k) if len(k) != l: raise Exception, 'Parameters must all have the same length' self.k = array(dtf,k) def __repr__(self): return '<DruckerPrager instance: {0} samples>'.format(len(self.E))
[docs] def dump2inp(self): ''' Returns materials in INP format suitable with abaqus input files. :rtype: string ''' out = '** {0}\n'.format(self.__repr__()) pattern = '*MATERIAL, NAME={0}\n*ELASTIC\n {1}, {2}\n*DRUCKER PRAGER\n {3}, {4}, {5}\n*DRUCKER PRAGER HARDENING\n {6}, 0.\n' for i in xrange(len(self.E)): out += pattern.format( self.labels[i], self.E[i], self.nu[i], self.beta[i], self.k[i], self.psi[i], self.sy[i]) return out[0:-1]
[docs]class Hollomon(object): r''' Represents von Hollom materials (i. e. power law haderning and von mises yield criterion) used for FEM simulations. :param E: Young's modulus. :type E: float, list, array.array :param nu: Poisson's ratio. :type nu: float, list, array.array :param sy: Yield stress. :type sy: float, list, array.array :param n: hardening exponent :type sy: float, list, array.array :param kind: kind of equation to be used (see below). Default is 1. :type kind: int .. note:: All inputs must have the same length or an exception will be raised. Several sets of equations are refered to as Hollomon stress-strain law. In all cases, we the strain decomposition :math:`\epsilon = \epsilon_e + \epsilon_p` is used and the elastic part is described by :math:`\sigma = E \epsilon_e = E \epsilon`. Only the plastic parts (i. e. :math:`\sigma > \sigma_y`) differ: * kind 1: .. math:: \sigma = \sigma_y \left( \epsilon E / \sigma_y \right)^n * kind 2: .. math:: \sigma = \sigma_y \left( 1 + \epsilon_p \right)^n = E \epsilon_e .. plot:: example_code/materials/Hollomon.py :include-source: ''' def __init__(self, labels='mat', E = 1., nu = 0.3, sy = 0.01, n = 0.2, kind = 1, dtf='d'): from array import array import numpy if type(labels) is str: labels=[labels] self.labels=labels l = len(labels) E = float_arg(E) if len(E) != l: raise Exception, 'Parameters must all have the same length' self.E=array(dtf,E) nu = float_arg(nu) if len(nu) != l: raise Exception, 'Parameters must all have the same length' self.nu=array(dtf,nu) sy = float_arg(sy) if len(sy) != l: raise Exception, 'Parameters must all have the same length' self.sy=array(dtf,sy) n = float_arg(n) if len(n) != l: raise Exception, 'Parameters must all have the same length' self.n=array(dtf,n) self.kind = kind def __repr__(self): return '<Hollomon instance: {0} samples>'.format(len(self.E))
[docs] def get_table(self, position=0, eps_max = 10., N = 100): ''' Returns the tabular data corresponding to the tensile stress strain law using log spacing. :param position: indice of the concerned material (default is 0). :type position: int :param eps_max: maximum strain to be computed. If kind is 1, eps_max is the total strain, if kind is 2, eps_max is the plastic strain. :type eps_max: float :param N: number of points to be computed. :type N: int :rtype: ``numpy.array`` ''' import numpy as np sy = self.sy[position] E = self.E[position] n = self.n[position] if self.kind == 1: ey = sy/E s = 10.**np.linspace(0., np.log10(eps_max/ey), N, endpoint = True) eps = ey * s sigma = sy * s**n if self.kind == 2: #eps_p = np.logspace(0., np.log10(eps_max +1.), N) -1. s = np.linspace(0., eps_max**n, N) eps_p = s**(1/n) sigma = sy * (1. + s) eps = eps_p + sigma / E return np.array([eps, sigma]).transpose()
[docs] def dump2inp(self, eps_max = 10., N = 100): ''' Returns materials in INP format suitable with abaqus input files. :param eps_max: maximum strain to be computed. :type eps_max: float :param N: number of points to be computed. :type N: int :rtype: string ''' out = '** {0}\n'.format(self.__repr__()) pattern = '*MATERIAL, NAME={0}\n*ELASTIC\n {1}, {2}\n*PLASTIC\n{3}\n' for i in xrange(len(self.E)): table = self.get_table(position = i, eps_max = eps_max, N = N) sigma = table[:,1] eps = table[:,0] #eps_p = eps - eps[0] eps_p = [eps[j] - sigma[j] / self.E[i] for j in xrange(len(eps))] data = '' for j in xrange(len(table)): data += ' {0}, {1}\n'.format(sigma[j], eps_p[j]) out += pattern.format(self.labels[i],self.E[i],self.nu[i],data[0:-1]) return out[0:-1]
[docs]class Bilinear(object): ''' Represents von Mises materials used for FEM simulations :param E: Young's modulus. :type E: float, list, array.array :param nu: Poisson's ratio. :type nu: float, list, array.array :param Ssat: Saturation stress. :type Ssat: float, list, array.array :param n: Slope of the first linear plastic law :type n: float, list, array.array :param Sy: Stress at zero plastic strain :type Sy: float, list, array.array .. note:: All inputs must have the same length or an exception will be raised. ''' def __init__(self, labels='mat', E = 1., nu = 0.3, Ssat = 1000., n=100., sy=100. ,dtf='d'): from array import array import numpy if type(labels) is str: labels=[labels] self.labels=labels l = len(labels) E = float_arg(E) if len(E) != l: raise Exception, 'Parameters must all have the same length' self.E=array(dtf,E) nu = float_arg(nu) if len(nu) != l: raise Exception, 'Parameters must all have the same length' self.nu=array(dtf,nu) Ssat = float_arg(Ssat) if len(Ssat) != l: raise Exception, 'Parameters must all have the same length' self.Ssat=array(dtf,Ssat) n = float_arg(n) if len(n) != l: raise Exception, 'Parameters must all have the same length' self.n=array(dtf,n) sy = float_arg(sy) if len(sy) != l: raise Exception, 'Parameters must all have the same length' self.sy=array(dtf,sy) def __repr__(self): return '<Bilinear instance: {0} samples>'.format(len(self.E))
[docs] def dump2inp(self): ''' Returns materials in INP format suitable with abaqus input files. :rtype: string ''' out = '** {0}\n'.format(self.__repr__()) pattern = '*MATERIAL, NAME={0}\n*ELASTIC\n {1}, {2}\n*PLASTIC\n {3}, 0.\n {4}, {5} \n' Eps_p_sat=[] for i in xrange(len(self.E)): Eps_p_sat.append(abs(self.Ssat[i] - self.sy[i])/self.n[i]) if self.sy[i] > self.Ssat[i]: self.sy[i] = self.Ssat[i] out += pattern.format(self.labels[i],self.E[i],self.nu[i],self.sy[i], self.Ssat[i], Eps_p_sat[i]) return out[0:-1]
class SiDoLo(object): ''' Represents constitutive equations via UMAT subroutines and SiDoLo used for FEM simulations :param: :type : .. note:: All inputs must have the same length or an exception will be raised. ''' def __init__(self, labels='mat', dictionary={}, umat={}, dirsid = '/tmp'): from array import array if type(labels) is str: labels=[labels] self.labels=labels self.dictionary=[dictionary] self.umat=[umat] self.dirsid=dirsid def __repr__(self): return '<UMAT/SiDoLo instance: {0} samples>'.format(len(self.labels)) def dump2inp(self): ''' Returns materials in a format suitable with Abaqus input files. :rtype: string ''' self.dump2coe() out = '** {0}\n'.format(self.__repr__()) # Initialisation pattern = '*MATERIAL, NAME={0}\n*USER MATERIAL, CONSTANTS=2\n {1}, {2}\n*DEPVAR\n {3}\n' for i in xrange(len(self.labels)): params = self.dictionary[i]['Parameters'] varint = self.dictionary[i]['Variables'] Lvarint = len(varint) out += pattern.format(self.labels[i],params['epsrk'],params['toly'],Lvarint) return out[0:-1] # La sortie est tout sauf le dernier element de out (ligne blanche) def dump2coe(self): ''' Returns materials coefficients in a format suitable with Abaqus/SiDoLo. :rtype: string ''' from collections import OrderedDict for i in xrange(len(self.labels)): # Definition des sous-dictionnaires coeffs = self.dictionary[i]['Coefficients'] varint = self.dictionary[i]['Variables'] # Ecriture dans un fichier formatte if self.dirsid[-1]!='/': self.dirsid = self.dirsid + '/' filename = self.dirsid + self.labels[i] + '.coe' fich = open(filename, 'w') fich.write('*list \n') motif = ' {:s}' for k, v in coeffs.iteritems(): fich.write(motif.format(k)) fich.write('\n') fich.write('*values \n') motif = ' {0:s} {1:f}\n' for k, v in coeffs.iteritems(): fich.write(motif.format(k,v)) fich.close() return class Ludwig(object): ''' Represents Hollomon power law hardening used for FEM simulations. :param E: Young's modulus. :type E: float, list, array.array :param nu: Poisson's ratio. :type nu: float, list, array.array :param sy: Yield stress. :type sy: float, list, array.array :param n: hardening exponent :type n: float, list, array.array :param K: strenght index :type K: float, list, array.array .. note:: All inputs must have the same length or an exception will be raised. .. plot:: example_code/materials/Hollomon.py :include-source: ''' def __init__(self, labels='mat', E = 1., nu = 0.3, sy = 150, K = 20., n = 0.2, dtf='d'): from array import array import numpy as np if type(labels) is str: labels=[labels] self.labels=labels l = len(labels) E = float_arg(E) if len(E) != l: raise Exception, 'Parameters must all have the same length' self.E=array(dtf,E) nu = float_arg(nu) if len(nu) != l: raise Exception, 'Parameters must all have the same length' self.nu=array(dtf,nu) K = float_arg(K) if len(K) != l: raise Exception, 'Parameters must all have the same length' self.K=array(dtf,K) n = float_arg(n) if len(n) != l: raise Exception, 'Parameters must all have the same length' self.n=array(dtf,n) sy = float_arg(sy) if len(sy) != l: raise Exception, 'Parameters must all have the same length' self.sy=array(dtf,sy) def __repr__(self): return '<Hollomon instance: {0} samples>'.format(len(self.E)) def get_table(self, position, eps_max = 1., N = 100): ''' Returns the tabular data corresponding to the tensile stress strain law using log spacing. :param eps_max: maximum strain to be computed. :type eps_max: float :param N: number of points to be computed. :type N: int :rtype: ``numpy.array`` ''' import numpy as np K = self.K[position] n = self.n[position] sy = self.sy[position] E = self.E[position] ey = sy/E s = 10.**np.linspace(0., np.log10(eps_max/ey), N, endpoint = True) eps_p_temp, sigma = [0],[sy] for i in range(0, len(s)): eps_p_temp.append(ey * s[i]) sigma.append(sy + K * (ey * s[i])**n) eps_p = np.asarray(eps_p_temp) return np.array([eps_p, sigma]).transpose() def dump2inp(self, eps_max = 1., N = 100): ''' Returns materials in INP format suitable with abaqus input files. :param eps_max: maximum strain to be computed. :type eps_max: float :param N: number of points to be computed. :type N: int :rtype: string ''' out = '** {0}\n'.format(self.__repr__()) pattern = '*MATERIAL, NAME={0}\n*ELASTIC\n {1}, {2}\n*PLASTIC\n{3}\n' for i in xrange(len(self.E)): table = self.get_table(position = i, eps_max = eps_max, N = N) sigma = table[:,1] eps_p = table[:,0] #eps = [eps_p[j] + sigma[j] / self.E[i] for j in xrange(len(eps_p))] data = '' for j in xrange(len(table)): data += ' {0}, {1}\n'.format(sigma[j], eps_p[j]) out += pattern.format(self.labels[i],self.E[i],self.nu[i],data[0:-1]) return out[0:-1]