def __call__(self, mat, virtual, state, **kwargs): """ Doubled out-of-diagonal strain entries! """ rindx = virtual.get_component_indices() cindx = state.get_component_indices() kindx = lindx = get_range_indices(state.dim) fi = nm.array(get_full_indices(state.dim)) val = virtual.get_element_zeros() for ir, irs in rindx: for ik, iks in kindx: irk = fi[ir, ik] irks = slice(irk, irk + 1) erk = virtual.grad(ir, ik) for ic, ics in cindx: for il, ils in lindx: icl = fi[ic, il] icls = slice(icl, icl + 1) ecl = state.grad(ic, il) val += mat[..., irks, icls] * erk * ecl return val
def eval_force(region_name): strain = problem.evaluate( 'ev_cauchy_strain.i.%s(u)' % region_name, mode='qp', verbose=False, ) D = problem.evaluate( 'ev_integrate_mat.i.%s(solid.D, u)' % region_name, mode='qp', verbose=False, ) normal = nm.array([1, 0, 0], dtype=nm.float64) s2f = get_full_indices(len(normal)) stress = nm.einsum('cqij,cqjk->cqik', D, strain) # Full (matrix) form of stress. mstress = stress[..., s2f, 0] # Force in normal direction. force = nm.einsum('cqij,i,j->cq', mstress, normal, normal) def get_force(ts, coors, mode=None, **kwargs): if mode == 'qp': return {'force': force.reshape(coors.shape[0], 1, 1)} aux = Material('aux', function=Function('get_force', get_force)) middle_force = -problem.evaluate( 'ev_integrate_mat.i.%s(aux.force, u)' % region_name, aux=aux, verbose=False, ) output('%s section axial force:' % region_name, middle_force)
def test_transform_data4(self): import numpy as nm import sfepy.mechanics.tensors as tn ok = True if not hasattr(nm, 'einsum'): self.report('no numpy.einsum(), skipping!') return ok expected = nm.zeros((6, 6), dtype=nm.float64) expected[0, 0] = expected[1, 1] = 1.0 phi = nm.deg2rad(30.) dr, v1, v2, om1, om2 = get_ortho_d(phi, phi + nm.deg2rad(90.)) # Rotate coordinate system by phi. mtx = tn.make_axis_rotation_matrix([0., 0., 1.], phi) do = tn.transform_data(dr[None, ...], mtx=mtx[None, ...]) _ok = nm.allclose(do, expected, rtol=0.0, atol=1e-14) self.report('sym. 4th-th order tensor rotation: %s' % _ok) ok = ok and _ok dt, vt1, vt2, omt1, omt2 = get_ortho_d(0, nm.deg2rad(90.)) expected1 = nm.zeros((3, 3), dtype=nm.float64) expected1[0, 0] = 1.0 expected2 = nm.zeros((3, 3), dtype=nm.float64) expected2[1, 1] = 1.0 omr1 = nm.einsum('pq,ip,jq->ij', om1, mtx, mtx) omr2 = nm.einsum('pq,ip,jq->ij', om2, mtx, mtx) ii = tn.get_sym_indices(3) jj = tn.get_full_indices(3) o1 = om1.flat[ii] o2 = om2.flat[ii] omr12 = tn.transform_data(o1[None,...], mtx=mtx[None, ...])[0, jj] omr22 = tn.transform_data(o2[None,...], mtx=mtx[None, ...])[0, jj] _ok1 = nm.allclose(omr1, expected1, rtol=0.0, atol=1e-14) _ok2 = nm.allclose(omr12, expected1, rtol=0.0, atol=1e-14) self.report('einsum-transform_data compatibility 1: %s %s' % (_ok1, _ok2)) ok = ok and _ok1 and _ok2 _ok1 = nm.allclose(omr2, expected2, rtol=0.0, atol=1e-14) _ok2 = nm.allclose(omr22, expected2, rtol=0.0, atol=1e-14) self.report('einsum-transform_data compatibility 2: %s %s' % (_ok1, _ok2)) ok = ok and _ok1 and _ok2 return ok
def d_fun(out, traction, val, grad_mv, div_mv, sg): tdim, tdim2 = (None, None) if traction is None else traction.shape[2:] dim = val.shape[2] sym = (dim + 1) * dim // 2 n_el, n_qp = div_mv.shape[:2] val2 = sg.normal if tdim is None: trac = nm.tile(nm.eye(dim), (n_el, n_qp, 1, 1)) elif tdim == 1: trac = nm.tile(nm.eye(dim), (n_el, n_qp, 1, 1)) * traction elif tdim == dim and tdim2 == 1: # Traction vector trac = nm.tile(nm.eye(dim), (n_el, n_qp, 1, 1)) val2 = traction elif tdim == dim and tdim2 == dim: # Traction tensor - nonsymmetric trac = traction elif tdim == sym: # Traction tensor remap = nm.array(get_full_indices(dim)).flatten() trac = traction[..., remap, :].reshape((-1, n_qp, dim, dim)) sa_trac = trac * div_mv sa_trac -= nm.einsum('qpik,qpkj->qpij', trac, grad_mv, optimize='greedy') aux = dot_sequences(val, sa_trac, 'ATB') aux = dot_sequences(aux, val2, 'AB') status = sg.integrate(out, aux) return status