def secondary(self, Ue): """ Calculate secondary variables ============================= INPUT: Ue : vector of primary variables at each node STORED: None RETURNS: svs : dictionary with secondary values """ nip = len(self.ipe) svs = {'wx': zeros(nip), 'wy': zeros(nip)} for k, ip in enumerate(self.ipe): S, G, _ = shape_derivs(self.xy, self.fce, ip) gra = dot(Ue, G) w = -dot(self.D, gra) svs['wx'][k] = w[0] svs['wy'][k] = w[1] return svs
def secondary(self, UPe): """ Calculate secondary variables ============================= INPUT: UPe : vector of primary variables at each node STORED: None RETURNS: svs : dictionary with secondary values """ Ue = array([UPe[i] for i in self.eqsU]) Pe = array([UPe[i] for i in self.eqsP]) nip = len(self.ipeU) svs = { 'sxE': zeros(nip), 'syE': zeros(nip), 'szE': zeros(nip), 'sxyE': zeros(nip), # effective values 'ex': zeros(nip), 'ey': zeros(nip), 'ez': zeros(nip), 'exy': zeros(nip) } sq2 = sqrt(2.0) for k, ip in enumerate(self.ipeU): S, G, _ = shape_derivs(self.xyU, self.fceU, ip) B = self.calc_B(G) eps = dot(B, Ue) # strains sig = dot(self.D, eps) # stresses svs['sxE'][k] = sig[0] svs['syE'][k] = sig[1] svs['szE'][k] = sig[2] svs['sxyE'][k] = sig[3] / sq2 svs['ex'][k] = eps[0] svs['ey'][k] = eps[1] svs['ez'][k] = eps[2] svs['exy'][k] = eps[3] / sq2 return svs
def secondary(self, Ue): """ Calculate secondary variables ============================= INPUT: Ue : vector of primary variables at each node STORED: None RETURNS: svs : dictionary with secondary values """ nip = len(self.ipe) svs = { 'sx': zeros(nip), 'sy': zeros(nip), 'sz': zeros(nip), 'sxy': zeros(nip), 'ex': zeros(nip), 'ey': zeros(nip), 'ez': zeros(nip), 'exy': zeros(nip) } sq2 = sqrt(2.0) for k, ip in enumerate(self.ipe): S, G, _ = shape_derivs(self.xy, self.fce, ip) B = self.calc_B(G) eps = dot(B, Ue) # strains sig = dot(self.D, eps) # stresses svs['sx'][k] = sig[0] svs['sy'][k] = sig[1] svs['sz'][k] = sig[2] svs['sxy'][k] = sig[3] / sq2 svs['ex'][k] = eps[0] svs['ey'][k] = eps[1] svs['ez'][k] = eps[2] svs['exy'][k] = eps[3] / sq2 return svs
def __init__(self, verts, params): """ 2D elasticity problem with porous media ======================================= Example of input: global_id tag x y verts = [[3, -100, 0.0, 0.0], [4, -100, 1.0, 0.0], [7, -100, 1.0, 1.0], [1, -100, 0.0, 1.0]] params = {'E':1., 'nu':1., 'pstress':True, 'thick':1., 'geom':'tri3', 'ipe':'QuaIp4', 'rho':1.0} pstress : plane-stress instead of plane-strain? [optional] thick : thickness for plane-stress only [optional] ipe : [optional] integration points geom types: tri3, tri6, qua4, qua8 INPUT: verts : list of vertices params : dictionary of parameters STORED: geom : geometry key pair, ex: (tri6,tri3), (qua8,qua4) fce, fcf : element and face shape/deriv functions nne, nnf : element and face number of nodes ipe, ipf : integration points of element and edge/face rho : density [optional] E : Young modulus nu : Poisson's coefficient pstress : is plane-stress problem instead of plane-strain? thick : thickness for plane-stress problems has_load : has applied distributed load to any side xy : matrix of coordinates of nodes D : constitutive modulus (matrix) K : stiffness matrix """ # set geometry if isinstance(params['geom'], str): self.geoU = params['geom'] self.geoP = params['geom'] else: self.geoU = params['geom'][0] self.geoP = params['geom'][1] self.fceU, self.nneU, self.fcfU, self.nnfU = get_shape_fcn(self.geoU) self.fceP, self.nneP, self.fcfP, self.nnfP = get_shape_fcn(self.geoP) self.ipeU, self.ipfU = get_ips(self.geoU) self.ipeP, self.ipfP = get_ips(self.geoP) if 'ipeU' in params: self.ipeU = params['ipeU'] if 'ipeP' in params: self.ipeP = params['ipeP'] # check if len(verts) != self.nneU: raise Exception('this element needs %d vertices exactly' % self.nneU) # set data self.E = params['E'] # Young modulus self.nu = params['nu'] # Poisson's coefficient self.kx = params['kx'] # x-conductivity self.ky = params['ky'] # y-conductivity self.has_load = False # has distributed loads self.has_flux = False # has flux specified # other parameters rhoS = params['rhoS'] # density of solid grains rhoW = params['rhoW'] # water real density gamW = params['gamW'] # water unit weight of reference eta = params['eta'] # porosity Kw = params['Kw'] # water bulk modulus rho = (1.0 - eta) * rhoS + eta * rhoW # density of mixture Cwb = eta / Kw # matrix of nodal coordinates self.xyU = zeros((2, self.nneU)) # 2 => 2D self.xyP = zeros((2, self.nneP)) # 2 => 2D for n, v in enumerate(verts): self.xyU[0][n] = v[2] # x-coordinates self.xyU[1][n] = v[3] # y-coordinates if n < self.nneP: self.xyP[0][n] = v[2] # x-coordinates self.xyP[1][n] = v[3] # y-coordinates # constitutive matrix (plane strain) nu = self.nu # Poisson coef cf = self.E / ((1.0 + nu) * (1.0 - 2.0 * nu)) self.D = cf * array([[1. - nu, nu, nu, 0.], [nu, 1. - nu, nu, 0.], [nu, nu, 1. - nu, 0.], [0., 0., 0., 1. - 2. * nu] ]) # conductivity matrix self.kap = array([[self.kx / gamW, 0.0], [0.0, self.ky / gamW]]) # iota tensor self.iota = array([1., 1., 1., 0.]) # K, M, Q and O matrices self.K = zeros((self.nneU * 2, self.nneU * 2)) self.M = zeros((self.nneU * 2, self.nneU * 2)) self.Q = zeros((self.nneU * 2, self.nneP)) self.O = zeros((self.nneP, self.nneU * 2)) for ip in self.ipeU: # K and M S, G, detJ = shape_derivs(self.xyU, self.fceU, ip) B = self.calc_B(G) N = self.calc_N(S) cf = detJ * ip[2] self.K += cf * dot(transpose(B), dot(self.D, B)) self.M += (cf * rho) * dot(transpose(N), N) # Q and O Sb, Gb, _ = shape_derivs(self.xyP, self.fceP, ip) self.Q += cf * dot(transpose(B), outer(self.iota, Sb)) self.O += (cf * rhoW) * dot(Gb, dot(self.kap, N)) #print detJ, detJb, detJ-detJb # L and H matrices self.L = zeros((self.nneP, self.nneP)) self.H = zeros((self.nneP, self.nneP)) for ip in self.ipeP: Sb, Gb, detJb = shape_derivs(self.xyP, self.fceP, ip) cf = detJb * ip[2] self.L += (cf * Cwb) * outer(Sb, Sb) self.H += cf * dot(Gb, dot(self.kap, transpose(Gb))) # local equation numbers neqs = self.nneU * 2 + self.nneP self.eqsP = [2 + n * 3 for n in range(self.nneP)] self.eqsU = [i for i in range(neqs) if i not in self.eqsP]
def __init__(self, verts, params): """ 2D elasticity problem ===================== Example of input: global_id tag x y verts = [[3, -100, 0.0, 0.0], [4, -100, 1.0, 0.0], [7, -100, 1.0, 1.0], [1, -100, 0.0, 1.0]] params = {'E':1., 'nu':1., 'pstress':True, 'thick':1., 'geom':'tri3', 'ipe':'QuaIp4', 'rho':1.0} pstress : plane-stress instead of plane-strain? [optional] thick : thickness for plane-stress only [optional] ipe : [optional] integration points geom types: tri3, tri6, qua4, qua8 INPUT: verts : list of vertices params : dictionary of parameters STORED: geom : geometry key [tri3,tri6,qua4,qua8] fce, fcf : element and face shape/deriv functions nne, nnf : element and face number of nodes ipe, ipf : integration points of element and edge/face rho : density [optional] E : Young modulus nu : Poisson's coefficient pstress : is plane-stress problem instead of plane-strain? thick : thickness for plane-stress problems has_load : has applied distributed load to any side xy : matrix of coordinates of nodes D : constitutive modulus (matrix) K : stiffness matrix """ # set geometry self.geom = params['geom'] self.fce, self.nne, self.fcf, self.nnf = get_shape_fcn(self.geom) self.ipe, self.ipf = get_ips(self.geom) if 'ipe' in params: self.ipe = params['ipe'] # check if len(verts) != self.nne: raise Exception('this element needs %d vertices exactly' % self.nne) # set data self.rho = 0.0 # density self.E = params['E'] # Young modulus self.nu = params['nu'] # Poisson's coefficient self.pstress = False # plane stress self.thick = 1.0 # thickness of element self.has_load = False # has distributed loads if 'rho' in params: self.rho = params['rho'] if 'pstress' in params: self.pstress = params['pstress'] # plane-stress? self.thick = params['thick'] # thickness # matrix of nodal coordinates self.xy = zeros((2, self.nne)) # 2 => 2D for n, v in enumerate(verts): self.xy[0][n] = v[2] # x-coordinates self.xy[1][n] = v[3] # y-coordinates # constitutive matrix nu = self.nu # Poisson coef if self.pstress: cf = self.E / (1.0 - nu**2.0) self.D = cf * array([[1., nu, 0., 0.], [nu, 1., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 1. - nu]]) else: # plane strain cf = self.E / ((1.0 + nu) * (1.0 - 2.0 * nu)) self.D = cf * array([[1. - nu, nu, nu, 0.], [nu, 1. - nu, nu, 0.], [nu, nu, 1. - nu, 0.], [0., 0., 0., 1. - 2. * nu]]) # K and M matrices self.K = zeros((self.nne * 2, self.nne * 2)) self.M = zeros((self.nne * 2, self.nne * 2)) for i, ip in enumerate(self.ipe): S, G, detJ = shape_derivs(self.xy, self.fce, ip) B = self.calc_B(G) N = self.calc_N(S) cf = detJ * ip[2] * self.thick self.K += cf * dot(transpose(B), dot(self.D, B)) self.M += (cf * self.rho) * dot(transpose(N), N)
def __init__(self, verts, params): """ 2D diffusion problem ==================== Solving: 2 2 du d u d u rho == - kx ==== - ky ==== = s(x) dt d x2 d y2 Example of input: global_id tag x y verts = [[3, -100, 0.0, 0.0], [4, -100, 1.0, 0.0], [7, -100, 1.0, 1.0], [1, -100, 0.0, 1.0]] params = {'rho':1., 'kx':1., 'ky':1., 'source':src_val_or_fcn, 'geom':qua4} Notes: src_val_or_fcn: can be a constant value or a callback function such as lambda x,y: x+y geom types: tri3, tri6, qua4, qua8 INPUT: verts : list of vertices params : dictionary of parameters STORED: geom : geometry key [tri3,tri6,qua4,qua8] fce, fcf : element and face shape/deriv functions nne, nnf : element and face number of nodes ipe, ipf : integration points of element and edge/face rho : rho parameter [optional] kx : x-conductivity ky : y-conductivity source : the source term [optional] has_flux : has flux applied to any side? has_conv : has convection applied to any side? has_source : has source term xy : matrix of coordinates of nodes D : matrix with kx and ky C : Ce matrix [rate of u] Kk : Kke matrix [conductivity] Fs : Fs vector [source] """ # set geometry self.geom = params['geom'] self.fce, self.nne, self.fcf, self.nnf = get_shape_fcn(self.geom) self.ipe, self.ipf = get_ips(self.geom) # check if len(verts) != self.nne: raise Exception('this element needs %d vertices exactly' % self.nne) # set data self.rho = 0.0 # rho parameter self.kx = params['kx'] # x-conductivity self.ky = params['ky'] # y-conductivity self.has_flux = False # has flux bry conditions self.has_conv = False # has convection bry conds self.has_source = False # has source term if 'rho' in params: self.rho = params['rho'] if 'source' in params: self.source = params['source'] self.has_source = True # matrix of nodal coordinates self.xy = zeros((2, self.nne)) # 2 => 2D for n, v in enumerate(verts): self.xy[0][n] = v[2] # x-coordinates self.xy[1][n] = v[3] # y-coordinates # conductivity matrix self.D = array([[self.kx, 0.0], [0.0, self.ky]]) # Ce, Kke and source self.C = zeros((self.nne, self.nne)) self.Kk = zeros((self.nne, self.nne)) self.Fs = zeros(self.nne) for ip in self.ipe: S, G, detJ = shape_derivs(self.xy, self.fce, ip) cf = detJ * ip[2] self.C += cf * self.rho * outer(S, S) self.Kk += cf * dot(G, dot(self.D, transpose(G))) if self.has_source: if isinstance(self.source, float): # constant value self.Fs += cf * self.source * S else: # function(x,y) xip, yip = ip_coords(S, self.xy) self.Fs += cf * self.source(xip, yip) * S