Opened 10 years ago

Closed 4 years ago

#3021 closed enhancement (fixed)

add curl and divergence functions to vectors

Reported by: jason Owned by: was
Priority: major Milestone: sage-6.4
Component: calculus Keywords:
Cc: eviatarbach Merged in:
Authors: Robert Bradshaw Reviewers: Eviatar Bach, Samuel Lelièvre, Travis Scrimshaw
Report Upstream: N/A Work issues:
Branch: 7b49240 (Commits) Commit: 7b49240972f369a441432b2e2736b9dbc65d1337
Dependencies: Stopgaps:

Description

Make curl work if the vector has 2 or 3 components. Is there a higher-dimensional analogue for curl?

Change History (30)

comment:1 Changed 10 years ago by jason

(After some discussion on IRC) It seems that Sage is really lacking in the differential geometry area. If some good work is done there, this request will likely automatically be satisfied.

A short term solution would be to write a vector field class.

comment:2 Changed 9 years ago by ncalexan

# a possible implementation of div, for irc user hedgehog

var('x, y, z')
(x, y, z)
f1 = x^2 + 2*y; f2 = x^3 + sin(z); f3 = y*z + 2
F = vector([f1, f2, f3])

print F(x=0, y=2, z=3)

def _variables(F):
    # this is a little funky -- we're finding all the variables that occur
    # in the components of F, and somehow choosing an ordering.  There are
    # other (better ways) but I'm not sure what the correct interface is.
    # For now, the user can specify the variables if they choose, just
    # like the gradient method.
    variables = list(set(flatten([ list(f.variables()) for f in F ])))
    variables.sort()
    return variables

def div(F, variables=None):
    assert len(F) == 3
    if variables is None:
        variables = _variables(F)

    s = 0
    for i in range(len(F)):
        s += F[i].derivative(variables[i])
    return s

print F
print div(F)
print div(F, variables=(y, x, z))

def curl(F, variables=None):
    assert len(F) == 3
    if variables is None:
        variables = _variables(F)
    assert len(variables) == 3
    x, y, z = variables
    Fx, Fy, Fz = F
    i = Fz.derivative(y) - Fy.derivative(z)
    j = Fz.derivative(z) - Fx.derivative(x)
    k = Fy.derivative(x) - Fz.derivative(y)
    return vector([i, j, k])
    
print curl(F)
print curl(F, variables=(y, x, z))

# let's assert that div(curl) == 0
# we need the variables because the ordering is suspect otherwise: for me,
# sage: _variables(F)
# [x, y, z]
# sage: _variables(curl(F))
# [z, x, y]
assert div(curl(F, variables=(x, y, z)), variables=(x, y, z)) == 0

comment:3 Changed 8 years ago by jason

  • Report Upstream set to N/A

See #5506 for a collection of things to add to a symbolic vectors class

comment:4 Changed 8 years ago by robertwb

There is a 7-dim curl. Why doesn't the generic vector one work?

comment:5 Changed 8 years ago by jason

  • Summary changed from add curl and divergence functions to symbolic vectors to add curl and divergence functions to vectors

What generic curl (I don't think it's in Sage right now)? Or are you saying we should just add curl to generic vectors? I agree; no reason to add this to just the callable symbolic vectors class (what was I thinking?).

comment:6 Changed 7 years ago by ddrake

Note that in the code above, it should be:

k = Fy.derivative(x) - Fx.derivative(y)

The "Fz" should be "Fx".

comment:7 Changed 7 years ago by robert.marik

Also

 j = Fx.derivative(z) - Fz.derivative(x)

comment:8 Changed 5 years ago by jdemeyer

  • Milestone changed from sage-5.11 to sage-5.12

comment:9 Changed 5 years ago by vbraun_spam

  • Milestone changed from sage-6.1 to sage-6.2

comment:10 Changed 5 years ago by eviatarbach

  • Cc eviatarbach added

comment:11 Changed 4 years ago by robertwb

  • Branch set to u/robertwb/ticket/3021
  • Modified changed from 03/11/14 07:34:59 to 03/11/14 07:34:59

comment:12 follow-up: Changed 4 years ago by robertwb

  • Commit set to 4e34d0d90624c54e233be003c460c3bbaf6e3dcf
  • Status changed from new to needs_review

New commits:

4e34d0dAdd divergence and curl to vectors.

comment:13 Changed 4 years ago by eviatarbach

I was just going to work on this today!

I haven't tested the code, but looks good. Just a few things:

  1. Is there any reason why you're converting the variables to their string representations in ._variables()?
  2. The parameter in Expression.gradient is called variables; I think it would be good to switch vars to variables for consistency.
  3. I think there should be test(s) for .curl() with the variables parameter.
  4. I believe the raise TypeError, "curl only defined for 3 dimensions" syntax is deprecated, and that the string should be passed as an argument.

comment:14 in reply to: ↑ 12 Changed 4 years ago by slelievre

Nitpicking on the error message in div: I would change it from "variable list must be equal to the dimension of self" to "number of variables must equal dimension of self".

About point 4 in eviatarbach's comment:

  • A reference for the change in exception raising syntax is PEP-3109.
  • the ValueError in div on follows the new syntax. By contrast, both the TypeError and ValueError in curl follow the old syntax.

comment:15 Changed 4 years ago by slelievre

More nitpicking:

  • Use "Return" instead of "Returns" in docstrings, see PEP 0257:

The docstring is a phrase ending in a period. It prescribes the function or method's effect as a command ("Do this", "Return that"), not as a description; e.g. don't write "Returns the pathname ...".

  • Should there be a docstring and tests for the _variables function?
  • In examples for div, remove extra space before w in R.<x,y,z, w> = QQ[]

comment:16 Changed 4 years ago by eviatarbach

Another thought:

The extracting of variables from each element and then sorting by name looks scary, and can give unexpected results (if your vector is (x1, x10, x2), I believe you would get 3 for the divergence instead of 1 as you might expect, since '10' comes before '2' in the alphanumeric sort). Unless there's a better solution, I think we should have it so that the variables list has to always be given explicitly.

Last edited 4 years ago by eviatarbach (previous) (diff)

comment:17 follow-up: Changed 4 years ago by jason

If your vectors are callable symbolic vectors, you should be able to get the list of arguments from the base ring (since you've already explicitly given an order to the variables):

sage: f(x,y,z)=(x*y,y*z,z^2)
sage: f
(x, y, z) |--> (x*y, y*z, z^2)
sage: type(f)
<class 'sage.modules.vector_callable_symbolic_dense.Vector_callable_symbolic_dense'>
sage: f.base_ring().arguments()
(x, y, z)

comment:18 in reply to: ↑ 17 Changed 4 years ago by eviatarbach

That's a great idea. I think we should have that for callable vectors.

For the record, Mathematica and Maple both have default coordinate systems, which is how they deal with this issue.

comment:19 Changed 4 years ago by vbraun_spam

  • Milestone changed from sage-6.2 to sage-6.3

comment:20 Changed 4 years ago by git

  • Commit changed from 4e34d0d90624c54e233be003c460c3bbaf6e3dcf to f353c94832b7ddd0b76d18eba32a1dd5440c3a8e

Branch pushed to git repo; I updated commit sha1. New commits:

f353c94Missing doctest.

comment:21 Changed 4 years ago by git

  • Commit changed from f353c94832b7ddd0b76d18eba32a1dd5440c3a8e to 8ab298e3617a2a803db07f27ad6515a1a8551821

Branch pushed to git repo; I updated commit sha1. New commits:

ae901d1Merge tag '6.2' into div-curl
8ab298eAddress reviewer comments.

comment:22 Changed 4 years ago by robertwb

I've addressed all the comments.

comment:23 Changed 4 years ago by vbraun_spam

  • Milestone changed from sage-6.3 to sage-6.4

comment:24 follow-up: Changed 4 years ago by kcrisman

I was going to look at this, but looks like Eviatar and Samuel are on top, so just think of this as a ping :)

comment:25 in reply to: ↑ 24 Changed 4 years ago by robertwb

Replying to kcrisman:

I was going to look at this, but looks like Eviatar and Samuel are on top, so just think of this as a ping :)

Feel free to look at this yourself :)

comment:26 Changed 4 years ago by tscrim

My 2 cents, I'd have curl also take 2-dim inputs and return a vector. It might also be a good idea for a way (likely another method) which takes a 2-dim input and return a scalar as a shorthand (a la Green's theorem).

+1 to getting these (fundamental) methods into Sage.

comment:27 Changed 4 years ago by robertwb

Are there any enhancements to this with-patch, 7-year-old ticket that simply can't be deferred 'till later so we can finally get this in?

comment:28 Changed 4 years ago by tscrim

  • Authors set to Robert Bradshaw
  • Branch changed from u/robertwb/ticket/3021 to u/tscrim/curl_divergence-3021
  • Commit changed from 8ab298e3617a2a803db07f27ad6515a1a8551821 to 7b49240972f369a441432b2e2736b9dbc65d1337
  • Reviewers set to Eviatar Bach, Samuel Lelièvre, Travis Scrimshaw

I added the 2-dim input. If you're happy with my changes, then I think we can set this to a positive review.


New commits:

0de71acMerge branch 'u/robertwb/ticket/3021' of trac.sagemath.org:sage into u/tscrim/curl_divergence-3021
7b49240Added 2-dim curl which returns a scalar value.

comment:29 Changed 4 years ago by robertwb

  • Status changed from needs_review to positive_review

comment:30 Changed 4 years ago by vbraun

  • Branch changed from u/tscrim/curl_divergence-3021 to 7b49240972f369a441432b2e2736b9dbc65d1337
  • Resolution set to fixed
  • Status changed from positive_review to closed
Note: See TracTickets for help on using tickets.