If you want to give the fields names I guess you should use
UndefinedFunction. Note that UndefinedFunction('f') dynamically creates a
subclass of AppliedUndef called "f".I think what you are doing is right, although let us know if you run into issues (SymPy has many bugs where things don't work correctly if you subclass things). It's clear to me that we should make this sort of thing easier, though. Aaron Meurer On Thu, Feb 4, 2016 at 7:49 PM, Bogdan Opanchuk <[email protected]> wrote: > Hello, > > I have a question about best practices in subclassing sympy. If there is a > good tutorial out there, I would be grateful for a direction, but I could > not find anything myself. The explanation of what I'm trying to achieve is > somewhat lengthy. > > I would like to use sympy to declare differential equations that are later > fed to a numerical solver. To simplify things for users, I want to have two > kinds of objects: > > Dimension: > - behaves like a Symbol with respect to sympy algorithms and printing > - carries additional attributes (in particular, the parameters of the > associated grid) > - the equality for these objects is checked based on the name _and_ the > attributes > > For instance, one would define > x = Dimension('x', 0, 1, 50) # a dimension 'x' with the grid of 50 points > on [0, 1] > y = Dimension('y', 0, 1, 50) > x2 = Dimension('x', 0, 1, 20) > xp = Dimension('x', 0, 1, 50) > > For all sympy algorithms the relation between `x` and `y` (or `x2`) is the > same as the relation between `Symbol('x')` and `Symbol('y')` (or > `Symbol('x2')`), and the relation between `x` and `xp` is the same as the > relation between `Symbol('x')` and `Symbol('x')` (that is, they're the same > object). > > Field: > - is initialized with a list of Dimension objects, which denote its > "native" dimensions (similarly to how one would write "f = f(x, y, t)" in a > paper) > - in sympy expressions behaves just as an undefined function called with > its native dimensions > > That is, if we have `f = Field('f', x, y)`, we can write, say `(f + > x).diff(x)` which will be equivalent to `(f(x, y) + x).diff(x)` > > - the equality is checked based on the name _and_ the list of native > dimensions > - it can be applied like a Function object; the resulting object still > carries around the original object's set of native dimensions > > In other words, if I have `f = Field('f', x, y)`, I can use `f(xp, y)` in > an expression, but I should be able to obtain the references to `x` and `y` > from it during the traversal. > > - during the application some arbitrary error-checking may be executed (I > just want to be able to intercept such an event, for example, to check that > integer dimensions are used for integer dimensions etc) > - optionally, a field not applied to anything, or applied to its "native" > dimensions is printed just as its name > > > I was able to implement a Dimension object (based on the implementation of > Symbol) as > > import numpy > from sympy import Symbol > from sympy.core.cache import cacheit > > class Dimension(Symbol): > > def __new_stage2__(cls, name, start, stop, points): > obj = super(Dimension, cls).__xnew__(cls, name, real=True) > obj.params = (start, stop, points) > obj.grid = numpy.linspace(start, stop, points, endpoint=False) > return obj > > def __new__(cls, name, *args, **kwds): > obj = Dimension.__xnew_cached_(cls, name, *args, **kwds) > return obj > > __xnew__ = staticmethod(__new_stage2__) > __xnew_cached_ = staticmethod(cacheit(__new_stage2__)) > > def _hashable_content(self): > return (Symbol._hashable_content(self), self.params) > > which seems to behave in the required way. I am still unclear how to > implement Field properly: should I subclass Function, or AppliedUndef, or > something else? Or am I doing something completely incompatible with > sympy's design? > > Thank you in advance. > > -- > You received this message because you are subscribed to the Google Groups > "sympy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at https://groups.google.com/group/sympy. > To view this discussion on the web visit > https://groups.google.com/d/msgid/sympy/4daad849-0456-4a85-9faf-fe930d75f161%40googlegroups.com > <https://groups.google.com/d/msgid/sympy/4daad849-0456-4a85-9faf-fe930d75f161%40googlegroups.com?utm_medium=email&utm_source=footer> > . > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "sympy" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/sympy. To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CAKgW%3D6LtCTrRLPf%3D60FoQWDQqmaJ2%2BetMguioW8FCRjCc3kMxw%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
