예제 #1
0
    def __call__(self, expr):
        V = self.space

        if isinstance(expr, (ScalarFunction, VectorFunction)):
            if expr.space is V:
                return expr

            elif isinstance(expr.projection_of, Projection):
                if expr.projection_of.projector.space is V:
                    return expr

        if isinstance(V, (ScalarFunctionSpace, VectorFunctionSpace)):
            name = 'Proj_' + random_string( 4 )
            F = element_of(V, name)
        else:
            raise TypeError('Only scalar and vector space are handled')

        F.set_as_projection(Projection(self, expr))
        return F
예제 #2
0
    def __new__(cls, expr, domain, eval=True):

        if eval:
            expr = Integral(expr, domain)
        obj = Basic.__new__(cls, expr, domain)

        # compute dim from fields if available
        ls = list(expr.atoms((ScalarField, VectorField)))
        if ls:
            F = ls[0]
            space = F.space

        else:
            tag = random_string( 3 )
            space_name = 'space_{}'.format(tag)
            space = ScalarFunctionSpace(space_name, domain)
            # TODO vector case

        obj._ldim = domain.dim
        obj._space = space

        return obj
예제 #3
0
def is_linear_expression(expr, args, integral=True, debug=True):
    """checks if an expression is linear with respect to the given arguments."""
    # ...
    left_args = []
    right_args = []

    for arg in args:
        tag = random_string(4)

        if isinstance(arg, ScalarTestFunction):
            left = ScalarTestFunction(arg.space, name='l_' + tag)
            right = ScalarTestFunction(arg.space, name='r_' + tag)

        elif isinstance(arg, VectorTestFunction):
            left = VectorTestFunction(arg.space, name='l_' + tag)
            right = VectorTestFunction(arg.space, name='r_' + tag)
        else:
            raise TypeError('argument must be a TestFunction')

        left_args += [left]
        right_args += [right]
    # ...

    # ... check addition
    newargs = [left + right for left, right in zip(left_args, right_args)]

    newexpr = expr.subs(zip(args, newargs))
    left_expr = expr.subs(zip(args, left_args))
    right_expr = expr.subs(zip(args, right_args))

    a = newexpr
    b = left_expr + right_expr

    if not ((a - b).expand() == 0):
        # TODO use a warning or exception?
        if debug:
            print('Failed to assert addition property')
            print('{} != {}'.format(a.expand(), b.expand()))

        return False

    # ...

    # ... check multiplication
    tag = random_string(4)
    coeff = Constant('alpha_' + tag)

    newexpr = expr
    for arg, left in zip(args, left_args):
        newarg = coeff * left
        newexpr = newexpr.subs(arg, newarg)

    atoms = list(newexpr.atoms(BasicOperator))
    subs = [e.func(*e.args, evaluate=True) for e in atoms]
    newexpr = newexpr.subs(zip(atoms, subs))

    left_expr = expr.subs(zip(args, left_args))
    left_expr = coeff * left_expr.subs(arg, left)

    if not ((newexpr - left_expr).expand() == 0):
        # TODO use a warning or exception?
        if debug:
            print('Failed to assert multiplication property')
            print('{} != {}'.format(newexpr, left_expr))

        return False
    # ...

    return True
예제 #4
0
def linearize(form, fields, trials=None):
    """
    Parameters
    ----------
    form : LinearForm
        Linear form F(v; u) to be linearized. F is nonlinear in the parameter u

    fields : [Scalar|Vector]TestFunction or tuple
        Function u with respect to which F should be differentiated.
        Tuple if element of ProductSpace.

    trials : [Scalar|Vector]TestFunction or tuple
        Trial function to be used in resulting bilinear form.

    Results
    -------
    a : BilinearForm
        a(u, v) is bilinear form obtained from linearization of F(v; u).

    """
    if not isinstance(form, LinearForm):
        raise TypeError('> Expecting a LinearForm')

    # ...
    if not isinstance(fields, (list, tuple, Tuple)):
        fields = [fields]

    for field in fields:
        if not isinstance(field, (ScalarTestFunction, VectorTestFunction)):
            raise TypeError('> Expecting a TestFunction', field)

    # ...
    if trials:
        if not isinstance(trials, (list, tuple, Tuple)):
            trials = [trials]

        for trial in trials:
            if not isinstance(trial, (ScalarTestFunction, VectorTestFunction)):
                raise TypeError('> Expecting a TestFunction', trial)
    else:
        trials = [
            x.space.element(x.name + '_trial_' + random_string(4))
            for x in fields
        ]

    # ...

    eps = Constant('eps_' + random_string(4))
    new_fields = [field + eps * trial for field, trial in zip(fields, trials)]

    integrals = form.expr.args if isinstance(form.expr, Add) else [form.expr]
    new_integrals = []

    for I in integrals:

        g0 = I.expr
        g1 = I.expr.subs(zip(fields, new_fields)).expand()
        dg_du = ((g1 - g0) / eps).series(eps, 0, 2).subs(eps, 0)

        if dg_du:
            new_I = integral(I.domain, dg_du)
            new_integrals.append(new_I)

    bilinear_expr = reduce(add, new_integrals)
    tests = form.variables

    return BilinearForm((trials, tests), bilinear_expr)
예제 #5
0
def is_linear_expression(expr, args, debug=True):
    """checks if an expression is linear with respect to the given arguments."""
    # ...
    left_args  = []
    right_args = []

    for arg in args:
        tag    = random_string( 4 )

        if isinstance(arg, ScalarTestFunction):
            left  = ScalarTestFunction(arg.space, name='l_' + tag)
            right = ScalarTestFunction(arg.space, name='r_' + tag)

        elif isinstance(arg, VectorTestFunction):
            left  = VectorTestFunction(arg.space, name='l_' + tag)
            right = VectorTestFunction(arg.space, name='r_' + tag)
        else:
            raise TypeError('argument must be a TestFunction')

        left_args  += [left]
        right_args += [right]
    # ...

    # ... check addition
    newexpr = expr
    for arg, left, right in zip(args, left_args, right_args):
        newarg  = left + right
        newexpr = newexpr.subs(arg, newarg)

    integrals = newexpr.atoms(DomainIntegral, BoundaryIntegral)

    for a in integrals:
        newexpr,_ = newexpr._xreplace({a:integral(a.domain, a.expr)})

    left_expr = expr
    for arg, left in zip(args, left_args):
        left_expr = left_expr.subs(arg, left)

    right_expr = expr
    for arg, right in zip(args, right_args):
        right_expr = right_expr.subs(arg, right)

    if not( newexpr == left_expr + right_expr ):
        # TODO use a warning or exception?
        if debug:
            print('Failed to assert addition property')
            print(newexpr , left_expr + right_expr)

#            print('===========')
#            print(arg, left, right)
#
#            print(expand(newexpr))
#            print(expand(left_expr))
#            print(expand(right_expr))
#            print(expand(newexpr) - expand(left_expr) - expand(right_expr))
#            import sys; sys.exit(0)


        return False

    # ...

    # ... check multiplication
    tag   = random_string( 4 )
    coeff = Constant('alpha_' + tag)

    newexpr = expr
    for arg, left in zip(args, left_args):
        newarg  = coeff * left
        newexpr = newexpr.subs(arg, newarg)

    left_expr = expr
    for arg, left in zip(args, left_args):
        left_expr = left_expr.subs(arg, left)

    left_expr = coeff * left_expr.subs(arg, left)

    if not( expand(newexpr) == expand(left_expr)):
        # TODO use a warning or exception?
        if debug:
            print('Failed to assert multiplication property')

        return False
    # ...

    return True