def get_green_strain_sym3d(mtx_c, c33): r""" Get the 3D Green strain tensor in symmetric storage. Parameters ---------- mtx_c ; array The in-plane right Cauchy-Green deformation tensor :math:`C_{ij}`, :math:`i, j = 1, 2`, shape `(n_el, n_qp, dim-1, dim-1)`. c33 : array The component :math:`C_{33}` computed from the incompressibility condition, shape `(n_el, n_qp)`. Returns ------- mtx_e : array The membrane Green strain :math:`E_{ij} = \frac{1}{2} (C_{ij}) - \delta_{ij}`, symmetric storage: items (11, 22, 33, 12, 13, 23), shape `(n_el, n_qp, sym, 1)`. """ n_el, n_qp, dm, _ = mtx_c.shape dim = dm + 1 sym = dim2sym(dim) mtx_e = nm.empty((n_el, n_qp, sym, 1), dtype=mtx_c.dtype) mtx_e[..., 0, 0] = 0.5 * (mtx_c[..., 0, 0] - 1.0) mtx_e[..., 1, 0] = 0.5 * (mtx_c[..., 1, 1] - 1.0) mtx_e[..., 2, 0] = 0.5 * (c33 - 1.0) mtx_e[..., 3, 0] = 0.5 * mtx_c[..., 0, 1] mtx_e[..., 4:, 0] = 0.0 return mtx_e
def create_omega(fdir): r""" Create the fibre direction tensor :math:`\omega_{ij} = d_i d_j`. """ n_el, n_qp, dim, _ = fdir.shape sym = dim2sym(dim) omega = nm.empty((n_el, n_qp, sym, 1), dtype=nm.float64) for ii, (ir, ic) in enumerate(iter_sym(dim)): omega[..., ii, 0] = fdir[..., ir, 0] * fdir[..., ic, 0] return omega
def get_eval_shape(self, mat, virtual, state, mode=None, term_mode=None, diff_var=None, **kwargs): from sfepy.mechanics.tensors import dim2sym n_el, n_qp, dim, n_en, n_c = self.get_data_shape(state) sym = dim2sym(dim) if mode != 'qp': n_qp = 1 return (n_el, n_qp, sym, 1), state.dtype
def get_eval_shape(self, a1, a2, h0, virtual, state, mode=None, term_mode=None, diff_var=None, **kwargs): n_el, n_qp, dim, n_en, n_c = self.get_data_shape(state) sym = dim2sym(dim) return (n_el, 1, sym, 1), state.dtype
def init_data_struct(self, state_shape, name='family_data'): from sfepy.mechanics.tensors import dim2sym n_el, n_qp, dim, n_en, n_c = state_shape sym = dim2sym(dim); sym shdict = dict(( (k, v) for k, v in six.iteritems(locals())\ if k in ['n_el', 'n_qp', 'dim', 'n_en', 'n_c', 'sym'])) data = Struct(name=name) setattr(data, 'names', self.data_names) for key in self.data_names: shape = [shdict[sh] if type(sh) is str else sh\ for sh in self.data_shapes[key]] setattr(data, key, nm.zeros(shape, dtype=nm.float64)) return data
def eval_function(out, a1, a2, h0, mtx_c, c33, mtx_b, mtx_t, geo, term_mode, fmode): if term_mode == 'strain': out_qp = membranes.get_green_strain_sym3d(mtx_c, c33) elif term_mode == 'stress': n_el, n_qp, dm, _ = mtx_c.shape dim = dm + 1 sym = dim2sym(dim) out_qp = nm.zeros((n_el, n_qp, sym, 1), dtype=mtx_c.dtype) stress = eval_membrane_mooney_rivlin(a1, a2, mtx_c, c33, 0) out_qp[..., 0:2, 0] = stress[..., 0:2, 0] out_qp[..., 3, 0] = stress[..., 2, 0] status = geo.integrate(out, out_qp, fmode) out[:, 0, :, 0] = transform_data(out.squeeze(), mtx=mtx_t) return status
def make_term_args(arg_shapes, arg_kinds, arg_types, ats_mode, domain, material_value=None, poly_space_base=None): from sfepy.base.base import basestr from sfepy.discrete import FieldVariable, Material, Variables, Materials from sfepy.discrete.fem import Field from sfepy.solvers.ts import TimeStepper from sfepy.mechanics.tensors import dim2sym omega = domain.regions['Omega'] dim = domain.shape.dim sym = dim2sym(dim) def _parse_scalar_shape(sh): if isinstance(sh, basestr): if sh == 'D': return dim elif sh == 'D2': return dim**2 elif sh == 'S': return sym elif sh == 'N': # General number ;) return 1 else: return int(sh) else: return sh def _parse_tuple_shape(sh): if isinstance(sh, basestr): return [_parse_scalar_shape(ii.strip()) for ii in sh.split(',')] else: return (int(sh),) args = {} str_args = [] materials = [] variables = [] for ii, arg_kind in enumerate(arg_kinds): if arg_kind != 'ts': if ats_mode is not None: extended_ats = arg_types[ii] + ('/%s' % ats_mode) else: extended_ats = arg_types[ii] try: sh = arg_shapes[arg_types[ii]] except KeyError: sh = arg_shapes[extended_ats] if arg_kind.endswith('variable'): shape = _parse_scalar_shape(sh[0] if isinstance(sh, tuple) else sh) field = Field.from_args('f%d' % ii, nm.float64, shape, omega, approx_order=1, poly_space_base=poly_space_base) if arg_kind == 'virtual_variable': if sh[1] is not None: istate = arg_types.index(sh[1]) else: # Only virtual variable in arguments. istate = -1 # -> Make fake variable. var = FieldVariable('u-1', 'unknown', field) var.set_constant(0.0) variables.append(var) var = FieldVariable('v', 'test', field, primary_var_name='u%d' % istate) elif arg_kind == 'state_variable': var = FieldVariable('u%d' % ii, 'unknown', field) var.set_constant(0.0) elif arg_kind == 'parameter_variable': var = FieldVariable('p%d' % ii, 'parameter', field, primary_var_name='(set-to-None)') var.set_constant(0.0) variables.append(var) str_args.append(var.name) args[var.name] = var elif arg_kind.endswith('material'): if sh is None: # Switched-off opt_material. continue prefix = '' if isinstance(sh, basestr): aux = sh.split(':') if len(aux) == 2: prefix, sh = aux if material_value is None: material_value = 1.0 shape = _parse_tuple_shape(sh) if (len(shape) > 1) or (shape[0] > 1): if ((len(shape) == 2) and (shape[0] == shape[1]) and (material_value != 0.0)): # Identity matrix. val = nm.eye(shape[0], dtype=nm.float64) else: # Array. val = nm.empty(shape, dtype=nm.float64) val.fill(material_value) values = {'%sc%d' % (prefix, ii) : val} elif (len(shape) == 1) and (shape[0] == 1): # Single scalar as a special value. values = {'.c%d' % ii : material_value} else: raise ValueError('wrong material shape! (%s)' % shape) mat = Material('m%d' % ii, values=values) materials.append(mat) str_args.append(mat.name + '.' + 'c%d' % ii) args[mat.name] = mat elif arg_kind == 'ts': ts = TimeStepper(0.0, 1.0, 1.0, 5) str_args.append('ts') args['ts'] = ts else: str_args.append('user%d' % ii) args[str_args[-1]] = None materials = Materials(materials) variables = Variables(variables) return args, str_args, materials, variables
def check_shapes(self, *args, **kwargs): """ Check term argument shapes at run-time. """ from sfepy.base.base import output from sfepy.mechanics.tensors import dim2sym dim = self.region.dim sym = dim2sym(dim) def _parse_scalar_shape(sh): if isinstance(sh, basestr): if sh == 'D': return dim elif sh == 'D2': return dim**2 elif sh == 'S': return sym elif sh == 'N': # General number. return nm.inf elif sh == 'str': return 'str' else: return int(sh) else: return sh def _parse_tuple_shape(sh): if isinstance(sh, basestr): return tuple( (_parse_scalar_shape(ii.strip()) for ii in sh.split(','))) else: return (int(sh), ) arg_kinds = get_arg_kinds(self.ats) arg_shapes_list = self.arg_shapes if not isinstance(arg_shapes_list, list): arg_shapes_list = [arg_shapes_list] # Loop allowed shapes until a match is found, else error. allowed_shapes = [] prev_shapes = {} actual_shapes = {} for _arg_shapes in arg_shapes_list: # Unset shapes are taken from the previous iteration. arg_shapes = copy(prev_shapes) arg_shapes.update(_arg_shapes) prev_shapes = arg_shapes allowed_shapes.append(arg_shapes) n_ok = 0 for ii, arg_kind in enumerate(arg_kinds): if arg_kind in ('user', 'ts'): n_ok += 1 continue arg = args[ii] key = '%s:%s' % (self.ats[ii], self.arg_names[ii]) if self.mode is not None: extended_ats = self.ats[ii] + ('/%s' % self.mode) else: extended_ats = self.ats[ii] try: sh = arg_shapes[self.ats[ii]] except KeyError: sh = arg_shapes[extended_ats] if arg_kind.endswith('variable'): n_el, n_qp, _dim, n_en, n_c = self.get_data_shape(arg) actual_shapes[key] = (n_c, ) shape = _parse_scalar_shape( sh[0] if isinstance(sh, tuple) else sh) if nm.isinf(shape): n_ok += 1 else: n_ok += shape == n_c elif arg_kind.endswith('material'): if arg is None: # Switched-off opt_material. n_ok += sh is None continue if sh is None: continue prefix = '' if isinstance(sh, basestr): aux = tuple(ii.strip() for ii in sh.split(':')) if len(aux) == 2: prefix, sh = aux if sh == 'str': n_ok += isinstance(arg, basestr) continue shape = _parse_tuple_shape(sh) ls = len(shape) aarg = nm.array(arg, ndmin=1) actual_shapes[key] = aarg.shape # Substiture general dimension 'N' with actual value. iinfs = nm.where(nm.isinf(shape))[0] if len(iinfs): shape = list(shape) for iinf in iinfs: shape[iinf] = aarg.shape[-ls + iinf] shape = tuple(shape) if (ls > 1) or (shape[0] > 1): # Array. n_ok += shape == aarg.shape[-ls:] actual_shapes[key] = aarg.shape[-ls:] elif (ls == 1) and (shape[0] == 1): # Scalar constant or callable as term argument from numbers import Number n_ok += isinstance(arg, Number) or callable(arg) else: n_ok += 1 if n_ok == len(arg_kinds): break else: term_str = self.get_str() output('allowed argument shapes for term "%s":' % term_str) output(allowed_shapes) output('actual argument shapes:') output(actual_shapes) raise ValueError( 'wrong arguments shapes for "%s" term! (see above)' % term_str)
def describe_deformation(el_disps, bfg): """ Describe deformation of a thin incompressible 2D membrane in 3D space, composed of flat finite element faces. The coordinate system of each element (face), i.e. the membrane mid-surface, should coincide with the `x`, `y` axes of the `x-y` plane. Parameters ---------- el_disps : array The displacements of element nodes, shape `(n_el, n_ep, dim)`. bfg : array The in-plane base function gradients, shape `(n_el, n_qp, dim-1, n_ep)`. Returns ------- mtx_c ; array The in-plane right Cauchy-Green deformation tensor :math:`C_{ij}`, :math:`i, j = 1, 2`. c33 : array The component :math:`C_{33}` computed from the incompressibility condition. mtx_b : array The discrete Green strain variation operator. """ sh = bfg.shape n_ep = sh[3] dim = el_disps.shape[2] sym2 = dim2sym(dim-1) # Repeat el_disps by number of quadrature points. el_disps_qp = insert_strided_axis(el_disps, 1, bfg.shape[1]) # Transformed (in-plane) displacement gradient with # shape (n_el, n_qp, 2 (-> a), 3 (-> i)), du_i/dX_a. du = dot_sequences(bfg, el_disps_qp) # Deformation gradient F w.r.t. in plane coordinates. # F_{ia} = dx_i / dX_a, # a \in {1, 2} (rows), i \in {1, 2, 3} (columns). mtx_f = du + nm.eye(dim - 1, dim, dtype=du.dtype) # Right Cauchy-Green deformation tensor C. # C_{ab} = F_{ka} F_{kb}, a, b \in {1, 2}. mtx_c = dot_sequences(mtx_f, mtx_f, 'ABT') # C_33 from incompressibility. c33 = 1.0 / (mtx_c[..., 0, 0] * mtx_c[..., 1, 1] - mtx_c[..., 0, 1]**2) # Discrete Green strain variation operator. mtx_b = nm.empty((sh[0], sh[1], sym2, dim * n_ep), dtype=nm.float64) mtx_b[..., 0, 0*n_ep:1*n_ep] = bfg[..., 0, :] * mtx_f[..., 0, 0:1] mtx_b[..., 0, 1*n_ep:2*n_ep] = bfg[..., 0, :] * mtx_f[..., 0, 1:2] mtx_b[..., 0, 2*n_ep:3*n_ep] = bfg[..., 0, :] * mtx_f[..., 0, 2:3] mtx_b[..., 1, 0*n_ep:1*n_ep] = bfg[..., 1, :] * mtx_f[..., 1, 0:1] mtx_b[..., 1, 1*n_ep:2*n_ep] = bfg[..., 1, :] * mtx_f[..., 1, 1:2] mtx_b[..., 1, 2*n_ep:3*n_ep] = bfg[..., 1, :] * mtx_f[..., 1, 2:3] mtx_b[..., 2, 0*n_ep:1*n_ep] = bfg[..., 1, :] * mtx_f[..., 0, 0:1] \ + bfg[..., 0, :] * mtx_f[..., 1, 0:1] mtx_b[..., 2, 1*n_ep:2*n_ep] = bfg[..., 0, :] * mtx_f[..., 1, 1:2] \ + bfg[..., 1, :] * mtx_f[..., 0, 1:2] mtx_b[..., 2, 2*n_ep:3*n_ep] = bfg[..., 0, :] * mtx_f[..., 1, 2:3] \ + bfg[..., 1, :] * mtx_f[..., 0, 2:3] return mtx_c, c33, mtx_b
def define(filename_mesh=None): eta = 3.6e-3 if filename_mesh is None: filename_mesh = osp.join(data_dir, 'meso_perf_2ch_puc.vtk') # filename_mesh = osp.join(data_dir, 'perf_mic_2chbx.vtk') mesh = Mesh.from_file(filename_mesh) poroela_micro_file = osp.join(data_dir, 'perf_BD2B_mic.py') dim = 3 sym = (dim + 1) * dim // 2 sym_eye = 'nm.array([1,1,0])' if dim == 2 else 'nm.array([1,1,1,0,0,0])' bbox = mesh.get_bounding_box() regions = define_box_regions(mesh.dim, bbox[0], bbox[1], eps=1e-3) regions.update({ 'Z': 'all', 'Gamma_Z': ('vertices of surface', 'facet'), # matrix 'Zm': 'cells of group 3', 'Zm_left': ('r.Zm *v r.Left', 'vertex'), 'Zm_right': ('r.Zm *v r.Right', 'vertex'), 'Zm_bottom': ('r.Zm *v r.Bottom', 'vertex'), 'Zm_top': ('r.Zm *v r.Top', 'vertex'), "Gamma_Zm": ('(r.Zm *v r.Zc1) +v (r.Zm *v r.Zc2)', 'facet', 'Zm'), 'Gamma_Zm1': ('r.Zm *v r.Zc1', 'facet', 'Zm'), 'Gamma_Zm2': ('r.Zm *v r.Zc2', 'facet', 'Zm'), # first canal 'Zc1': 'cells of group 1', 'Zc01': ('r.Zc1 -v r.Gamma_Zc1', 'vertex'), 'Zc1_left': ('r.Zc01 *v r.Left', 'vertex'), 'Zc1_right': ('r.Zc01 *v r.Right', 'vertex'), # 'Zc1_bottom': ('r.Zc01 *v r.Bottom', 'vertex'), # 'Zc1_top': ('r.Zc01 *v r.Top', 'vertex'), 'Gamma_Zc1': ('r.Zm *v r.Zc1', 'facet', 'Zc1'), 'Center_c1': ('vertex 973', 'vertex'), # canal center # 'Center_c1': ('vertex 1200', 'vertex'), # canal center # second canal 'Zc2': 'cells of group 2', 'Zc02': ('r.Zc2 -v r.Gamma_Zc2', 'vertex'), 'Zc2_left': ('r.Zc02 *v r.Left', 'vertex'), 'Zc2_right': ('r.Zc02 *v r.Right', 'vertex'), # 'Zc2_bottom': ('r.Zc02 *v r.Bottom', 'vertex'), # 'Zc2_top': ('r.Zc02 *v r.Top', 'vertex'), 'Gamma_Zc2': ('r.Zm *v r.Zc2', 'facet', 'Zc2'), 'Center_c2': ('vertex 487', 'vertex'), # canal center # 'Center_c2': ('vertex 1254', 'vertex'), # canal center }) if dim == 3: regions.update({ 'Zm_far': ('r.Zm *v r.Far', 'vertex'), 'Zm_near': ('r.Zm *v r.Near', 'vertex'), # 'Zc1_far': ('r.Zc01 *v r.Far', 'vertex'), # 'Zc1_near': ('r.Zc01 *v r.Near', 'vertex'), # 'Zc2_far': ('r.Zc02 *v r.Far', 'vertex'), # 'Zc2_near': ('r.Zc02 *v r.Near', 'vertex'), }) fields = { 'one': ('real', 'scalar', 'Z', 1), 'displacement': ('real', 'vector', 'Zm', 1), 'pressure_m': ('real', 'scalar', 'Zm', 1), 'pressure_c1': ('real', 'scalar', 'Zc1', 1), 'displacement_c1': ('real', 'vector', 'Zc1', 1), 'velocity1': ('real', 'vector', 'Zc1', 2), 'pressure_c2': ('real', 'scalar', 'Zc2', 1), 'displacement_c2': ('real', 'vector', 'Zc2', 1), 'velocity2': ('real', 'vector', 'Zc2', 2), } variables = { # displacement 'u': ('unknown field', 'displacement', 0), 'v': ('test field', 'displacement', 'u'), 'Pi_u': ('parameter field', 'displacement', 'u'), 'U1': ('parameter field', 'displacement', '(set-to-None)'), 'U2': ('parameter field', 'displacement', '(set-to-None)'), 'uc1': ('unknown field', 'displacement_c1', 6), 'vc1': ('test field', 'displacement_c1', 'uc1'), 'uc2': ('unknown field', 'displacement_c2', 7), 'vc2': ('test field', 'displacement_c2', 'uc2'), # velocity in canal 1 'w1': ('unknown field', 'velocity1', 1), 'z1': ('test field', 'velocity1', 'w1'), 'Pi_w1': ('parameter field', 'velocity1', 'w1'), 'par1_w1': ('parameter field', 'velocity1', '(set-to-None)'), 'par2_w1': ('parameter field', 'velocity1', '(set-to-None)'), # velocity in canal 2 'w2': ('unknown field', 'velocity2', 2), 'z2': ('test field', 'velocity2', 'w2'), 'Pi_w2': ('parameter field', 'velocity2', 'w2'), 'par1_w2': ('parameter field', 'velocity2', '(set-to-None)'), 'par2_w2': ('parameter field', 'velocity2', '(set-to-None)'), # pressure 'pm': ('unknown field', 'pressure_m', 3), 'qm': ('test field', 'pressure_m', 'pm'), 'Pm1': ('parameter field', 'pressure_m', '(set-to-None)'), 'Pm2': ('parameter field', 'pressure_m', '(set-to-None)'), 'Pi_pm': ('parameter field', 'pressure_m', 'pm'), 'pc1': ('unknown field', 'pressure_c1', 4), 'qc1': ('test field', 'pressure_c1', 'pc1'), 'par1_pc1': ('parameter field', 'pressure_c1', '(set-to-None)'), 'par2_pc1': ('parameter field', 'pressure_c1', '(set-to-None)'), 'pc2': ('unknown field', 'pressure_c2', 5), 'qc2': ('test field', 'pressure_c2', 'pc2'), 'par1_pc2': ('parameter field', 'pressure_c2', '(set-to-None)'), 'par2_pc2': ('parameter field', 'pressure_c2', '(set-to-None)'), # one 'one': ('parameter field', 'one', '(set-to-None)'), } functions = { 'match_x_plane': (per.match_x_plane,), 'match_y_plane': (per.match_y_plane,), 'match_z_plane': (per.match_z_plane,), 'get_homog': (lambda ts, coors, mode=None, problem=None, **kwargs:\ get_homog(coors, mode, problem, poroela_micro_file, **kwargs),), } materials = { 'hmatrix': 'get_homog', 'fluid': ({ 'eta_c': eta * nm.eye(dim2sym(dim)), }, ), 'mat': ({ 'k1': nm.array([[1, 0, 0]]).T, 'k2': nm.array([[0, 1, 0]]).T, 'k3': nm.array([[0, 0, 1]]).T, }, ), } ebcs = { 'fixed_u': ('Corners', { 'um.all': 0.0 }), 'fixed_pm': ('Corners', { 'p.0': 0.0 }), 'fixed_w1': ('Center_c1', { 'w1.all': 0.0 }), 'fixed_w2': ('Center_c2', { 'w2.all': 0.0 }), } epbcs, periodic = get_periodic_bc([('u', 'Zm'), ('pm', 'Zm'), ('pc1', 'Zc1'), ('w1', 'Zc1'), ('pc2', 'Zc2'), ('w2', 'Zc2')]) all_periodic1 = periodic['per_w1'] + periodic['per_pc1'] all_periodic2 = periodic['per_w2'] + periodic['per_pc2'] integrals = { 'i': 4, } options = { 'coefs': 'coefs', 'coefs_filename': 'coefs_meso', 'requirements': 'requirements', 'volume': { 'variables': ['u', 'pc1', 'pc2'], 'expression': 'd_volume.i.Zm(u) + d_volume.i.Zc1(pc1)+d_volume.i.Zc2(pc2)', }, 'output_dir': data_dir + '/results/meso', 'file_per_var': True, 'save_format': 'vtk', # Global setting. 'dump_format': 'h5', # Global setting. 'absolute_mesh_path': True, 'multiprocessing': False, 'ls': 'ls', 'nls': 'ns_m15', 'output_prefix': 'Meso:', } solvers = { 'ls': ('ls.mumps', {}), 'ls_s1': ('ls.schur_mumps', { 'schur_variables': ['pc1'], 'fallback': 'ls' }), 'ls_s2': ('ls.schur_mumps', { 'schur_variables': ['pc2'], 'fallback': 'ls' }), 'ns': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-14, 'eps_r': 1e-3, 'problem': 'nonlinear' }), 'ns_em15': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-15, 'eps_r': 1e-3, 'problem': 'nonlinear' }), 'ns_em12': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-12, 'eps_r': 1e-3, 'problem': 'nonlinear' }), 'ns_em9': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-9, 'eps_r': 1e-3, 'problem': 'nonlinear' }), 'ns_em6': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-4, 'eps_r': 1e-3, 'problem': 'nonlinear' }), } #Definition of homogenized coefficients, see (33)-(35) coefs = { 'A': { 'requires': ['pis_u', 'corrs_omega_ij'], 'expression': 'dw_lin_elastic.i.Zm(hmatrix.A, U1, U2)', 'set_variables': [('U1', ('corrs_omega_ij', 'pis_u'), 'u'), ('U2', ('corrs_omega_ij', 'pis_u'), 'u')], 'class': cb.CoefSymSym, }, 'B_aux1': { 'status': 'auxiliary', 'requires': ['corrs_omega_ij'], 'expression': '- dw_surface_ltr.i.Gamma_Zm(U1)', # !!! - 'set_variables': [('U1', 'corrs_omega_ij', 'u')], 'class': cb.CoefSym, }, 'B_aux2': { 'status': 'auxiliary', 'requires': ['corrs_omega_ij', 'pis_u', 'corr_one'], 'expression': 'dw_biot.i.Zm(hmatrix.B, U1, one)', 'set_variables': [('U1', ('corrs_omega_ij', 'pis_u'), 'u'), ('one', 'corr_one', 'one')], 'class': cb.CoefSym, }, 'B': { 'requires': ['c.B_aux1', 'c.B_aux2', 'c.vol_c'], 'expression': 'c.B_aux1 + c.B_aux2 + c.vol_c* %s' % sym_eye, 'class': cb.CoefEval, }, 'H11': { 'requires': ['corrs_phi_k_1'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', 'corrs_phi_k_1', 'pm'), ('Pm2', 'corrs_phi_k_1', 'pm')], 'class': cb.CoefDimDim, }, 'H12': { 'requires': ['corrs_phi_k_1', 'corrs_phi_k_2'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', 'corrs_phi_k_1', 'pm'), ('Pm2', 'corrs_phi_k_2', 'pm')], 'class': cb.CoefDimDim, }, 'H21': { 'requires': ['corrs_phi_k_1', 'corrs_phi_k_2'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', 'corrs_phi_k_2', 'pm'), ('Pm2', 'corrs_phi_k_1', 'pm')], 'class': cb.CoefDimDim, }, 'H22': { 'requires': ['corrs_phi_k_2'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', 'corrs_phi_k_2', 'pm'), ('Pm2', 'corrs_phi_k_2', 'pm')], 'class': cb.CoefDimDim, }, 'K': { 'requires': ['corrs_pi_k', 'pis_pm'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', ('corrs_pi_k', 'pis_pm'), 'pm'), ('Pm2', ('corrs_pi_k', 'pis_pm'), 'pm')], 'class': cb.CoefDimDim, }, 'Q1': { 'requires': ['corrs_phi_k_1', 'pis_pm'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', 'pis_pm', 'pm'), ('Pm2', 'corrs_phi_k_1', 'pm')], 'class': cb.CoefDimDim, }, 'P1': { 'requires': ['c.Q1', 'c.vol'], 'expression': 'c.vol["fraction_Zc1"] * nm.eye(%d) - c.Q1' % dim, 'class': cb.CoefEval, }, 'P1T': { 'requires': ['c.P1'], 'expression': 'c.P1.T', 'class': cb.CoefEval, }, 'Q2': { 'requires': ['corrs_phi_k_2', 'pis_pm'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', 'pis_pm', 'pm'), ('Pm2', 'corrs_phi_k_2', 'pm')], 'class': cb.CoefDimDim, }, 'P2': { 'requires': ['c.Q2', 'c.vol'], 'expression': 'c.vol["fraction_Zc2"] * nm.eye(%d) - c.Q2' % dim, 'class': cb.CoefEval, }, 'P2T': { 'requires': ['c.P2'], 'expression': 'c.P2.T', 'class': cb.CoefEval, }, 'M_aux1': { 'status': 'auxiliary', 'requires': [], 'expression': 'ev_volume_integrate_mat.i.Zm(hmatrix.M, one)', 'set_variables': [], 'class': cb.CoefOne, }, 'M_aux2': { 'status': 'auxiliary', 'requires': ['corrs_omega_p', 'corr_one'], 'expression': 'dw_biot.i.Zm(hmatrix.B, U1, one)', 'set_variables': [('U1', 'corrs_omega_p', 'u'), ('one', 'corr_one', 'one')], 'class': cb.CoefOne, }, 'M_aux3': { 'status': 'auxiliary', 'requires': ['corrs_omega_p'], 'expression': ' dw_surface_ltr.i.Gamma_Zm(U1)', 'set_variables': [('U1', 'corrs_omega_p', 'u')], 'class': cb.CoefOne, }, 'M': { 'requires': ['c.M_aux1', 'c.M_aux2', 'c.M_aux3'], 'expression': 'c.M_aux1 + c.M_aux2 -c.M_aux3 ', 'class': cb.CoefEval, }, 'S1': { 'requires': ['corrs_psi_ij_1', 'pis_w1'], 'expression': 'dw_lin_elastic.i.Zc1(fluid.eta_c, par1_w1, par2_w1)', 'set_variables': [('par1_w1', ('corrs_psi_ij_1', 'pis_w1'), 'w1'), ('par2_w1', ('corrs_psi_ij_1', 'pis_w1'), 'w1')], 'class': cb.CoefSymSym, }, 'S2': { 'requires': ['corrs_psi_ij_2', 'pis_w2'], 'expression': 'dw_lin_elastic.i.Zc2(fluid.eta_c, par1_w2, par2_w2)', 'set_variables': [('par1_w2', ('corrs_psi_ij_2', 'pis_w2'), 'w2'), ('par2_w2', ('corrs_psi_ij_2', 'pis_w2'), 'w2')], 'class': cb.CoefSymSym, }, 'vol': { 'regions': ['Zm', 'Zc1', 'Zc2'], 'expression': 'd_volume.i.%s(one)', 'class': cb.VolumeFractions, }, 'surf_vol': { 'regions': ['Zm', 'Zc1', 'Zc2'], 'expression': 'd_surface.i.%s(one)', 'class': cb.VolumeFractions, }, 'surf_c': { 'requires': ['c.surf_vol'], 'expression': 'c.surf_vol["fraction_Zc1"]+c.surf_vol["fraction_Zc2"]', 'class': cb.CoefEval, }, 'vol_c': { 'requires': ['c.vol'], 'expression': 'c.vol["fraction_Zc1"]+c.vol["fraction_Zc2"]', 'class': cb.CoefEval, }, 'filenames': {}, } #Definition of mesoscopic corrector problems requirements = { 'corr_one': { 'variable': 'one', 'expression': "nm.ones((problem.fields['one'].n_vertex_dof, 1), dtype=nm.float64)", 'class': cb.CorrEval, }, 'pis_u': { 'variables': ['u'], 'class': cb.ShapeDimDim, 'save_name': 'corrs_pis_u', 'dump_variables': ['u'], }, 'pis_pm': { 'variables': ['pm'], 'class': cb.ShapeDim, }, 'pis_w1': { 'variables': ['w1'], 'class': cb.ShapeDimDim, }, 'pis_w2': { 'variables': ['w2'], 'class': cb.ShapeDimDim, }, # Corrector problem, see (31)_1 'corrs_omega_ij': { 'requires': ['pis_u'], 'ebcs': ['fixed_u'], 'epbcs': periodic['per_u'], 'is_linear': True, 'equations': { 'balance_of_forces': """dw_lin_elastic.i.Zm(hmatrix.A, v, u) = - dw_lin_elastic.i.Zm(hmatrix.A, v, Pi_u)""" }, 'set_variables': [('Pi_u', 'pis_u', 'u')], 'class': cb.CorrDimDim, 'save_name': 'corrs_omega_ij', 'dump_variables': ['u'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em6' }, 'is_linear': True, }, # Corrector problem, see (31)_2 'corrs_omega_p': { 'requires': ['corr_one'], 'ebcs': ['fixed_u'], 'epbcs': periodic['per_u'], 'equations': { 'balance_of_forces': """dw_lin_elastic.i.Zm(hmatrix.A, v, u) = dw_biot.i.Zm(hmatrix.B, v, one) - dw_surface_ltr.i.Gamma_Zm(v)""", }, 'set_variables': [('one', 'corr_one', 'one')], 'class': cb.CorrOne, 'save_name': 'corrs_omega_p', 'dump_variables': ['u'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em9' }, }, # Corrector problem, see (31)_3 'corrs_pi_k': { 'requires': ['pis_pm'], 'ebcs': [], # ['fixed_pm'], 'epbcs': periodic['per_pm'], 'is_linear': True, 'equations': { 'eq': """dw_diffusion.i.Zm(hmatrix.K, qm, pm) = - dw_diffusion.i.Zm(hmatrix.K, qm, Pi_pm)""", }, 'set_variables': [('Pi_pm', 'pis_pm', 'pm')], 'class': cb.CorrDim, 'save_name': 'corrs_pi_k', 'dump_variables': ['pm'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em12' }, }, # Corrector problem, see (31)_4 'corrs_phi_k_1': { 'requires': [], 'ebcs': [], 'epbcs': periodic['per_pm'], 'equations': { 'eq': """dw_diffusion.i.Zm(hmatrix.K, qm, pm) = - dw_surface_ndot.i.Gamma_Zm1(mat.k%d, qm)""", }, 'class': cb.CorrEqPar, 'eq_pars': [(ii + 1) for ii in range(dim)], 'save_name': 'corrs_phi_k_1', 'dump_variables': ['pm'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em9' }, }, 'corrs_phi_k_2': { 'requires': [], 'ebcs': [], 'epbcs': periodic['per_pm'], 'equations': { 'eq': """dw_diffusion.i.Zm(hmatrix.K, qm, pm) = - dw_surface_ndot.i.Gamma_Zm2(mat.k%d, qm)""", }, 'class': cb.CorrEqPar, 'eq_pars': [(ii + 1) for ii in range(dim)], 'save_name': 'corrs_phi_k_2', 'dump_variables': ['pm'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em9' }, }, # Corrector problem, see (32) 'corrs_psi_ij_1': { 'requires': ['pis_w1'], 'ebcs': ['fixed_w1'], 'epbcs': periodic['per_w1'] + periodic['per_pc1'], 'equations': { 'eq1': """2*dw_lin_elastic.i.Zc1(fluid.eta_c, z1, w1) - dw_stokes.i.Zc1(z1, pc1) = - 2*dw_lin_elastic.i.Zc1(fluid.eta_c, z1, Pi_w1)""", 'eq2': """dw_stokes.i.Zc1(w1, qc1) = - dw_stokes.i.Zc1(Pi_w1, qc1)""" }, 'set_variables': [('Pi_w1', 'pis_w1', 'w1')], 'class': cb.CorrDimDim, 'save_name': 'corrs_psi_ij_1', 'dump_variables': ['w1', 'pc1'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em15' }, # 'solvers': {'ls': 'ls_s1', 'nls': 'ns_em15'}, 'is_linear': True, }, 'corrs_psi_ij_2': { 'requires': ['pis_w2'], 'ebcs': ['fixed_w2'], 'epbcs': periodic['per_w2'] + periodic['per_pc2'], 'equations': { 'eq1': """2*dw_lin_elastic.i.Zc2(fluid.eta_c, z2, w2) - dw_stokes.i.Zc2(z2, pc2) = - 2*dw_lin_elastic.i.Zc2(fluid.eta_c, z2, Pi_w2)""", 'eq2': """dw_stokes.i.Zc2(w2, qc2) = - dw_stokes.i.Zc2(Pi_w2, qc2)""" }, 'set_variables': [('Pi_w2', 'pis_w2', 'w2')], 'class': cb.CorrDimDim, 'save_name': 'corrs_psi_ij_1', 'dump_variables': ['w2', 'pc2'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em15' }, # 'solvers': {'ls': 'ls_s2', 'nls': 'ns_em15'}, 'is_linear': True, }, } return locals()
def eval_membrane_mooney_rivlin(a1, a2, mtx_c, c33, mode): """ Evaluate stress or tangent stiffness of the Mooney-Rivlin membrane. [1] Baoguo Wu, Xingwen Du and Huifeng Tan: A three-dimensional FE nonlinear analysis of membranes, Computers & Structures 59 (1996), no. 4, 601--605. """ a12 = 2.0 * a1[..., 0, 0] a22 = 2.0 * a2[..., 0, 0] sh = mtx_c.shape sym = dim2sym(sh[2]) c11 = mtx_c[..., 0, 0] c12 = mtx_c[..., 0, 1] c22 = mtx_c[..., 1, 1] pressure = c33 * (a12 + a22 * (c11 + c22)) if mode == 0: out = nm.empty((sh[0], sh[1], sym, 1)) # S_11, S_22, S_12. out[..., 0, 0] = -pressure * c22 * c33 + a12 + a22 * (c22 + c33) out[..., 1, 0] = -pressure * c11 * c33 + a12 + a22 * (c11 + c33) out[..., 2, 0] = +pressure * c12 * c33 - a22 * c12 else: out = nm.empty((sh[0], sh[1], sym, sym)) dp11 = a22 * c33 - pressure * c22 * c33 dp22 = a22 * c33 - pressure * c11 * c33 dp12 = 2.0 * pressure * c12 * c33 # D_11, D_22, D_33 out[..., 0, 0] = - 2.0 * ((a22 - pressure * c22) * c22 * c33**2 + c33 * c22 * dp11) out[..., 1, 1] = - 2.0 * ((a22 - pressure * c11) * c11 * c33**2 + c33 * c11 * dp22) out[..., 2, 2] = - a22 + pressure * (c33 + 2.0 * c12**2 * c33**2) \ + c12 * c33 * dp12 # D_21, D_31, D_32 out[..., 1, 0] = 2.0 * ((a22 - pressure * c33 - (a22 - pressure * c11) * c22 * c33**2) - c33 * c11 * dp11) out[..., 2, 0] = 2.0 * (-pressure * c12 * c22 * c33**2 + c12 * c33 * dp11) out[..., 2, 1] = 2.0 * (-pressure * c12 * c11 * c33**2 + c12 * c33 * dp22) out[..., 0, 1] = out[..., 1, 0] out[..., 0, 2] = out[..., 2, 0] out[..., 1, 2] = out[..., 2, 1] # D_12, D_13, D_23 ## out[..., 0, 1] = 2.0 * ((a22 - pressure * c33 ## - (a22 - pressure * c22) * c11 * c33**2) ## - c33 * c22 * dp22) ## out[..., 0, 2] = 2.0 * (a22 - pressure * c22) * c12 * c33**2 \ ## - c33 * c22 * dp12 ## out[..., 1, 2] = 2.0 * (a22 - pressure * c11) * c12 * c33**2 \ ## - c33 * c11 * dp12 return out
def make_term_args(arg_shapes, arg_kinds, arg_types, ats_mode, domain): from sfepy.base.base import basestr from sfepy.fem import Field, FieldVariable, Material, Variables, Materials from sfepy.mechanics.tensors import dim2sym omega = domain.regions['Omega'] dim = domain.shape.dim sym = dim2sym(dim) def _parse_scalar_shape(sh): if isinstance(sh, basestr): if sh == 'D': return dim elif sh == 'S': return sym elif sh == 'N': # General number ;) return 5 else: return int(sh) else: return sh def _parse_tuple_shape(sh): if isinstance(sh, basestr): return [_parse_scalar_shape(ii.strip()) for ii in sh.split(',')] else: return (int(sh), ) args = {} str_args = [] materials = [] variables = [] for ii, arg_kind in enumerate(arg_kinds): if ats_mode is not None: extended_ats = arg_types[ii] + ('/%s' % ats_mode) else: extended_ats = arg_types[ii] try: sh = arg_shapes[arg_types[ii]] except KeyError: sh = arg_shapes[extended_ats] if arg_kind.endswith('variable'): shape = _parse_scalar_shape(sh[0] if isinstance(sh, tuple) else sh) field = Field.from_args('f%d' % ii, nm.float64, shape, omega, approx_order=1) if arg_kind == 'virtual_variable': if sh[1] is not None: istate = arg_types.index(sh[1]) else: # Only virtual variable in arguments. istate = -1 # -> Make fake variable. var = FieldVariable('u-1', 'unknown', field, shape) var.set_constant(0.0) variables.append(var) var = FieldVariable('v', 'test', field, shape, primary_var_name='u%d' % istate) elif arg_kind == 'state_variable': var = FieldVariable('u%d' % ii, 'unknown', field, shape) var.set_constant(0.0) elif arg_kind == 'parameter_variable': var = FieldVariable('p%d' % ii, 'parameter', field, shape, primary_var_name='(set-to-None)') var.set_constant(0.0) variables.append(var) str_args.append(var.name) args[var.name] = var elif arg_kind.endswith('material'): if sh is None: # Switched-off opt_material. continue prefix = '' if isinstance(sh, basestr): aux = sh.split(':') if len(aux) == 2: prefix, sh = aux shape = _parse_tuple_shape(sh) if (len(shape) > 1) or (shape[0] > 1): # Array. values = { '%sc%d' % (prefix, ii): nm.ones(shape, dtype=nm.float64) } elif (len(shape) == 1) and (shape[0] == 1): # Single scalar as a special value. values = {'.c%d' % ii: 1.0} else: raise ValueError('wrong material shape! (%s)' % shape) mat = Material('m%d' % ii, values=values) materials.append(mat) str_args.append(mat.name + '.' + 'c%d' % ii) args[mat.name] = mat else: str_args.append('user%d' % ii) args[str_args[-1]] = None materials = Materials(materials) variables = Variables(variables) return args, str_args, materials, variables
def check_shapes(self, *args, **kwargs): """ Check term argument shapes at run-time. """ from sfepy.base.base import output from sfepy.mechanics.tensors import dim2sym dim = self.region.dim sym = dim2sym(dim) def _parse_scalar_shape(sh): if isinstance(sh, basestr): if sh == 'D': return dim elif sh == 'S': return sym elif sh == 'N': # General number. return nm.inf else: return int(sh) else: return sh def _parse_tuple_shape(sh): if isinstance(sh, basestr): return tuple((_parse_scalar_shape(ii.strip()) for ii in sh.split(','))) else: return (int(sh),) arg_kinds = get_arg_kinds(self.ats) arg_shapes_list = self.arg_shapes if not isinstance(arg_shapes_list, list): arg_shapes_list = [arg_shapes_list] # Loop allowed shapes until a match is found, else error. allowed_shapes = [] prev_shapes = {} for _arg_shapes in arg_shapes_list: # Unset shapes are taken from the previous iteration. arg_shapes = copy(prev_shapes) arg_shapes.update(_arg_shapes) prev_shapes = arg_shapes allowed_shapes.append(arg_shapes) n_ok = 0 for ii, arg_kind in enumerate(arg_kinds): if arg_kind in ('user', 'ts'): n_ok += 1 continue arg = args[ii] if self.mode is not None: extended_ats = self.ats[ii] + ('/%s' % self.mode) else: extended_ats = self.ats[ii] try: sh = arg_shapes[self.ats[ii]] except KeyError: sh = arg_shapes[extended_ats] if arg_kind.endswith('variable'): n_el, n_qp, _dim, n_en, n_c = self.get_data_shape(arg) shape = _parse_scalar_shape(sh[0] if isinstance(sh, tuple) else sh) if nm.isinf(shape): n_ok += 1 else: n_ok += shape == n_c elif arg_kind.endswith('material'): if arg is None: # Switched-off opt_material. n_ok += sh is None continue if sh is None: continue prefix = '' if isinstance(sh, basestr): aux = sh.split(':') if len(aux) == 2: prefix, sh = aux shape = _parse_tuple_shape(sh) ls = len(shape) aarg = nm.array(arg, ndmin=1) # Substiture general dimension 'N' with actual value. iinfs = nm.where(nm.isinf(shape))[0] if len(iinfs): shape = list(shape) for iinf in iinfs: shape[iinf] = aarg.shape[-ls+iinf] shape = tuple(shape) if (ls > 1) or (shape[0] > 1): # Array. n_ok += shape == aarg.shape[-ls:] elif (ls == 1) and (shape[0] == 1): # Scalar constant. from numbers import Number n_ok += isinstance(arg, Number) else: n_ok += 1 if n_ok == len(arg_kinds): break else: term_str = '%s.%d.%s(%s)' % (self.name, self.integral.order, self.region.name, self.arg_str) output('allowed argument shapes for term "%s":' % term_str) output(allowed_shapes) raise ValueError('wrong arguments shapes for "%s" term! (see above)' % term_str)