def sum(self, o, *operands): code = {} # Loop operands that has to be summend. for op in operands: # If entries does already exist we can add the code, # otherwise just dump them in the element tensor. for key, val in sorted(op.items()): if key in code: code[key].append(val) else: code[key] = [val] # Add sums and group if necessary. for key, val in sorted_by_key(code): if len(val) > 1: code[key] = create_sum(val) elif val: code[key] = val[0] else: error("Where did the values go?") # If value is zero just ignore it. if abs(code[key].val) < format["epsilon"]: del code[key] return code
def sum(self, o, *operands): code = {} # Loop operands that has to be summend. for op in operands: # If entries does already exist we can add the code, # otherwise just dump them in the element tensor. for key, val in sorted(op.items()): if key in code: code[key].append(val) else: code[key] = [val] # Add sums and group if necessary. for key, val in sorted_by_key(code): if len(val) > 1: code[key] = create_sum(val) elif val: code[key] = val[0] else: error("Where did the values go?") # If value is zero just ignore it. if abs(code[key].val) < format["epsilon"]: del code[key] return code
def sum(self, o, *operands): #print("Visiting Sum: " + repr(o) + "\noperands: " + "\n".join(map(repr, operands))) code = {} # Loop operands that has to be summend. for op in operands: # If entries does already exist we can add the code, otherwise just # dump them in the element tensor. for key, val in op.items(): if key in code: code[key].append(val) else: code[key] = [val] # Add sums and group if necessary. for key, val in code.items(): if len(val) > 1: code[key] = create_sum(val) elif val: code[key] = val[0] else: error("Where did the values go?") # If value is zero just ignore it. if abs(code[key].val) < format["epsilon"]: del code[key] return code
def _reduce_expression(expr, symbols, const_dict, f_name, use_expr_type=False): if use_expr_type: if expr not in const_dict: const_dict[expr] = len(const_dict) return create_symbol(f_name(const_dict[expr]), expr.t) # Only something to be done if we have more than one symbol. if len(symbols) > 1: sym_type = symbols[0].t # Create new symbol. if expr._prec == 2: new_sym = create_product(symbols) elif expr._prec == 3: new_sym = create_sum(symbols) if new_sym not in const_dict: const_dict[new_sym] = len(const_dict) s = create_symbol(f_name(const_dict[new_sym]), sym_type) return [s] return symbols
def _reduce_expression(expr, symbols, const_dict, f_name, use_expr_type=False): if use_expr_type: if expr not in const_dict: const_dict[expr] = len(const_dict) return create_symbol(f_name(const_dict[expr]), expr.t) # Only something to be done if we have more than one symbol. if len(symbols) > 1: sym_type = symbols[0].t # Create new symbol. if expr._prec == 2: new_sym = create_product(symbols) elif expr._prec == 3: new_sym = create_sum(symbols) if new_sym not in const_dict: const_dict[new_sym] = len(const_dict) s = create_symbol(f_name(const_dict[new_sym]), sym_type) return [s] return symbols
def create_function(self, ufl_function, derivatives, component, local_comp, local_offset, ffc_element, is_quad_element, transformation, multiindices, tdim, gdim, avg): "Create code for basis functions, and update relevant tables of used basis." ffc_assert( ufl_function in self._function_replace_values, "Expecting ufl_function to have been mapped prior to this call.") # Prefetch formats to speed up code generation. f_transform = format["transform"] f_detJ = format["det(J)"] # Reset code code = [] # Handle affine mappings. if transformation == "affine": # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(tdim)] if not any(deriv): deriv = [] # Create function name. function_name = self._create_function_name( component, deriv, avg, is_quad_element, ufl_function, ffc_element) if function_name: # Add transformation if needed. code.append( self.__apply_transform(function_name, derivatives, multi, tdim, gdim)) # Handle non-affine mappings. else: ffc_assert( avg is None, "Taking average is not supported for non-affine mappings.") # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(tdim)] if not any(deriv): deriv = [] if transformation in [ "covariant piola", "contravariant piola" ]: for c in range(tdim): function_name = self._create_function_name( c + local_offset, deriv, avg, is_quad_element, ufl_function, ffc_element) if function_name: # Multiply basis by appropriate transform. if transformation == "covariant piola": dxdX = create_symbol( f_transform("JINV", c, local_comp, tdim, gdim, self.restriction), GEO) function_name = create_product( [dxdX, function_name]) elif transformation == "contravariant piola": detJ = create_fraction( create_float(1), create_symbol(f_detJ(self.restriction), GEO)) dXdx = create_symbol( f_transform("J", local_comp, c, gdim, tdim, self.restriction), GEO) function_name = create_product( [detJ, dXdx, function_name]) # Add transformation if needed. code.append( self.__apply_transform(function_name, derivatives, multi, tdim, gdim)) elif transformation == "double covariant piola": # g_ij = (Jinv)_ki G_kl (Jinv)lj i = local_comp // tdim j = local_comp % tdim for k in range(tdim): for l in range(tdim): # Create mapping and basis name. function_name = self._create_function_name( k * tdim + l + local_offset, deriv, avg, is_quad_element, ufl_function, ffc_element) J1 = create_symbol( f_transform("JINV", k, i, tdim, gdim, self.restriction), GEO) J2 = create_symbol( f_transform("JINV", l, j, tdim, gdim, self.restriction), GEO) function_name = create_product( [J1, function_name, J2]) # Add transformation if needed. code.append( self.__apply_transform(function_name, derivatives, multi, tdim, gdim)) elif transformation == "double contravariant piola": # g_ij = (detJ)^(-2) J_ik G_kl J_jl i = local_comp // tdim j = local_comp % tdim for k in range(tdim): for l in range(tdim): # Create mapping and basis name. function_name = self._create_function_name( k * tdim + l + local_offset, deriv, avg, is_quad_element, ufl_function, ffc_element) J1 = create_symbol( f_transform("J", i, k, tdim, gdim, self.restriction), GEO) J2 = create_symbol( f_transform("J", j, l, tdim, gdim, self.restriction), GEO) invdetJ = create_fraction( create_float(1), create_symbol(f_detJ(self.restriction), GEO)) function_name = create_product( [invdetJ, invdetJ, J1, function_name, J2]) # Add transformation if needed. code.append( self.__apply_transform(function_name, derivatives, multi, tdim, gdim)) else: error("Transformation is not supported: ", repr(transformation)) if not code: return create_float(0.0) elif len(code) > 1: code = create_sum(code) else: code = code[0] return code
def create_argument(self, ufl_argument, derivatives, component, local_comp, local_offset, ffc_element, transformation, multiindices, tdim, gdim, avg): "Create code for basis functions, and update relevant tables of used basis." # Prefetch formats to speed up code generation. f_transform = format["transform"] f_detJ = format["det(J)"] # Reset code code = {} # Affine mapping if transformation == "affine": # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(tdim)] if not any(deriv): deriv = [] # Create mapping and basis name. mapping, basis = self._create_mapping_basis( component, deriv, avg, ufl_argument, ffc_element) if mapping not in code: code[mapping] = [] if basis is not None: # Add transformation if needed. code[mapping].append( self.__apply_transform(basis, derivatives, multi, tdim, gdim)) # Handle non-affine mappings. else: ffc_assert( avg is None, "Taking average is not supported for non-affine mappings.") # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(tdim)] if not any(deriv): deriv = [] if transformation in [ "covariant piola", "contravariant piola" ]: for c in range(tdim): # Create mapping and basis name. mapping, basis = self._create_mapping_basis( c + local_offset, deriv, avg, ufl_argument, ffc_element) if mapping not in code: code[mapping] = [] if basis is not None: # Multiply basis by appropriate transform. if transformation == "covariant piola": dxdX = create_symbol( f_transform("JINV", c, local_comp, tdim, gdim, self.restriction), GEO) basis = create_product([dxdX, basis]) elif transformation == "contravariant piola": detJ = create_fraction( create_float(1), create_symbol(f_detJ(self.restriction), GEO)) dXdx = create_symbol( f_transform("J", local_comp, c, gdim, tdim, self.restriction), GEO) basis = create_product([detJ, dXdx, basis]) # Add transformation if needed. code[mapping].append( self.__apply_transform(basis, derivatives, multi, tdim, gdim)) elif transformation == "double covariant piola": # g_ij = (Jinv)_ki G_kl (Jinv)lj i = local_comp // tdim j = local_comp % tdim for k in range(tdim): for l in range(tdim): # Create mapping and basis name. mapping, basis = self._create_mapping_basis( k * tdim + l + local_offset, deriv, avg, ufl_argument, ffc_element) if mapping not in code: code[mapping] = [] if basis is not None: J1 = create_symbol( f_transform("JINV", k, i, tdim, gdim, self.restriction), GEO) J2 = create_symbol( f_transform("JINV", l, j, tdim, gdim, self.restriction), GEO) basis = create_product([J1, basis, J2]) # Add transformation if needed. code[mapping].append( self.__apply_transform( basis, derivatives, multi, tdim, gdim)) elif transformation == "double contravariant piola": # g_ij = (detJ)^(-2) J_ik G_kl J_jl i = local_comp // tdim j = local_comp % tdim for k in range(tdim): for l in range(tdim): # Create mapping and basis name. mapping, basis = self._create_mapping_basis( k * tdim + l + local_offset, deriv, avg, ufl_argument, ffc_element) if mapping not in code: code[mapping] = [] if basis is not None: J1 = create_symbol( f_transform("J", i, k, gdim, tdim, self.restriction), GEO) J2 = create_symbol( f_transform("J", j, l, gdim, tdim, self.restriction), GEO) invdetJ = create_fraction( create_float(1), create_symbol(f_detJ(self.restriction), GEO)) basis = create_product( [invdetJ, invdetJ, J1, basis, J2]) # Add transformation if needed. code[mapping].append( self.__apply_transform( basis, derivatives, multi, tdim, gdim)) else: error("Transformation is not supported: " + repr(transformation)) # Add sums and group if necessary. for key, val in list(code.items()): if len(val) > 1: code[key] = create_sum(val) else: code[key] = val[0] return code
def _extract_variables(val, basis_consts, ip_consts, geo_consts, t_set, optimisation): f_G = format["geometry constant"] f_I = format["ip constant"] f_B = format["basis constant"] if val._prec == 0: return val elif val._prec == 1: if val.base_expr is None: return val new_base = _extract_variables(val.base_expr, basis_consts, ip_consts, geo_consts, t_set, optimisation) new_sym = create_symbol(val.v, val.t, new_base, val.base_op) if new_sym.t == BASIS: return _reduce_expression(new_sym, [], basis_consts, f_B, True) elif new_sym.t == IP: return _reduce_expression(new_sym, [], ip_consts, f_I, True) elif new_sym.t == GEO: return _reduce_expression(new_sym, [], geo_consts, f_G, True) # First handle child classes of product and sum. elif val._prec in (2, 3): new_vars = [] for v in val.vrs: new_vars.append( _extract_variables(v, basis_consts, ip_consts, geo_consts, t_set, optimisation)) if val._prec == 2: new_val = create_product(new_vars) if val._prec == 3: new_val = create_sum(new_vars) elif val._prec == 4: num = _extract_variables(val.num, basis_consts, ip_consts, geo_consts, t_set, optimisation) denom = _extract_variables(val.denom, basis_consts, ip_consts, geo_consts, t_set, optimisation) return create_fraction(num, denom) else: error("Unknown symbolic type: %s" % repr(val)) # Sort variables of product and sum. b_c, i_c, g_c = [], [], [] for v in new_val.vrs: if v.t == BASIS: if optimisation == "precompute_basis_const": b_c.append(v) elif v.t == IP: i_c.append(v) else: g_c.append(v) vrs = new_val.vrs[:] for v in g_c + i_c + b_c: vrs.remove(v) i_c.extend(_reduce_expression(new_val, g_c, geo_consts, f_G)) vrs.extend(_reduce_expression(new_val, i_c, ip_consts, f_I)) vrs.extend(_reduce_expression(new_val, b_c, basis_consts, f_B)) # print "b_c: " # for b in b_c: # print b # print "basis" # for k,v in basis_consts.items(): # print "k: ", k # print "v: ", v # print "geo" # for k,v in geo_consts.items(): # print "k: ", k # print "v: ", v # print "ret val: ", val if len(vrs) > 1: if new_val._prec == 2: new_object = create_product(vrs) elif new_val._prec == 3: new_object = create_sum(vrs) else: error("Must have product or sum here: %s" % repr(new_val)) if new_object.t == BASIS: if optimisation == "precompute_ip_const": return new_object elif optimisation == "precompute_basis_const": return _reduce_expression(new_object, [], basis_consts, f_B, True) elif new_object.t == IP: return _reduce_expression(new_object, [], ip_consts, f_I, True) elif new_object.t == GEO: return _reduce_expression(new_object, [], geo_consts, f_G, True) return vrs[0]
def create_function(self, ufl_function, derivatives, component, local_comp, local_offset, ffc_element, is_quad_element, transformation, multiindices, tdim, gdim, avg): "Create code for basis functions, and update relevant tables of used basis." ffc_assert( ufl_function in self._function_replace_values, "Expecting ufl_function to have been mapped prior to this call.") # Prefetch formats to speed up code generation. f_transform = format["transform"] f_detJ = format["det(J)"] # Reset code code = [] # Handle affine mappings. if transformation == "affine": # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(tdim)] if not any(deriv): deriv = [] # Create function name. function_name = self._create_function_name( component, deriv, avg, is_quad_element, ufl_function, ffc_element) if function_name: # Add transformation if needed. code.append( self.__apply_transform(function_name, derivatives, multi, tdim, gdim)) # Handle non-affine mappings. else: ffc_assert( avg is None, "Taking average is not supported for non-affine mappings.") # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(tdim)] if not any(deriv): deriv = [] for c in range(tdim): function_name = self._create_function_name( c + local_offset, deriv, avg, is_quad_element, ufl_function, ffc_element) if function_name: # Multiply basis by appropriate transform. if transformation == "covariant piola": dxdX = create_symbol( f_transform("JINV", c, local_comp, tdim, gdim, self.restriction), GEO, loop_index=[c * gdim + local_comp], iden="K%s" % _choose_map(self.restriction)) function_name = create_product( [dxdX, function_name]) elif transformation == "contravariant piola": detJ = create_fraction( create_float(1), create_symbol(f_detJ(self.restriction), GEO, iden=f_detJ(self.restriction))) dXdx = create_symbol(f_transform("J", local_comp, c, gdim, tdim, self.restriction), GEO, \ loop_index=[local_comp*tdim + c], iden="J%s" % _choose_map(self.restriction)) function_name = create_product( [detJ, dXdx, function_name]) else: error("Transformation is not supported: ", repr(transformation)) # Add transformation if needed. code.append( self.__apply_transform(function_name, derivatives, multi, tdim, gdim)) if not code: return create_float(0.0) elif len(code) > 1: code = create_sum(code) else: code = code[0] return code
def create_argument(self, ufl_argument, derivatives, component, local_comp, local_offset, ffc_element, transformation, multiindices, tdim, gdim, avg): "Create code for basis functions, and update relevant tables of used basis." # Prefetch formats to speed up code generation. f_transform = format["transform"] f_detJ = format["det(J)"] # Reset code code = {} # Affine mapping if transformation == "affine": # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(tdim)] if not any(deriv): deriv = [] # Create mapping and basis name. mapping, basis = self._create_mapping_basis( component, deriv, avg, ufl_argument, ffc_element) if isinstance(mapping, list): for ma, ba in zip(mapping, basis): if not ma in code: code[ma] = [] if basis is not None: # Add transformation if needed. code[ma].append( self.__apply_transform(ba, derivatives, multi, tdim, gdim)) else: if not mapping in code: code[mapping] = [] if basis is not None: # Add transformation if needed. code[mapping].append( self.__apply_transform(basis, derivatives, multi, tdim, gdim)) # Handle non-affine mappings. else: ffc_assert( avg is None, "Taking average is not supported for non-affine mappings.") # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(tdim)] if not any(deriv): deriv = [] for c in range(tdim): # Create mapping and basis name. mapping, basis = self._create_mapping_basis( c + local_offset, deriv, avg, ufl_argument, ffc_element) if not mapping in code: code[mapping] = [] if basis is not None: # Multiply basis by appropriate transform. if transformation == "covariant piola": dxdX = create_symbol( f_transform("JINV", c, local_comp, tdim, gdim, self.restriction), GEO, loop_index=[c * gdim + local_comp], iden="K%s" % _choose_map(self.restriction)) basis = create_product([dxdX, basis]) elif transformation == "contravariant piola": detJ = create_fraction(create_float(1), \ create_symbol(f_detJ(self.restriction), GEO, iden=f_detJ(self.restriction))) dXdx = create_symbol(f_transform("J", local_comp, c, gdim, tdim, self.restriction), GEO, \ loop_index=[local_comp*tdim + c], iden="J%s" % _choose_map(self.restriction)) basis = create_product([detJ, dXdx, basis]) else: error("Transformation is not supported: " + repr(transformation)) # Add transformation if needed. code[mapping].append( self.__apply_transform(basis, derivatives, multi, tdim, gdim)) # Add sums and group if necessary. for key, val in list(code.items()): if len(val) > 1: code[key] = create_sum(val) else: code[key] = val[0] return code
def _extract_variables(val, basis_consts, ip_consts, geo_consts, t_set, optimisation): f_G = format["geometry constant"] f_I = format["ip constant"] f_B = format["basis constant"] if val._prec == 0: return val elif val._prec == 1: if val.base_expr is None: return val new_base = _extract_variables(val.base_expr, basis_consts, ip_consts, geo_consts, t_set, optimisation) new_sym = create_symbol(val.v, val.t, new_base, val.base_op) if new_sym.t == BASIS: return _reduce_expression(new_sym, [], basis_consts, f_B, True) elif new_sym.t == IP: return _reduce_expression(new_sym, [], ip_consts, f_I, True) elif new_sym.t == GEO: return _reduce_expression(new_sym, [], geo_consts, f_G, True) # First handle child classes of product and sum. elif val._prec in (2, 3): new_vars = [] for v in val.vrs: new_vars.append(_extract_variables(v, basis_consts, ip_consts, geo_consts, t_set, optimisation)) if val._prec == 2: new_val = create_product(new_vars) if val._prec == 3: new_val = create_sum(new_vars) elif val._prec == 4: num = _extract_variables(val.num, basis_consts, ip_consts, geo_consts, t_set, optimisation) denom = _extract_variables(val.denom, basis_consts, ip_consts, geo_consts, t_set, optimisation) return create_fraction(num, denom) else: error("Unknown symbolic type: %s" % repr(val)) # Sort variables of product and sum. b_c, i_c, g_c = [], [], [] for v in new_val.vrs: if v.t == BASIS: if optimisation == "precompute_basis_const": b_c.append(v) elif v.t == IP: i_c.append(v) else: g_c.append(v) vrs = new_val.vrs[:] for v in g_c + i_c + b_c: vrs.remove(v) i_c.extend(_reduce_expression(new_val, g_c, geo_consts, f_G)) vrs.extend(_reduce_expression(new_val, i_c, ip_consts, f_I)) vrs.extend(_reduce_expression(new_val, b_c, basis_consts, f_B)) # print "b_c: " # for b in b_c: # print b # print "basis" # for k,v in basis_consts.items(): # print "k: ", k # print "v: ", v # print "geo" # for k,v in geo_consts.items(): # print "k: ", k # print "v: ", v # print "ret val: ", val if len(vrs) > 1: if new_val._prec == 2: new_object = create_product(vrs) elif new_val._prec == 3: new_object = create_sum(vrs) else: error("Must have product or sum here: %s" % repr(new_val)) if new_object.t == BASIS: if optimisation == "precompute_ip_const": return new_object elif optimisation == "precompute_basis_const": return _reduce_expression(new_object, [], basis_consts, f_B, True) elif new_object.t == IP: return _reduce_expression(new_object, [], ip_consts, f_I, True) elif new_object.t == GEO: return _reduce_expression(new_object, [], geo_consts, f_G, True) return vrs[0]
def create_function(self, ufl_function, derivatives, component, local_comp, local_offset, ffc_element, is_quad_element, transformation, multiindices, tdim, gdim, avg): "Create code for basis functions, and update relevant tables of used basis." ffc_assert(ufl_function in self._function_replace_values, "Expecting ufl_function to have been mapped prior to this call.") # Prefetch formats to speed up code generation. f_transform = format["transform"] f_detJ = format["det(J)"] # Reset code code = [] # Handle affine mappings. if transformation == "affine": # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(tdim)] if not any(deriv): deriv = [] # Create function name. function_name = self._create_function_name(component, deriv, avg, is_quad_element, ufl_function, ffc_element) if function_name: # Add transformation if needed. code.append(self.__apply_transform(function_name, derivatives, multi, tdim, gdim)) # Handle non-affine mappings. else: ffc_assert(avg is None, "Taking average is not supported for non-affine mappings.") # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(tdim)] if not any(deriv): deriv = [] if transformation in ["covariant piola", "contravariant piola"]: for c in range(tdim): function_name = self._create_function_name(c + local_offset, deriv, avg, is_quad_element, ufl_function, ffc_element) if function_name: # Multiply basis by appropriate transform. if transformation == "covariant piola": dxdX = create_symbol(f_transform("JINV", c, local_comp, tdim, gdim, self.restriction), GEO) function_name = create_product([dxdX, function_name]) elif transformation == "contravariant piola": detJ = create_fraction(create_float(1), create_symbol(f_detJ(self.restriction), GEO)) dXdx = create_symbol(f_transform("J", local_comp, c, gdim, tdim, self.restriction), GEO) function_name = create_product([detJ, dXdx, function_name]) # Add transformation if needed. code.append(self.__apply_transform(function_name, derivatives, multi, tdim, gdim)) elif transformation == "double covariant piola": # g_ij = (Jinv)_ki G_kl (Jinv)lj i = local_comp // tdim j = local_comp % tdim for k in range(tdim): for l in range(tdim): # Create mapping and basis name. function_name = self._create_function_name( k * tdim + l + local_offset, deriv, avg, is_quad_element, ufl_function, ffc_element) J1 = create_symbol( f_transform("JINV", k, i, tdim, gdim, self.restriction), GEO) J2 = create_symbol( f_transform("JINV", l, j, tdim, gdim, self.restriction), GEO) function_name = create_product([J1, function_name, J2]) # Add transformation if needed. code.append(self.__apply_transform( function_name, derivatives, multi, tdim, gdim)) elif transformation == "double contravariant piola": # g_ij = (detJ)^(-2) J_ik G_kl J_jl i = local_comp // tdim j = local_comp % tdim for k in range(tdim): for l in range(tdim): # Create mapping and basis name. function_name = self._create_function_name( k * tdim + l + local_offset, deriv, avg, is_quad_element, ufl_function, ffc_element) J1 = create_symbol( f_transform("J", i, k, tdim, gdim, self.restriction), GEO) J2 = create_symbol( f_transform("J", j, l, tdim, gdim, self.restriction), GEO) invdetJ = create_fraction( create_float(1), create_symbol(f_detJ(self.restriction), GEO)) function_name = create_product([invdetJ, invdetJ, J1, function_name, J2]) # Add transformation if needed. code.append(self.__apply_transform(function_name, derivatives, multi, tdim, gdim)) else: error("Transformation is not supported: ", repr(transformation)) if not code: return create_float(0.0) elif len(code) > 1: code = create_sum(code) else: code = code[0] return code
def create_argument(self, ufl_argument, derivatives, component, local_comp, local_offset, ffc_element, transformation, multiindices, tdim, gdim, avg): "Create code for basis functions, and update relevant tables of used basis." # Prefetch formats to speed up code generation. f_transform = format["transform"] f_detJ = format["det(J)"] # Reset code code = {} # Affine mapping if transformation == "affine": # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(tdim)] if not any(deriv): deriv = [] # Create mapping and basis name. mapping, basis = self._create_mapping_basis(component, deriv, avg, ufl_argument, ffc_element) if mapping not in code: code[mapping] = [] if basis is not None: # Add transformation if needed. code[mapping].append(self.__apply_transform(basis, derivatives, multi, tdim, gdim)) # Handle non-affine mappings. else: ffc_assert(avg is None, "Taking average is not supported for non-affine mappings.") # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(tdim)] if not any(deriv): deriv = [] if transformation in ["covariant piola", "contravariant piola"]: for c in range(tdim): # Create mapping and basis name. mapping, basis = self._create_mapping_basis(c + local_offset, deriv, avg, ufl_argument, ffc_element) if mapping not in code: code[mapping] = [] if basis is not None: # Multiply basis by appropriate transform. if transformation == "covariant piola": dxdX = create_symbol(f_transform("JINV", c, local_comp, tdim, gdim, self.restriction), GEO) basis = create_product([dxdX, basis]) elif transformation == "contravariant piola": detJ = create_fraction(create_float(1), create_symbol(f_detJ(self.restriction), GEO)) dXdx = create_symbol(f_transform("J", local_comp, c, gdim, tdim, self.restriction), GEO) basis = create_product([detJ, dXdx, basis]) # Add transformation if needed. code[mapping].append(self.__apply_transform(basis, derivatives, multi, tdim, gdim)) elif transformation == "double covariant piola": # g_ij = (Jinv)_ki G_kl (Jinv)lj i = local_comp // tdim j = local_comp % tdim for k in range(tdim): for l in range(tdim): # Create mapping and basis name. mapping, basis = self._create_mapping_basis( k * tdim + l + local_offset, deriv, avg, ufl_argument, ffc_element) if mapping not in code: code[mapping] = [] if basis is not None: J1 = create_symbol( f_transform("JINV", k, i, tdim, gdim, self.restriction), GEO) J2 = create_symbol( f_transform("JINV", l, j, tdim, gdim, self.restriction), GEO) basis = create_product([J1, basis, J2]) # Add transformation if needed. code[mapping].append( self.__apply_transform( basis, derivatives, multi, tdim, gdim)) elif transformation == "double contravariant piola": # g_ij = (detJ)^(-2) J_ik G_kl J_jl i = local_comp // tdim j = local_comp % tdim for k in range(tdim): for l in range(tdim): # Create mapping and basis name. mapping, basis = self._create_mapping_basis( k * tdim + l + local_offset, deriv, avg, ufl_argument, ffc_element) if mapping not in code: code[mapping] = [] if basis is not None: J1 = create_symbol( f_transform("J", i, k, gdim, tdim, self.restriction), GEO) J2 = create_symbol( f_transform("J", j, l, gdim, tdim, self.restriction), GEO) invdetJ = create_fraction( create_float(1), create_symbol(f_detJ(self.restriction), GEO)) basis = create_product([invdetJ, invdetJ, J1, basis, J2]) # Add transformation if needed. code[mapping].append( self.__apply_transform( basis, derivatives, multi, tdim, gdim)) else: error("Transformation is not supported: " + repr(transformation)) # Add sums and group if necessary. for key, val in list(code.items()): if len(val) > 1: code[key] = create_sum(val) else: code[key] = val[0] return code
def create_argument(self, ufl_argument, derivatives, component, local_comp, local_offset, ffc_element, transformation, multiindices, tdim, gdim, avg): "Create code for basis functions, and update relevant tables of used basis." ffc_assert(ufl_argument in self._function_replace_values, "Expecting ufl_argument to have been mapped prior to this call.") # Prefetch formats to speed up code generation. f_transform = format["transform"] f_detJ = format["det(J)"] # Reset code code = {} # Affine mapping if transformation == "affine": # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(self.tdim)] if not any(deriv): deriv = [] # Create mapping and basis name. mapping, basis = self._create_mapping_basis(component, deriv, avg, ufl_argument, ffc_element) if not mapping in code: code[mapping] = [] if basis is not None: # Add transformation if needed. code[mapping].append(self.__apply_transform(basis, derivatives, multi, tdim, gdim)) # Handle non-affine mappings. else: ffc_assert(avg is None, "Taking average is not supported for non-affine mappings.") # Loop derivatives and get multi indices. for multi in multiindices: deriv = [multi.count(i) for i in range(self.tdim)] if not any(deriv): deriv = [] for c in range(self.tdim): # Create mapping and basis name. mapping, basis = self._create_mapping_basis(c + local_offset, deriv, avg, ufl_argument, ffc_element) if not mapping in code: code[mapping] = [] if basis is not None: # Multiply basis by appropriate transform. if transformation == "covariant piola": dxdX = create_symbol(f_transform("JINV", c, local_comp, tdim, gdim, self.restriction), GEO) basis = create_product([dxdX, basis]) elif transformation == "contravariant piola": detJ = create_fraction(create_float(1), create_symbol(f_detJ(self.restriction), GEO)) dXdx = create_symbol(f_transform("J", local_comp, c, gdim, tdim, self.restriction), GEO) basis = create_product([detJ, dXdx, basis]) else: error("Transformation is not supported: " + repr(transformation)) # Add transformation if needed. code[mapping].append(self.__apply_transform(basis, derivatives, multi, tdim, gdim)) # Add sums and group if necessary. for key, val in code.items(): if len(val) > 1: code[key] = create_sum(val) else: code[key] = val[0] return code