Ejemplo n.º 1
0
def test_segregated_derivative_of_convection(self):
    cell = tetrahedron
    V = FiniteElement("CG", cell, 1)
    W = VectorElement("CG", cell, 1)

    u = Coefficient(W)
    v = Coefficient(W)
    du = TrialFunction(V)
    dv = TestFunction(V)

    L = dot(dot(u, nabla_grad(u)), v)

    Lv = {}
    Lvu = {}
    for i in range(cell.geometric_dimension()):
        Lv[i] = derivative(L, v[i], dv)
        for j in range(cell.geometric_dimension()):
            Lvu[i, j] = derivative(Lv[i], u[j], du)

    for i in range(cell.geometric_dimension()):
        for j in range(cell.geometric_dimension()):
            form = Lvu[i, j]*dx
            fd = compute_form_data(form)
            pf = fd.preprocessed_form
            a = expand_indices(pf)
            # print (i,j), str(a)

    k = Index()
    for i in range(cell.geometric_dimension()):
        for j in range(cell.geometric_dimension()):
            actual = Lvu[i, j]
            expected = du*u[i].dx(j)*dv + u[k]*du.dx(k)*dv
            assertEqualBySampling(actual, expected)
Ejemplo n.º 2
0
def test_segregated_derivative_of_convection(self):
    cell = tetrahedron
    V = FiniteElement("CG", cell, 1)
    W = VectorElement("CG", cell, 1)

    u = Coefficient(W)
    v = Coefficient(W)
    du = TrialFunction(V)
    dv = TestFunction(V)

    L = dot(dot(u, nabla_grad(u)), v)

    Lv = {}
    Lvu = {}
    for i in range(cell.geometric_dimension()):
        Lv[i] = derivative(L, v[i], dv)
        for j in range(cell.geometric_dimension()):
            Lvu[i, j] = derivative(Lv[i], u[j], du)

    for i in range(cell.geometric_dimension()):
        for j in range(cell.geometric_dimension()):
            form = Lvu[i, j]*dx
            fd = compute_form_data(form)
            pf = fd.preprocessed_form
            a = expand_indices(pf)
            # print (i,j), str(a)

    k = Index()
    for i in range(cell.geometric_dimension()):
        for j in range(cell.geometric_dimension()):
            actual = Lvu[i, j]
            expected = du*u[i].dx(j)*dv + u[k]*du.dx(k)*dv
            assertEqualBySampling(actual, expected)
Ejemplo n.º 3
0
def splitUFLForm(form):
    phi = form.arguments()[0]
    dphi = Grad(phi)

    source = ExprTensor(phi.ufl_shape)
    flux = ExprTensor(dphi.ufl_shape)
    boundarySource = ExprTensor(phi.ufl_shape)

    form = expand_indices(expand_derivatives(expand_compounds(form)))
    for integral in form.integrals():
        if integral.integral_type() == 'cell':
            fluxExprs = splitMultiLinearExpr(integral.integrand(), [phi])
            for op in fluxExprs:
                if op[0] == phi:
                    source = source + fluxExprs[op]
                elif op[0] == dphi:
                    flux = flux + fluxExprs[op]
                else:
                    raise Exception('Invalid derivative encountered in bulk integral: ' + str(op[0]))
        elif integral.integral_type() == 'exterior_facet':
            fluxExprs = splitMultiLinearExpr(integral.integrand(), [phi])
            for op in fluxExprs:
                if op[0] == phi:
                    boundarySource = boundarySource + fluxExprs[op]
                else:
                    raise Exception('Invalid derivative encountered in boundary integral: ' + str(op[0]))
        else:
            raise NotImplementedError('Integrals of type ' + integral.integral_type() + ' are not supported.')

    return source, flux, boundarySource
Ejemplo n.º 4
0
def generateCode(predefined, expressions, coefficients=None, tempVars=True):
    expressions = [applyRestrictions(expand_indices(apply_derivatives(apply_algebra_lowering(expr)))) for expr in expressions]
    generator = CodeGenerator(predefined, coefficients, tempVars)
    results = map_expr_dags(generator, expressions)
    l = list(generator.using)
    l.sort()
    return l + generator.code, results
Ejemplo n.º 5
0
def is_zero_ufl_expression(expr, return_val=False):
    """
    Is the given expression always identically zero or not
    Returns a boolean by default, but will return the actual
    evaluated expression value if return_val=True

    This function is somewhat brittle. If the ufl library
    changes how forms are processed (additional steps or other
    complexity is added) then this function must be extended
    to be able to break the expressions down into the smallest
    possible parts.
    """
    # Reduce the complexity of the expression as much as possible
    expr = expand_derivatives(expr)
    expr = expand_compounds(expr)
    expr = expand_indices(expr)
    expr = IndexSimplificator().visit(expr)

    # Perform the zero-form estimation
    val = EstimateZeroForms().visit(expr)
    val = int(val)

    # val > 0 if the form is (likely) non-Zero and 0 if it is
    # provably identically Zero()
    if return_val:
        return val
    else:
        return val == 0
Ejemplo n.º 6
0
def codeDG(self):
    code = self._code()

    u = self.trialFunction
    ubar = Coefficient(u.ufl_function_space())
    penalty = self.penalty
    if penalty is None:
        penalty = 1
    if isinstance(penalty, Expr):
        if penalty.ufl_shape == ():
            penalty = as_vector([penalty])
        try:
            penalty = expand_indices(
                expand_derivatives(expand_compounds(penalty)))
        except:
            pass
        assert penalty.ufl_shape == u.ufl_shape
        dmPenalty = as_vector([
            replace(
                expand_derivatives(diff(replace(penalty, {u: ubar}),
                                        ubar))[i, i], {ubar: u})
            for i in range(u.ufl_shape[0])
        ])
    else:
        dmPenalty = None

    code.append(AccessModifier("public"))
    x = SpatialCoordinate(self.space.cell())
    predefined = {}
    self.predefineCoefficients(predefined, x)
    spatial = Variable('const auto', 'y')
    predefined.update({
        x:
        UnformattedExpression(
            'auto', 'entity().geometry().global( Dune::Fem::coordinate( x ) )')
    })
    generateMethod(code,
                   penalty,
                   'RRangeType',
                   'penalty',
                   args=['const Point &x', 'const DRangeType &u'],
                   targs=['class Point', 'class DRangeType'],
                   static=False,
                   const=True,
                   predefined=predefined)
    generateMethod(code,
                   dmPenalty,
                   'RRangeType',
                   'linPenalty',
                   args=['const Point &x', 'const DRangeType &u'],
                   targs=['class Point', 'class DRangeType'],
                   static=False,
                   const=True,
                   predefined=predefined)
    return code
Ejemplo n.º 7
0
def test_expand_indices():
    element = FiniteElement("Lagrange", triangle, 2)
    v = TestFunction(element)
    u = TrialFunction(element)

    def evaluate(form):
        return form.cell_integral()[0].integrand()((), {v: 3, u: 5})  # TODO: How to define values of derivatives?

    a = div(grad(v)) * u * dx
    # a1 = evaluate(a)
    a = expand_derivatives(a)
    # a2 = evaluate(a)
    a = expand_indices(a)
def cppcode(form,*args):
    import ufl.algorithms as alg

    # expand_derivatives calls expand_compounds for us

    g = form
    # g = alg.expand_compounds(g)
    g = alg.expand_derivatives(g)
    g = alg.expand_indices(g)
    s = g.__str__()
    for var in args:
        s = s.replace(var.__str__(),
                      var.expression().cppcode)
    return s
Ejemplo n.º 9
0
def test_mixed_tensor_symmetries():
    from ufl.algorithms import expand_indices, expand_compounds

    S = FiniteElement('CG', triangle, 1)
    V = VectorElement('CG', triangle, 1)
    T = TensorElement('CG', triangle, 1, symmetry=True)

    # M has dimension 4+1, symmetries are 2->1
    M = T * S
    P = Coefficient(M)
    M = inner(P, P) * dx

    M2 = expand_indices(expand_compounds(M))
    assert '[1]' in str(M2)
    assert '[2]' not in str(M2)

    # M has dimension 2+(1+4), symmetries are 5->4
    M = V * (S * T)
    P = Coefficient(M)
    M = inner(P, P) * dx

    M2 = expand_indices(expand_compounds(M))
    assert '[4]' in str(M2)
    assert '[5]' not in str(M2)
Ejemplo n.º 10
0
def test_mixed_tensor_symmetries():
    from ufl.algorithms import expand_indices, expand_compounds

    S = FiniteElement('CG', triangle, 1)
    V = VectorElement('CG', triangle, 1)
    T = TensorElement('CG', triangle, 1, symmetry=True)

    # M has dimension 4+1, symmetries are 2->1
    M = T * S
    P = Coefficient(M)
    M = inner(P, P) * dx

    M2 = expand_indices(expand_compounds(M))
    assert '[1]' in str(M2)
    assert '[2]' not in str(M2)

    # M has dimension 2+(1+4), symmetries are 5->4
    M = V * (S * T)
    P = Coefficient(M)
    M = inner(P, P) * dx

    M2 = expand_indices(expand_compounds(M))
    assert '[4]' in str(M2)
    assert '[5]' not in str(M2)
Ejemplo n.º 11
0
def test_expand_indices():
    element = FiniteElement("Lagrange", triangle, 2)
    v = TestFunction(element)
    u = TrialFunction(element)

    def evaluate(form):
        return form.cell_integral()[0].integrand()((), {
            v: 3,
            u: 5
        })  # TODO: How to define values of derivatives?

    a = div(grad(v)) * u * dx
    # a1 = evaluate(a)
    a = expand_derivatives(a)
    # a2 = evaluate(a)
    a = expand_indices(a)
Ejemplo n.º 12
0
def splitForm(form, arguments=None):
    if arguments is None:
        arguments = form.arguments()

    form = applyRestrictions(form)
    form = expand_indices(apply_derivatives(apply_algebra_lowering(form)))
    form = applyRestrictions(form)

    integrals = {}
    for integral in form.integrals():
        right = splitMultiLinearExpr(integral.integrand(), arguments)
        left = integrals.get(integral.integral_type())
        if left is not None:
            right = sumTensorMaps(left, right)
        integrals[integral.integral_type()] = right

    return integrals
Ejemplo n.º 13
0
def expr2latex(expr, variables=None):
    "This is a test specific function for formatting ufl to LaTeX."

    # Preprocessing expression before applying formatting.  In a
    # compiler, one should probably assume that these have been
    # applied and use ExprFormatter directly.
    expr_data = preprocess_expression(expr)
    expr = expand_indices(expr_data.preprocessed_expr)

    # This formatter is a multifunction with single operator
    # formatting rules for generic LaTeX formatting
    latex_formatter = LatexFormatter()

    # This final formatter implements a generic framework handling
    # indices etc etc.
    variables = variables or {}
    expr_formatter = ExprFormatter(latex_formatter, variables)
    code = expr_formatter.visit(expr)
    return code
def _find_linear_terms(rhs_exprs, u):
    """Help function that takes a list of rhs expressions and return a
    list of bools determining what component, rhs_exprs[i], is linear
    wrt u[i].

    """

    uu = [Constant(1.0) for _ in rhs_exprs]
    if len(rhs_exprs) > 1:
        repl = {u: ufl.as_vector(uu)}
    else:
        repl = {u: uu[0]}

    linear_terms = []
    for i, ui in enumerate(uu):
        comp_i_s = expand_indices(ufl.replace(rhs_exprs[i], repl))
        linear_terms.append(ui in extract_coefficients(comp_i_s) and
                            ui not in extract_coefficients(
                                expand_derivatives(ufl.diff(comp_i_s, ui))))
    return linear_terms
Ejemplo n.º 15
0
def process_form(F):
    global msize, mtime

    printmem()
    print "size of form", asizeof(F)
    print_expr_size(F.cell_integrals()[0].integrand())

    t1 = time.time()
    print 'starting preprocess'
    Ffd = F.compute_form_data()
    t2 = time.time()
    print 'preprocess took %d s' % (t2 - t1)
    print "size of form data (in MB)", asizeof(Ffd) / float(1024**2)
    print_expr_size(Ffd.preprocessed_form.cell_integrals()[0].integrand())
    printmem()

    printmem()
    t1 = time.time()
    print 'starting expand_indices'
    eiF = expand_indices(Ffd.preprocessed_form)
    t2 = time.time()
    print 'expand_indices took %d s' % (t2 - t1)
    #print "REPR LEN", len(repr(eiF))
    msize = asizeof(eiF) / float(1024**2)
    mtime = t2 - t1
    print "size of expanded form (in MB)", msize
    print_expr_size(eiF.cell_integrals()[0].integrand())
    printmem()

    t1 = time.time()
    print 'starting graph building'
    FG = Graph(eiF.cell_integrals()[0].integrand())
    t2 = time.time()
    print 'graph building took %d s' % (t2 - t1)
    print "size of graph (in MB)", asizeof(FG) / float(1024**2)
    printmem()

    return eiF
Ejemplo n.º 16
0
def process_form(F):
    global msize, mtime

    printmem()
    print "size of form", asizeof(F)
    print_expr_size(F.cell_integrals()[0].integrand())

    t1 = time.time()
    print 'starting preprocess'
    Ffd = F.compute_form_data()
    t2 = time.time()
    print 'preprocess took %d s' % (t2-t1)
    print "size of form data (in MB)", asizeof(Ffd)/float(1024**2)
    print_expr_size(Ffd.preprocessed_form.cell_integrals()[0].integrand())
    printmem()

    printmem()
    t1 = time.time()
    print 'starting expand_indices'
    eiF = expand_indices(Ffd.preprocessed_form)
    t2 = time.time()
    print 'expand_indices took %d s' % (t2-t1)
    #print "REPR LEN", len(repr(eiF))
    msize = asizeof(eiF)/float(1024**2)
    mtime = t2-t1
    print "size of expanded form (in MB)", msize
    print_expr_size(eiF.cell_integrals()[0].integrand())
    printmem()

    t1 = time.time()
    print 'starting graph building'
    FG = Graph(eiF.cell_integrals()[0].integrand())
    t2 = time.time()
    print 'graph building took %d s' % (t2-t1)
    print "size of graph (in MB)", asizeof(FG)/float(1024**2)
    printmem()

    return eiF
Ejemplo n.º 17
0
def expr2cpp(expr, variables=None):
    "This is a test specific function for formatting ufl to C++."

    # Preprocessing expression before applying formatting.
    # In a compiler, one should probably assume that these
    # have been applied and use ExprFormatter directly.
    expr_data = preprocess_expression(expr)

    # Applying expand_indices instead of going through
    # compiler algorithm to get scalar valued expressions
    # that can be directlly formatted into C++
    expr = expand_indices(expr_data.preprocessed_expr)

    # This formatter is a multifunction implementing target
    # specific C++ formatting rules
    cpp_formatter = ToyCppLanguageFormatter(dh, ir)

    # This final formatter implements a generic framework handling indices etc etc.
    expr_formatter = ExprFormatter(cpp_formatter, variables or {})

    # Finally perform the formatting
    code = expr_formatter.visit(expr)
    return code
def _rush_larsen_scheme_generator_adm(rhs_form, solution, time, order,
                                      generalized, perturbation):
    """Generates a list of forms and solutions for the adjoint
    linearisation of the Rush-Larsen scheme

    *Arguments*
        rhs_form (ufl.Form)
            A UFL form representing the rhs for a time differentiated equation
        solution (_Function_)
            The prognostic variable
        time (_Constant_)
            A Constant holding the time at the start of the time step
        order (int)
            The order of the scheme
        generalized (bool)
            If True generate a generalized Rush Larsen scheme, linearizing all
            components.
        perturbation (Function)
            The vector on which we compute the adjoint action.

    """

    DX = _check_form(rhs_form)

    if DX != ufl.dP:
        raise TypeError("Expected a form with a Pointintegral.")

    # Create time step
    dt = Constant(0.1)

    # Get test function
    #    arguments = rhs_form.arguments()
    #    coefficients = rhs_form.coefficients()

    # Get time dependent expressions
    time_dep_expressions = _time_dependent_expressions(rhs_form, time)

    # Extract rhs expressions from form
    rhs_integrand = rhs_form.integrals()[0].integrand()
    rhs_exprs, v = extract_tested_expressions(rhs_integrand)
    vector_rhs = len(v.ufl_shape) > 0 and v.ufl_shape[0] > 1

    system_size = v.ufl_shape[0] if vector_rhs else 1

    # Fix for indexing of v for scalar expressions
    v = v if vector_rhs else [v]

    # Extract linear terms if not using generalized Rush Larsen
    if not generalized:
        linear_terms = _find_linear_terms(rhs_exprs, solution)
    else:
        linear_terms = [True for _ in range(system_size)]

    # Wrap the rhs expressions into a ufl vector type
    rhs_exprs = ufl.as_vector([rhs_exprs[i] for i in range(system_size)])
    rhs_jac = ufl.diff(rhs_exprs, solution)

    # Takes time!
    if vector_rhs:
        diff_rhs_exprs = [expand_indices(expand_derivatives(rhs_jac[ind, ind]))
                          for ind in range(system_size)]
        soln = solution
    else:
        diff_rhs_exprs = [expand_indices(expand_derivatives(rhs_jac[0]))]
        solution = [solution]
        soln = solution[0]

    ufl_stage_forms = []
    dolfin_stage_forms = []
    dt_stage_offsets = []
    trial = TrialFunction(soln.function_space())

    # Stage solutions (3 per order rhs, linearized, and final step)
    # If 2nd order the final step for 1 step is a stage
    if order == 1:
        stage_solutions = []

        # Fetch the original step
        rl_ufl_form = _rush_larsen_step(rhs_exprs, diff_rhs_exprs,
                                        linear_terms, system_size,
                                        solution, None, dt, time, 1.0,
                                        0.0, v, DX,
                                        time_dep_expressions)

        # If this is commented out, we don't get NaNs.  Yhy is
        # solution a list of length zero anyway?
        rl_ufl_form = safe_action(safe_adjoint(derivative(rl_ufl_form, soln, trial)),
                                  perturbation)

    elif order == 2:
        # Stage solution for order 2
        fn_space = soln.function_space()

        stage_solutions = [Function(fn_space, name="y_1/2"),
                           Function(fn_space, name="y_1"),
                           Function(fn_space, name="y_bar_1/2")]

        y_half_form = _rush_larsen_step(rhs_exprs, diff_rhs_exprs,
                                        linear_terms, system_size,
                                        solution, None, dt, time, 0.5,
                                        0.0, v, DX,
                                        time_dep_expressions)

        y_one_form = _rush_larsen_step(rhs_exprs, diff_rhs_exprs,
                                       linear_terms, system_size,
                                       solution, stage_solutions[0],
                                       dt, time, 1.0, 0.5, v, DX,
                                       time_dep_expressions)

        y_bar_half_form = safe_action(safe_adjoint(derivative(y_one_form,
                                                              stage_solutions[0], trial)), perturbation)

        rl_ufl_form = safe_action(safe_adjoint(derivative(y_one_form, soln, trial)), perturbation) + \
            safe_action(safe_adjoint(derivative(y_half_form, soln, trial)), stage_solutions[2])

        ufl_stage_forms.append([y_half_form])
        ufl_stage_forms.append([y_one_form])
        ufl_stage_forms.append([y_bar_half_form])
        dolfin_stage_forms.append([Form(y_half_form)])
        dolfin_stage_forms.append([Form(y_one_form)])
        dolfin_stage_forms.append([Form(y_bar_half_form)])

    # Get last stage form
    last_stage = Form(rl_ufl_form)

    human_form = "%srush larsen %s" % ("generalized " if generalized else "",
                                       str(order))

    return rhs_form, linear_terms, ufl_stage_forms, dolfin_stage_forms, last_stage, \
        stage_solutions, dt, dt_stage_offsets, human_form, perturbation
def _rush_larsen_scheme_generator(rhs_form, solution, time, order, generalized):
    """Generates a list of forms and solutions for a given Butcher
    tableau

    *Arguments*
        rhs_form (ufl.Form)
            A UFL form representing the rhs for a time differentiated equation
        solution (_Function_)
            The prognostic variable
        time (_Constant_)
            A Constant holding the time at the start of the time step
        order (int)
            The order of the scheme
        generalized (bool)
            If True generate a generalized Rush Larsen scheme, linearizing all
            components.

    """

    DX = _check_form(rhs_form)

    if DX != ufl.dP:
        raise TypeError("Expected a form with a Pointintegral.")

    # Create time step
    dt = Constant(0.1)

    # Get test function
    #    arguments = rhs_form.arguments()
    #    coefficients = rhs_form.coefficients()

    # Get time dependent expressions
    time_dep_expressions = _time_dependent_expressions(rhs_form, time)

    # Extract rhs expressions from form
    rhs_integrand = rhs_form.integrals()[0].integrand()
    rhs_exprs, v = extract_tested_expressions(rhs_integrand)
    vector_rhs = len(v.ufl_shape) > 0 and v.ufl_shape[0] > 1

    system_size = v.ufl_shape[0] if vector_rhs else 1

    # Fix for indexing of v for scalar expressions
    v = v if vector_rhs else [v]

    # Extract linear terms if not using generalized Rush Larsen
    if not generalized:
        linear_terms = _find_linear_terms(rhs_exprs, solution)
    else:
        linear_terms = [True for _ in range(system_size)]

    # Wrap the rhs expressions into a ufl vector type
    rhs_exprs = ufl.as_vector([rhs_exprs[i] for i in range(system_size)])
    rhs_jac = ufl.diff(rhs_exprs, solution)

    # Takes time!
    if vector_rhs:
        diff_rhs_exprs = [expand_indices(expand_derivatives(rhs_jac[ind, ind]))
                          for ind in range(system_size)]
    else:
        diff_rhs_exprs = [expand_indices(expand_derivatives(rhs_jac[0]))]
        solution = [solution]

    ufl_stage_forms = []
    dolfin_stage_forms = []
    dt_stage_offsets = []

    # Stage solutions (3 per order rhs, linearized, and final step)
    # If 2nd order the final step for 1 step is a stage
    if order == 1:
        stage_solutions = []
        rl_ufl_form = _rush_larsen_step(rhs_exprs, diff_rhs_exprs, linear_terms,
                                        system_size, solution, None, dt, time, 1.0,
                                        0.0, v, DX, time_dep_expressions)
    elif order == 2:

        # Stage solution for order 2
        if vector_rhs:
            stage_solutions = [Function(solution.function_space(), name="y_1/2")]
        else:
            stage_solutions = [Function(solution[0].function_space(), name="y_1/2")]

        stage_form = _rush_larsen_step(rhs_exprs, diff_rhs_exprs,
                                       linear_terms, system_size,
                                       solution, None, dt, time, 0.5,
                                       0.0, v, DX,
                                       time_dep_expressions)

        rl_ufl_form = _rush_larsen_step(rhs_exprs, diff_rhs_exprs,
                                        linear_terms, system_size,
                                        solution, stage_solutions[0],
                                        dt, time, 1.0, 0.5, v, DX,
                                        time_dep_expressions)

        ufl_stage_forms.append([stage_form])
        dolfin_stage_forms.append([Form(stage_form)])

    # Get last stage form
    last_stage = Form(rl_ufl_form)

    human_form = "%srush larsen %s" % ("generalized " if generalized else "",
                                       str(order))

    return rhs_form, linear_terms, ufl_stage_forms, dolfin_stage_forms, last_stage, \
        stage_solutions, dt, dt_stage_offsets, human_form, None