Пример #1
0
    def division(self, x):
        "Return parts_of_numerator/denominator."

        # Get numerator and denominator
        numerator, denominator = x.operands()

        # Check for Arguments in the denominator
        if any(
                isinstance(t, Argument)
                for t in traverse_terminals(denominator)):
            error(
                "Found Argument in denominator of %s , this is an invalid expression."
                % repr(x))

        # Visit numerator
        numerator_parts, provides = self.visit(numerator)

        # If numerator is zero, return zero. (No need to check whether
        # it provides too much, already checked by visit.)
        if isinstance(numerator_parts, Zero):
            return (zero(x), set())

        # Reuse x if possible, otherwise reconstruct from (parts of)
        # numerator and denominator
        x = self.reuse_if_possible(x, numerator_parts, denominator)

        return (x, provides)
    def expr(self, x):
        """The default is a nonlinear operator not accepting any
        Arguments among its children."""

        # FIXME: This check makes this an O(n^2) algorithm...
        if any(isinstance(t, Argument) for t in traverse_terminals(x)):
            error("Found Argument in %s, this is an invalid expression." % repr(x))
        return (x, set())
Пример #3
0
def _expr_equals2(a, b):
    # Cutoff for different type
    if type(a) != type(b):
        return False
    # Cutoff for same object
    if a is b:
        return True
    from ufl.algorithms.traversal import traverse_terminals, traverse_operands
    # Check for equal terminals
    for x, y in izip(traverse_terminals(a), traverse_terminals(b)):
        if x != y:
            return False
    # Check for matching operator types
    for x, y in izip(traverse_operands(a), traverse_operands(b)):
        if type(x) != type(y):
            return False
    # Equal terminals and operands, a and b must be equal
    return True
Пример #4
0
def _expr_equals2(a, b):
    # Cutoff for different type
    if type(a) != type(b):
        return False
    # Cutoff for same object
    if a is b:
        return True
    from ufl.algorithms.traversal import traverse_terminals, traverse_operands
    # Check for equal terminals
    for x,y in izip(traverse_terminals(a), traverse_terminals(b)):
        if x != y:
            return False
    # Check for matching operator types
    for x,y in izip(traverse_operands(a), traverse_operands(b)):
        if type(x) != type(y):
            return False
    # Equal terminals and operands, a and b must be equal
    return True
Пример #5
0
    def expr(self, x):
        """The default is a nonlinear operator not accepting any
        Arguments among its children."""

        # FIXME: This check makes this an O(n^2) algorithm...
        if any(isinstance(t, Argument) for t in traverse_terminals(x)):
            error("Found Argument in %s, this is an invalid expression." %
                  repr(x))
        return (x, set())
Пример #6
0
def extract_type(a, ufl_type):
    """Build a set of all objects of class ufl_type found in a.
    The argument a can be a Form, Integral or Expr."""
    if issubclass(ufl_type, Terminal):
        return set(o for e in iter_expressions(a) \
                     for o in traverse_terminals(e) \
                     if isinstance(o, ufl_type))
    return set(o for e in iter_expressions(a) \
                 for o in post_traversal(e) \
                 if isinstance(o, ufl_type))
Пример #7
0
def extract_type(a, ufl_type):
    """Build a set of all objects of class ufl_type found in a.
    The argument a can be a Form, Integral or Expr."""
    if issubclass(ufl_type, Terminal):
        return set(o for e in iter_expressions(a) \
                     for o in traverse_terminals(e) \
                     if isinstance(o, ufl_type))
    return set(o for e in iter_expressions(a) \
                 for o in post_traversal(e) \
                 if isinstance(o, ufl_type))
Пример #8
0
def extract_domains(integrand):
    from ufl.terminal import FormArgument
    from ufl.algorithms.traversal import traverse_terminals
    regions = set()
    for t in traverse_terminals(integrand): # FIXME: Need to analyse which components of functions are actually referenced
        if isinstance(t, FormArgument):
            reg = t.element().regions() # FIXME: Implement
            regions.update(reg)
            regions.update(r.top_domain() for r in reg)
        # FIXME: Check geometry here too when that becomes necessary
    return sorted(regions)
Пример #9
0
def extract_top_domains(integrand):
    from ufl.terminal import FormArgument
    from ufl.algorithms.traversal import traverse_terminals
    top_domains = set()
    for t in traverse_terminals(integrand):
        if isinstance(t, FormArgument):
            domain = t.element().domain()
            if domain is not None:
                top_domains.add(domain.top_domain())
        # FIXME: Check geometry here too when that becomes necessary
    return sorted(top_domains)
Пример #10
0
def has_type(a, ufl_types):
    """Check if any class from ufl_types is found in a.
    The argument a can be a Form, Integral or Expr."""
    if issubclass(ufl_types, Expr):
        ufl_types = (ufl_types,)
    if all(issubclass(ufl_type, Terminal) for ufl_type in ufl_types):
        return any(isinstance(o, ufl_types) \
                   for e in iter_expressions(a) \
                   for o in traverse_terminals(e))
    return any(isinstance(o, ufl_types) \
               for e in iter_expressions(a) \
               for o in post_traversal(e))
Пример #11
0
def has_type(a, ufl_types):
    """Check if any class from ufl_types is found in a.
    The argument a can be a Form, Integral or Expr."""
    if issubclass(ufl_types, Expr):
        ufl_types = (ufl_types, )
    if all(issubclass(ufl_type, Terminal) for ufl_type in ufl_types):
        return any(isinstance(o, ufl_types) \
                   for e in iter_expressions(a) \
                   for o in traverse_terminals(e))
    return any(isinstance(o, ufl_types) \
               for e in iter_expressions(a) \
               for o in post_traversal(e))
Пример #12
0
def is_globally_constant(expr):
    """Check if an expression is globally constant, which
    includes spatially independent constant coefficients that
    are not known before assembly time."""

    from ufl.algorithms.traversal import traverse_terminals
    from ufl.argument import Argument
    from ufl.coefficient import Coefficient

    for e in traverse_terminals(expr):
        if isinstance(e, Argument):
            return False
        if isinstance(e, Coefficient) and e.element().family() != "Real":
            return False
        if not e.is_cellwise_constant():
            return False

    # All terminals passed constant check
    return True
Пример #13
0
def is_globally_constant(expr):
    """Check if an expression is globally constant, which
    includes spatially independent constant coefficients that
    are not known before assembly time."""

    from ufl.algorithms.traversal import traverse_terminals
    from ufl.argument import Argument
    from ufl.coefficient import Coefficient

    for e in traverse_terminals(expr):
        if isinstance(e, Argument):
            return False
        if isinstance(e, Coefficient) and e.element().family() != "Real":
            return False
        if not e.is_cellwise_constant():
            return False

    # All terminals passed constant check
    return True
    def division(self, x):
        "Return parts_of_numerator/denominator."

        # Get numerator and denominator
        numerator, denominator = x.operands()

        # Check for Arguments in the denominator
        if any(isinstance(t, Argument) for t in traverse_terminals(denominator)):
            error("Found Argument in denominator of %s , this is an invalid expression." % repr(x))

        # Visit numerator
        numerator_parts, provides = self.visit(numerator)

        # If numerator is zero, return zero. (No need to check whether
        # it provides too much, already checked by visit.)
        if isinstance(numerator_parts, Zero):
            return (zero(x), set())

        # Reuse x if possible, otherwise reconstruct from (parts of)
        # numerator and denominator
        x = self.reuse_if_possible(x, numerator_parts, denominator)

        return (x, provides)
Пример #15
0
def validate_form(form): # TODO: Can we make this return a list of errors instead of raising exception?
    """Performs all implemented validations on a form. Raises exception if something fails."""
    errors = []
    warnings = []

    if not isinstance(form, Form):
        msg = "Validation failed, not a Form:\n%s" % repr(form)
        error(msg)
        #errors.append(msg)
        #return errors

    # FIXME: Add back check for multilinearity
    # Check that form is multilinear
    #if not is_multilinear(form):
    #    errors.append("Form is not multilinear in arguments.")

    # FIXME DOMAIN: Add check for consistency between domains somehow
    domains = set(t.domain()
                  for e in iter_expressions(form)
                  for t in traverse_terminals(e)) - set((None,))
    if not domains:
        errors.append("Missing domain definition in form.")

    top_domains = set(dom.top_domain() for dom in domains if dom is not None)
    if not top_domains:
        errors.append("Missing domain definition in form.")
    elif len(top_domains) > 1:
        warnings.append("Multiple top domain definitions in form: %s" % str(top_domains))

    # Check that cell is the same everywhere
    cells = set(dom.cell() for dom in top_domains) - set((None,))
    if not cells:
        errors.append("Missing cell definition in form.")
    elif len(cells) > 1:
        errors.append("Multiple cell definitions in form: %s" % str(cells))

    # Check that no Coefficient or Argument instance
    # have the same count unless they are the same
    coefficients = {}
    arguments = {}
    for e in iter_expressions(form):
        for f in traverse_terminals(e):
            if isinstance(f, Coefficient):
                c = f.count()
                if c in coefficients:
                    g = coefficients[c]
                    if not f is g:
                        errors.append("Found different Coefficients with " + \
                                   "same count: %s and %s." % (repr(f), repr(g)))
                else:
                    coefficients[c] = f

            elif isinstance(f, Argument):
                c = f.count()
                if c in arguments:
                    g = arguments[c]
                    if not f is g:
                        if c == -2: msg = "TestFunctions"
                        elif c == -1: msg = "TrialFunctions"
                        else: msg = "Arguments with same count"
                        msg = "Found different %s: %s and %s." % (msg, repr(f), repr(g))
                        errors.append(msg)
                else:
                    arguments[c] = f

    # Check that all integrands are scalar
    for expression in iter_expressions(form):
        if not is_true_ufl_scalar(expression):
            errors.append("Found non-scalar integrand expression:\n%s\n%s" % \
                              (str(expression), repr(expression)))

    # Check that restrictions are permissible
    for integral in form.integrals():
        # Only allow restricitions on interior facet integrals and surface measures
        if integral.measure().domain_type() in (Measure.INTERIOR_FACET, Measure.SURFACE):
            check_restrictions(integral.integrand(), True)
        else:
            check_restrictions(integral.integrand(), False)

    # Raise exception with all error messages
    # TODO: Return errors list instead, need to collect messages from all validations above first.
    if errors:
        final_msg = 'Found errors in validation of form:\n%s' % '\n\n'.join(errors)
        error(final_msg)