コード例 #1
0
    def power(self, o):
        #print("\n\nVisiting Power: " + repr(o))

        # Get base and exponent.
        base, expo = o.ufl_operands

        # Visit base to get base code.
        base_code = self.visit(base)

        # TODO: Are these safety checks needed?
        ffc_assert(() in base_code and len(base_code) == 1,
                   "Only support function type base: " + repr(base_code))

        # Get the base code and create power.
        val = base_code[()]

        # Handle different exponents
        if isinstance(expo, IntValue):
            return {(): create_product([val] * expo.value())}
        elif isinstance(expo, FloatValue):
            if self.parameters["format"] == "pyop2":
                exp = create_float(expo.value())
            else:
                exp = format["floating point"](expo.value())
            var = format["std power"][self.parameters["format"]](str(val), exp)
            if self.parameters["format"] == "pyop2":
                sym = create_funcall(var, [val, exp])
            else:
                sym = create_symbol(var, val.t, val, 1, iden=var)
            return {(): sym}
        elif isinstance(expo, (Coefficient, Operator)):
            exp = self.visit(expo)[()]
            #            print "pow exp: ", exp
            #            print "pow val: ", val
            var = format["std power"][self.parameters["format"]](str(val), exp)
            if self.parameters["format"] == "pyop2":
                sym = create_funcall(var, [val, exp])
            else:
                sym = create_symbol(var, val.t, val, 1, iden=var)
            return {(): sym}
        else:
            error("power does not support this exponent: " + repr(expo))
コード例 #2
0
 def _format_scalar_value(self, value):
     # print("format_scalar_value: %d" % value)
     if value is None:
         return {(): create_float(0.0)}
     return {(): create_float(value)}
コード例 #3
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
コード例 #4
0
    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
コード例 #5
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
コード例 #6
0
    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
コード例 #7
0
ファイル: evaluatebasis.py プロジェクト: doru1004/FFC
def _compute_basisvalues(data, dof_data):
    """From FIAT_NEW.expansions."""

    UNROLL = True

    # Prefetch formats to speed up code generation.
    f_comment     = format["comment"]
    f_add         = format["add"]
    f_mul         = format["mul"]
    f_imul        = format["imul"]
    f_sub         = format["sub"]
    f_group       = format["grouping"]
    f_assign      = format["assign"]
    f_sqrt        = format["sqrt"]["ufc"]
    f_x           = format["x coordinate"]
    f_y           = format["y coordinate"]
    f_z           = format["z coordinate"]
    f_double      = format["float declaration"]
    f_basisvalue  = format["basisvalues"]
    f_component   = format["component"]
    f_float       = format["floating point"]
    f_uint        = format["uint declaration"]
    f_tensor      = format["tabulate tensor"]
    f_loop        = format["generate loop"]
    f_decl        = format["declaration"]
    f_tmp         = format["tmp value"]
    f_int         = format["int"]

    f_r = format["free indices"][0]

    # Create temporary values.
    f1, f2, f3, f4, f5  = [create_symbol(f_tmp(i), CONST) for i in range(0,5)]

    # Get embedded degree.
    embedded_degree = dof_data["embedded_degree"]

    # Create helper symbols.
    symbol_p    = create_symbol(f_r, CONST)
    symbol_x    = create_symbol(f_x, CONST)
    symbol_y    = create_symbol(f_y, CONST)
    symbol_z    = create_symbol(f_z, CONST)
    int_n1   = f_int(embedded_degree + 1)
    float_1 = create_float(1)
    float_2 = create_float(2)
    float_0_5   = create_float(0.5)
    float_0_25  = create_float(0.25)

    # Initialise return code.
    code = [""]

    # Create zero array for basisvalues.
    # Get number of members of the expansion set.
    num_mem = dof_data["num_expansion_members"]
    code += [f_comment("Array of basisvalues")]
    code += [f_decl(f_double, f_component(f_basisvalue, num_mem), f_tensor([0.0]*num_mem))]

    # Declare helper variables, will be removed if not used.
    code += ["", f_comment("Declare helper variables")] # Keeping this here to avoid changing references

    # Get the element cell name
    element_cellname = data["cellname"]

    def _jrc(a, b, n):
        an = float( ( 2*n+1+a+b)*(2*n+2+a+b))/ float( 2*(n+1)*(n+1+a+b))
        bn = float( (a*a-b*b) * (2*n+1+a+b))/ float( 2*(n+1)*(2*n+a+b)*(n+1+a+b) )
        cn = float( (n+a)*(n+b)*(2*n+2+a+b))/ float( (n+1)*(n+1+a+b)*(2*n+a+b) )
        return (an,bn,cn)

    # 1D
    if (element_cellname == "interval"):
        # FIAT_NEW.expansions.LineExpansionSet.
        # FIAT_NEW code
        # psitilde_as = jacobi.eval_jacobi_batch(0,0,n,ref_pts)
        # FIAT_NEW.jacobi.eval_jacobi_batch(a,b,n,xs)
        # The initial value basisvalue 0 is always 1.0
        # FIAT_NEW code
        # for ii in range(result.shape[1]):
        #    result[0,ii] = 1.0 + xs[ii,0] - xs[ii,0]
        code += ["", f_comment("Compute basisvalues")]
        code += [f_assign(f_component(f_basisvalue, 0), f_float(1.0))]

        # Only continue if the embedded degree is larger than zero.
        if embedded_degree > 0:

            # FIAT_NEW.jacobi.eval_jacobi_batch(a,b,n,xs).
            # result[1,:] = 0.5 * ( a - b + ( a + b + 2.0 ) * xsnew )
            # The initial value basisvalue 1 is always x
            code += [f_assign(f_component(f_basisvalue, 1), f_x)]

            # Only active is embedded_degree > 1.
            if embedded_degree > 1:
                # FIAT_NEW.jacobi.eval_jacobi_batch(a,b,n,xs).
                # apb = a + b (equal to 0 because of function arguments)
                # for k in range(2,n+1):
                #    a1 = 2.0 * k * ( k + apb ) * ( 2.0 * k + apb - 2.0 )
                #    a2 = ( 2.0 * k + apb - 1.0 ) * ( a * a - b * b )
                #    a3 = ( 2.0 * k + apb - 2.0 )  \
                #        * ( 2.0 * k + apb - 1.0 ) \
                #        * ( 2.0 * k + apb )
                #    a4 = 2.0 * ( k + a - 1.0 ) * ( k + b - 1.0 ) \
                #        * ( 2.0 * k + apb )
                #    a2 = a2 / a1
                #    a3 = a3 / a1
                #    a4 = a4 / a1
                #    result[k,:] = ( a2 + a3 * xsnew ) * result[k-1,:] \
                #        - a4 * result[k-2,:]

                # The below implements the above (with a = b = apb = 0)
                for r in range(2, embedded_degree+1):

                    # Define helper variables
                    a1 = 2.0*r*r*(2.0*r - 2.0)
                    a3 = ((2.0*r - 2.0)*(2.0*r - 1.0 )*(2.0*r))/a1
                    a4 = (2.0*(r - 1.0)*(r - 1.0)*(2.0*r))/a1

                    assign_to = f_component(f_basisvalue, r)
                    assign_from = f_sub([f_mul([f_x, f_component(f_basisvalue, r-1), f_float(a3)]),
                                         f_mul([f_component(f_basisvalue, r-2), f_float(a4)])])
                    code += [f_assign(assign_to, assign_from)]

        # Scale values.
        # FIAT_NEW.expansions.LineExpansionSet.
        # FIAT_NEW code
        # results = numpy.zeros( ( n+1 , len(pts) ) , type( pts[0][0] ) )
        # for k in range( n + 1 ):
        #    results[k,:] = psitilde_as[k,:] * math.sqrt( k + 0.5 )
        lines = []
        loop_vars = [(str(symbol_p), 0, int_n1)]
        # Create names.
        basis_k = create_symbol(f_component(f_basisvalue, str(symbol_p)), CONST)
        # Compute value.
        fac1 = create_symbol( f_sqrt(str(symbol_p + float_0_5)), CONST )
        lines += [format["imul"](str(basis_k), str(fac1))]
        # Create loop (block of lines).
        code += f_loop(lines, loop_vars)
    # 2D
    elif (element_cellname == "triangle"):
        # FIAT_NEW.expansions.TriangleExpansionSet.

        # Compute helper factors
        # FIAT_NEW code
        # f1 = (1.0+2*x+y)/2.0
        # f2 = (1.0 - y) / 2.0
        # f3 = f2**2
        fac1 = create_fraction(float_1 + float_2*symbol_x + symbol_y, float_2)
        fac2 = create_fraction(float_1 - symbol_y, float_2)
        code += [f_decl(f_double, str(f1), fac1)]
        code += [f_decl(f_double, str(f2), fac2)]
        code += [f_decl(f_double, str(f3), f2*f2)]

        code += ["", f_comment("Compute basisvalues")]
        # The initial value basisvalue 0 is always 1.0.
        # FIAT_NEW code
        # for ii in range( results.shape[1] ):
        #    results[0,ii] = 1.0 + apts[ii,0]-apts[ii,0]+apts[ii,1]-apts[ii,1]
        code += [f_assign(f_component(f_basisvalue, 0), f_float(1.0))]

        def _idx2d(p, q):
            return (p + q)*(p + q + 1)//2 + q

        # Only continue if the embedded degree is larger than zero.
        if embedded_degree > 0:

            # The initial value of basisfunction 1 is equal to f1.
            # FIAT_NEW code
            # results[idx(1,0),:] = f1
            code += [f_assign(f_component(f_basisvalue, 1), str(f1))]

            # NOTE: KBO: The order of the loops is VERY IMPORTANT!!
            # Only active is embedded_degree > 1.
            if embedded_degree > 1:
                # FIAT_NEW code (loop 1 in FIAT)
                # for p in range(1,n):
                #    a = (2.0*p+1)/(1.0+p)
                #    b = p / (p+1.0)
                #    results[idx(p+1,0)] = a * f1 * results[idx(p,0),:] \
                #        - p/(1.0+p) * f3 *results[idx(p-1,0),:]
                # FIXME: KBO: Is there an error in FIAT? why is b not used?

                for r in range(1, embedded_degree):
                    rr = _idx2d((r + 1), 0)
                    assign_to = f_component(f_basisvalue, rr)
                    ss = _idx2d(r, 0)
                    tt = _idx2d((r - 1), 0)
                    A = (2*r + 1.0)/(r + 1)
                    B = r/(1.0 + r)
                    v1 = f_mul([f_component(f_basisvalue, ss), f_float(A),
                                str(f1)])
                    v2 = f_mul([f_component(f_basisvalue, tt), f_float(B),
                                str(f3)])
                    assign_from = f_sub([v1, v2])
                    code += [f_assign(assign_to, assign_from)]

            # FIAT_NEW code (loop 2 in FIAT).
            # for p in range(n):
            #    results[idx(p,1),:] = 0.5 * (1+2.0*p+(3.0+2.0*p)*y) \
            #        * results[idx(p,0)]

            for r in range(0, embedded_degree):
                # (p+q)*(p+q+1)//2 + q
                rr = _idx2d(r, 1)
                assign_to = f_component(f_basisvalue, rr)
                ss = _idx2d(r, 0)
                A = 0.5*(1 + 2*r)
                B = 0.5*(3 + 2*r)
                C = f_add([f_float(A), f_mul([f_float(B), str(symbol_y)])])
                assign_from = f_mul([f_component(f_basisvalue, ss),
                                     f_group(C)])
                code += [f_assign(assign_to, assign_from)]

            # Only active is embedded_degree > 1.
            if embedded_degree > 1:
                # FIAT_NEW code (loop 3 in FIAT).
                # for p in range(n-1):
                #    for q in range(1,n-p):
                #        (a1,a2,a3) = jrc(2*p+1,0,q)
                #        results[idx(p,q+1),:] \
                #            = ( a1 * y + a2 ) * results[idx(p,q)] \
                #            - a3 * results[idx(p,q-1)]

                for r in range(0, embedded_degree - 1):
                    for s in range(1, embedded_degree - r):
                        rr = _idx2d(r, (s + 1))
                        ss = _idx2d(r, s)
                        tt = _idx2d(r, s - 1)
                        A, B, C = _jrc(2*r + 1, 0, s)
                        assign_to = f_component(f_basisvalue, rr)
                        assign_from = f_sub([f_mul([f_component(f_basisvalue, ss), f_group(f_add([f_float(B), f_mul([str(symbol_y), f_float(A)])]))]),
                                             f_mul([f_component(f_basisvalue, tt), f_float(C)])])
                        code += [f_assign(assign_to, assign_from)]

            # FIAT_NEW code (loop 4 in FIAT).
            # for p in range(n+1):
            #    for q in range(n-p+1):
            #        results[idx(p,q),:] *= math.sqrt((p+0.5)*(p+q+1.0))
            n1 = embedded_degree + 1
            for r in range(0, n1):
                for s in range(0, n1 - r):
                    rr = _idx2d(r, s)
                    A = (r + 0.5)*(r + s + 1)
                    assign_to = f_component(f_basisvalue, rr)
                    code += [f_imul(assign_to, f_sqrt(A))]

    # 3D
    elif (element_cellname == "tetrahedron"):

        # FIAT_NEW code (compute index function) TetrahedronExpansionSet.
        # def idx(p,q,r):
        #     return (p+q+r)*(p+q+r+1)*(p+q+r+2)//6 + (q+r)*(q+r+1)//2 + r
        def _idx3d(p, q, r):
            return (p+q+r)*(p+q+r+1)*(p+q+r+2)//6 + (q+r)*(q+r+1)//2 + r

        # FIAT_NEW.expansions.TetrahedronExpansionSet.

        # Compute helper factors.
        # FIAT_NEW code
        # factor1 = 0.5 * ( 2.0 + 2.0*x + y + z )
        # factor2 = (0.5*(y+z))**2
        # factor3 = 0.5 * ( 1 + 2.0 * y + z )
        # factor4 = 0.5 * ( 1 - z )
        # factor5 = factor4 ** 2
        fac1 = create_product([float_0_5, float_2 + float_2*symbol_x + symbol_y + symbol_z])
        fac2 = create_product([float_0_25, symbol_y + symbol_z, symbol_y + symbol_z])
        fac3 = create_product([float_0_5, float_1 + float_2*symbol_y + symbol_z])
        fac4 = create_product([float_0_5, float_1 - symbol_z])
        code += [f_decl(f_double, str(f1), fac1)]
        code += [f_decl(f_double, str(f2), fac2)]
        code += [f_decl(f_double, str(f3), fac3)]
        code += [f_decl(f_double, str(f4), fac4)]
        code += [f_decl(f_double, str(f5), f4*f4)]

        code += ["", f_comment("Compute basisvalues")]
        # The initial value basisvalue 0 is always 1.0.
        # FIAT_NEW code
        # for ii in range( results.shape[1] ):
        #    results[0,ii] = 1.0 + apts[ii,0]-apts[ii,0]+apts[ii,1]-apts[ii,1]
        code += [f_assign(f_component(f_basisvalue, 0), f_float(1.0))]

        # Only continue if the embedded degree is larger than zero.
        if embedded_degree > 0:

            # The initial value of basisfunction 1 is equal to f1.
            # FIAT_NEW code
            # results[idx(1,0),:] = f1
            code += [f_assign(f_component(f_basisvalue, 1), str(f1))]

            # NOTE: KBO: The order of the loops is VERY IMPORTANT!!
            # Only active is embedded_degree > 1
            if embedded_degree > 1:

                # FIAT_NEW code (loop 1 in FIAT).
                # for p in range(1,n):
                #    a1 = ( 2.0 * p + 1.0 ) / ( p + 1.0 )
                #    a2 = p / (p + 1.0)
                #    results[idx(p+1,0,0)] = a1 * factor1 * results[idx(p,0,0)] \
                #        -a2 * factor2 * results[ idx(p-1,0,0) ]
                for r in range(1, embedded_degree):
                    rr = _idx3d((r + 1), 0, 0)
                    ss = _idx3d(r, 0, 0)
                    tt = _idx3d((r - 1), 0, 0)
                    A = (2*r + 1.0)/(r + 1)
                    B = r/(r + 1.0)
                    assign_to = f_component(f_basisvalue, rr)
                    assign_from = f_sub([f_mul([f_float(A), str(f1), f_component(f_basisvalue, ss)]), f_mul([f_float(B), str(f2), f_component(f_basisvalue, tt)])])
                    code += [f_assign(assign_to, assign_from)]

            # FIAT_NEW code (loop 2 in FIAT).
            # q = 1
            # for p in range(0,n):
            #    results[idx(p,1,0)] = results[idx(p,0,0)] \
            #        * ( p * (1.0 + y) + ( 2.0 + 3.0 * y + z ) / 2 )

            for r in range(0, embedded_degree):
                rr = _idx3d(r, 1, 0)
                ss = _idx3d(r, 0, 0)
                assign_to = f_component(f_basisvalue, rr)
                term0 = f_mul([f_float(0.5), f_group(f_add([f_float(2), f_mul([f_float(3), str(symbol_y)]), str(symbol_z)]))])
                if r == 0:
                    assign_from = f_mul([term0, f_component(f_basisvalue, ss)])
                else:
                    term1 = f_mul([f_float(r), f_group(f_add([f_float(1), str(symbol_y)]))])
                    assign_from = f_mul([f_group(f_add([term0, term1])), f_component(f_basisvalue, ss)])
                code += [f_assign(assign_to, assign_from)]

            # Only active is embedded_degree > 1.
            if embedded_degree > 1:
                # FIAT_NEW code (loop 3 in FIAT).
                # for p in range(0,n-1):
                #    for q in range(1,n-p):
                #        (aq,bq,cq) = jrc(2*p+1,0,q)
                #        qmcoeff = aq * factor3 + bq * factor4
                #        qm1coeff = cq * factor5
                #        results[idx(p,q+1,0)] = qmcoeff * results[idx(p,q,0)] \
                #            - qm1coeff * results[idx(p,q-1,0)]

                for r in range(0, embedded_degree - 1):
                    for s in range(1, embedded_degree - r):
                        rr = _idx3d(r, (s + 1), 0)
                        ss = _idx3d(r, s, 0)
                        tt = _idx3d(r, s - 1, 0)
                        (A, B, C) = _jrc(2*r + 1, 0, s)
                        assign_to = f_component(f_basisvalue, rr)
                        term0 = f_mul([f_group(f_add([f_mul([f_float(A), str(f3)]), f_mul([f_float(B), str(f4)])])), f_component(f_basisvalue, ss)])
                        term1 = f_mul([f_float(C), str(f5), f_component(f_basisvalue, tt)])
                        assign_from = f_sub([term0, term1])
                        code += [f_assign(assign_to, assign_from)]

            # FIAT_NEW code (loop 4 in FIAT).
            # now handle r=1
            # for p in range(n):
            #    for q in range(n-p):
            #        results[idx(p,q,1)] = results[idx(p,q,0)] \
            #            * ( 1.0 + p + q + ( 2.0 + q + p ) * z )
            for r in range(0, embedded_degree):
                for s in range(0, embedded_degree - r):
                    rr = _idx3d(r, s, 1)
                    ss = _idx3d(r, s, 0)
                    assign_to = f_component(f_basisvalue, rr)
                    A = f_add([f_mul([f_float(2 + r + s), str(symbol_z)]), f_float(1 + r + s)])
                    assign_from = f_mul([f_group(A), f_component(f_basisvalue, ss)])
                    code += [f_assign(assign_to, assign_from)]

            # Only active is embedded_degree > 1.
            if embedded_degree > 1:
                # FIAT_NEW code (loop 5 in FIAT).
                # general r by recurrence
                # for p in range(n-1):
                #     for q in range(0,n-p-1):
                #         for r in range(1,n-p-q):
                #             ar,br,cr = jrc(2*p+2*q+2,0,r)
                #             results[idx(p,q,r+1)] = \
                #                         (ar * z + br) * results[idx(p,q,r) ] \
                #                         - cr * results[idx(p,q,r-1) ]
                for r in range(embedded_degree - 1):
                    for s in range(0, embedded_degree - r - 1):
                        for t in range(1, embedded_degree - r - s):
                            rr = _idx3d(r, s, ( t + 1))
                            ss = _idx3d(r, s, t)
                            tt = _idx3d(r, s, t - 1)

                            (A, B, C) = _jrc(2*r + 2*s + 2, 0, t)
                            assign_to = f_component(f_basisvalue, rr)
                            az_b = f_group(f_add([f_float(B), f_mul([f_float(A), str(symbol_z)])]))
                            assign_from = f_sub([f_mul([f_component(f_basisvalue, ss), az_b]), f_mul([f_float(C), f_component(f_basisvalue, tt)])])
                            code += [f_assign(assign_to, assign_from)]

            # FIAT_NEW code (loop 6 in FIAT).
            # for p in range(n+1):
            #    for q in range(n-p+1):
            #        for r in range(n-p-q+1):
            #            results[idx(p,q,r)] *= math.sqrt((p+0.5)*(p+q+1.0)*(p+q+r+1.5))
            for r in range(embedded_degree + 1):
                for s in range(embedded_degree - r + 1):
                    for t in range(embedded_degree - r - s + 1):
                        rr = _idx3d(r, s, t)
                        A = (r + 0.5)*(r + s + 1)*(r + s + t + 1.5)
                        assign_to = f_component(f_basisvalue, rr)
                        multiply_by = f_sqrt(A)
                        myline = f_imul(assign_to, multiply_by)
                        code += [myline]

    else:
        error("Cannot compute basis values for shape: %d" % elemet_cell_domain)

    return code + [""]
コード例 #8
0
 def _format_scalar_value(self, value):
     # print("format_scalar_value: %d" % value)
     if value is None:
         return {(): create_float(0.0)}
     return {(): create_float(value)}
コード例 #9
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
コード例 #10
0
    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
コード例 #11
0
    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
コード例 #12
0
ファイル: evaluatebasis.py プロジェクト: firedrakeproject/ffc
def _compute_basisvalues(data, dof_data):
    """From FIAT_NEW.expansions."""

    UNROLL = True

    # Prefetch formats to speed up code generation.
    f_comment = format["comment"]
    f_add = format["add"]
    f_mul = format["mul"]
    f_imul = format["imul"]
    f_sub = format["sub"]
    f_group = format["grouping"]
    f_assign = format["assign"]
    f_sqrt = format["sqrt"]["ufc"]
    f_x = format["x coordinate"]
    f_y = format["y coordinate"]
    f_z = format["z coordinate"]
    f_double = format["float declaration"]
    f_basisvalue = format["basisvalues"]
    f_component = format["component"]
    f_float = format["floating point"]
    f_uint = format["uint declaration"]
    f_tensor = format["tabulate tensor"]
    f_loop = format["generate loop"]
    f_decl = format["declaration"]
    f_tmp = format["tmp value"]
    f_int = format["int"]

    f_r = format["free indices"][0]

    # Create temporary values.
    f1, f2, f3, f4, f5 = [create_symbol(f_tmp(i), CONST) for i in range(0, 5)]

    # Get embedded degree.
    embedded_degree = dof_data["embedded_degree"]

    # Create helper symbols.
    symbol_p = create_symbol(f_r, CONST)
    symbol_x = create_symbol(f_x, CONST)
    symbol_y = create_symbol(f_y, CONST)
    symbol_z = create_symbol(f_z, CONST)
    int_n1 = f_int(embedded_degree + 1)
    float_1 = create_float(1)
    float_2 = create_float(2)
    float_0_5 = create_float(0.5)
    float_0_25 = create_float(0.25)

    # Initialise return code.
    code = [""]

    # Create zero array for basisvalues.
    # Get number of members of the expansion set.
    num_mem = dof_data["num_expansion_members"]
    code += [f_comment("Array of basisvalues")]
    code += [
        f_decl(f_double, f_component(f_basisvalue, num_mem),
               f_tensor([0.0] * num_mem))
    ]

    # Declare helper variables, will be removed if not used.
    code += ["", f_comment("Declare helper variables")
             ]  # Keeping this here to avoid changing references

    # Get the element cell name
    element_cellname = data["cellname"]

    def _jrc(a, b, n):
        an = float((2 * n + 1 + a + b) *
                   (2 * n + 2 + a + b)) / float(2 * (n + 1) * (n + 1 + a + b))
        bn = float((a * a - b * b) *
                   (2 * n + 1 + a + b)) / float(2 * (n + 1) * (2 * n + a + b) *
                                                (n + 1 + a + b))
        cn = float((n + a) * (n + b) * (2 * n + 2 + a + b)) / float(
            (n + 1) * (n + 1 + a + b) * (2 * n + a + b))
        return (an, bn, cn)

    # 1D
    if (element_cellname == "interval"):
        # FIAT_NEW.expansions.LineExpansionSet.
        # FIAT_NEW code
        # psitilde_as = jacobi.eval_jacobi_batch(0,0,n,ref_pts)
        # FIAT_NEW.jacobi.eval_jacobi_batch(a,b,n,xs)
        # The initial value basisvalue 0 is always 1.0
        # FIAT_NEW code
        # for ii in range(result.shape[1]):
        #    result[0,ii] = 1.0 + xs[ii,0] - xs[ii,0]
        code += ["", f_comment("Compute basisvalues")]
        code += [f_assign(f_component(f_basisvalue, 0), f_float(1.0))]

        # Only continue if the embedded degree is larger than zero.
        if embedded_degree > 0:

            # FIAT_NEW.jacobi.eval_jacobi_batch(a,b,n,xs).
            # result[1,:] = 0.5 * ( a - b + ( a + b + 2.0 ) * xsnew )
            # The initial value basisvalue 1 is always x
            code += [f_assign(f_component(f_basisvalue, 1), f_x)]

            # Only active is embedded_degree > 1.
            if embedded_degree > 1:
                # FIAT_NEW.jacobi.eval_jacobi_batch(a,b,n,xs).
                # apb = a + b (equal to 0 because of function arguments)
                # for k in range(2,n+1):
                #    a1 = 2.0 * k * ( k + apb ) * ( 2.0 * k + apb - 2.0 )
                #    a2 = ( 2.0 * k + apb - 1.0 ) * ( a * a - b * b )
                #    a3 = ( 2.0 * k + apb - 2.0 )  \
                #        * ( 2.0 * k + apb - 1.0 ) \
                #        * ( 2.0 * k + apb )
                #    a4 = 2.0 * ( k + a - 1.0 ) * ( k + b - 1.0 ) \
                #        * ( 2.0 * k + apb )
                #    a2 = a2 / a1
                #    a3 = a3 / a1
                #    a4 = a4 / a1
                #    result[k,:] = ( a2 + a3 * xsnew ) * result[k-1,:] \
                #        - a4 * result[k-2,:]

                # The below implements the above (with a = b = apb = 0)
                for r in range(2, embedded_degree + 1):

                    # Define helper variables
                    a1 = 2.0 * r * r * (2.0 * r - 2.0)
                    a3 = ((2.0 * r - 2.0) * (2.0 * r - 1.0) * (2.0 * r)) / a1
                    a4 = (2.0 * (r - 1.0) * (r - 1.0) * (2.0 * r)) / a1

                    assign_to = f_component(f_basisvalue, r)
                    assign_from = f_sub([
                        f_mul([
                            f_x,
                            f_component(f_basisvalue, r - 1),
                            f_float(a3)
                        ]),
                        f_mul([f_component(f_basisvalue, r - 2),
                               f_float(a4)])
                    ])
                    code += [f_assign(assign_to, assign_from)]

        # Scale values.
        # FIAT_NEW.expansions.LineExpansionSet.
        # FIAT_NEW code
        # results = numpy.zeros( ( n+1 , len(pts) ) , type( pts[0][0] ) )
        # for k in range( n + 1 ):
        #    results[k,:] = psitilde_as[k,:] * math.sqrt( k + 0.5 )
        lines = []
        loop_vars = [(str(symbol_p), 0, int_n1)]
        # Create names.
        basis_k = create_symbol(f_component(f_basisvalue, str(symbol_p)),
                                CONST)
        # Compute value.
        fac1 = create_symbol(f_sqrt(str(symbol_p + float_0_5)), CONST)
        lines += [format["imul"](str(basis_k), str(fac1))]
        # Create loop (block of lines).
        code += f_loop(lines, loop_vars)
    # 2D
    elif (element_cellname == "triangle"):
        # FIAT_NEW.expansions.TriangleExpansionSet.

        # Compute helper factors
        # FIAT_NEW code
        # f1 = (1.0+2*x+y)/2.0
        # f2 = (1.0 - y) / 2.0
        # f3 = f2**2
        fac1 = create_fraction(float_1 + float_2 * symbol_x + symbol_y,
                               float_2)
        fac2 = create_fraction(float_1 - symbol_y, float_2)
        code += [f_decl(f_double, str(f1), fac1)]
        code += [f_decl(f_double, str(f2), fac2)]
        code += [f_decl(f_double, str(f3), f2 * f2)]

        code += ["", f_comment("Compute basisvalues")]
        # The initial value basisvalue 0 is always 1.0.
        # FIAT_NEW code
        # for ii in range( results.shape[1] ):
        #    results[0,ii] = 1.0 + apts[ii,0]-apts[ii,0]+apts[ii,1]-apts[ii,1]
        code += [f_assign(f_component(f_basisvalue, 0), f_float(1.0))]

        def _idx2d(p, q):
            return (p + q) * (p + q + 1) // 2 + q

        # Only continue if the embedded degree is larger than zero.
        if embedded_degree > 0:

            # The initial value of basisfunction 1 is equal to f1.
            # FIAT_NEW code
            # results[idx(1,0),:] = f1
            code += [f_assign(f_component(f_basisvalue, 1), str(f1))]

            # NOTE: KBO: The order of the loops is VERY IMPORTANT!!
            # Only active is embedded_degree > 1.
            if embedded_degree > 1:
                # FIAT_NEW code (loop 1 in FIAT)
                # for p in range(1,n):
                #    a = (2.0*p+1)/(1.0+p)
                #    b = p / (p+1.0)
                #    results[idx(p+1,0)] = a * f1 * results[idx(p,0),:] \
                #        - p/(1.0+p) * f3 *results[idx(p-1,0),:]
                # FIXME: KBO: Is there an error in FIAT? why is b not used?

                for r in range(1, embedded_degree):
                    rr = _idx2d((r + 1), 0)
                    assign_to = f_component(f_basisvalue, rr)
                    ss = _idx2d(r, 0)
                    tt = _idx2d((r - 1), 0)
                    A = (2 * r + 1.0) / (r + 1)
                    B = r / (1.0 + r)
                    v1 = f_mul(
                        [f_component(f_basisvalue, ss),
                         f_float(A),
                         str(f1)])
                    v2 = f_mul(
                        [f_component(f_basisvalue, tt),
                         f_float(B),
                         str(f3)])
                    assign_from = f_sub([v1, v2])
                    code += [f_assign(assign_to, assign_from)]

            # FIAT_NEW code (loop 2 in FIAT).
            # for p in range(n):
            #    results[idx(p,1),:] = 0.5 * (1+2.0*p+(3.0+2.0*p)*y) \
            #        * results[idx(p,0)]

            for r in range(0, embedded_degree):
                # (p+q)*(p+q+1)//2 + q
                rr = _idx2d(r, 1)
                assign_to = f_component(f_basisvalue, rr)
                ss = _idx2d(r, 0)
                A = 0.5 * (1 + 2 * r)
                B = 0.5 * (3 + 2 * r)
                C = f_add([f_float(A), f_mul([f_float(B), str(symbol_y)])])
                assign_from = f_mul(
                    [f_component(f_basisvalue, ss),
                     f_group(C)])
                code += [f_assign(assign_to, assign_from)]

            # Only active is embedded_degree > 1.
            if embedded_degree > 1:
                # FIAT_NEW code (loop 3 in FIAT).
                # for p in range(n-1):
                #    for q in range(1,n-p):
                #        (a1,a2,a3) = jrc(2*p+1,0,q)
                #        results[idx(p,q+1),:] \
                #            = ( a1 * y + a2 ) * results[idx(p,q)] \
                #            - a3 * results[idx(p,q-1)]

                for r in range(0, embedded_degree - 1):
                    for s in range(1, embedded_degree - r):
                        rr = _idx2d(r, (s + 1))
                        ss = _idx2d(r, s)
                        tt = _idx2d(r, s - 1)
                        A, B, C = _jrc(2 * r + 1, 0, s)
                        assign_to = f_component(f_basisvalue, rr)
                        assign_from = f_sub([
                            f_mul([
                                f_component(f_basisvalue, ss),
                                f_group(
                                    f_add([
                                        f_float(B),
                                        f_mul([str(symbol_y),
                                               f_float(A)])
                                    ]))
                            ]),
                            f_mul([f_component(f_basisvalue, tt),
                                   f_float(C)])
                        ])
                        code += [f_assign(assign_to, assign_from)]

            # FIAT_NEW code (loop 4 in FIAT).
            # for p in range(n+1):
            #    for q in range(n-p+1):
            #        results[idx(p,q),:] *= math.sqrt((p+0.5)*(p+q+1.0))
            n1 = embedded_degree + 1
            for r in range(0, n1):
                for s in range(0, n1 - r):
                    rr = _idx2d(r, s)
                    A = (r + 0.5) * (r + s + 1)
                    assign_to = f_component(f_basisvalue, rr)
                    code += [f_imul(assign_to, f_sqrt(A))]

    # 3D
    elif (element_cellname == "tetrahedron"):

        # FIAT_NEW code (compute index function) TetrahedronExpansionSet.
        # def idx(p,q,r):
        #     return (p+q+r)*(p+q+r+1)*(p+q+r+2)//6 + (q+r)*(q+r+1)//2 + r
        def _idx3d(p, q, r):
            return (p + q + r) * (p + q + r + 1) * (p + q + r + 2) // 6 + (
                q + r) * (q + r + 1) // 2 + r

        # FIAT_NEW.expansions.TetrahedronExpansionSet.

        # Compute helper factors.
        # FIAT_NEW code
        # factor1 = 0.5 * ( 2.0 + 2.0*x + y + z )
        # factor2 = (0.5*(y+z))**2
        # factor3 = 0.5 * ( 1 + 2.0 * y + z )
        # factor4 = 0.5 * ( 1 - z )
        # factor5 = factor4 ** 2
        fac1 = create_product(
            [float_0_5, float_2 + float_2 * symbol_x + symbol_y + symbol_z])
        fac2 = create_product(
            [float_0_25, symbol_y + symbol_z, symbol_y + symbol_z])
        fac3 = create_product(
            [float_0_5, float_1 + float_2 * symbol_y + symbol_z])
        fac4 = create_product([float_0_5, float_1 - symbol_z])
        code += [f_decl(f_double, str(f1), fac1)]
        code += [f_decl(f_double, str(f2), fac2)]
        code += [f_decl(f_double, str(f3), fac3)]
        code += [f_decl(f_double, str(f4), fac4)]
        code += [f_decl(f_double, str(f5), f4 * f4)]

        code += ["", f_comment("Compute basisvalues")]
        # The initial value basisvalue 0 is always 1.0.
        # FIAT_NEW code
        # for ii in range( results.shape[1] ):
        #    results[0,ii] = 1.0 + apts[ii,0]-apts[ii,0]+apts[ii,1]-apts[ii,1]
        code += [f_assign(f_component(f_basisvalue, 0), f_float(1.0))]

        # Only continue if the embedded degree is larger than zero.
        if embedded_degree > 0:

            # The initial value of basisfunction 1 is equal to f1.
            # FIAT_NEW code
            # results[idx(1,0),:] = f1
            code += [f_assign(f_component(f_basisvalue, 1), str(f1))]

            # NOTE: KBO: The order of the loops is VERY IMPORTANT!!
            # Only active is embedded_degree > 1
            if embedded_degree > 1:

                # FIAT_NEW code (loop 1 in FIAT).
                # for p in range(1,n):
                #    a1 = ( 2.0 * p + 1.0 ) / ( p + 1.0 )
                #    a2 = p / (p + 1.0)
                #    results[idx(p+1,0,0)] = a1 * factor1 * results[idx(p,0,0)] \
                #        -a2 * factor2 * results[ idx(p-1,0,0) ]
                for r in range(1, embedded_degree):
                    rr = _idx3d((r + 1), 0, 0)
                    ss = _idx3d(r, 0, 0)
                    tt = _idx3d((r - 1), 0, 0)
                    A = (2 * r + 1.0) / (r + 1)
                    B = r / (r + 1.0)
                    assign_to = f_component(f_basisvalue, rr)
                    assign_from = f_sub([
                        f_mul([
                            f_float(A),
                            str(f1),
                            f_component(f_basisvalue, ss)
                        ]),
                        f_mul([
                            f_float(B),
                            str(f2),
                            f_component(f_basisvalue, tt)
                        ])
                    ])
                    code += [f_assign(assign_to, assign_from)]

            # FIAT_NEW code (loop 2 in FIAT).
            # q = 1
            # for p in range(0,n):
            #    results[idx(p,1,0)] = results[idx(p,0,0)] \
            #        * ( p * (1.0 + y) + ( 2.0 + 3.0 * y + z ) / 2 )

            for r in range(0, embedded_degree):
                rr = _idx3d(r, 1, 0)
                ss = _idx3d(r, 0, 0)
                assign_to = f_component(f_basisvalue, rr)
                term0 = f_mul([
                    f_float(0.5),
                    f_group(
                        f_add([
                            f_float(2),
                            f_mul([f_float(3), str(symbol_y)]),
                            str(symbol_z)
                        ]))
                ])
                if r == 0:
                    assign_from = f_mul([term0, f_component(f_basisvalue, ss)])
                else:
                    term1 = f_mul([
                        f_float(r),
                        f_group(f_add([f_float(1), str(symbol_y)]))
                    ])
                    assign_from = f_mul([
                        f_group(f_add([term0, term1])),
                        f_component(f_basisvalue, ss)
                    ])
                code += [f_assign(assign_to, assign_from)]

            # Only active is embedded_degree > 1.
            if embedded_degree > 1:
                # FIAT_NEW code (loop 3 in FIAT).
                # for p in range(0,n-1):
                #    for q in range(1,n-p):
                #        (aq,bq,cq) = jrc(2*p+1,0,q)
                #        qmcoeff = aq * factor3 + bq * factor4
                #        qm1coeff = cq * factor5
                #        results[idx(p,q+1,0)] = qmcoeff * results[idx(p,q,0)] \
                #            - qm1coeff * results[idx(p,q-1,0)]

                for r in range(0, embedded_degree - 1):
                    for s in range(1, embedded_degree - r):
                        rr = _idx3d(r, (s + 1), 0)
                        ss = _idx3d(r, s, 0)
                        tt = _idx3d(r, s - 1, 0)
                        (A, B, C) = _jrc(2 * r + 1, 0, s)
                        assign_to = f_component(f_basisvalue, rr)
                        term0 = f_mul([
                            f_group(
                                f_add([
                                    f_mul([f_float(A), str(f3)]),
                                    f_mul([f_float(B), str(f4)])
                                ])),
                            f_component(f_basisvalue, ss)
                        ])
                        term1 = f_mul([
                            f_float(C),
                            str(f5),
                            f_component(f_basisvalue, tt)
                        ])
                        assign_from = f_sub([term0, term1])
                        code += [f_assign(assign_to, assign_from)]

            # FIAT_NEW code (loop 4 in FIAT).
            # now handle r=1
            # for p in range(n):
            #    for q in range(n-p):
            #        results[idx(p,q,1)] = results[idx(p,q,0)] \
            #            * ( 1.0 + p + q + ( 2.0 + q + p ) * z )
            for r in range(0, embedded_degree):
                for s in range(0, embedded_degree - r):
                    rr = _idx3d(r, s, 1)
                    ss = _idx3d(r, s, 0)
                    assign_to = f_component(f_basisvalue, rr)
                    A = f_add([
                        f_mul([f_float(2 + r + s),
                               str(symbol_z)]),
                        f_float(1 + r + s)
                    ])
                    assign_from = f_mul(
                        [f_group(A), f_component(f_basisvalue, ss)])
                    code += [f_assign(assign_to, assign_from)]

            # Only active is embedded_degree > 1.
            if embedded_degree > 1:
                # FIAT_NEW code (loop 5 in FIAT).
                # general r by recurrence
                # for p in range(n-1):
                #     for q in range(0,n-p-1):
                #         for r in range(1,n-p-q):
                #             ar,br,cr = jrc(2*p+2*q+2,0,r)
                #             results[idx(p,q,r+1)] = \
                #                         (ar * z + br) * results[idx(p,q,r) ] \
                #                         - cr * results[idx(p,q,r-1) ]
                for r in range(embedded_degree - 1):
                    for s in range(0, embedded_degree - r - 1):
                        for t in range(1, embedded_degree - r - s):
                            rr = _idx3d(r, s, (t + 1))
                            ss = _idx3d(r, s, t)
                            tt = _idx3d(r, s, t - 1)

                            (A, B, C) = _jrc(2 * r + 2 * s + 2, 0, t)
                            assign_to = f_component(f_basisvalue, rr)
                            az_b = f_group(
                                f_add([
                                    f_float(B),
                                    f_mul([f_float(A),
                                           str(symbol_z)])
                                ]))
                            assign_from = f_sub([
                                f_mul([f_component(f_basisvalue, ss), az_b]),
                                f_mul([
                                    f_float(C),
                                    f_component(f_basisvalue, tt)
                                ])
                            ])
                            code += [f_assign(assign_to, assign_from)]

            # FIAT_NEW code (loop 6 in FIAT).
            # for p in range(n+1):
            #    for q in range(n-p+1):
            #        for r in range(n-p-q+1):
            #            results[idx(p,q,r)] *= math.sqrt((p+0.5)*(p+q+1.0)*(p+q+r+1.5))
            for r in range(embedded_degree + 1):
                for s in range(embedded_degree - r + 1):
                    for t in range(embedded_degree - r - s + 1):
                        rr = _idx3d(r, s, t)
                        A = (r + 0.5) * (r + s + 1) * (r + s + t + 1.5)
                        assign_to = f_component(f_basisvalue, rr)
                        multiply_by = f_sqrt(A)
                        myline = f_imul(assign_to, multiply_by)
                        code += [myline]

    else:
        error("Cannot compute basis values for shape: %d" % elemet_cell_domain)

    return code + [""]