Ask Your Question

Basic work on tensor components

asked 2018-04-20 15:26:41 -0500

Patrick gravatar image

My SageManifolds notebooks typically start with a bunch of home made function designed to access components of tensors. But they are based on a common hacky function relying on very shallow understanding of the internals of SageManifolds. Am I missing some builtin equivalent? What is the proper way of doing this?

def maps(fun, tensor):
    """ Applies fun to all components of a copy of tensor """
    res = tensor.copy()
    if tensor.tensor_type() == (0, 0):
        for k, v in res._express.items():
            res._express[k] = k.function(fun(v.expr()))
        for k, v in res.comp()._comp.items():
            res.comp()._comp[k] = res.domain().scalar_field(fun(v.expr()))
    return res

def simp(tensor):
    return maps(lambda f: simplify(f), tensor)

def dev(tensor):
    return maps(lambda f: expand(f), tensor)

def factorize(tensor):
    return maps(lambda f: factor(f), tensor)

def subs(tensor, d):
    return maps(lambda f: f.subs(d), tensor)


edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted

answered 2018-04-22 15:30:21 -0500

eric_g gravatar image

For the moment, there is no builtin equivalent. Your way of implementing this is basically correct. However, I would not perform the loop on res but rather on tensor, in order to avoid looping on the items of a dictionary while modifying it, especially when items() becomes an iterator in Python3. Moreover, one can replace

res._express[k] = k.function(fun(v.expr()))


res.add_expr(fun(v.expr()), chart=k)

and one can use recursivity to simplify the tensor part, i.e. replace

res.comp()._comp[k] = res.domain().scalar_field(fun(v.expr()))


res.comp()._comp[k] = maps(fun, v)

Finally, the tensor part of your code is valid only for the manifold's default frame (because res.comp() returns the components with respect to that frame). It can easily be generalized to any frame by adding the argument frame=None to maps and replacing comp() by comp(frame).

With the above changes, the code becomes:

def maps(fun, tensor, frame=None):
    """ Applies fun to all components of a copy of tensor """
    res = tensor.copy()
    if tensor.tensor_type() == (0, 0):
        for k, v in tensor._express.items():
            res.add_expr(fun(v.expr()), chart=k)
        for k, v in tensor.comp(frame)._comp.items():
            res.comp(frame)._comp[k] = maps(fun, v)
    return res
edit flag offensive delete link more


Thank you very much! I think it would make sense to add this to the lib (as well as a method doing this in place instead of a root namespace function returning a new object). I use SageManifolds only when computations are complicated, and then I always need simplify and his friends expand and factor.

Patrick gravatar imagePatrick ( 2018-04-23 01:54:01 -0500 )edit

Indeed, this would make sense. Note that internally, all tensor computations use simplifications according to this simplifying sequence. But this does not involve factor for instance, nor any specific substitution. Would you agree to create a ticket implementing this? (see e.g. these possible guide lines)

eric_g gravatar imageeric_g ( 2018-04-24 07:14:05 -0500 )edit
eric_g gravatar imageeric_g ( 2020-02-24 05:04:46 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower


Asked: 2018-04-20 15:26:41 -0500

Seen: 149 times

Last updated: Apr 22 '18