def get_fargs(self, mtx_d, drill, virtual, state, mode=None, term_mode=None, diff_var=None, **kwargs): from sfepy.discrete.variables import create_adof_conn vv, vu = virtual, state geo, _ = self.get_mapping(vv) # Displacements of element nodes. vec_u = vu() econn = vu.field.get_econn('volume', self.region) adc = create_adof_conn(nm.arange(vu.n_dof, dtype=nm.int32), econn, 6, 0) el_u = vec_u[adc] qp_coors = geo.qp.vals dsg = shell10x.get_dsg_strain(geo.coors_loc, geo.qp.vals) mtx_b = shell10x.create_strain_matrix(geo.bfgm, geo.dxidx, dsg) mtx_be = shell10x.add_eas_dofs(mtx_b, qp_coors, geo.det, geo.det0, geo.dxidx0) mtx_dr = shell10x.rotate_elastic_tensor(mtx_d, geo.bfu, geo.ebs) mtx_k_qp = ddot(ddot(mtx_be, mtx_dr, 'ATB'), mtx_be, 'AB') # Integrate. mtx_k = (mtx_k_qp * (geo.det * geo.qp.weights)[..., None, None]).sum(1) # Static condensation. k11 = mtx_k[:, :24, :24] k12 = mtx_k[:, :24, 24:] k22 = mtx_k[:, 24:, 24:] mtx_k = k11 - ddot(ddot(k12, nm.linalg.inv(k22)), k12.transpose( 0, 2, 1)) if drill != 0.0: coefs = mtx_dr[..., 3, 3].mean(1) * geo.volume * drill mtx_k = shell10x.lock_drilling_rotations(mtx_k, geo.ebs, coefs) # DOFs in mtx_k are DOF-by-DOF. Transform is u and phi node-by-node. blocks = nm.arange(24).reshape(2, 3, 4) blocks = blocks.transpose((0, 2, 1)).reshape((-1, 3)) shell10x.transform_asm_matrices(mtx_k[:, None, ...], geo.mtx_t, blocks) fmode = diff_var is not None return (mtx_k, el_u, fmode)
def lock_drilling_rotations(mtx, ebs, coefs): """ Lock the drilling rotations in the stiffness matrix. """ mtx_drl = create_drl_transform(ebs) mtx_idrl = nm.linalg.inv(mtx_drl) mtx_tr = ddot(ddot(mtx_drl, mtx), mtx_idrl) idrl = nm.arange(20, 24) mtx_tr[:, idrl, idrl] = coefs[:, None] mtx2 = ddot(ddot(mtx_idrl, mtx_tr), mtx_drl) return mtx2
def rotate_elastic_tensor(mtx_d, bfu, ebs): """ Rotate the elastic tensor into the local coordinate system of each cell. The local coordinate system results from interpolation of `ebs` with the bilinear basis. """ # ! mtx_ts is not orthonormal for non-planar cells! mtx_ts = nm.einsum('qi,cijk->cqjk', bfu[:, 0, :], ebs) # print nm.einsum('cqji,cqjk->cqik', mtx_ts, mtx_ts) # ? double entries here? tt = create_strain_transform(mtx_ts) mtx_dr = ddot(ddot(tt, mtx_d, 'ATB'), tt, 'AB') return mtx_dr
def function(out, mtx_k, el_u, fmode): if fmode == 0: out[:, 0, ...] = ddot(mtx_k, el_u[..., None], 'AB') else: out[:, 0, ...] = mtx_k return 0
def get_fargs(self, mtx_d, drill, virtual, state, mode=None, term_mode=None, diff_var=None, **kwargs): from sfepy.discrete.variables import create_adof_conn vv, vu = virtual, state geo, _ = self.get_mapping(vv) # Displacements of element nodes. vec_u = vu() econn = vu.field.get_econn('volume', self.region) adc = create_adof_conn(nm.arange(vu.n_dof, dtype=nm.int32), econn, 6, 0) el_u = vec_u[adc] qp_coors = geo.qp.vals dsg = shell10x.get_dsg_strain(geo.coors_loc, geo.qp.vals) mtx_b = shell10x.create_strain_matrix(geo.bfgm, geo.dxidx, dsg) mtx_be = shell10x.add_eas_dofs(mtx_b, qp_coors, geo.det, geo.det0, geo.dxidx0) mtx_dr = shell10x.rotate_elastic_tensor(mtx_d, geo.bfu, geo.ebs) mtx_k_qp = ddot(ddot(mtx_be, mtx_dr, 'ATB'), mtx_be, 'AB') # Integrate. mtx_k = (mtx_k_qp * (geo.det * geo.qp.weights)[..., None, None]).sum(1) # Static condensation. k11 = mtx_k[:, :24, :24] k12 = mtx_k[:, :24, 24:] k22 = mtx_k[:, 24:, 24:] mtx_k = k11 - ddot(ddot(k12, nm.linalg.inv(k22)), k12.transpose(0, 2, 1)) if drill != 0.0: coefs = mtx_dr[..., 3, 3].mean(1) * geo.volume * drill mtx_k = shell10x.lock_drilling_rotations(mtx_k, geo.ebs, coefs) # DOFs in mtx_k are DOF-by-DOF. Transform is u and phi node-by-node. blocks = nm.arange(24).reshape(2, 3, 4) blocks = blocks.transpose((0, 2, 1)).reshape((-1, 3)) shell10x.transform_asm_matrices(mtx_k[:, None, ...], geo.mtx_t, blocks) fmode = diff_var is not None return (mtx_k, el_u, fmode)
def transform_asm_matrices(out, mtx_t, blocks): """ Transform matrix assembling contributions to global coordinate system, one node at a time. Parameters ---------- out : array The array of matrices, transformed in-place. mtx_t : array The array of transposed transformation matrices :math:`T`, see :func:`create_transformation_matrix`. blocks : array The DOF blocks that are """ for ir in blocks: ir = ir[:, None] for ic in blocks: fn = out[:, 0, ir, ic] out[:, 0, ir, ic] = ddot(ddot(mtx_t, fn, 'AB'), mtx_t, 'ABT')
def get_mapping(self, qp_coors, weights): """ Get the mapping for given quadrature points and weights. """ domain = self.region.domain mesh = domain.mesh iels = self.region.get_cells() conn = nm.take(domain.get_conn(), iels.astype(nm.int32), axis=0) e_coors = mesh.coors[conn] mtx_t = shell10x.create_transformation_matrix(e_coors) e_centres = mesh.cmesh.get_centroids(2)[iels] coors_loc = ddot((e_coors - e_centres[:, None, :]), mtx_t) ebs = shell10x.create_local_bases(coors_loc) rops = shell10x.create_rotation_ops(ebs) ps = self.field.poly_space qp_coors0 = nm.array([[0.5, 0.5, 0.5]]) # Should be thickness, but not used anywhere. qp_weights0 = nm.array([0.0]) dxidx0, det0 = shell10x.get_mapping_data(ebs, rops, ps, coors_loc, qp_coors0, qp_weights0, special_dx3=True) aux = shell10x.get_mapping_data(ebs, rops, ps, coors_loc, qp_coors, weights) coors_loc_3d, bfu, bfgm, dxidx, det = aux self.coors_loc = coors_loc self.e_centres = e_centres self.mtx_t = mtx_t self.ebs = ebs self.rops = rops self.dxidx0 = dxidx0 self.det0 = det0 self.coors_loc_3d = coors_loc_3d self.bfu = bfu self.bfgm = bfgm self.dxidx = dxidx self.det = det self.volume = (det * weights).sum(1) return self