def bar7(): print('---------------------------------------------------------------') print('Two clamped beams link in parallel') print('and loaded by force at right end') print('[5]-[6]-[7]-[8]-[9]') print('[0]-[1]-[2]-[3]-[4]') print('u[5] = u[0], u[0] = 0, u[4] = 0.5 * u[9], R[4] = 1') K = SysMtxAssembly() dof_map1, mtx_arr1 = get_bar_mtx_array(shape=4) K.add_mtx_array(dof_map_arr=dof_map1, mtx_arr=mtx_arr1) dof_map2, mtx_arr2 = get_bar_mtx_array(shape=4) K.add_mtx_array(dof_map_arr=dof_map2 + 5, mtx_arr=mtx_arr2) # add load R = zeros(K.n_dofs) # load at the coupled end nodes is doubled R[9] = 1 R[4] = 1 # add constraints K.register_constraint(a=5, alpha=[1], ix_a=[0]) K.register_constraint(a=0, u_a=0.) # clamped end K.register_constraint(a=4, alpha=[0.5], ix_a=[9]) # add load R = zeros(K.n_dofs) # load at the coupled end nodes is doubled R[9] = 1 R[4] = 1 print('u =', K.solve(R)) print()
def bar2(): print '---------------------------------------------------------------' print 'Clamped bar composed of two linked bars loaded at the right end' print '[00]-[01]-[02]-[03]-[04]-[05]-[06]-[07]-[08]-[09]-[10]' print '[11]-[12]-[13]-[14]-[15]-[16]-[17]-[18]-[19]-[20]-[21]' print 'u[0] = 0, u[5] = u[16], R[-1] = R[21] = 10' K = SysMtxAssembly() dof_map1, mtx_arr1 = get_bar_mtx_array( shape = 10 ) K.add_mtx_array( dof_map_arr = dof_map1, mtx_arr = mtx_arr1 ) dof_map2, mtx_arr2 = get_bar_mtx_array( shape = 10 ) # Note the dof map of the second br must be adjusted to start # the DOF enumeration with 3 n_dofs1 = K.n_dofs K.add_mtx_array( dof_map_arr = dof_map2+n_dofs1, mtx_arr = mtx_arr2 ) # add constraints K.register_constraint( a = 0, u_a = 0. ) # clamped end K.register_constraint( a = 5, alpha = [1], ix_a = [16] ) # add load R = zeros( K.n_dofs ) R[-1] = 10 print 'u =', K.solve( R ) print print '---------------------------------------------------------------' print 'Clamped bar composed of two linked bars control displ at right' print 'u[0] = 0, u[5] = u[16], u[21] = 1' # Remove the load and put a unit displacement at the right end # Note, the load is irrelevant in this case and will be rewritten # K.register_constraint( a = 21, u_a = 1 ) print 'u =', K.solve( R ) print
def bar1(): print '---------------------------------------------------------------' print 'Clamped bar loaded at the right end with unit displacement' print '[00]-[01]-[02]-[03]-[04]-[05]-[06]-[07]-[08]-[09]-[10]' print 'u[0] = 0, u[10] = 1' K = SysMtxAssembly() dof_map, mtx_arr = get_bar_mtx_array(shape=10) K.add_mtx_array(dof_map_arr=dof_map, mtx_arr=mtx_arr) K.register_constraint(a=0, u_a=0.) # clamped end K.register_constraint(a=10, u_a=1.) K.register_constraint(a=10, u_a=1.) K_dense = DenseMtx(assemb=K) R = zeros(K.n_dofs) print 'K\n', K_dense print 'R\n', R print 'K_arrays' for i, sys_mtx_array in enumerate(K.sys_mtx_arrays): print 'i\n', sys_mtx_array.mtx_arr K.apply_constraints(R) K_dense = DenseMtx(assemb=K) print 'K\n', K_dense print 'R\n', R print 'K_arrays' for i, sys_mtx_array in enumerate(K.sys_mtx_arrays): print 'i\n', sys_mtx_array.mtx_arr print 'u =', K.solve(R) print
def bar1(): print('---------------------------------------------------------------') print('Clamped bar loaded at the right end with unit displacement') print('[00]-[01]-[02]-[03]-[04]-[05]-[06]-[07]-[08]-[09]-[10]') print('u[0] = 0, u[10] = 1') K = SysMtxAssembly() dof_map, mtx_arr = get_bar_mtx_array(shape=10) K.add_mtx_array(dof_map_arr=dof_map, mtx_arr=mtx_arr) K.register_constraint(a=0, u_a=0.) # clamped end K.register_constraint(a=10, u_a=1.) K.register_constraint(a=10, u_a=1.) K_dense = DenseMtx(assemb=K) R = zeros(K.n_dofs) print('K\n', K_dense) print('R\n', R) print('K_arrays') for i, sys_mtx_array in enumerate(K.sys_mtx_arrays): print('i\n', sys_mtx_array.mtx_arr) K.apply_constraints(R) K_dense = DenseMtx(assemb=K) print('K\n', K_dense) print('R\n', R) print('K_arrays') for i, sys_mtx_array in enumerate(K.sys_mtx_arrays): print('i\n', sys_mtx_array.mtx_arr) print('u =', K.solve(R)) print()
def bar2(): print('---------------------------------------------------------------') print('Clamped bar composed of two linked bars loaded at the right end') print('[00]-[01]-[02]-[03]-[04]-[05]-[06]-[07]-[08]-[09]-[10]') print('[11]-[12]-[13]-[14]-[15]-[16]-[17]-[18]-[19]-[20]-[21]') print('u[0] = 0, u[5] = u[16], R[-1] = R[21] = 10') K = SysMtxAssembly() dof_map1, mtx_arr1 = get_bar_mtx_array(shape=10) K.add_mtx_array(dof_map_arr=dof_map1, mtx_arr=mtx_arr1) dof_map2, mtx_arr2 = get_bar_mtx_array(shape=10) # Note the dof map of the second br must be adjusted to start # the DOF enumeration with 3 n_dofs1 = K.n_dofs K.add_mtx_array(dof_map_arr=dof_map2 + n_dofs1, mtx_arr=mtx_arr2) # add constraints K.register_constraint(a=0, u_a=0.) # clamped end K.register_constraint(a=5, alpha=[1], ix_a=[16]) # add load R = zeros(K.n_dofs) R[-1] = 10 print('u =', K.solve(R)) print() print('---------------------------------------------------------------') print('Clamped bar composed of two linked bars control displ at right') print('u[0] = 0, u[5] = u[16], u[21] = 1') # Remove the load and put a unit displacement at the right end # Note, the load is irrelevant in this case and will be rewritten # K.register_constraint(a=21, u_a=1) print('u =', K.solve(R)) print()
def bar7(): print '---------------------------------------------------------------' print 'Two clamped beams link in parallel' print 'and loaded by force at right end' print '[5]-[6]-[7]-[8]-[9]' print '[0]-[1]-[2]-[3]-[4]' print 'u[5] = u[0], u[0] = 0, u[4] = 0.5 * u[9], R[4] = 1' K = SysMtxAssembly() dof_map1, mtx_arr1 = get_bar_mtx_array( shape = 4 ) K.add_mtx_array( dof_map_arr = dof_map1, mtx_arr = mtx_arr1 ) dof_map2, mtx_arr2 = get_bar_mtx_array( shape = 4 ) K.add_mtx_array( dof_map_arr = dof_map2+5, mtx_arr = mtx_arr2 ) # add load R = zeros( K.n_dofs ) # load at the coupled end nodes is doubled R[9] = 1 R[4] = 1 # add constraints K.register_constraint( a = 5, alpha = [1], ix_a = [0] ) K.register_constraint( a = 0, u_a = 0. ) # clamped end K.register_constraint( a = 4, alpha = [0.5], ix_a = [9] ) # add load R = zeros( K.n_dofs ) # load at the coupled end nodes is doubled R[9] = 1 R[4] = 1 print 'u =', K.solve( R ) print
def bar1(): print '---------------------------------------------------------------' print 'Clamped bar loaded at the right end with unit displacement' print '[00]-[01]-[02]-[03]-[04]-[05]-[06]-[07]-[08]-[09]-[10]' print 'u[0] = 0, u[10] = 1' K = SysMtxAssembly() dof_map, mtx_arr = get_bar_mtx_array(shape=10) K.add_mtx_array(dof_map_arr=dof_map, mtx_arr=mtx_arr) K.register_constraint(a=0, u_a=0.) # clamped end K.register_constraint(a=10, u_a=1.) K.register_constraint(a=10, u_a=1.) DenseMtx(assemb=K).configure_traits() R = zeros(K.n_dofs) print 'u =', K.solve(R) print
def bar1(): print '---------------------------------------------------------------' print 'Clamped bar loaded at the right end with unit displacement' print '[00]-[01]-[02]-[03]-[04]-[05]-[06]-[07]-[08]-[09]-[10]' print 'u[0] = 0, u[10] = 1' K = SysMtxAssembly() dof_map, mtx_arr = get_bar_mtx_array( shape = 10 ) K.add_mtx_array( dof_map_arr = dof_map, mtx_arr = mtx_arr ) K.register_constraint( a = 0, u_a = 0. ) # clamped end K.register_constraint( a = 10, u_a = 1. ) K.register_constraint( a = 10, u_a = 1. ) DenseMtx( assemb = K ).configure_traits() R = zeros( K.n_dofs ) print 'u =', K.solve( R ) print
def get_corr_pred(self, U, d_U, t, F_ext, fixed, F_inter, eps): # parameters mats_eval = self.mats_eval fets_eval = self.fets_eval domain = self.domain elem_dof_map = domain.elem_dof_map n_e = domain.n_active_elems n_dof_r, n_dim_dof = self.fets_eval.dof_r.shape n_dim_dof = 2 n_dofs = domain.n_dofs J_det = np.linalg.det(self.J_mtx) w_ip = fets_eval.ip_weights n_el_dofs = n_dof_r * n_dim_dof n_ip = self.fets_eval.n_gp # evaluate internal force increment D = mats_eval.get_D(eps, t, n_e, n_ip) # element displacement increment d_u_e = d_U[elem_dof_map] #[n_e, n_dof_r, n_dim_dof] d_u_n = d_u_e.reshape(n_e, n_dof_r, n_dim_dof) #[n_e, n_ip, n_s] d_eps = np.einsum('einsd,end->eis', self.B, d_u_n) # stress increment #[n_e, n_ip, n_s] d_sig = np.einsum('eist,eit->eis', D, d_eps) # internal force increment # [n_e, n_n, n_dim_dof] d_f_inter_e = np.einsum('eis,einsd,ei->end', d_sig, self.B, J_det) d_f_inter_e = d_f_inter_e.reshape(n_e, n_dof_r * n_dim_dof) d_F_inter = np.zeros(n_dofs) np.add.at(d_F_inter, elem_dof_map, d_f_inter_e) # fixed dof d_F_inter[fixed] = 0. # update internal force F_inter += d_F_inter # update strain and D matrix eps += d_eps D = mats_eval.get_D(eps, t, n_e, n_ip) # update stiffness matrix K = np.einsum('i,einsd,eist,eimtf,ei->endmf', w_ip, self.B, D, self.B, J_det) K_mtx = SysMtxAssembly() K_mtx.add_mtx_array(K.reshape(-1, n_el_dofs, n_el_dofs), elem_dof_map) K_mtx.register_constraint(a=fixed) return F_ext - F_inter, K_mtx, F_inter, eps
def bar8(): print '---------------------------------------------------------------' print 'Single clamped element with two constraints' print 'within a single element' print '[0]-[1]' print 'u[0] = u[1], u[1] = 1' K = SysMtxAssembly() dof_map1, mtx_arr1 = get_bar_mtx_array( shape = 1 ) K.add_mtx_array( dof_map_arr = dof_map1, mtx_arr = mtx_arr1 ) # add constraints K.register_constraint( a = 0, alpha = [1], ix_a = [1] ) K.register_constraint( a = 1, u_a = 1. ) # clamped end # add load R = zeros( K.n_dofs ) print 'u =', K.solve( R ) print
def bar8(): print('---------------------------------------------------------------') print('Single clamped element with two constraints') print('within a single element') print('[0]-[1]') print('u[0] = u[1], u[1] = 1') K = SysMtxAssembly() dof_map1, mtx_arr1 = get_bar_mtx_array(shape=1) K.add_mtx_array(dof_map_arr=dof_map1, mtx_arr=mtx_arr1) # add constraints K.register_constraint(a=0, alpha=[1], ix_a=[1]) K.register_constraint(a=1, u_a=1.) # clamped end # add load R = zeros(K.n_dofs) print('u =', K.solve(R)) print()
def bar9(): print '---------------------------------------------------------------' print 'Single clamped element with two constraints' print 'within a single element' print '[0]-[1]-[2]-[3]' print 'u[0] = u[1], u[1] = 1' K = SysMtxAssembly() dof_map1, mtx_arr1 = get_bar_mtx_array(shape=3) K.add_mtx_array(dof_map_arr=dof_map1, mtx_arr=mtx_arr1) # add constraints K.register_constraint(a=0) K.register_constraint(a=3, u_a=1.) # clamped end # add load R = zeros(K.n_dofs) print 'u =', K.solve(R) print K.register_constraint(a=1, alpha=[1], ix_a=[2]) print 'u =', K.solve(R) print
def bar6(): print('---------------------------------------------------------------') print('Clamped bar with 4 elements. Elements 2-4 are reinforced ') print('with another bar with 1 element linked proportianally') print('[0]-[1]-[2]-[3]-[4]') print(' [5]-[6]') print('u[0] = 0, u[1] = u[5], u[3] = u[7], u[4] = 1') K = SysMtxAssembly() dof_map1, mtx_arr1 = get_bar_mtx_array(shape=4) K.add_mtx_array(dof_map_arr=dof_map1, mtx_arr=mtx_arr1) dof_map2, mtx_arr2 = get_bar_mtx_array(shape=1) K.add_mtx_array(dof_map_arr=dof_map2 + 5, mtx_arr=mtx_arr2) # add constraints K.register_constraint(a=0, u_a=0.) # clamped end K.register_constraint(a=5, alpha=[0.5, 0.5], ix_a=[1, 2]) K.register_constraint(a=6, alpha=[0.5, 0.5], ix_a=[2, 3]) K.register_constraint(a=4, u_a=1.) # loaded end # add load R = zeros(K.n_dofs) print('u =', K.solve(R)) print()
def bar6(): print '---------------------------------------------------------------' print 'Clamped bar with 4 elements. Elements 2-4 are reinforced ' print 'with another bar with 1 element linked proportianally' print '[0]-[1]-[2]-[3]-[4]' print ' [5]-[6]' print 'u[0] = 0, u[1] = u[5], u[3] = u[7], u[4] = 1' K = SysMtxAssembly() dof_map1, mtx_arr1 = get_bar_mtx_array( shape = 4 ) K.add_mtx_array( dof_map_arr = dof_map1, mtx_arr = mtx_arr1 ) dof_map2, mtx_arr2 = get_bar_mtx_array( shape = 1 ) K.add_mtx_array( dof_map_arr = dof_map2+5, mtx_arr = mtx_arr2 ) # add constraints K.register_constraint( a = 0, u_a = 0. ) # clamped end K.register_constraint( a = 5, alpha = [0.5,0.5], ix_a = [1,2] ) K.register_constraint( a = 6, alpha = [0.5,0.5], ix_a = [2,3] ) K.register_constraint( a = 4, u_a = 1. ) # loaded end # add load R = zeros( K.n_dofs ) print 'u =', K.solve( R ) print
def bar3(): print('---------------------------------------------------------------') print('Clamped bar with recursive constraints (load at right end)') print('[0]-[1]-[2]-[3]') print('u[1] = 0.5 * u[2], u[2] = 1 * u[3], R[3] = 11') K = SysMtxAssembly() dof_map, mtx_arr = get_bar_mtx_array(shape=3) K.add_mtx_array(dof_map_arr=dof_map, mtx_arr=mtx_arr) K.register_constraint(a=0, u_a=0.) # clamped end K.register_constraint(a=1, alpha=[0.5], ix_a=[2]) K.register_constraint(a=2, alpha=[1.0], ix_a=[3]) R = zeros(K.n_dofs) R[3] = 1 K.apply_constraints(R) print('u =', K.solve()) print() print('---------------------------------------------------------------') print('Clamped bar with recursive constraints (displ at right end)') print('u[1] = 0.5 * u[2], u[2] = 1.0 * u[3], u[3] = 1') K.register_constraint(a=3, u_a=1) print('u =', K.solve(R)) print()
def bar5(): print('---------------------------------------------------------------') print('Clamped bar with 4 elements. Elements 2-4 are reinforced ') print('with another bar with 3 elements') print('[0]-[1]-[2]-[3]-[4]') print(' [5]-[6]-[7]') print('u[0] = 0, u[1] = u[5], u[3] = u[7], u[4] = 1') # assemble the matrix K = SysMtxAssembly() dof_map1, mtx_arr1 = get_bar_mtx_array(shape=4) K.add_mtx_array(dof_map_arr=dof_map1, mtx_arr=mtx_arr1) dof_map2, mtx_arr2 = get_bar_mtx_array(shape=2) K.add_mtx_array(dof_map_arr=dof_map2 + 5, mtx_arr=mtx_arr2) # add constraints K.register_constraint(a=0, u_a=0.) # clamped end K.register_constraint(a=1, alpha=[1], ix_a=[5]) K.register_constraint(a=3, alpha=[1], ix_a=[7]) K.register_constraint(a=4, u_a=1.) # loaded end # add load R = zeros(K.n_dofs) print('u =', K.solve(R)) print()
def bar3(): print '---------------------------------------------------------------' print 'Clamped bar with recursive constraints (load at right end)' print '[0]-[1]-[2]-[3]' print 'u[1] = 0.5 * u[2], u[2] = 1 * u[3], R[3] = 11' K = SysMtxAssembly() dof_map, mtx_arr = get_bar_mtx_array( shape = 3 ) K.add_mtx_array( dof_map_arr = dof_map, mtx_arr = mtx_arr ) K.register_constraint( a = 0, u_a = 0. ) # clamped end K.register_constraint( a = 1, alpha = [0.5], ix_a = [2] ) K.register_constraint( a = 2, alpha = [1.0], ix_a = [3] ) R = zeros( K.n_dofs ) R[3] = 1 K.apply_constraints(R) print 'u =', K.solve( ) print print '---------------------------------------------------------------' print 'Clamped bar with recursive constraints (displ at right end)' print 'u[1] = 0.5 * u[2], u[2] = 1.0 * u[3], u[3] = 1' K.register_constraint( a = 3, u_a = 1 ) print 'u =', K.solve( R ) print
def bar5(): print '---------------------------------------------------------------' print 'Clamped bar with 4 elements. Elements 2-4 are reinforced ' print 'with another bar with 3 elements' print '[0]-[1]-[2]-[3]-[4]' print ' [5]-[6]-[7]' print 'u[0] = 0, u[1] = u[5], u[3] = u[7], u[4] = 1' # assemble the matrix K = SysMtxAssembly() dof_map1, mtx_arr1 = get_bar_mtx_array( shape = 4 ) K.add_mtx_array( dof_map_arr = dof_map1, mtx_arr = mtx_arr1 ) dof_map2, mtx_arr2 = get_bar_mtx_array( shape = 2 ) K.add_mtx_array( dof_map_arr = dof_map2+5, mtx_arr = mtx_arr2 ) # add constraints K.register_constraint( a = 0, u_a = 0. ) # clamped end K.register_constraint( a = 1, alpha = [1], ix_a = [5] ) K.register_constraint( a = 3, alpha = [1], ix_a = [7] ) K.register_constraint( a = 4, u_a = 1. ) # loaded end # add load R = zeros( K.n_dofs ) print 'u =', K.solve( R ) print
def bar4(): print('---------------------------------------------------------------') print('Clamped bar 3 domains, each with 2 elems (displ at right end)') print('[0]-[1]-[2] [3]-[4]-[5] [6]-[7]-[8]') print('u[0] = 0, u[2] = u[3], u[5] = u[6], u[8] = 1') K = SysMtxAssembly() dof_map1, mtx_arr1 = get_bar_mtx_array(shape=2) K.add_mtx_array(dof_map_arr=dof_map1, mtx_arr=mtx_arr1) dof_map2, mtx_arr2 = get_bar_mtx_array(shape=2) K.add_mtx_array(dof_map_arr=dof_map2 + 3, mtx_arr=mtx_arr2) dof_map3, mtx_arr3 = get_bar_mtx_array(shape=2) K.add_mtx_array(dof_map_arr=dof_map3 + 6, mtx_arr=mtx_arr3) # add constraints K.register_constraint(a=0, u_a=0.) # clamped end K.register_constraint(a=2, alpha=[1], ix_a=[3]) K.register_constraint(a=5, alpha=[1], ix_a=[6]) K.register_constraint(a=8, u_a=1.) # loaded end # add load R = zeros(K.n_dofs) print('u =', K.solve(R)) print()
def bar4(): print '---------------------------------------------------------------' print 'Clamped bar 3 domains, each with 2 elems (displ at right end)' print '[0]-[1]-[2] [3]-[4]-[5] [6]-[7]-[8]' print 'u[0] = 0, u[2] = u[3], u[5] = u[6], u[8] = 1' K = SysMtxAssembly() dof_map1, mtx_arr1 = get_bar_mtx_array( shape = 2 ) K.add_mtx_array( dof_map_arr = dof_map1, mtx_arr = mtx_arr1 ) dof_map2, mtx_arr2 = get_bar_mtx_array( shape = 2 ) K.add_mtx_array( dof_map_arr = dof_map2+3, mtx_arr = mtx_arr2 ) dof_map3, mtx_arr3 = get_bar_mtx_array( shape = 2 ) K.add_mtx_array( dof_map_arr = dof_map3+6, mtx_arr = mtx_arr3 ) # add constraints K.register_constraint( a = 0, u_a = 0. ) # clamped end K.register_constraint( a = 2, alpha = [1], ix_a = [3] ) K.register_constraint( a = 5, alpha = [1], ix_a = [6] ) K.register_constraint( a = 8, u_a = 1. ) # loaded end # add load R = zeros( K.n_dofs ) print 'u =', K.solve( R ) print
class TStepper(HasTraits): '''Time stepper object for non-linear Newton-Raphson solver. ''' mats_eval = Property(Instance(MATSEvalFatigue)) '''Finite element formulation object. ''' @cached_property def _get_mats_eval(self): return MATSEvalFatigue() fets_eval = Property(Instance(FETS1D52ULRHFatigue)) '''Finite element formulation object. ''' @cached_property def _get_fets_eval(self): return FETS1D52ULRHFatigue() A = Property() '''array containing the A_m, L_b, A_f ''' def _get_A(self): return np.array( [self.fets_eval.A_m, self.fets_eval.P_b, self.fets_eval.A_f]) # Number of elements n_e_x = 20 # length L_x = Float(200) domain = Property(Instance(FEGrid), depends_on='L_x') '''Diescretization object. ''' @cached_property def _get_domain(self): # Element definition domain = FEGrid(coord_max=(self.L_x, ), shape=(self.n_e_x, ), fets_eval=self.fets_eval) return domain # Boundary condition manager # bcond_mngr = Instance(BCondMngr) def _bcond_mngr_default(self): return BCondMngr() bcond_list = Property(List(BCDof)) '''Convenience constructor This property provides the possibility to write tstepper.bcond_list = [BCDof(var='u',dof=5,value=0, ... ] The result gets propagated to the BCondMngr ''' def _get_bcond_list(self): return self.bcond_mngr.bcond_list def _set_bcond_list(self, bcond_list): self.bcond_mngr.bcond_list = bcond_list J_mtx = Property(depends_on='L_x') '''Array of Jacobian matrices. ''' @cached_property def _get_J_mtx(self): fets_eval = self.fets_eval domain = self.domain # [ d, n ] geo_r = fets_eval.geo_r.T # [ d, n, i ] dNr_geo = geo_r[:, :, None] * np.array([1, 1]) * 0.5 # [ i, n, d ] dNr_geo = np.einsum('dni->ind', dNr_geo) # [ n_e, n_geo_r, n_dim_geo ] elem_x_map = domain.elem_X_map # [ n_e, n_ip, n_dim_geo, n_dim_geo ] J_mtx = np.einsum('ind,enf->eidf', dNr_geo, elem_x_map) return J_mtx J_det = Property(depends_on='L_x') '''Array of Jacobi determinants. ''' @cached_property def _get_J_det(self): return np.linalg.det(self.J_mtx) B = Property(depends_on='L_x') '''The B matrix ''' @cached_property def _get_B(self): '''Calculate and assemble the system stiffness matrix. ''' mats_eval = self.mats_eval fets_eval = self.fets_eval domain = self.domain n_s = mats_eval.n_s - 1 n_dof_r = fets_eval.n_dof_r n_nodal_dofs = fets_eval.n_nodal_dofs n_ip = fets_eval.n_gp n_e = domain.n_active_elems #[ d, i] r_ip = fets_eval.ip_coords[:, :-2].T # [ d, n ] geo_r = fets_eval.geo_r.T # [ d, n, i ] dNr_geo = geo_r[:, :, None] * np.array([1, 1]) * 0.5 # [ i, n, d ] dNr_geo = np.einsum('dni->ind', dNr_geo) J_inv = np.linalg.inv(self.J_mtx) # shape function for the unknowns # [ d, n, i] Nr = 0.5 * (1. + geo_r[:, :, None] * r_ip[None, :]) dNr = 0.5 * geo_r[:, :, None] * np.array([1, 1]) # [ i, n, d ] Nr = np.einsum('dni->ind', Nr) dNr = np.einsum('dni->ind', dNr) Nx = Nr # [ n_e, n_ip, n_dof_r, n_dim_dof ] dNx = np.einsum('eidf,inf->eind', J_inv, dNr) B = np.zeros((n_e, n_ip, n_dof_r, n_s, n_nodal_dofs), dtype='f') B_N_n_rows, B_N_n_cols, N_idx = [1, 1], [0, 1], [0, 0] B_dN_n_rows, B_dN_n_cols, dN_idx = [0, 2], [0, 1], [0, 0] B_factors = np.array([-1, 1], dtype='float_') B[:, :, :, B_N_n_rows, B_N_n_cols] = (B_factors[None, None, :] * Nx[:, :, N_idx]) B[:, :, :, B_dN_n_rows, B_dN_n_cols] = dNx[:, :, :, dN_idx] return B def apply_essential_bc(self): '''Insert initial boundary conditions at the start up of the calculation.. ''' self.K = SysMtxAssembly() for bc in self.bcond_list: bc.apply_essential(self.K) def apply_bc(self, step_flag, K_mtx, F_ext, t_n, t_n1): '''Apply boundary conditions for the current load increement ''' for bc in self.bcond_list: bc.apply(step_flag, None, K_mtx, F_ext, t_n, t_n1) def get_corr_pred(self, step_flag, U, d_U, eps, sig, t_n, t_n1, xs_pi, alpha, z, w): '''Function calculationg the residuum and tangent operator. ''' mats_eval = self.mats_eval fets_eval = self.fets_eval domain = self.domain elem_dof_map = domain.elem_dof_map n_e = domain.n_active_elems n_dof_r, n_dim_dof = self.fets_eval.dof_r.shape n_nodal_dofs = self.fets_eval.n_nodal_dofs n_el_dofs = n_dof_r * n_nodal_dofs # [ i ] w_ip = fets_eval.ip_weights d_u_e = d_U[elem_dof_map] #[n_e, n_dof_r, n_dim_dof] d_u_n = d_u_e.reshape(n_e, n_dof_r, n_nodal_dofs) #[n_e, n_ip, n_s] d_eps = np.einsum('einsd,end->eis', self.B, d_u_n) # print'B =', self.B # update strain eps += d_eps # material response state variables at integration point sig, D, xs_pi, alpha, z, w = mats_eval.get_corr_pred( eps, d_eps, sig, t_n, t_n1, xs_pi, alpha, z, w) # print'D=',D # system matrix self.K.reset_mtx() Ke = np.einsum('i,s,einsd,eist,eimtf,ei->endmf', w_ip, self.A, self.B, D, self.B, self.J_det) self.K.add_mtx_array(Ke.reshape(-1, n_el_dofs, n_el_dofs), elem_dof_map) # internal forces # [n_e, n_n, n_dim_dof] Fe_int = np.einsum('i,s,eis,einsd,ei->end', w_ip, self.A, sig, self.B, self.J_det) F_int = np.bincount(elem_dof_map.flatten(), weights=Fe_int.flatten()) F_ext = np.zeros_like(F_int, dtype=np.float_) self.apply_bc(step_flag, self.K, F_ext, t_n, t_n1) return F_ext - F_int, F_int, self.K, eps, sig, xs_pi, alpha, z, w, D
class TStepper(HasTraits): '''Time stepper object for non-linear Newton-Raphson solver. ''' mats_eval = Instance(IMATSEval) '''Finite element formulation object. ''' def _mats_eval_default(self): return MATSBondSlipFatigue() fets_eval = Instance(IFETSEval) '''Finite element formulation object. ''' def _fets_eval_default(self): return FETS1D52ULRHFatigue() A = Property() '''array containing the A_m, L_b, A_f ''' def _get_A(self): return np.array([self.fets_eval.A_m, self.fets_eval.P_b, self.fets_eval.A_f]) sdomain = Instance(FEGrid) #========================================================================= # index maps #========================================================================= dof_ECid = Property(depends_on='+input') '''For a given element, layer, node number and dimension return the dof number ''' @cached_property def _get_dof_ECid(self): dof_EiCd = self.sdomain.dof_grid.cell_dof_map[..., np.newaxis] return np.einsum('EiCd->ECid', dof_EiCd) I_Ei = Property(depends_on='+input') '''For a given element and its node number return the global index of the node''' @cached_property def _get_I_Ei(self): return self.sdomain.geo_grid.cell_grid.cell_node_map dof_E = Property(depends_on='+input') '''Get ordered array of degrees of freedom corresponding to each element. ''' @cached_property def _get_dof_E(self): return self.dof_ECid.reshape(-1, self.fets_eval.n_e_dofs) dof_ICd = Property(depends_on='+input') '''Get degrees of freedom ''' @cached_property def _get_dof_ICd(self): return self.sdomain.dof_grid.dofs dofs = Property(depends_on='_input') '''Get degrees of freedom flat''' @cached_property def _get_dofs(self): return self.dof_ICd.flatten() #========================================================================= # Coordinate arrays #========================================================================= X_Id = Property(depends_on='+input') 'Coordinate of the node `I` in dimension `d`' @cached_property def _get_X_Id(self): return self.sdomain.geo_grid.cell_grid.point_x_arr X_Eid = Property(depends_on='+input') 'Coordinate of the node `i` in element `E` in dimension `d`' @cached_property def _get_X_Eid(self): return self.X_Id[self.I_Ei, :] X_Emd = Property(depends_on='+input') 'Coordinate of the integration point `m` of an element `E` in dimension `d`' @cached_property def _get_X_Emd(self): N_mi_geo = self.fets_eval.N_mi_geo return np.einsum('mi,Eid->Emd', N_mi_geo, self.X_Eid) X_J = Property(depends_on='+input') '''Return ordered vector of nodal coordinates respecting the the order of the flattened array of elements, nodes and spatial dimensions.''' @cached_property def _get_X_J(self): return self.X_Eid.flatten() X_M = Property(depends_on='+input') '''Return ordered vector of global coordinates of integration points respecting the the order of the flattened array of elements, nodes and spatial dimensions. Can be used for point-value visualization of response variables.''' @cached_property def _get_X_M(self): return self.X_Emd.flatten() #========================================================================= # cached time-independent terms #========================================================================= dN_Eimd = Property '''Shape function derivatives in every integration point ''' def _get_dN_Eimd(self): return self.constant_terms[0] sN_Cim = Property '''Slip operator between the layers C = 0,1 ''' def _get_sN_Cim(self): return self.constant_terms[1] constant_terms = Property(depends_on='+input') '''Procedure calculating all constant terms of the finite element algorithm including the geometry mapping (Jacobi), shape functions and the kinematics needed for the integration of stresses and stifnesses in every material point. ''' @cached_property def _get_constant_terms(self): fet = self.fets_eval dN_mid_geo = fet.dN_mid_geo N_mi = fet.N_mi dN_mid = fet.dN_mid # Geometry approximation / Jacobi transformation J_Emde = np.einsum('mid,Eie->Emde', dN_mid_geo, self.X_Eid) J_inv_Emed = np.linalg.inv(J_Emde) # Quadratic forms dN_Eimd = np.einsum('mid,Eied->Eime', dN_mid, J_inv_Emed) sN_Cim = np.einsum('C,mi->Cim', SWITCH_C, N_mi) return dN_Eimd, sN_Cim # Boundary condition manager # bcond_mngr = Instance(BCondMngr) def _bcond_mngr_default(self): return BCondMngr() bcond_list = Property(List(BCDof)) '''Convenience constructor This property provides the possibility to write tstepper.bcond_list = [BCDof(var='u',dof=5,value=0, ... ] The result gets propagated to the BCondMngr ''' def _get_bcond_list(self): return self.bcond_mngr.bcond_list def _set_bcond_list(self, bcond_list): self.bcond_mngr.bcond_list = bcond_list J_mtx = Property(depends_on='L_x') '''Array of Jacobian matrices. ''' @cached_property def _get_J_mtx(self): fets_eval = self.fets_eval domain = self.sdomain # [ d, n ] geo_r = fets_eval.geo_r.T # [ d, n, i ] dNr_geo = geo_r[:, :, None] * np.array([1, 1]) * 0.5 # [ i, n, d ] dNr_geo = np.einsum('dni->ind', dNr_geo) # [ n_e, n_geo_r, n_dim_geo ] elem_x_map = domain.elem_X_map # [ n_e, n_ip, n_dim_geo, n_dim_geo ] J_mtx = np.einsum('ind,enf->eidf', dNr_geo, elem_x_map) return J_mtx J_det = Property(depends_on='L_x') '''Array of Jacobi determinants. ''' @cached_property def _get_J_det(self): return np.linalg.det(self.J_mtx) B = Property(depends_on='L_x') '''The B matrix ''' @cached_property def _get_B(self): '''Calculate and assemble the system stiffness matrix. ''' mats_eval = self.mats_eval fets_eval = self.fets_eval domain = self.sdomain n_s = mats_eval.n_s - 1 n_dof_r = fets_eval.n_dof_r n_nodal_dofs = fets_eval.n_nodal_dofs n_ip = fets_eval.n_gp n_e = domain.n_active_elems #[ d, i] r_ip = fets_eval.ip_coords[:, :-2].T # [ d, n ] geo_r = fets_eval.geo_r.T # [ d, n, i ] dNr_geo = geo_r[:, :, None] * np.array([1, 1]) * 0.5 # [ i, n, d ] dNr_geo = np.einsum('dni->ind', dNr_geo) J_inv = np.linalg.inv(self.J_mtx) # shape function for the unknowns # [ d, n, i] Nr = 0.5 * (1. + geo_r[:, :, None] * r_ip[None, :]) dNr = 0.5 * geo_r[:, :, None] * np.array([1, 1]) # [ i, n, d ] Nr = np.einsum('dni->ind', Nr) dNr = np.einsum('dni->ind', dNr) Nx = Nr # [ n_e, n_ip, n_dof_r, n_dim_dof ] dNx = np.einsum('eidf,inf->eind', J_inv, dNr) B = np.zeros((n_e, n_ip, n_dof_r, n_s, n_nodal_dofs), dtype='f') B_N_n_rows, B_N_n_cols, N_idx = [1, 1], [0, 1], [0, 0] B_dN_n_rows, B_dN_n_cols, dN_idx = [0, 2], [0, 1], [0, 0] B_factors = np.array([-1, 1], dtype='float_') B[:, :, :, B_N_n_rows, B_N_n_cols] = (B_factors[None, None, :] * Nx[:, :, N_idx]) B[:, :, :, B_dN_n_rows, B_dN_n_cols] = dNx[:, :, :, dN_idx] return B def apply_essential_bc(self): '''Insert initial boundary conditions at the start up of the calculation.. ''' self.K = SysMtxAssembly() for bc in self.bcond_list: bc.apply_essential(self.K) def apply_bc(self, step_flag, K_mtx, F_ext, t_n, t_n1): '''Apply boundary conditions for the current load increement ''' for bc in self.bcond_list: bc.apply(step_flag, None, K_mtx, F_ext, t_n, t_n1) def get_corr_pred(self, step_flag, U, d_U, eps, sig, t_n, t_n1, xs_pi, alpha, z, kappa, w): '''Function calculationg the residuum and tangent operator. ''' mats_eval = self.mats_eval fets_eval = self.fets_eval domain = self.sdomain elem_dof_map = domain.elem_dof_map n_e = domain.n_active_elems n_dof_r, n_dim_dof = self.fets_eval.dof_r.shape n_nodal_dofs = self.fets_eval.n_nodal_dofs n_el_dofs = n_dof_r * n_nodal_dofs # [ i ] w_ip = fets_eval.ip_weights d_u_e = d_U[elem_dof_map] #[n_e, n_dof_r, n_dim_dof] d_u_n = d_u_e.reshape(n_e, n_dof_r, n_nodal_dofs) #[n_e, n_ip, n_s] d_eps = np.einsum('Einsd,End->Eis', self.B, d_u_n) # print'B =', self.B # update strain eps += d_eps # material response state variables at integration point sig, D, xs_pi, alpha, z, w = mats_eval.get_corr_pred( eps, d_eps, sig, t_n, t_n1, xs_pi, alpha, z, kappa, w) # print'D=',D # system matrix self.K.reset_mtx() Ke = np.einsum('i,s,einsd,eist,eimtf,ei->endmf', w_ip, self.A, self.B, D, self.B, self.J_det) self.K.add_mtx_array( Ke.reshape(-1, n_el_dofs, n_el_dofs), elem_dof_map) # internal forces # [n_e, n_n, n_dim_dof] Fe_int = np.einsum('i,s,eis,einsd,ei->end', w_ip, self.A, sig, self.B, self.J_det) F_int = np.bincount(elem_dof_map.flatten(), weights=Fe_int.flatten()) F_ext = np.zeros_like(F_int, dtype=np.float_) self.apply_bc(step_flag, self.K, F_ext, t_n, t_n1) return F_ext - F_int, F_int, self.K, eps, sig, xs_pi, alpha, z, w, D
class TStepper(HasTraits): '''Time stepper object for non-linear Newton-Raphson solver. ''' mats_eval = Property(Instance(MATSEval)) '''Finite element formulation object. ''' @cached_property def _get_mats_eval(self): return MATSEval() fets_eval = Property(Instance(FETS1D52ULRH)) '''Finite element formulation object. ''' @cached_property def _get_fets_eval(self): return FETS1D52ULRH() A = Property '''array containing the A_m, L_b, A_f ''' @cached_property def _get_A(self): return np.array([self.fets_eval.A_m, self.fets_eval.L_b, self.fets_eval.A_f]) # specimen length L_x = Float(18.4) # Number of elements n_e_x = Int(10) domain = Property(Instance(FEGrid), depends_on='L_x, n_e_x') '''Diescretization object. ''' @cached_property def _get_domain(self): # Element definition domain = FEGrid(coord_max=(self.L_x,), shape=(self.n_e_x,), fets_eval=self.fets_eval) return domain bc_list = List(Instance(BCDof)) J_mtx = Property(depends_on='L_x, n_e_x') '''Array of Jacobian matrices. ''' @cached_property def _get_J_mtx(self): fets_eval = self.fets_eval domain = self.domain # [ d, n ] geo_r = fets_eval.geo_r.T # [ d, n, i ] dNr_geo = geo_r[:, :, None] * np.array([1, 1]) * 0.5 # [ i, n, d ] dNr_geo = np.einsum('dni->ind', dNr_geo) # [ n_e, n_geo_r, n_dim_geo ] elem_x_map = domain.elem_X_map # [ n_e, n_ip, n_dim_geo, n_dim_geo ] J_mtx = np.einsum('ind,enf->eidf', dNr_geo, elem_x_map) return J_mtx J_det = Property(depends_on='L_x, n_e_x') '''Array of Jacobi determinants. ''' @cached_property def _get_J_det(self): return np.linalg.det(self.J_mtx) B = Property(depends_on='L_x, n_e_x') '''The B matrix ''' @cached_property def _get_B(self): '''Calculate and assemble the system stiffness matrix. ''' mats_eval = self.mats_eval fets_eval = self.fets_eval domain = self.domain n_s = mats_eval.n_s n_dof_r = fets_eval.n_dof_r n_nodal_dofs = fets_eval.n_nodal_dofs n_ip = fets_eval.n_gp n_e = domain.n_active_elems #[ d, i] r_ip = fets_eval.ip_coords[:, :-2].T # [ d, n ] geo_r = fets_eval.geo_r.T # [ d, n, i ] dNr_geo = geo_r[:, :, None] * np.array([1, 1]) * 0.5 # [ i, n, d ] dNr_geo = np.einsum('dni->ind', dNr_geo) J_inv = np.linalg.inv(self.J_mtx) # shape function for the unknowns # [ d, n, i] Nr = 0.5 * (1. + geo_r[:, :, None] * r_ip[None,:]) dNr = 0.5 * geo_r[:, :, None] * np.array([1, 1]) # [ i, n, d ] Nr = np.einsum('dni->ind', Nr) dNr = np.einsum('dni->ind', dNr) Nx = Nr # [ n_e, n_ip, n_dof_r, n_dim_dof ] dNx = np.einsum('eidf,inf->eind', J_inv, dNr) B = np.zeros((n_e, n_ip, n_dof_r, n_s, n_nodal_dofs), dtype='f') B_N_n_rows, B_N_n_cols, N_idx = [1, 1], [0, 1], [0, 0] B_dN_n_rows, B_dN_n_cols, dN_idx = [0, 2], [0, 1], [0, 0] B_factors = np.array([-1, 1], dtype='float_') B[:, :,:, B_N_n_rows, B_N_n_cols] = (B_factors[None, None,:] * Nx[:, :, N_idx]) B[:, :,:, B_dN_n_rows, B_dN_n_cols] = dNx[:,:,:, dN_idx] return B def apply_essential_bc(self): '''Insert initial boundary conditions at the start up of the calculation.. ''' self.K = SysMtxAssembly() for bc in self.bc_list: bc.apply_essential(self.K) def apply_bc(self, step_flag, K_mtx, F_ext, t_n, t_n1): '''Apply boundary conditions for the current load increement ''' for bc in self.bc_list: bc.apply(step_flag, None, K_mtx, F_ext, t_n, t_n1) def get_corr_pred(self, step_flag, d_U, eps, sig, t_n, t_n1): '''Function calculationg the residuum and tangent operator. ''' mats_eval = self.mats_eval fets_eval = self.fets_eval domain = self.domain elem_dof_map = domain.elem_dof_map n_e = domain.n_active_elems n_dof_r, n_dim_dof = self.fets_eval.dof_r.shape n_nodal_dofs = self.fets_eval.n_nodal_dofs n_el_dofs = n_dof_r * n_nodal_dofs # [ i ] w_ip = fets_eval.ip_weights d_u_e = d_U[elem_dof_map] #[n_e, n_dof_r, n_dim_dof] d_u_n = d_u_e.reshape(n_e, n_dof_r, n_nodal_dofs) #[n_e, n_ip, n_s] d_eps = np.einsum('einsd,end->eis', self.B, d_u_n) # update strain eps += d_eps # if np.any(sig) == np.nan: # sys.exit() # material response state variables at integration point sig, D = mats_eval.get_corr_pred(eps, d_eps, sig, t_n, t_n1) # system matrix self.K.reset_mtx() Ke = np.einsum('i,s,einsd,eist,eimtf,ei->endmf', w_ip, self.A, self.B, D, self.B, self.J_det) self.K.add_mtx_array( Ke.reshape(-1, n_el_dofs, n_el_dofs), elem_dof_map) # internal forces # [n_e, n_n, n_dim_dof] Fe_int = np.einsum('i,s,eis,einsd,ei->end', w_ip, self.A, sig, self.B, self.J_det) F_int = -np.bincount(elem_dof_map.flatten(), weights=Fe_int.flatten()) self.apply_bc(step_flag, self.K, F_int, t_n, t_n1) return F_int, self.K, eps, sig
# shape function for the unknowns are identical with the geomeetric # approximation dNr = dNr_geo # [ n_e, n_ip, n_dof_r, n_dim_dof ] dNx = np.einsum('eidf,inf->eind', J_inv, dNr) B = np.zeros((n_e, n_ip, n_dof_r, n_s, n_dim_dof), dtype='f') B_n_rows, B_n_cols, dNx_d = [0, 1, 2, 2], [0, 1, 0, 1], [0, 1, 1, 0] B[:, :, :, B_n_rows, B_n_cols] = dNx[:, :, :, dNx_d] #========================================================================= # System matrix #========================================================================= K = np.einsum('i,einsd,st,eimtf,ei->endmf', w_ip, B, D_el, B, J_det) K_mtx = SysMtxAssembly() K_mtx.add_mtx_array(K.reshape(-1, n_el_dofs, n_el_dofs), elem_dof_map) #========================================================================= # Load vector #========================================================================= R = np.zeros((n_dofs,), dtype='float_') R[[8, 10]] = 1.0 K_mtx.register_constraint(a=0) K_mtx.register_constraint(a=1) K_mtx.register_constraint(a=2) u = K_mtx.solve(R) print 'u', u
dNx = np.einsum('eidf,inf->eind', J_inv, dNr) B = np.zeros((n_e, n_ip, n_dof_r, n_s, n_dim_dof), dtype='f') B_N_n_rows, B_N_n_cols, N_idx = [1, 1], [0, 1], [0, 0] B_dN_n_rows, B_dN_n_cols, dN_idx = [0, 2], [0, 1], [0, 0] B_factors = np.array([-1, 1], dtype='float_') B[:, :, :, B_N_n_rows, B_N_n_cols] = (B_factors[None, None, :] * Nx[:, :, N_idx]) B[:, :, :, B_dN_n_rows, B_dN_n_cols] = dNx[:, :, :, dN_idx] #========================================================================= # System matrix #========================================================================= K = np.einsum('i,einsd,st,eimtf,ei->endmf', w_ip, B, D_el, B, J_det) K_mtx = SysMtxAssembly() K_mtx.add_mtx_array(K.reshape(-1, n_el_dofs, n_el_dofs), elem_dof_map) #========================================================================= # BC and solver #========================================================================= R = np.zeros((n_dofs, ), dtype='float_') R[2 * n_e_x + 1] = 1.0 K_mtx.register_constraint(a=0) # K_mtx.register_constraint(a=2 * n_e_x + 1, u_a=1.0) u = K_mtx.solve(R) # print 'u', u #========================================================================= # internal force #=========================================================================
class TStepper(HasTraits): '''Time stepper object for non-linear Newton-Raphson solver. ''' mats_eval = Property(Instance(MATSEval)) '''Finite element formulation object. ''' @cached_property def _get_mats_eval(self): return MATSEval() fets_eval = Property(Instance(FETS1D52ULRH)) '''Finite element formulation object. ''' @cached_property def _get_fets_eval(self): return FETS1D52ULRH() A = Property() '''array containing the A_m, L_b, A_f ''' @cached_property def _get_A(self): return np.array( [self.fets_eval.A_m, self.fets_eval.L_b, self.fets_eval.A_f]) domain = Property(Instance(FEGrid)) '''Diescretization object. ''' @cached_property def _get_domain(self): # Number of elements n_e_x = 15 # length L_x = 150.0 # Element definition domain = FEGrid(coord_max=(L_x, ), shape=(n_e_x, ), fets_eval=self.fets_eval) return domain bc_list = List(Instance(BCDof)) J_mtx = Property '''Array of Jacobian matrices. ''' @cached_property def _get_J_mtx(self): fets_eval = self.fets_eval domain = self.domain # [ d, n ] geo_r = fets_eval.geo_r.T # [ d, n, i ] dNr_geo = geo_r[:, :, None] * np.array([1, 1]) * 0.5 # [ i, n, d ] dNr_geo = np.einsum('dni->ind', dNr_geo) # [ n_e, n_geo_r, n_dim_geo ] elem_x_map = domain.elem_X_map # [ n_e, n_ip, n_dim_geo, n_dim_geo ] J_mtx = np.einsum('ind,enf->eidf', dNr_geo, elem_x_map) return J_mtx J_det = Property '''Array of Jacobi determinants. ''' @cached_property def _get_J_det(self): return np.linalg.det(self.J_mtx) B = Property '''The B matrix ''' @cached_property def _get_B(self): '''Calculate and assemble the system stiffness matrix. ''' mats_eval = self.mats_eval fets_eval = self.fets_eval domain = self.domain n_s = mats_eval.n_s n_dof_r = fets_eval.n_dof_r n_nodal_dofs = fets_eval.n_nodal_dofs n_ip = fets_eval.n_gp n_e = domain.n_active_elems #[ d, i] r_ip = fets_eval.ip_coords[:, :-2].T # [ d, n ] geo_r = fets_eval.geo_r.T # [ d, n, i ] dNr_geo = geo_r[:, :, None] * np.array([1, 1]) * 0.5 # [ i, n, d ] dNr_geo = np.einsum('dni->ind', dNr_geo) J_inv = np.linalg.inv(self.J_mtx) # shape function for the unknowns # [ d, n, i] Nr = 0.5 * (1. + geo_r[:, :, None] * r_ip[None, :]) dNr = 0.5 * geo_r[:, :, None] * np.array([1, 1]) # [ i, n, d ] Nr = np.einsum('dni->ind', Nr) dNr = np.einsum('dni->ind', dNr) Nx = Nr # [ n_e, n_ip, n_dof_r, n_dim_dof ] dNx = np.einsum('eidf,inf->eind', J_inv, dNr) B = np.zeros((n_e, n_ip, n_dof_r, n_s, n_nodal_dofs), dtype='f') B_N_n_rows, B_N_n_cols, N_idx = [1, 1], [0, 1], [0, 0] B_dN_n_rows, B_dN_n_cols, dN_idx = [0, 2], [0, 1], [0, 0] B_factors = np.array([-1, 1], dtype='float_') B[:, :, :, B_N_n_rows, B_N_n_cols] = (B_factors[None, None, :] * Nx[:, :, N_idx]) B[:, :, :, B_dN_n_rows, B_dN_n_cols] = dNx[:, :, :, dN_idx] return B def apply_essential_bc(self): '''Insert initial boundary conditions at the start up of the calculation.. ''' self.K = SysMtxAssembly() for bc in self.bc_list: bc.apply_essential(self.K) def apply_bc(self, step_flag, K_mtx, F_ext, t_n, t_n1): '''Apply boundary conditions for the current load increement ''' for bc in self.bc_list: bc.apply(step_flag, None, K_mtx, F_ext, t_n, t_n1) def get_corr_pred(self, step_flag, d_U, eps, sig, t_n, t_n1): '''Function calculationg the residuum and tangent operator. ''' mats_eval = self.mats_eval fets_eval = self.fets_eval domain = self.domain elem_dof_map = domain.elem_dof_map n_e = domain.n_active_elems n_dof_r, n_dim_dof = self.fets_eval.dof_r.shape n_nodal_dofs = self.fets_eval.n_nodal_dofs n_el_dofs = n_dof_r * n_nodal_dofs # [ i ] w_ip = fets_eval.ip_weights d_u_e = d_U[elem_dof_map] #[n_e, n_dof_r, n_dim_dof] d_u_n = d_u_e.reshape(n_e, n_dof_r, n_nodal_dofs) #[n_e, n_ip, n_s] d_eps = np.einsum('einsd,end->eis', self.B, d_u_n) # update strain eps += d_eps # if np.any(sig) == np.nan: # sys.exit() # material response state variables at integration point sig, D = mats_eval.get_corr_pred(eps, d_eps, sig, t_n, t_n1) # system matrix self.K.reset_mtx() Ke = np.einsum('i,s,einsd,eist,eimtf,ei->endmf', w_ip, self.A, self.B, D, self.B, self.J_det) self.K.add_mtx_array(Ke.reshape(-1, n_el_dofs, n_el_dofs), elem_dof_map) # internal forces # [n_e, n_n, n_dim_dof] Fe_int = np.einsum('i,s,eis,einsd,ei->end', w_ip, self.A, sig, self.B, self.J_det) F_int = -np.bincount(elem_dof_map.flatten(), weights=Fe_int.flatten()) self.apply_bc(step_flag, self.K, F_int, t_n, t_n1) return F_int, self.K, eps, sig
Created on 05.02.2017 @author: Yingxiong ''' from numpy import array, zeros, arange, array_equal, hstack, dot from mathkit.matrix_la.sys_mtx_assembly import SysMtxAssembly shape = 5 el_mtx = array([[10, -10], [-10, 10]], dtype='float_') mtx_arr = array([el_mtx for i in range(shape)], dtype=float) dof_map = array([arange(shape), arange(shape) + 1], dtype=int).transpose() K = SysMtxAssembly() K.add_mtx_array(dof_map_arr=dof_map, mtx_arr=mtx_arr) K.register_constraint(a=0, u_a=0.) # clamped end K.register_constraint(a=4, u_a=2.) K.register_constraint(a=2, u_a=1.) R = zeros(K.n_dofs) R[-1] = 10. print 'u =', K.solve(R) print R print K.sys_mtx_arrays[0].mtx_arr