コード例 #1
0
def _expression_mathfunction(expr, parameters):
    name_map = {
        'abs': 'fabs',
        'ln': 'log',

        # Bessel functions
        'cyl_bessel_j': 'jn',
        'cyl_bessel_y': 'yn',

        # Modified Bessel functions (C++ only)
        #
        # These mappings work for FEniCS only, and fail with Firedrake
        # since no Boost available.
        'cyl_bessel_i': 'boost::math::cyl_bessel_i',
        'cyl_bessel_k': 'boost::math::cyl_bessel_k',
    }
    name = name_map.get(expr.name, expr.name)
    if name == 'jn':
        nu, arg = expr.children
        if nu == gem.Zero():
            return coffee.FunCall('j0', expression(arg, parameters))
        elif nu == gem.one:
            return coffee.FunCall('j1', expression(arg, parameters))
    if name == 'yn':
        nu, arg = expr.children
        if nu == gem.Zero():
            return coffee.FunCall('y0', expression(arg, parameters))
        elif nu == gem.one:
            return coffee.FunCall('y1', expression(arg, parameters))
    return coffee.FunCall(name,
                          *[expression(c, parameters) for c in expr.children])
コード例 #2
0
def _expression_mathfunction(expr, ctx):

    from tsfc.coffee import math_table

    math_table = math_table.copy()
    math_table['abs'] = ('abs', 'cabs')

    complex_mode = int(is_complex(ctx.scalar_type))

    # Bessel functions
    if expr.name.startswith('cyl_bessel_'):
        if complex_mode:
            msg = "Bessel functions for complex numbers: missing implementation"
            raise NotImplementedError(msg)
        nu, arg = expr.children
        nu_thunk = lambda: expression(nu, ctx)
        arg_loopy = expression(arg, ctx)
        if expr.name == 'cyl_bessel_j':
            if nu == gem.Zero():
                return p.Variable("j0")(arg_loopy)
            elif nu == gem.one:
                return p.Variable("j1")(arg_loopy)
            else:
                return p.Variable("jn")(nu_thunk(), arg_loopy)
        if expr.name == 'cyl_bessel_y':
            if nu == gem.Zero():
                return p.Variable("y0")(arg_loopy)
            elif nu == gem.one:
                return p.Variable("y1")(arg_loopy)
            else:
                return p.Variable("yn")(nu_thunk(), arg_loopy)

        # Modified Bessel functions (C++ only)
        #
        # These mappings work for FEniCS only, and fail with Firedrake
        # since no Boost available.
        if expr.name in ['cyl_bessel_i', 'cyl_bessel_k']:
            name = 'boost::math::' + expr.name
            return p.Variable(name)(nu_thunk(), arg_loopy)

        assert False, "Unknown Bessel function: {}".format(expr.name)

    # Other math functions
    name = math_table[expr.name][complex_mode]
    if name is None:
        raise RuntimeError("{} not supported in complex mode".format(expr.name))

    return p.Variable(name)(*[expression(c, ctx) for c in expr.children])
コード例 #3
0
ファイル: loopy.py プロジェクト: jmv2009/tsfc
def _expression_mathfunction(expr, ctx):
    if expr.name.startswith('cyl_bessel_'):
        # Bessel functions
        if is_complex(ctx.scalar_type):
            raise NotImplementedError("Bessel functions for complex numbers: "
                                      "missing implementation")
        nu, arg = expr.children
        nu_ = expression(nu, ctx)
        arg_ = expression(arg, ctx)
        # Modified Bessel functions (C++ only)
        #
        # These mappings work for FEniCS only, and fail with Firedrake
        # since no Boost available.
        if expr.name in {'cyl_bessel_i', 'cyl_bessel_k'}:
            name = 'boost::math::' + expr.name
            return p.Variable(name)(nu_, arg_)
        else:
            # cyl_bessel_{jy} -> {jy}
            name = expr.name[-1:]
            if nu == gem.Zero():
                return p.Variable(f"{name}0")(arg_)
            elif nu == gem.one:
                return p.Variable(f"{name}1")(arg_)
            else:
                return p.Variable(f"{name}n")(nu_, arg_)
    else:
        if expr.name == "ln":
            name = "log"
        else:
            name = expr.name
        # Not all mathfunctions apply to complex numbers, but this
        # will be picked up in loopy. This way we allow erf(real(...))
        # in complex mode (say).
        return p.Variable(name)(*(expression(c, ctx) for c in expr.children))
コード例 #4
0
ファイル: coffee.py プロジェクト: blechta/tsfc
def _expression_mathfunction(expr, parameters):
    name_map = {
        'abs': 'fabs',
        'ln': 'log',

        # Bessel functions
        'cyl_bessel_j': 'jn',
        'cyl_bessel_y': 'yn',

        # Modified Bessel functions (C++ only)
        #
        # These mappings work for FEniCS only, and fail with Firedrake
        # since no Boost available.
        'cyl_bessel_i': 'boost::math::cyl_bessel_i',
        'cyl_bessel_k': 'boost::math::cyl_bessel_k',
    }
    complex_name_map = {
        'ln': 'clog',
        'conj': 'conj'
        # TODO: Are there different complex Bessel Functions?
    }
    if parameters.scalar_type == 'double complex':
        name = complex_name_map.get(expr.name, expr.name)
        if name in {
                'sin', 'cos', 'tan', 'sqrt', 'exp', 'abs', 'sinh', 'cosh',
                'tanh', 'sinh', 'acos', 'asin', 'atan', 'real', 'imag'
        }:
            name = 'c' + expr.name
    else:
        name = name_map.get(expr.name, expr.name)
    if name == 'jn':
        nu, arg = expr.children
        if nu == gem.Zero():
            return coffee.FunCall('j0', expression(arg, parameters))
        elif nu == gem.one:
            return coffee.FunCall('j1', expression(arg, parameters))
    if name == 'yn':
        nu, arg = expr.children
        if nu == gem.Zero():
            return coffee.FunCall('y0', expression(arg, parameters))
        elif nu == gem.one:
            return coffee.FunCall('y1', expression(arg, parameters))
    return coffee.FunCall(name,
                          *[expression(c, parameters) for c in expr.children])
コード例 #5
0
def _expression_mathfunction(expr, parameters):
    complex_mode = int(is_complex(parameters.scalar_type))

    # Bessel functions
    if expr.name.startswith('cyl_bessel_'):
        if complex_mode:
            msg = "Bessel functions for complex numbers: missing implementation"
            raise NotImplementedError(msg)
        nu, arg = expr.children
        nu_thunk = lambda: expression(nu, parameters)
        arg_coffee = expression(arg, parameters)
        if expr.name == 'cyl_bessel_j':
            if nu == gem.Zero():
                return coffee.FunCall('j0', arg_coffee)
            elif nu == gem.one:
                return coffee.FunCall('j1', arg_coffee)
            else:
                return coffee.FunCall('jn', nu_thunk(), arg_coffee)
        if expr.name == 'cyl_bessel_y':
            if nu == gem.Zero():
                return coffee.FunCall('y0', arg_coffee)
            elif nu == gem.one:
                return coffee.FunCall('y1', arg_coffee)
            else:
                return coffee.FunCall('yn', nu_thunk(), arg_coffee)

        # Modified Bessel functions (C++ only)
        #
        # These mappings work for FEniCS only, and fail with Firedrake
        # since no Boost available.
        if expr.name in ['cyl_bessel_i', 'cyl_bessel_k']:
            name = 'boost::math::' + expr.name
            return coffee.FunCall(name, nu_thunk(), arg_coffee)

        assert False, "Unknown Bessel function: {}".format(expr.name)

    # Other math functions
    name = math_table[expr.name][complex_mode]
    if name is None:
        raise RuntimeError("{} not supported in complex mode".format(
            expr.name))
    return coffee.FunCall(name,
                          *[expression(c, parameters) for c in expr.children])