Length of vectors in `plot_vector_field3d()`

83 views
Skip to first unread message

Niranjana K M

unread,
Jun 19, 2022, 6:26:55 AM6/19/22
to sage-devel
Dear all,
    I tried to plot constant vector fields.
plot_vector_field3d((1,0,0), (x,-2,2), (y,-2,2), (z,-2,2))
    and
plot_vector_field3d((2,0,0), (x,-2,2), (y,-2,2), (z,-2,2))
    Length of the arrows of first one are equal to the second one. I expect that the length of arrows in second to be double that of the first. Also their lengths are not equal to their magnitudes.
    Is it a bug? If it is the normal behavior, then any work around to have length of the arrows to be equal to that of the magnitudes of the vectors in the field.

PS : The following shows vectors in the filed have their lengths equal to their magnitudes. As expected.
plot_vector_field3d((x,0,0), (x,-2,2), (y,-2,2), (z,-2,2))

With regards
Niranjana

Niranjana K M

unread,
Jun 19, 2022, 7:38:11 AM6/19/22
to sage-devel
Dear all,
    I figured it out. It  has to do with
scaled_vectors = [v/max_len for v in vectors]
line 141 of  $SAGE_ROOT/local/var/lib/sage/venv-python3.9/lib/python3.9/site-packages/sage/plot/plot3d/plot_field3d.py
Can we have scaling optional in sage? I just propose it, with a new keyword argument default with `scaled=True`.
if scaled:
    scaled_vectors = [v/max_len for v in vectors]
else:
    scaled_vectors = vectors
I can sense the consequences, when `scaled=False` and when the vector field is such that the vector lengths are too large to over print on the vectors ahead of them. At user's  risk, if he really wants them not to be scaled and can play with range and plot_points to avoid overprinting.

PS 1: I was trying to demonstrate and calculate electric flux through a hemisphere with constant field. While plotting the constant field i felt them not to be scaled.
PS 2: I thank and appreciate sage community for bringing out such a wonderful software. I have been following it since last 10+ years, since version 3.  I am really excited while exploring the section Differential Geometry of Parametrized Surfaces and sections on Manifolds, to see how Sage grew from missing functions to manifolds. I just loved it.

with regards,
Niranjana

Vincent Delecroix

unread,
Jun 19, 2022, 8:22:28 AM6/19/22
to sage-devel
Nice catch indeed. I am not sure that "scaled=True/False" is the most
flexible design. You might just want to apply *some* scale, not
necessarily the one making the max length being one. I imagine that it
would be nice to allow "scaled" to be a positive floating point
number. In other words

if scaled is True: # boolean
scaled_vectors = [v/max_len for v in vectors]
elif scaled is False: # boolean
scaled_vectors = vectors
else: # assume that scaled is a ratio
scaled = float(scaled)
assert scaled > 0
scaled_vectors = [v / scaled for v in vectors]

What do you think?

Do you know how to open a ticket on https://trac.sagemath.org? Details
are in the developer guide
(https://doc.sagemath.org/html/en/developer/index.html).

Best
Vincent
> --
> You received this message because you are subscribed to the Google Groups "sage-devel" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sage-devel/facb394b-bd32-40fc-9c59-60eff0deaa02n%40googlegroups.com.

Eric Gourgoulhon

unread,
Jun 19, 2022, 10:12:08 AM6/19/22
to sage-devel
Hi,

There is no such length issue if you use vector fields on the Euclidean 3-space, instead of plot_vector_field3d with a tuple of components. For instance:

sage: E.<x,y,z> = EuclideanSpace()
sage: v1 = E.vector_field(1, 0, 0)
sage: v2 = E.vector_field(2, 0, 0)
sage: v1.plot()
sage: v2.plot()

yields 3d plots with arrows for v2 twice longer than those for v1, as you can check by running

sage: v1.plot() + v2.plot(color='red')

Note that the plot() method of vector fields has the optional argument "scale" to control the length of the arrows:

sage: v1.plot(scale=2)

yields the same plot as v2.plot()

Note also that the default coordinate range for the plot is (-8, 8). To use (-2, 2) as in your example, run

sage: v1.plot(max_range=2, scale=0.5)

which is a shortcut for

sage: v1.plot(ranges={x: (-2, 2), y: (-2, 2), z: (-2, 2)}, scale=0.5)


Side remark: plots of vector fields are much faster with Sage 9.6 than with previous versions.

Best wishes,

Eric.

Niranjana K M

unread,
Jun 19, 2022, 11:55:53 AM6/19/22
to sage-devel
@Vincent

On Sunday, June 19, 2022 at 5:52:28 PM UTC+5:30 vdelecroix wrote:
Nice catch indeed. I am not sure that "scaled=True/False" is the most
flexible design. You might just want to apply *some* scale, not
necessarily the one making the max length being one. I imagine that it
would be nice to allow "scaled" to be a positive floating point
number. In other words

if scaled is True: # boolean
scaled_vectors = [v/max_len for v in vectors]
elif scaled is False: # boolean
scaled_vectors = vectors
else: # assume that scaled is a ratio
scaled = float(scaled)
assert scaled > 0
scaled_vectors = [v / scaled for v in vectors]

What do you think?

That will be nice. The same effect can be obtained by multiplying the vector components by scaling factor and plot them with scaled=False.
 

Do you know how to open a ticket on https://trac.sagemath.org? Details
are in the developer guide
(https://doc.sagemath.org/html/en/developer/index.html).

I don't know how to open a ticket. I will see the guide.
 

Niranjana K M

unread,
Jun 19, 2022, 1:11:24 PM6/19/22
to sage-devel
@Eric

That's very nice. Thanks for pointing towards sage manifold. I am also on 9.6.

It seems  E.vector_field().plot( method is much slower than plot_vector_field3d(). Check once with time().
Internally plot_vector_field3d() uses a  plot() function, may be different from this from sage manifolds.

sage:    time(E.vector_field(4, 0, 0).plot(number_values=4))
CPU times: user 4.07 s, sys: 83.6 ms, total: 4.15 s Wall time: 3.84 s

sage:   time(plot_vector_field3d((4,0,0), (x,-8,8), (y,-8,8), (z,-8,8), scaled=False, plot_points=4, colors='blue'))
CPU times: user 54.1 ms, sys: 42 µs, total: 54.2 ms Wall time: 51.2 ms

With plot_vector_field3d() the vector lines go on becoming thin as length increases and thick for small size.
E.vector_field().plot() uses lines of constant thickness irrespective of size.
While exploring on setting line thickness I found both are using different plot methods.

For plot_vector_field3d() Reference says:
 -- any other keywords are passed on to the plot command for each arrow.
Eg: thickness=4 like that of 2d plot() command.

For plot() in sage manifold Reference says:
**extra_options – extra options for the arrow plot, like linestyle, width or arrowsize (see arrow2d() and arrow3d() for details)
Eg: width=6

Does this make speed difference or is it due to E.vector_field() ?

Eric Gourgoulhon

unread,
Jun 19, 2022, 4:28:27 PM6/19/22
to sage-devel
Le dimanche 19 juin 2022 à 19:11:24 UTC+2, niran...@gmail.com a écrit :

For plot() in sage manifold Reference says:
**extra_options – extra options for the arrow plot, like linestyle, width or arrowsize (see arrow2d() and arrow3d() for details)
Eg: width=6

Does this make speed difference or is it due to E.vector_field() ?

The speed difference is due to a very different implementation of VectorField.plot() as compared to plot_vector_field3d():  at each point of the mesh, a tangent vector is created and the method TangentVector.plot() is called. See
This is far from optimal but this offers a greater flexibility, for instance plotting vector fields on non-rectangular meshes, like vector fields on an submanifold or along a curve, see e.g.
for some examples.
Some performance improvements have been implemented in Sage 9.6 thanks to Marius Gerbershagen, cf.
but there is room for further significative improvements, by getting rid of the call to TangentVector.plot(). This is on the to do list...
Any volunteer is welcome...

Eric.


Niranjana K M

unread,
Jun 20, 2022, 12:01:12 PM6/20/22
to sage-...@googlegroups.com
@Vincent

On Sun, Jun 19, 2022 at 5:52 PM Vincent Delecroix <20100.d...@gmail.com> wrote:
Nice catch indeed. I am not sure that "scaled=True/False" is the most
flexible design. You might just want to apply *some* scale, not
necessarily the one making the max length being one. I imagine that it
would be nice to allow "scaled" to be a positive floating point
number. In other words

if scaled is True: # boolean
    scaled_vectors = [v/max_len for v in vectors]
elif scaled is False: # boolean
    scaled_vectors = vectors
else: # assume that scaled is a ratio
    scaled = float(scaled)
    assert scaled > 0
    scaled_vectors = [v / scaled for v in vectors]

What do you think?
 
Nice. It will implement scaling as available in vector_field().plot(). Let the scaling be a factor multiplication (it will avoid dividing by 0 if scaled=0) and let it be positive or negative (for which the arrows reverse in direction).
Is it necessary to convert scaled into a float? Any real number is fine to multiply.
A slight modified version:

if scaled is True: # boolean
    scaled_vectors = [v/max_len for v in vectors]
elif scaled is False: # boolean
    scaled_vectors = vectors
else: # assume that scaled is a real number
    #scaled = float(scaled)
    assert scaled in RR
    scaled_vectors = [v*scaled for v in vectors]

Do you know how to open a ticket on https://trac.sagemath.org? Details
are in the developer guide
(https://doc.sagemath.org/html/en/developer/index.html).


I read the guide. Shall I open a ticket?


Vincent Delecroix

unread,
Jun 20, 2022, 5:27:11 PM6/20/22
to sage-devel
I think it is desirable to use the same argument conventions as the
method VectorField.plot(). In particular use `scale` and not `scaled`.
I don't know whether VectorField.plot() supports a default rescaling
as you proposed.

>> Do you know how to open a ticket on https://trac.sagemath.org? Details
>> are in the developer guide
>> (https://doc.sagemath.org/html/en/developer/index.html).
>>
>
> I read the guide. Shall I open a ticket?

Sure. You can go on. Don't forget to mention the ticket number you
open in this e-mail discussion.

Best
Vincent

Niranjana K M

unread,
Jun 21, 2022, 2:58:06 AM6/21/22
to sage-...@googlegroups.com
@Vincent
 
I think it is desirable to use the same argument conventions as the
method VectorField.plot(). In particular use `scale` and not `scaled`.
I don't know whether VectorField.plot() supports a default rescaling
as you proposed.

Ok let us change into `scale`. Also I have a new version of it. scale='auto' (a string, not a real number) be the default keyword and the code be:

    if scale in RR:
        scaled_vectors = [v*scale for v in vectors]
    else: # For `scale` is anything other than real
        max_len = max(v.norm() for v in vectors)

        scaled_vectors = [v/max_len for v in vectors]
Sure. You can go on. Don't forget to mention the ticket number you
open in this e-mail discussion.
 
I have opened a ticket for this. Check it out once.


Regards
Niranjana
Reply all
Reply to author
Forward
0 new messages