Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I'm trying to plot the gradient field of a function in such a way that is possible to change it easily, only editing the function.

Consider the code:

xmin := -2; xmax := -xmin; ymin := -2; ymax := -ymin;
f[x_, y_] := x^2 + y^2
Plot3D[f[x, y], {x, xmin, xmax}, {y, ymin, ymax}]

enter image description here

So, the following code produces a very fancy result:

VectorPlot[{2 x, 2 y}, {x, xmin, xmax}, {y, ymin, ymax}, 
 StreamPoints -> Coarse, StreamColorFunction -> Hue]

enter image description here

Since {D[f[x, y], x], D[f[x, y], y]} produces {2 x, 2 y} I tried to define

Gradf := {D[f[x, y], x], D[f[x, y], y]}

and use

VectorPlot[Gradf, {x, xmin, xmax}, {y, ymin, ymax}, 
 StreamPoints -> Coarse, StreamColorFunction -> Hue]

but I got a lot of errors as

General::ivar: -1.99971 is not a valid variable. >>

General::stop: Further output of General::ivar will be suppressed during this calculation. >>

I really don't understand why it is not working.

Any idea how to solve this so I could only change the definition of f and plot again?

share|improve this question
1  
Gradf[x_, y_] = {D[f[x, y], x], D[f[x, y], y]} instead of Gradf := .... Then it works perfectly. See here –  Öskå May 22 at 23:46
    
It's basically trying to find the Derivative of your function with the x = some value, instead of the Variable x because of the SetDelayed. So it says "-1.9something is not a valid variable" with which it can find the derivative. It's like saying D[x,0]. –  Öskå May 22 at 23:48
    
@Öskå, I'm getting Set::write: Tag List in {2 x,2 y}[x_,y_] is Protected. >>. The same with :=. –  Sigur May 22 at 23:49
4  
You can answer your own question if you like, enlightened by these comments :) If not, I will do it tomorrow. It's too late here for me to write a properly written answer :) –  Öskå May 22 at 23:56
1  
Why not just the following? With[{gradient = Grad[f[x, y], {x, y}]}, VectorPlot[gradient, {x, xmin, xmax}, {y, ymin, ymax}, StreamPoints -> Coarse, StreamColorFunction -> Hue]] –  murray May 24 at 15:01

1 Answer 1

up vote 3 down vote accepted

The problem is that by defining Gradf as fun := D[x^2,x] you are saying "Ok, you will find the Derivative of x^2 in terms of x later on." by using SetDelayed (:=).

Thus, when fun appears in your VerctorPlot or more generally Plot, Mathematica sees it as: "Ok, now I'm going to find the Derivative of fun in terms of x, for each x = {0, 10}":

Plot[fun, {x, 0, 10}]

General::ivar: 0.0002042857142857143` is not a valid variable.

meaning that Mathematica, as you commanded, is trying to find the Derivative of x^2 in terms of x with x equal to 0.0002042857142857143 (case n°1 bellow). Which is obviously not possible since x is not a Variable anymore.

A part of the excellent answer from rm-rf here says:

  • If you're plotting a function, whose definition depends on the output of another possibly expensive computation (such as Integrate, DSolve, Sum, etc. and their numerical equivalents) use = or use an Evaluate with :=. Failure to do so will redo the computation for every plot point! This is the #1 reason for "slow plotting".

Then all you have to do is to follow what has been said above: defining your function with Set (=) so it Evaluates the function to x before plotting it (case n°2 bellow), or Evaluate fun inside Plot so it Evaluates the fun to x before plotting (case n°3 bellow). What is internally happening can be seen with Trace:

Trace@With[{fun := D[x^2, x]}, Plot[fun, {x, 0, 10}]]

Mathematica graphics

Trace@With[{fun = D[x^2, x]}, Plot[fun, {x, 0, 10}]]

Mathematica graphics

Trace@With[{fun := D[x^2, x]}, Plot[Evaluate@fun, {x, 0, 10}]]

Mathematica graphics


Now to answer the question on your specific case you have two possibilities:

xmin := -2; xmax := -xmin; ymin := -2; ymax := -ymin;
f[x_, y_] := x^2 + y^2

With[{Gradf = {D[f[x, y], x], D[f[x, y], y]}}, 
  VectorPlot[Gradf, {x, xmin, xmax}, {y, ymin, ymax}, 
  StreamPoints -> Coarse, StreamColorFunction -> Hue]]

(* or *)

With[{Gradf := {D[f[x, y], x], D[f[x, y], y]}}, 
  VectorPlot[Evaluate@Gradf, {x, xmin, xmax}, {y, ymin, ymax}, 
  StreamPoints -> Coarse, StreamColorFunction -> Hue]]

Mathematica graphics

share|improve this answer
    
Thanks so much. I didn't know about Trace. Very interesting. –  Sigur May 23 at 16:45
1  
@Sigur You are welcome :) I hope it helped you to understand what's really happening inside the box :) –  Öskå May 23 at 16:57
    
Do you know how to plot the integral curve of the Grad field and also its image on the surface to show the path of highest grow level? –  Sigur May 27 at 0:59
    
@Sigur I'm afraid that I don't really understand what you intend to do.. :) Assuming that the "surface" is the Plot3D, what would you exactly like to do? –  Öskå May 27 at 11:00
    
Ow, sorry. I'd like to plot on the 3d surface the path obtained applying the function to the path on domain corresponding to the Grad directions, that is, perpendicular to level curves. So I could see the path on the surface where the function has the faster growth. For some functions, this is easy (for example, $z=x^2+y^2$). –  Sigur May 27 at 23:13

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.