def compute_ir(analysis, parameters):
    "Compute intermediate representation."

    begin("Compiler stage 2: Computing intermediate representation")

    # Set code generation parameters
    set_float_formatting(int(parameters["precision"]))

    # Extract data from analysis
    form_datas, elements, element_numbers = analysis

    # Compute representation of elements
    info("Computing representation of %d elements" % len(elements))
    ir_elements = [_compute_element_ir(e, i, element_numbers) \
                       for (i, e) in enumerate(elements)]

    # Compute representation of dofmaps
    info("Computing representation of %d dofmaps" % len(elements))
    ir_dofmaps = [_compute_dofmap_ir(e, i, element_numbers)
                      for (i, e) in enumerate(elements)]

    # Compute and flatten representation of integrals
    info("Computing representation of integrals")
    irs = [_compute_integral_ir(fd, i, parameters) \
               for (i, fd) in enumerate(form_datas)]
    ir_integrals = [ir for ir in chain(*irs) if not ir is None]

    # Compute representation of forms
    info("Computing representation of forms")
    ir_forms = [_compute_form_ir(fd, i, element_numbers) \
                    for (i, fd) in enumerate(form_datas)]

    end()

    return ir_elements, ir_dofmaps, ir_integrals, ir_forms
示例#2
0
def compute_ir(analysis, prefix, parameters, object_names=None):
    "Compute intermediate representation."

    begin("Compiler stage 2: Computing intermediate representation")

    # Set code generation parameters
    set_float_formatting(int(parameters["precision"]))

    # Extract data from analysis
    form_datas, elements, element_numbers, coordinate_elements = analysis

    # Compute representation of elements
    if not parameters["format"] == "pyop2":
        info("Computing representation of %d elements" % len(elements))
        ir_elements = [_compute_element_ir(e, prefix, element_numbers)
                       for e in elements]
    else:
        ir_elements = [None]

    # Compute representation of dofmaps
    if not parameters["format"] == "pyop2":
        info("Computing representation of %d dofmaps" % len(elements))
        ir_dofmaps = [_compute_dofmap_ir(e, prefix, element_numbers)
                      for e in elements]
        # Compute representation of coordinate mappings
        info("Computing representation of %d coordinate mappings" % len(coordinate_elements))
        ir_compute_coordinate_mappings = [_compute_coordinate_mapping_ir(e, prefix, element_numbers)
                                          for e in coordinate_elements]
    else:
        ir_dofmaps = [None]
        ir_compute_coordinate_mappings = [None]

    # Compute and flatten representation of integrals
    info("Computing representation of integrals")
    irs = [_compute_integral_ir(fd, i, prefix, element_numbers, parameters, object_names=object_names)
           for (i, fd) in enumerate(form_datas)]
    ir_integrals = [ir for ir in chain(*irs) if not ir is None]

    # Compute representation of forms
    if not parameters["format"] == "pyop2":
        info("Computing representation of forms")
        ir_forms = [_compute_form_ir(fd, i, prefix, element_numbers)
                    for (i, fd) in enumerate(form_datas)]
    else:
        ir_forms = [None]

    end()

    return ir_elements, ir_dofmaps, ir_compute_coordinate_mappings, ir_integrals, ir_forms
def compute_ir(analysis, parameters):
    "Compute intermediate representation."

    begin("Compiler stage 2: Computing intermediate representation")

    # Set code generation parameters
    set_float_formatting(int(parameters["precision"]))

    # Extract data from analysis
    form_datas, elements, element_numbers = analysis

    # Compute representation of elements
    info("Computing representation of %d elements" % len(elements))
    ir_elements = [_compute_element_ir(e, i, element_numbers) \
                       for (i, e) in enumerate(elements)]

    # Compute representation of dofmaps
    info("Computing representation of %d dofmaps" % len(elements))
    ir_dofmaps = [
        _compute_dofmap_ir(e, i, element_numbers)
        for (i, e) in enumerate(elements)
    ]

    # Compute and flatten representation of integrals
    info("Computing representation of integrals")
    irs = [_compute_integral_ir(fd, i, parameters) \
               for (i, fd) in enumerate(form_datas)]
    ir_integrals = [ir for ir in chain(*irs) if not ir is None]

    # Compute representation of forms
    info("Computing representation of forms")
    ir_forms = [_compute_form_ir(fd, i, element_numbers) \
                    for (i, fd) in enumerate(form_datas)]

    end()

    return ir_elements, ir_dofmaps, ir_integrals, ir_forms
示例#4
0
# You should have received a copy of the GNU Lesser General Public License
# along with FFC. If not, see <http://www.gnu.org/licenses/>.
#
# First added:  2010-01-06
# Last changed: 2010-03-11

# Pyhton modules
import unittest
import time

# FFC modules
from ffc.quadrature.symbolics import *
from ffc.cpp import format, set_float_formatting
from ffc.parameters import FFC_PARAMETERS

set_float_formatting(FFC_PARAMETERS['precision'])


class TestElasticityTerm(unittest.TestCase):
    def testElasticityTerm(self):
        # expr:  0.25*W1*det*(FE0_C2_D001[0][j]*FE0_C2_D001[0][k]*Jinv_00*Jinv_21 + FE0_C2_D001[0][j]*FE0_C2_D001[0][k]*Jinv_00*Jinv_21)
        expr = Product([
            FloatValue(0.25),
            Symbol('W1', GEO),
            Symbol('det', GEO),
            Sum([
                Product([
                    Symbol('FE0_C2_D001_0_j', BASIS),
                    Symbol('FE0_C2_D001_0_k', BASIS),
                    Symbol('Jinv_00', GEO),
                    Symbol('Jinv_21', GEO)
示例#5
0
# You should have received a copy of the GNU Lesser General Public License
# along with FFC. If not, see <http://www.gnu.org/licenses/>.
#
# First added:  2010-01-06
# Last changed: 2010-02-01

# Pyhton modules
from __future__ import print_function
import unittest
import time

# FFC modules
from ffc.quadrature.symbolics import *
from ffc.cpp import format, set_float_formatting
from ffc.parameters import FFC_PARAMETERS
set_float_formatting(FFC_PARAMETERS['precision'])

class TestRealExamples(unittest.TestCase):

    def testRealExamples(self):

#        p = Product([
#                    Sum([
#                        Product([
#                                  Symbol('w[5][0]', GEO),
#                                  Fraction(
#                                            Product([
#                                                    Symbol('FE0_C1_D01[ip][k]', BASIS), Symbol('Jinv_10', GEO)
#                                                    ]),
#                                            Product([
#                                                    Symbol('w[5][0]', GEO), Symbol('w[5][0]', GEO)
示例#6
0
def compile_coordinate_element(ufl_coordinate_element):
    """Generates C code for changing to reference coordinates.

    :arg ufl_coordinate_element: UFL element of the coordinates
    :returns: C code as string
    """
    from ffc.cpp import set_float_formatting, format
    from ffc.fiatinterface import create_actual_fiat_element
    from ffc.symbolic import ssa_arrays, c_print
    from FIAT.reference_element import two_product_cell
    import ufl
    import sympy as sp
    import numpy as np

    # Set code generation parameters
    parameters = _check_parameters(None)
    set_float_formatting(int(parameters["precision"]))

    def dX_norm_square(topological_dimension):
        return " + ".join("dX[{0}]*dX[{0}]".format(i)
                          for i in xrange(topological_dimension))

    def X_isub_dX(topological_dimension):
        return "\n".join("\tX[{0}] -= dX[{0}];".format(i)
                         for i in xrange(topological_dimension))

    def is_affine(ufl_element):
        return ufl_element.cell().is_simplex() and ufl_element.degree() <= 1 and ufl_element.family() in ["Discontinuous Lagrange", "Lagrange"]

    def inside_check(ufl_cell, fiat_cell):
        dim = ufl_cell.topological_dimension()
        point = tuple(sp.Symbol("X[%d]" % i) for i in xrange(dim))

        return " && ".join("(%s)" % arg for arg in fiat_cell.contains_point(point, epsilon=1e-14).args)

    def init_X(fiat_element):
        f_float  = format["floating point"]
        f_assign = format["assign"]

        fiat_cell = fiat_element.get_reference_element()
        vertices = np.array(fiat_cell.get_vertices())
        X = np.average(vertices, axis=0)
        return "\n".join(f_assign("X[%d]" % i, f_float(v)) for i, v in enumerate(X))

    def to_reference_coordinates(ufl_cell, fiat_element):
        f_decl          = format["declaration"]
        f_float_decl    = format["float declaration"]

        # Get the element cell name and geometric dimension.
        cell = ufl_cell
        gdim = cell.geometric_dimension()
        tdim = cell.topological_dimension()

        code = []

        # Symbolic tabulation
        tabs = fiat_element.tabulate(1, np.array([[sp.Symbol("X[%d]" % i) for i in xrange(tdim)]]))
        tabs = sorted((d, value.reshape(value.shape[:-1])) for d, value in tabs.iteritems())

        # Generate code for intermediate values
        s_code, d_phis = ssa_arrays(map(lambda (k, v): v, tabs), prefix="t")
        phi = d_phis.pop(0)

        for name, value in s_code:
            code += [f_decl(f_float_decl, name, c_print(value))]

        # Cell coordinate data
        C = np.array([[sp.Symbol("C[%d][%d]" % (i, j)) for j in range(gdim)]
                       for i in range(fiat_element.space_dimension())])

        # Generate physical coordinates
        x = phi.dot(C)
        for i, e in enumerate(x):
            code += ["\tx[%d] = %s;" % (i, e)]

        # Generate Jacobian
        grad_phi = np.vstack(reversed(d_phis))
        J = np.transpose(grad_phi.dot(C))
        for i, row in enumerate(J):
            for j, e in enumerate(row):
                code += ["\tJ[%d * %d + %d] = %s;" % (i, tdim, j, e)]

        # Get code snippets for Jacobian, inverse of Jacobian and mapping of
        # coordinates from physical element to the FIAT reference element.
        code_ = [format["compute_jacobian_inverse"](cell)]
        # FIXME: use cell orientations!
        # if needs_orientation:
        #     code_ += [format["orientation"]["ufc"](tdim, gdim)]
        # FIXME: ugly hack
        code_ = "\n".join(code_).split("\n")
        code_ = filter(lambda line: not line.startswith(("double J", "double K", "double detJ")), code_)
        code += code_

        x = np.array([sp.Symbol("x[%d]" % i) for i in xrange(gdim)])
        x0 = np.array([sp.Symbol("x0[%d]" % i) for i in xrange(gdim)])
        K = np.array([[sp.Symbol("K[%d]" % (i*gdim + j)) for j in range(gdim)]
                      for i in range(tdim)])

        dX = K.dot(x - x0)
        for i, e in enumerate(dX):
            code += ["\tdX[%d] = %s;" % (i, e)]

        return "\n".join(code)

    # Create FIAT element
    element = create_actual_fiat_element(ufl_coordinate_element)
    cell = ufl_coordinate_element.cell()

    # calculate_basisvalues, vdim = calculate_basisvalues(cell, element)
    extruded = isinstance(element.get_reference_element(), two_product_cell)

    code = {
        "geometric_dimension": cell.geometric_dimension(),
        "topological_dimension": cell.topological_dimension(),
        "inside_predicate": inside_check(cell, element.get_reference_element()),
        "to_reference_coords": to_reference_coordinates(cell, element),
        "init_X": init_X(element),
        "max_iteration_count": 1 if is_affine(ufl_coordinate_element) else 16,
        "convergence_epsilon": 1e-12,
        "dX_norm_square": dX_norm_square(cell.topological_dimension()),
        "X_isub_dX": X_isub_dX(cell.topological_dimension()),
        "extruded_arg": ", int nlayers" if extruded else "",
        "nlayers": ", f->n_layers" if extruded else "",
    }

    evaluate_template_c = """#include <math.h>
#include <firedrake_geometry.h>

struct ReferenceCoords {
	double X[%(geometric_dimension)d];
	double J[%(geometric_dimension)d * %(topological_dimension)d];
	double K[%(topological_dimension)d * %(geometric_dimension)d];
	double detJ;
};

static inline void to_reference_coords_kernel(void *result_, double *x0, int *return_value, double **C)
{
	struct ReferenceCoords *result = (struct ReferenceCoords *) result_;

	const int space_dim = %(geometric_dimension)d;

	/*
	 * Mapping coordinates from physical to reference space
	 */

	double *X = result->X;
%(init_X)s
	double x[space_dim];
	double *J = result->J;
	double *K = result->K;
	double detJ;

    double dX[%(topological_dimension)d];
    int converged = 0;

    for (int it = 0; !converged && it < %(max_iteration_count)d; it++) {
%(to_reference_coords)s

         if (%(dX_norm_square)s < %(convergence_epsilon)g * %(convergence_epsilon)g) {
             converged = 1;
         }

%(X_isub_dX)s
    }

	result->detJ = detJ;

	// Are we inside the reference element?
	*return_value = %(inside_predicate)s;
}

static inline void wrap_to_reference_coords(void *result_, double *x, int *return_value,
                                            double *coords, int *coords_map%(extruded_arg)s, int cell);

int to_reference_coords(void *result_, struct Function *f, int cell, double *x)
{
	int return_value;
	wrap_to_reference_coords(result_, x, &return_value, f->coords, f->coords_map%(nlayers)s, cell);
	return return_value;
}
"""

    return evaluate_template_c % code
示例#7
0
def compile_element(ufl_element, cdim):
    """Generates C code for point evaluations.

    :arg ufl_element: UFL element of the function space
    :arg cdim: ``cdim`` of the function space
    :returns: C code as string
    """
    from ffc.cpp import set_float_formatting, format
    from ffc.fiatinterface import create_actual_fiat_element
    from ffc.symbolic import ssa_arrays, c_print
    from FIAT.reference_element import two_product_cell
    import ufl
    import sympy as sp
    import numpy as np

    # Set code generation parameters
    parameters = _check_parameters(None)
    set_float_formatting(int(parameters["precision"]))

    def calculate_basisvalues(ufl_cell, fiat_element):
        f_component     = format["component"]
        f_decl          = format["declaration"]
        f_float_decl    = format["float declaration"]
        f_tensor        = format["tabulate tensor"]
        f_new_line      = format["new line"]

        tdim = ufl_cell.topological_dimension()
        gdim = ufl_cell.geometric_dimension()

        code = []

        # Symbolic tabulation
        tabs = fiat_element.tabulate(0, np.array([[sp.Symbol("reference_coords.X[%d]" % i)
                                                   for i in xrange(tdim)]]))
        tabs = tabs[(0,) * tdim]
        tabs = tabs.reshape(tabs.shape[:-1])

        # Generate code for intermediate values
        s_code, (theta,) = ssa_arrays([tabs])
        for name, value in s_code:
            code += [f_decl(f_float_decl, name, c_print(value))]

        # Prepare Jacobian, Jacobian inverse and determinant
        s_detJ = sp.Symbol('detJ')
        s_J = np.array([[sp.Symbol("J[{i}*{tdim} + {j}]".format(i=i, j=j, tdim=tdim))
                         for j in range(tdim)]
                        for i in range(gdim)])
        s_Jinv = np.array([[sp.Symbol("K[{i}*{gdim} + {j}]".format(i=i, j=j, gdim=gdim))
                            for j in range(gdim)]
                           for i in range(tdim)])

        # Apply transformations
        phi = []
        for i, val in enumerate(theta):
            mapping = fiat_element.mapping()[i]
            if mapping == "affine":
                phi.append(val)
            elif mapping == "contravariant piola":
                phi.append(s_J.dot(val) / s_detJ)
            elif mapping == "covariant piola":
                phi.append(s_Jinv.transpose().dot(val))
            else:
                error("Unknown mapping: %s" % mapping)
        phi = np.asarray(phi, dtype=object)

        # Dump tables of basis values
        code += ["", "\t// Values of basis functions"]
        code += [f_decl("double", f_component("phi", phi.shape),
                        f_new_line + f_tensor(phi))]

        shape = phi.shape
        if len(shape) <= 1:
            vdim = 1
        elif len(shape) == 2:
            vdim = shape[1]
        return "\n".join(code), vdim

    # Create FIAT element
    element = create_actual_fiat_element(ufl_element)
    cell = ufl_element.cell()

    calculate_basisvalues, vdim = calculate_basisvalues(cell, element)
    extruded = isinstance(element.get_reference_element(), two_product_cell)

    code = {
        "cdim": cdim,
        "vdim": vdim,
        "geometric_dimension": cell.geometric_dimension(),
        "ndofs": element.space_dimension(),
        "calculate_basisvalues": calculate_basisvalues,
        "extruded_arg": ", int nlayers" if extruded else "",
        "nlayers": ", f->n_layers" if extruded else "",
    }

    evaluate_template_c = """static inline void evaluate_kernel(double *result, double *phi_, double **F)
{
    const int ndofs = %(ndofs)d;
    const int cdim = %(cdim)d;
    const int vdim = %(vdim)d;

    double (*phi)[vdim] = (double (*)[vdim]) phi_;

    // F: ndofs x cdim
    // phi: ndofs x vdim
    // result = F' * phi: cdim x vdim
    //
    // Usually cdim == 1 or vdim == 1.

    for (int q = 0; q < cdim * vdim; q++) {
        result[q] = 0.0;
    }
    for (int i = 0; i < ndofs; i++) {
        for (int c = 0; c < cdim; c++) {
            for (int v = 0; v < vdim; v++) {
                result[c*vdim + v] += F[i][c] * phi[i][v];
            }
        }
    }
}

static inline void wrap_evaluate(double *result, double *phi, double *data, int *map%(extruded_arg)s, int cell);

int evaluate(struct Function *f, double *x, double *result)
{
	struct ReferenceCoords reference_coords;
	int cell = locate_cell(f, x, %(geometric_dimension)d, &to_reference_coords, &reference_coords);
	if (cell == -1) {
		return -1;
	}

	if (!result) {
		return 0;
	}

	double *J = reference_coords.J;
	double *K = reference_coords.K;
	double detJ = reference_coords.detJ;

%(calculate_basisvalues)s

	wrap_evaluate(result, (double *)phi, f->f, f->f_map%(nlayers)s, cell);
	return 0;
}
"""

    return evaluate_template_c % code
示例#8
0
#
# You should have received a copy of the GNU Lesser General Public License
# along with FFC. If not, see <http://www.gnu.org/licenses/>.
#
# First added:  2010-01-06
# Last changed: 2010-02-01

# Pyhton modules
import unittest
import time

# FFC modules
from ffc.quadrature.symbolics import *
from ffc.cpp import format, set_float_formatting
from ffc.parameters import FFC_PARAMETERS
set_float_formatting(FFC_PARAMETERS["precision"])

class TestFloat(unittest.TestCase):

    def testFloat(self):
            "Test simple FloatValue instance."
            f0 = FloatValue(1.5)
            f1 = FloatValue(-5)
            f2 = FloatValue(-1e-14)
            f3 = FloatValue(-1e-11)
            f4 = FloatValue(1.5)

    #        print "\nTesting FloatValue"
    #        print "f0: '%s'" %f0
    #        print "f1: '%s'" %f1
    #        print "f2: '%s'" %f2