Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This question already has an answer here:

I have an expression depending on the two variables z and t, and the derivative of a known function $f(t,z)$.
Something like:

$$myexp \ =\ t\ z\ \partial_z\ f(t,z)$$

Now I want to make a change of variables

$$x^+ = t + z\\ x^- = t - z$$

with inverse transformation

$$ t = \frac{1}{2}(x^+ + x^-)\\ z = \frac{1}{2}(x^+ - x^-)$$

The consequent transformation of the derivates read:

$$ \partial_+ = \frac{1}{2}(\partial_t + \partial_z)\\ \partial_- = \frac{1}{2}(\partial_t - \partial_z) $$

I now just want to know, how I can replace the derivatives in Mathematica.

myexp = t*z D[f[t, z], z];
myexp /. {t -> 1/2 (xp + xm), z -> 1/2 (xp - xm)}

gives me

1/4 (-xm+xp) (xm+xp) (f^(0,1))[(xm+xp)/2,1/2 (-xm+xp)]

which is not $$ \frac{1}{4} [(x^+)^2- (x^-)^2]\ \ (\partial_+ \ \tilde f(x^+, x^-) - \partial_-\ \tilde f(x^+, x^-) $$

what I actually would like to have. The transformation of $f$ to $\tilde f$ works with the rule above, but not for the derivative.

Is there a smart way to do this?

share|improve this question

marked as duplicate by Jens, Öskå, RunnyKine, Simon Woods, m_goldberg Aug 27 '14 at 2:04

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

Closely related: How to change coordinates of a differential operator? The main thing is to apply the chain rule. This question is simpler than the linked one because the transformation is linear. – Jens Aug 26 '14 at 16:14
Thank you for these links, Jens. I also found them before I posted the question and knew they were related, but I was not able to extract the solution for my simpler problem. But since they are even more general, I will study them in more detail again. – Crunchip Aug 26 '14 at 16:45
You can look at the FullForm of your expression and apply a simple replacement rule like Derivative[0, 1][a_][t, z] :> (Derivative[0, 1][a][xm, xp] + Derivative[1, 0][a][xm, xp]) for each of your light cone coordinates – gpap Aug 26 '14 at 17:47
After at least two answers that provide additional information that is not provided in any previous question (in particular, how to do this with multiple independent variables), why has this retroactively been marked duplicate? – Kellen Myers Aug 28 '14 at 14:45
up vote 3 down vote accepted

I still like the differential way (below), but here's a direct way. It is similar to the linked duplicate, Change variables in differential expressions, but I don't conflate $f$ and $\tilde f$, which error is made by its OP and adhered to in the answers. Let f0 represent $\tilde f$. Then f is equivalent under the change of variables, to

f == Function[{t, z}, f0[t + z, t - z]].

Hence to the answer:

t*z D[f[t, z], z] /. 
   f -> Function[{t, z}, f0[t + z, t - z]] /.
   {t -> (xm + xp)/2, z -> 1/2 (-xm + xp)} // Simplify

Mathematica graphics

Well, it is shorter than my original answer (in part because I didn't define the transformations but hand coded the formulas explicitly).

Original answer

I like to use Dt and let Mathematica take care of the chain rule. Dt represents the derivative as a linear transformation in terms of the differentials of the variables (e.g. Dt[t] etc.). You'll need a symbol for the transformed function $\tilde f$. Let's call it f0. You'll also need to start with the total differential and hold the evaluation of the differentiation in myexp until after the change of variables has been done. At the end, we'll evaluate the differential at {Dt[t] == 0, Dt[z] == t*z} to find the transformed expression for myexp.

Clear[f, f0, t, z, xp, xm];

df = Hold[Dt[f[t, z]]];

Now set up the transforms as replaces rules:

fnxf = {f0[xp_, xm_] :> f[t, z] /. invxf};
fninvxf = {f[t_, z_] :> f0[xp, xm] /. xf};

xf = {xp -> t + z, xm -> t - z};
invxf = First@Solve[{xp, xm} == ({xp, xm} /. xf), {t, z}];

Apply them to the differential df and release the hold. To get the value at {Dt[t] == 0, Dt[z] == t*z}, which is the sought-after transformation of myexp, we transform the pair of equations and solve them for Dt[xp], Dt[xm].

df /. fninvxf /. invxf // ReleaseHold;
% /. First@Solve[{Dt[t] == 0, Dt[z] == t*z} /. invxf, {Dt[xp], Dt[xm]}] // Simplify

Mathematica graphics

share|improve this answer
I don't see myself conflating anything (see f2). Kudos on the most elegant answer, but there's no need to rub it in. – Kellen Myers Aug 28 '14 at 14:43
@KellenMyers I wasn't talking about your answer at all, but explicitly about the duplicate question (see link above). In it, the functions corresponding to $f$ and $\tilde f$ are called B[r] and B[x], as if B was the same function in each. It was like how one says, "$y$ is a function of $x$, and $x$ is a function of $t$; therefore $y$ is a function of $t$." The same symbol $y$ is used but it's a different function, esp. when it is coded in Mathematica. The solutions to the duplicate do what was asked; but strictly following their procedure wouldn't solve this question.... – Michael E2 Aug 28 '14 at 16:58
@KellenMyers ...I thought the difference might be confusing to someone since it the question is indicated to be a duplicate. (It roughly is, but I dislike the fact that this question is better posed from a mathematical point of view, yet is the closed question.) In any case, I upvoted your answer yesterday. If it was downvoted because of the sign between the partials, they should have said and encouraged you to fix that. (It would be good if you did, IMO.) – Michael E2 Aug 28 '14 at 16:59
I am happy to acknowledge it. I'm pretty sure "no need to rub it in" (following some kudos) is not any type of formal accusation that requires such a rebuttal, and there's no need to explain to me why any of that is necessary -- it's already in my answer. – Kellen Myers Sep 1 '14 at 17:20
@KellenMyers OK, I just didn't want there to be any misunderstanding between us. I'll delete my previous remark. – Michael E2 Sep 1 '14 at 17:31

There are ways to do this with replacement, as comments suggest. However, it can be messy if you're jumping in with a two-variable function. Let's work from the examples to see how it goes:

f'[x] /. f -> (f[g[#]] &)

This makes a substitution from $f'(x)$ where $x=g(x)$ (or, more appropriately, $g(t)$):

f'[t] /. f -> (f[g[#]] &)

This distinction between $x$ and $t$ may be part of the hang-up. It's easy to replace $x$ with other things, like $x=g(t)+h(t)^2$ or the like:

f'[t] /. f -> (f[g[#]+h[#]^2] &)

And so we see Mathematica can do the chain rule and substitute accordingly. But notice what happens if we need two variables now. Say we want to do something with $f(x,y)$ where $x=g(t)+h(t)^2$ and just leave $y$ alone:

D[f[t, y], t] /. f -> (f[g[#]+h[#]^2] &)

We need $f$ to still be a function of $t$ and $y$, but when we plug in, all we get is $t$ because our expression for $f$ in the replacement only has one argument. We can fix it:

D[f[t, y], t] /. f -> (f[g[#]+h[#]^2,y] &)

However, to be completely clear, we are replacing the function f with another function (which we are also calling f). Rather than explicitly state its second input as y, we can infer it as:

f'[t, y] /. f -> (f[g[#1] + h[#1]^2, #2] &)

This is a much safer bet, because how that will work even if I change y (which we want to do momentarily). So to summarize the syntax, you have now f a function of two variables. When you do this change-of-variables replacement using ->, you have to give it an expression that depends on its inputs, which are abstractly given as #1 and #2.

For what you want, you can do the same.

D[f[t, z], t] /. f -> (f[g[#1, #2], h[#1, #2]] &)

That will just return the usual total derivative for $\partial_t f(g(t,z),h(t,z))$. You can make this what you want by making the first input of $f$ instead of $g(t,z)$ use $(1/2)(x_1(t,z)+x_2(t,z))$ and likewise replacing $h(t,z)$ to get:

D[f[t, z], t] /. f -> (f[1/2(x1[#1, #2]+x2[#1,#2]),1/2(x1[#1, #2]-x2[#1,#2])] &)

That seems to be what the general suggestion is in the comments. (I've renamed $x_+$ to x1, $x_-$ to x2, and eventually $\bar{f}$ will be f2.)

Of course, there is more to your expression, and this is where other advice seems to stop. But here is exactly where we might want to be careful. You also want to reassign the partials -- this is the tricky part. We're done the calculus, so we can throw away the t and z a bit:

D[f[t, z], t] /. f -> (f[1/2(x1[#1, #2]+x2[#1,#2]),1/2(x1[#1, #2]-x2[#1,#2])] &)
% /. {x1[t, z] -> x1, x2[t, z] -> x2}

Then we want to get rid of partials, so:

% /. Derivative[1, 0][f][1/2 (x1 + x2), 1/2 (x1 - x2)] :>
 (Derivative[1, 0][f2][x1, x2] +  Derivative[1, 0][f2][x1, x2])
% /. Derivative[0, 1][f][1/2 (x1 + x2), 1/2 (x1 - x2)] :>
 (Derivative[1, 0][f2][x1, x2] - Derivative[0, 1][f2][x1, x2])

There are x1[t,z] floating around because we never got rid of them, so:

% /. Thread[Flatten[D[{x1[t, z], x2[t, z]}, {{t, z}}]] :> {1, 1, 1, -1}]

Finally, you can put your $t$ and $z$ back and replace them:

t z % /. {t->1/2(x1+x2),z->1/2(x1-x2)}

(If you had started with the t z D[f[t,z],t] from the beginning it would work too.)

In summary, here's a quick version:

myexp = t z D[f[t, z], t]
(* Replace f[t,z] with f[x1,x2] *)
% /. f -> (f[1/2 (x1[#1, #2] + x2[#1, #2]), 1/2 (x1[#1, #2] - x2[#1, #2])] &)
(* Replace xi[t,z] with just xi *)
% /. {x1[t, z] -> x1, x2[t, z] -> x2}
(* Replace t and z partials with x1 and x2 partials *)
% /. Derivative[1, 0][f][1/2 (x1 + x2), 1/2 (x1 - x2)] :>
 (Derivative[1, 0][f2][x1, x2] + Derivative[0, 1][f2][x1, x2])
% /. Derivative[0, 1][f][1/2 (x1 + x2), 1/2 (x1 - x2)] :>
 (Derivative[1, 0][f2][x1, x2] - Derivative[0, 1][f2][x1, x2])
(* Replace t and z partials of x1 and x2 with their actual values
 (which are 1, 1, 1, -1 *)
% /. Thread[Flatten[D[{x1[t, z], x2[t, z]}, {{t, z}}]] :> {1, 1, 1, -1}]
(* Finally, get rid of any leftover t and z*)
% /. {t -> 1/2 (x1 + x2), z -> 1/2 (x1 - x2)}

That'll do it, although having checked all over, I seem to get a sign error and I'm not sure why. I'm getting a plus between the two partials...?

I think many people said "just use the chain rule, here are examples" missed the part of your question that requires you to substitute the differentials w.r.t your new variables $x_1$ and $x_2$. With a little more work, I think we could hash this code out to be repeatable for any specified change-of-variables.

share|improve this answer
Thank you. I really got confused with applying things to a two-variable-functions. The minus sign comes from the partial derivative with respect to z and not t, so everything is fine. – Crunchip Aug 27 '14 at 11:59
Ah, I think I see the typo but I'm glad to hear my explanation may have helped bridge the gap between the comments (and the questions to which they link) and your work. :) – Kellen Myers Aug 28 '14 at 3:46

you can always define the transformation rule for your variable and operator by defining the Jacobian

J1 = D[{xp, xm}, #] & /@ {t, z} (*Jacobian*)
J2 = Inverse[J]

right now I am using dq for the partial derivative. They are distinguished from the variable by the transformation rule (look at the use of J1 and J2)

Now in your final expression use t1,z1 and dz1 in place of t, z and $\partial_z$ and finally replace dx and dy by the partial derivative term.

t1 z1 dz1 /. {dx -> D[g[x, y], x], dy -> D[g[x, y], y]}

and you will find your desired answer. I use here x,y for $x^+,x^-$ and g[x_,y_]=f[t1,z1]. If you use f[t1,z1] at last step Mathematica will use chain rule and you will get different result. So either evaluate g[x,y] beforehand, or just keep g[x,y].

Although it may be out of context, but it looks like your are doing some problem in general relativity. In that case you may find it more useful to define the transformations of operator by Christoffel symbols. You may find this site helpful if you want to find the connection terms for a given coordinate transformation.

share|improve this answer

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