ASKSAGE: Sage Q&A Forum - RSS feedhttps://ask.sagemath.org/questions/Q&A Forum for SageenCopyright Sage, 2010. Some rights reserved under creative commons license.Sat, 13 Apr 2019 21:27:14 +0200Arrow length goes wild near poles in vector field plothttps://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/Running this piece of code
x, y = var('x y')
f = 1/sqrt(x^2 + y^2)
grad = f.gradient([x, y])
plot_vector_field(grad, (x, -1, 1), (y, -1, 1)).show()
gives me this
![image description](/upfiles/15551465192765043.png)
As you can see the arrows very close to the pole "cross out" the whole pic. Obviously they are very large vectors, but they do harm the overall image. I have other plots where its worse. How can I work around that? Can I blank out the direct proximity of the pole, somehow? Can I limit the vectors' length? How?Sat, 13 Apr 2019 11:11:53 +0200https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/Answer by rburing for <p>Running this piece of code</p>
<pre><code>x, y = var('x y')
f = 1/sqrt(x^2 + y^2)
grad = f.gradient([x, y])
plot_vector_field(grad, (x, -1, 1), (y, -1, 1)).show()
</code></pre>
<p>gives me this</p>
<p><img alt="image description" src="/upfiles/15551465192765043.png"></p>
<p>As you can see the arrows very close to the pole "cross out" the whole pic. Obviously they are very large vectors, but they do harm the overall image. I have other plots where its worse. How can I work around that? Can I blank out the direct proximity of the pole, somehow? Can I limit the vectors' length? How?</p>
https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?answer=46124#post-id-46124Yes, you can limit the proximity to the pole:
my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None,
lambda x,y: grad[1].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
![limit proximity to pole](/upfiles/15551480709763106.png)
or limit the length of the vectors:
my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None,
lambda x,y: grad[1].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
![limit vector length](/upfiles/15551480858493696.png)Sat, 13 Apr 2019 11:35:43 +0200https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?answer=46124#post-id-46124Comment by stockh0lm for <p>Yes, you can limit the proximity to the pole:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None,
lambda x,y: grad[1].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit proximity to pole" src="/upfiles/15551480709763106.png"></p>
<p>or limit the length of the vectors:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None,
lambda x,y: grad[1].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit vector length" src="/upfiles/15551480858493696.png"></p>
https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46125#post-id-46125neat! thank you, rburing! I do need to figure out those lambda functions...
Could you please explain a little what happens in those lambda functions? especially the .subs() is confusing to me. Also the "else None" seems to be the limitation and only happens if abs(x) + abs(y) exceed the limit, but how does it limit, really? it does not replace anything in that case, does it? Is my_grad just a copy of grad? and it only copies if it does not exceed? does the subs() only happen in case if() is true?
is it perhaps like this (in pseudo code): if (grad_len < 7) then (copy x and y), else (don't). why would you have two subs in the second case, not just one as in the first?Sat, 13 Apr 2019 12:50:00 +0200https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46125#post-id-46125Comment by rburing for <p>Yes, you can limit the proximity to the pole:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None,
lambda x,y: grad[1].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit proximity to pole" src="/upfiles/15551480709763106.png"></p>
<p>or limit the length of the vectors:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None,
lambda x,y: grad[1].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit vector length" src="/upfiles/15551480858493696.png"></p>
https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46130#post-id-46130Your `grad` is a pair of symbolic expressions; `my_grad` is a pair of functions of `x` and `y` (defined inline, using `lambda`). The function `plot_vector_field` accepts both forms; in the first case it substitutes numeric values into the expressions and in the second case it *calls* the functions with numeric arguments. The functions in `my_grad` return the same result as `grad` would (by substituting into the expressions), but when some condition is not satisfied they return `None` instead (which causes `plot_vector_field` not to plot the vector).
In the second example `subs()` is used in the condition, because it depends not just on the position (the numeric `x` and `y`) but also the vector length (i.e. on `grad` or `grad_len`, into which the numeric `x` and `y` are substituted).Sat, 13 Apr 2019 14:04:09 +0200https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46130#post-id-46130Comment by stockh0lm for <p>Yes, you can limit the proximity to the pole:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None,
lambda x,y: grad[1].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit proximity to pole" src="/upfiles/15551480709763106.png"></p>
<p>or limit the length of the vectors:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None,
lambda x,y: grad[1].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit vector length" src="/upfiles/15551480858493696.png"></p>
https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46131#post-id-46131thanks so kindly!Sat, 13 Apr 2019 16:42:16 +0200https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46131#post-id-46131Comment by stockh0lm for <p>Yes, you can limit the proximity to the pole:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None,
lambda x,y: grad[1].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit proximity to pole" src="/upfiles/15551480709763106.png"></p>
<p>or limit the length of the vectors:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None,
lambda x,y: grad[1].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit vector length" src="/upfiles/15551480858493696.png"></p>
https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46134#post-id-46134wow, i tried the second approach (so much more flexible!) and it almost brought my box to the knees - out of memory and CPU to the max... the simple example worked for me, too, but my real gradient field didn't.
what is so insanely memory intensive about this?Sat, 13 Apr 2019 18:20:06 +0200https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46134#post-id-46134Comment by rburing for <p>Yes, you can limit the proximity to the pole:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None,
lambda x,y: grad[1].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit proximity to pole" src="/upfiles/15551480709763106.png"></p>
<p>or limit the length of the vectors:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None,
lambda x,y: grad[1].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit vector length" src="/upfiles/15551480858493696.png"></p>
https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46136#post-id-46136It was using the symbolic expression for the length of the gradient vector, which was not a very good idea. I updated the answer. Now the gradient vector is computed numerically first, and then the length is taken. Another optimization is to use the conditional (`if ... else None`) only on the first coordinate. There is still some inefficiency since one component of the numerical gradient is computed twice (once for the condition, and once for the return value). Let me know if it is still too inefficient.Sat, 13 Apr 2019 19:11:28 +0200https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46136#post-id-46136Comment by stockh0lm for <p>Yes, you can limit the proximity to the pole:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None,
lambda x,y: grad[1].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit proximity to pole" src="/upfiles/15551480709763106.png"></p>
<p>or limit the length of the vectors:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None,
lambda x,y: grad[1].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit vector length" src="/upfiles/15551480858493696.png"></p>
https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46137#post-id-46137it is still super slow. You can see my code in full if you check out my mail to sage-support google group, topic
https://groups.google.com/forum/#!topic/sage-support/Uvkd46KNrWM
i would be happy for any improvements! I intent do work more with this geometry and add a few more electrostatic effects, which will make the computations even more involved. This vektor field will be plotted a few more times.Sat, 13 Apr 2019 20:14:23 +0200https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46137#post-id-46137Comment by rburing for <p>Yes, you can limit the proximity to the pole:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None,
lambda x,y: grad[1].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit proximity to pole" src="/upfiles/15551480709763106.png"></p>
<p>or limit the length of the vectors:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None,
lambda x,y: grad[1].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit vector length" src="/upfiles/15551480858493696.png"></p>
https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46138#post-id-46138Your definition of `my_grad` there can't be right because `grad_phi_ges` still contains many symbolic constants. Looks like you meant to use `pic` (which is `grad_phi_ges` with some numerical values substituted in) instead. For me it works fine when I run
my_grad = [lambda x,z: pic[0].subs(x=x,z=z) if abs(pic.subs(x=x,z=z)) < 3 else None,
lambda x,z: pic[1].subs(x=x,z=z)]
plot_vector_field(my_grad, (x,-1,1), (z,-1,1), color='blue', plot_points=22, axes_labels=['$x$ in [m]','$z$ in [m]'],typeset='latex', frame=True, axes=False)Sat, 13 Apr 2019 20:31:08 +0200https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46138#post-id-46138Comment by stockh0lm for <p>Yes, you can limit the proximity to the pole:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None,
lambda x,y: grad[1].subs(x=x,y=y) if x^2 + y^2 > 0.1 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit proximity to pole" src="/upfiles/15551480709763106.png"></p>
<p>or limit the length of the vectors:</p>
<pre><code>my_grad = [lambda x,y: grad[0].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None,
lambda x,y: grad[1].subs(x=x,y=y) if abs(grad.subs(x=x,y=y)) < 7 else None]
plot_vector_field(my_grad, (x,-1,1), (y,-1,1)).show()
</code></pre>
<p><img alt="limit vector length" src="/upfiles/15551480858493696.png"></p>
https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46140#post-id-46140you are right, i was confused on several steps on the way. thank you for debugging this for me. (even though that was not my intention.)Sat, 13 Apr 2019 21:27:14 +0200https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?comment=46140#post-id-46140Answer by eric_g for <p>Running this piece of code</p>
<pre><code>x, y = var('x y')
f = 1/sqrt(x^2 + y^2)
grad = f.gradient([x, y])
plot_vector_field(grad, (x, -1, 1), (y, -1, 1)).show()
</code></pre>
<p>gives me this</p>
<p><img alt="image description" src="/upfiles/15551465192765043.png"></p>
<p>As you can see the arrows very close to the pole "cross out" the whole pic. Obviously they are very large vectors, but they do harm the overall image. I have other plots where its worse. How can I work around that? Can I blank out the direct proximity of the pole, somehow? Can I limit the vectors' length? How?</p>
https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?answer=46135#post-id-46135An alternative is to define `f` on the Euclidean plane minus a small disk around the origin:
E.<x,y> = EuclideanSpace()
U = E.open_subset('U', coord_def={E.cartesian_coordinates(): x^2+y^2>0.2})
f = U.scalar_field(1/sqrt(x^2+y^2))
grad = f.gradient()
grad.plot(max_range=1, scale=0.1)
![gradient plot](/upfiles/15551738032649321.png)Sat, 13 Apr 2019 18:47:08 +0200https://ask.sagemath.org/question/46123/arrow-length-goes-wild-near-poles-in-vector-field-plot/?answer=46135#post-id-46135