예제 #1
0
def init_eval(method, name):

    if (name not in method.inits_evals.keys() or
            method.inits_evals[name] is None):

        if VERBOSE >= 2:
            print('    Init value for {}'.format(name))

        if name in method.ops_names:
            obj = copy.copy(getattr(method, name+'_op'))
            sobj = eval_op(method, obj)
        elif name == 'y':
            obj = copy.copy(geteval(method, 'output'))
            sobj = substitute(obj, method.subscpp)
            sobj = numpy.asarray(sobj, dtype=float)
        else:
            obj = copy.copy(geteval(method, name))
            sobj = substitute(obj, method.subscpp)
            while not len(free_symbols(sobj)) == 0:
                sobjpre = copy.copy(sobj)
                sobj = substitute(sobj, method.subscpp)
                if sobj == sobjpre:
                    freesymbs = free_symbols(sobj)
                    text = 'Missing substitution symbols: {}'.format(freesymbs)
                    raise AttributeError(text)
            if not isinstance(sobj, (float, list)):
                sobj = numpy.asarray(sobj.tolist(), dtype=float)
            else:
                sobj = numpy.asarray(sobj, dtype=float)
        method.inits_evals[name] = sobj
예제 #2
0
    def o(self, ind=None, imin=None, imax=None, decim=None):
        """
o
==

Generator of values for observers.

Parameters
-----------
ind: int or None, optional
    Index of the observer. If None, values for every observers are
    returned (default).
imin: int or None, optional
    Starting index. If None, imin=0 (default).
imax: int or None,
    Stoping index. If None, imax=simu.config['nt'] (default).
decim: int or None,
    decimation factor. If None, decim = int(simu.config['nt']/1000) (default)

Returns
-------

ps_generator: generator
    A python generator of scalar discrete sources power value ps[i] for each
    time step i starting from index imin to index imax with decimation
    factor decim (i.e. the value is generated if i-imin % decim == 0), with
    ps[i] = u[i] dot y[i].

        """
        options = self.config['load']
        options = {
            'imin': options['imin'] if imin is None else imin,
            'imax': options['imax'] if imax is None else imax,
            'decim': options['decim'] if decim is None else decim
        }
        obs_expr = [
            e.subs(self.subs()) for e in self.method.observers.values()
        ]

        obs_symbs = free_symbols(obs_expr)
        index = len(self.method.args()) - len(obs_expr)

        obs_args, obs_inds = find(obs_symbs, self.method.args()[:index])

        obs = lambdify(obs_args, obs_expr, theano=self.config['theano'])
        obs_args = lambdify(self.method.args()[:index],
                            obs_args,
                            theano=self.config['theano'])

        if ind is None:
            for arg in self.args(**options):
                yield obs(*obs_args(*arg))
        else:
            for arg in self.args(**options):
                yield obs(*obs_args(*arg))[ind]
예제 #3
0
 def setfunc(self, name, expr=None):
     if VERBOSE >= 3:
         print('        Build {}'.format(name))
     if expr is None:
         expr = geteval(self, name)
     symbs = free_symbols(expr)
     args, inds = find(symbs, self.args())
     setattr(self, name + '_expr', expr)
     setattr(self, name + '_args', args)
     setattr(self, name + '_inds', inds)
     self.funcs_names.append(name)
예제 #4
0
 def setarg(self, name):
     if VERBOSE >= 3:
         print('        Build {}'.format(name))
     expr = geteval(self, name)
     # retrieve expr symbols
     symbs = free_symbols(expr)
     # retrieve ordered symbols (args) and indices in self.args
     args, inds = find(symbs, self.args())
     setattr(self, name + '_expr', expr)
     setattr(self, name + '_args', args)
     setattr(self, name + '_inds', inds)
     self.args_names.append(name)
예제 #5
0
    def pd(self, imin=None, imax=None, decim=None):
        """
pd
==

Generator of discrete dissipated power values.

Parameters
-----------
imin: int or None, optional
    Starting index. If None, imin=0 (default).
imax: int or None,
    Stoping index. If None, imax=simu.config['nt'] (default).
decim: int or None,
    decimation factor. If None, decim = int(simu.config['nt']/1000) (default)

Returns
-------

pd_generator: generator
    A python generator of scalar discrete dissipated power value pd[i] for each
    time step i starting from index imin to index imax with decimation
    factor decim (i.e. the value is generated if i-imin % decim == 0), with
    pd[i] = w[i] dot z[i].

        """
        options = self.config['load']
        options = {
            'imin': options['imin'] if imin is None else imin,
            'imax': options['imax'] if imax is None else imax,
            'decim': options['decim'] if decim is None else decim
        }

        R_expr = self.method.R().subs(self.subs())

        R_symbs = free_symbols(R_expr)

        R_args, R_inds = find(R_symbs, self.method.args())

        R = lambdify(R_args, R_expr, theano=self.config['theano'])
        R_args = lambdify(self.method.args(),
                          R_args,
                          theano=self.config['theano'])
        for w, z, a, b, args, o in zip(self.w(**options), self.z(**options),
                                       self.a(**options), self.b(**options),
                                       self.args(**options),
                                       self.o(**options)):
            yield scalar_product(w, z) + \
                scalar_product(a,
                               a,
                               R(*R_args(*(list(args)+list(o)))))
예제 #6
0
    def expr_to_numeric(core, name, allargs, theano=False, vectorize=True):
        """
        Return an evaluator of the function :code:`getarg(nums.method, names + '_expr')`,
        with a mapping to some of the arguments in :code:`nums.args`, using
        sympy or theano lambdification.

        Parameters
        ----------

        core : Core

        name : str

        theano : bool
        
        vectorize : bool

        Return
        ------

        func : function
            Evaluator
        """
        expr = geteval(core, name)
        if expr is not None:
            symbs = free_symbols(expr)
            args, inds = find(symbs, allargs)  # args are symbs reorganized
            func = lambdify(args, expr, subs=core.subs, theano=theano)
            func = numpy.vectorize(func)
            func.func_doc = """
    Evaluate `{0}`.

    Parameters
    ----------
    """.format(name) + ''.join(
                ["""
    {} : float
    """.format(str(a)) for a in args]) + """

    Return
    ------

    {0} : numpy array
        The numerical valuation of {0}.
            """.format(name)

        else:
            func, args, inds = None, None, None

        return func, args, inds
예제 #7
0
    def E(self, imin=None, imax=None, decim=None):
        """
E
===

Generator of discrete energy's values.

Parameters
-----------
imin: int or None, optional
    Starting index. If None, imin=0 (default).
imax: int or None,
    Stoping index. If None, imax=simu.config['nt'] (default).
decim: int or None,
    decimation factor. If None, decim = int(simu.config['nt']/1000) (default)

Returns
-------

E_generator: generator
    A python generator of scalar discrete energy's value E[i] for each time
    step i starting from index imin to index imax with decimation factor decim
    (i.e. the value is generated if i-imin % decim == 0).
        """
        options = self.config['load']
        options = {
            'imin': options['imin'] if imin is None else imin,
            'imax': options['imax'] if imax is None else imax,
            'decim': options['decim'] if decim is None else decim
        }

        H_expr = self.method.H.subs(self.method.subs)
        H_symbs = free_symbols(H_expr)
        H_args, H_inds = find(H_symbs, self.method.args())
        H = lambdify(H_args, H_expr, theano=self.config['theano'])
        H_args = lambdify(self.method.args(),
                          H_args,
                          theano=self.config['theano'])

        for args, o in zip(self.args(**options), self.o(**options)):
            a = (list(args) + list(o))
            yield H(*H_args(*a))
예제 #8
0
def lambdify(args, expr, subs=None, simplify=False, theano=True):
    """
lambdify
********
Returns a lambda function for numerical evaluation of symbolic expression
defined by :code:`expr` with arguments defined by :code:`args`. It basically
uses :code:`sympy.lambdify`, or :code:`theano` if available on the system.

Parameters
----------

args : list of sympy.Symbols
    Arguments symbols for the symbolic expression; defines also the number of
    arguments of the returned numeric function.

expr : sympy.Expr, list of sympy.Expr, or sympy.SparseMatrix.
    Symbolic expression to lambdify.

subs: dict (optional)
    If all the symbols in :code:`expr` are not in :code:`args`, the remaining
    numerical values for replacements must be provided in this dictionary, with
    :code:`subs={symb1: val1, ...}` with :code`symb1` a symbol and :code`val1`
    the numerical value (float or int).

simplify : bool (optional)
    If True, expression is simplified before lambdification (default is False).

theano : bool (optional)
    If True, expression is compiled with theano. Then it's a compromise between
    the time for compiling C code vs. the acceleration of numerical evaluation.
    The default is True.

Return
------

f : callable
    Fast evaluation of expr provided len(args) numerical values.
    """
    # Avoid side effects of simplifications and substitutions
    expr = copy.copy(expr)

    # Check for types
    types.is_known_test(expr)

    # Substitutions
    if subs is not None:
        expr = substitute(expr, subs)

    # Simplification
    if simplify:
        expr = simp(expr)

    # sympify expression so that floats and ints are converted to sympy.Expr
    # expr = sympify(expr)

    missing_symbols = free_symbols(expr).difference(args)
    if not len(missing_symbols) == 0:
        raise AttributeError('Missing free symbols {}'.format(missing_symbols))

    # Choose backend (theano or numpy)
    if isinstance(expr, types.matrix_types):
        expr_ = sympy.Matrix(expr)
    else:
        expr_ = expr
    if theano and got_theano:
        return theano_lambdify(args, expr_)
    else:
        return numpy_lambdify(args, expr_)
예제 #9
0
    def expr_to_numeric(core, name, allargs, theano=None, vectorize=True):
        """
        Return an evaluator of the function :code:`getarg(nums.method, names + '_expr')`,
        with a mapping to some of the arguments in :code:`nums.args`, using
        sympy or theano lambdification.

        Parameters
        ----------

        core : Core

        name : str

        theano : bool

        vectorize : bool

        Return
        ------

        func : function
            Evaluator
        """

        # set theano
        if theano is None:
            theano = THEANO

        # recover func from core
        expr = geteval(core, name)

        if expr is not None:

            # recover symbols from expr
            symbs = free_symbols(expr)

            # args are symbs reorganized
            args, inds = find(symbs, allargs)

            if isinstance(expr, types.vector_types):
                func = vector_expr_to_numeric(args,
                                              expr,
                                              subs=core.subs,
                                              theano=theano,
                                              vectorize=vectorize)
            else:
                func = scalar_expr_to_numeric(args,
                                              expr,
                                              subs=core.subs,
                                              theano=theano,
                                              vectorize=vectorize)

            func.__doc__ = """
    Evaluate `{0}`.

    Parameters
    ----------
    """.format(name) + ''.join(
                ["""
    {} : float
    """.format(str(a)) for a in args]) + """

    Return
    ------

    {0} : numpy array
        The numerical valuation of {0}.
            """.format(name)

        else:
            print('Expression {0} is None'.format(name))
            func, args, inds = None, None, None

        return func, args, inds
예제 #10
0
    def expr_to_numeric(core, name, allargs, theano=False, vectorize=True):
        """
        Return an evaluator of the function :code:`getarg(nums.method, names + '_expr')`,
        with a mapping to some of the arguments in :code:`nums.args`, using
        sympy or theano lambdification.

        Parameters
        ----------

        core : Core

        name : str

        theano : bool

        vectorize : bool

        Return
        ------

        func : function
            Evaluator
        """
        expr = geteval(core, name)
        if expr is not None:
            symbs = free_symbols(expr)
            args, inds = find(symbs, allargs)  # args are symbs reorganized
            f = lambdify(args, expr, subs=core.subs, theano=theano)

            # Cope with vector evaluation of functions with arguments
            if vectorize and len(args) > 0:
                func = numpy.vectorize(f)
            # Cope with vector evaluation of functions with no arguments
            elif vectorize and len(args) == 0:

                def func(*args):
                    if len(args) == 0:
                        return numpy.array(f())
                    elif isinstance(args[0], list):
                        return numpy.array([
                            f(),
                        ] * len(args[0]))
                    elif isinstance(args[0], numpy.ndarray):
                        return numpy.array([
                            f(),
                        ] * args[0].shape[0])
                    else:
                        return numpy.array(f())
            # No vectorization
            else:
                func = f

            func.func_doc = """
    Evaluate `{0}`.

    Parameters
    ----------
    """.format(name) + ''.join(
                ["""
    {} : float
    """.format(str(a)) for a in args]) + """

    Return
    ------

    {0} : numpy array
        The numerical valuation of {0}.
            """.format(name)

        else:
            print('Expression {0} is None'.format(name))
            func, args, inds = None, None, None

        return func, args, inds
예제 #11
0
def evalfunc_generator(nums, name):
    """
    Return an evaluator of the function :code:`getarg(nums.method, names + '_expr')`,
    with a mapping to some of the arguments in :code:`nums.args`, using
    sympy or theano lambdification.

    Parameters
    ----------

    nums : Numeric

    name : str

    Return
    ------

    func : function
        Evaluator
    """
    try:
        expr = getattr(nums.method, name + '_expr')
        args = getattr(nums.method, name + '_args')
        inds = getattr(nums.method, name + '_inds')
    except AttributeError:
        expr = geteval(nums.method, name)
        symbs = free_symbols(expr)
        args, inds = find(symbs, nums.method.args())

    func = lambdify(args,
                    expr,
                    subs=nums.method.subs,
                    theano=nums.config['theano'])

    if len(inds) > 0:
        inds = numpy.array(inds)
    else:
        inds = list()

    def eval_func():
        return func(*nums.args[inds])

    if isinstance(expr, core_types.scalar_types):
        num_types.scalar_test(eval_func())
    elif isinstance(expr, core_types.vector_types):
        num_types.vector_test(eval_func())
    elif isinstance(expr, core_types.matrix_types):
        num_types.matrix_test(eval_func())
    else:
        raise TypeError('Lambdified function output type not understood.')

    eval_func.__doc__ = """
        Evaluate :code:`{0}`.

        Return
        ------

        _{0} : numpy array
            The current evaluation of :code:`{0}`, with shape {1}.
    """.format(name,
               eval_func().shape)

    return eval_func
예제 #12
0
    def dtE(self, imin=None, imax=None, decim=None, DtE='DxhDtx'):
        """
dtE
===

Generator of discrete energy's time variation values.

Parameters
-----------
imin: int or None, optional
    Starting index. If None, imin=0 (default).
imax: int or None,
    Stoping index. If None, imax=simu.config['nt'] (default).
decim: int or None,
    decimation factor. If None, decim = int(simu.config['nt']/1000) (default)
DtE: str in {'deltaH', 'DxhDtx'}, optional
    Method for the computation of discrete energy's time variation. If DtE is
    'deltaH', the output with index i is (H[t[i+1]]-H[t[i]]) * samplerate. If
    DtE is 'DxhDtx', the output with index i is (dxH[i] dot dtx[i]).

Returns
-------

dtE_generator: generator
    A python generator of scalar discrete energy's time variation value DtE[i]
    for each time step i starting from index imin to index imax with decimation
    factor decim (i.e. the value is generated if i-imin % decim == 0).
        """
        options = self.config['load']
        options = {
            'imin': options['imin'] if imin is None else imin,
            'imax': options['imax'] if imax is None else imax,
            'decim': options['decim'] if decim is None else decim
        }

        if DtE == 'deltaH':
            H_expr = self.method.H.subs(self.method.subs)
            H_symbs = free_symbols(H_expr)
            H_args, H_inds = find(H_symbs, self.method.args())
            H = lambdify(H_args, H_expr, theano=self.config['theano'])
            H_args = lambdify(self.method.args(),
                              H_args,
                              theano=self.config['theano'])

            Hpost_expr = self.method.H.subs(self.subs())
            subs = {}
            for x, dx in zip(self.method.x, self.method.dx()):
                subs.update({x: x + dx})

            Hpost_expr = Hpost_expr.subs(subs)
            Hpost_symbs = free_symbols(Hpost_expr)
            Hpost_args, Hpost_inds = find(Hpost_symbs, self.method.args())
            Hpost = lambdify(Hpost_args,
                             Hpost_expr,
                             theano=self.config['theano'])
            Hpost_args = lambdify(self.method.args(),
                                  Hpost_args,
                                  theano=self.config['theano'])
            for args, o in zip(self.args(**options), self.o(**options)):
                a = (list(args) + list(o))
                yield (Hpost(*Hpost_args(*a)) -
                       H(*H_args(*a))) * self.config['fs']

        elif DtE == 'DxhDtx':
            for dtx, dxh in zip(self.dtx(**options), self.dxH(**options)):
                yield scalar_product(dtx, dxh)
예제 #13
0
    def expr_to_numeric(core, name, allargs, theano=False, vectorize=True):
        """
        Return an evaluator of the function :code:`getarg(nums.method, names + '_expr')`,
        with a mapping to some of the arguments in :code:`nums.args`, using
        sympy or theano lambdification.

        Parameters
        ----------

        core : Core

        name : str

        theano : bool

        vectorize : bool

        Return
        ------

        func : function
            Evaluator
        """
        expr = geteval(core, name)
        if expr is not None:
            symbs = free_symbols(expr)
            args, inds = find(symbs, allargs)  # args are symbs reorganized
            f = lambdify(args, expr, subs=core.subs,
                         theano=theano)

            # Cope with vector evaluation of functions with arguments
            if vectorize and len(args) > 0:
                func = numpy.vectorize(f)
            # Cope with vector evaluation of functions with no arguments
            elif vectorize and len(args) == 0:
                def func(*args):
                    if len(args) == 0:
                        return numpy.array(f())
                    elif isinstance(args[0], list):
                        return numpy.array([f(), ]*len(args[0]))
                    elif isinstance(args[0], numpy.ndarray):
                        return numpy.array([f(), ]*args[0].shape[0])
                    else:
                        return numpy.array(f())
            # No vectorization
            else:
                func = f

            func.func_doc = """
    Evaluate `{0}`.

    Parameters
    ----------
    """.format(name) + ''.join(["""
    {} : float
    """.format(str(a)) for a in args]) + """

    Return
    ------

    {0} : numpy array
        The numerical valuation of {0}.
            """.format(name)

        else:
            print('Expression {0} is None'.format(name))
            func, args, inds = None, None, None

        return func, args, inds
예제 #14
0
def lambdify(args, expr, subs=None, simplify=False, theano=True):
    """
lambdify
********
Returns a lambda function for numerical evaluation of symbolic expression
defined by :code:`expr` with arguments defined by :code:`args`. It basically
uses :code:`sympy.lambdify`, or :code:`theano` if available on the system.

Parameters
----------

args : list of sympy.Symbols
    Arguments symbols for the symbolic expression; defines also the number of
    arguments of the returned numeric function.

expr : sympy.Expr, list of sympy.Expr, or sympy.SparseMatrix.
    Symbolic expression to lambdify.

subs: dict (optional)
    If all the symbols in :code:`expr` are not in :code:`args`, the remaining
    numerical values for replacements must be provided in this dictionary, with
    :code:`subs={symb1: val1, ...}` with :code`symb1` a symbol and :code`val1`
    the numerical value (float or int).

simplify : bool (optional)
    If True, expression is simplified before lambdification (default is False).

theano : bool (optional)
    If True, expression is compiled with theano. Then it's a compromise between
    the time for compiling C code vs. the acceleration of numerical evaluation.
    The default is True.

Return
------

f : callable
    Fast evaluation of expr provided len(args) numerical values.
    """
    # Avoid side effects of simplifications and substitutions
    expr = copy.copy(expr)

    # Check for types
    types.is_known_test(expr)

    # Substitutions
    if subs is not None:
        expr = substitute(expr, subs)

    # Simplification
    if simplify:
        expr = simp(expr)

    # sympify expression so that floats and ints are converted to sympy.Expr
    # expr = sympify(expr)

    missing_symbols = free_symbols(expr).difference(args)
    if not len(missing_symbols) == 0:
        raise AttributeError('Missing free symbols {}'.format(missing_symbols))

    # Choose backend (theano or numpy)
    if isinstance(expr, types.matrix_types):
        expr_ = sympy.Matrix(expr)
    else:
        expr_ = expr
    if theano and got_theano:
        return theano_lambdify(args, expr_)
    else:
        return numpy_lambdify(args, expr_)