1
$\begingroup$

I have a function (for example F[x_]:=Cos[x]). I want to define a function like Fdot[x_,xdot_]:=Dt[F[x]]

where xdot represents Dt[x]. For example, to define Fdot one might naivley try

Fdot[x_,Dt[x]_]:=Dt[F[x]],

I am hoping to define Fdot in a manner like the above attempt. I can run Dt[F[x]] then edit the answer to rewrite Dt[x] as a new variable then define Fdot (the brute force way) but I was looking for a less manual way because I have to do it for multiple variables and two derivatives. Fdotdot[x_,y_,xdot_,ydot_,xdotdot_,ydotot_]:=

Knowing how to do the first example I can probably figure out how to do my more complicated example.

$\endgroup$
  • $\begingroup$ Welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Read the faq! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! $\endgroup$ – Michael E2 Apr 28 '15 at 15:17
  • $\begingroup$ You can format inline code and code blocks by selecting it and clicking the {} button above the edit window. The edit window help button ? is also useful for learning how to format your questions and answers. $\endgroup$ – Michael E2 Apr 28 '15 at 15:17
  • $\begingroup$ Do you want to replace Dt[x] with xdot, etc.? (That's my guess, anyway.) $\endgroup$ – Michael E2 Apr 28 '15 at 15:22
  • $\begingroup$ I think I want a little more than just replace. If I have a function F[x(t)] then dF/dt = (dF/dx)(dx/dt). I just want to define a new function Fdot in terms of x and dx/dt. F is rather complex, but Dt[F] returns the derivitive nicely, but I want to set that to a new function but I want the Dt[x] to be a variable of that function so I can have Fdot[Xpos, xVel] $\endgroup$ – Michael Apr 28 '15 at 16:19
2
$\begingroup$

Is this the sort of thing you're after?

Fdot[x_, xdot_] = Dt[F[x]] /. {Dt[x] -> xdot};

Discussion

There are some pitfalls in this simple approach. Since Set works by evaluating the right-hand side before making the definition, if F, x or xdot have any values (OwnValues or in the case of F also DownValues for F[x]), they will be used in the definition, creating a different function than the one created when they have no values. In the case where F is undefined, then the definition will depend on the external symbol F.

These things may or may not be desired, or even may be unimportant. For instance, since D[F[x], x] will not work if x has a numeric value. So it is unlikely to be important to Block the symbol in creating the definition. It is more likely that the dependence of the definition of F will be a source of annoyance and perhaps confusion. For instance if F[x_] := Cos[x] is executed before the definition of Fdot, Fdot[x0, xdot0] will always use Sin[x0] * xdot0 (unless a new definition is executed). If F[x_] := Cos[x] is executed after the definition of Fdot, Fdot[x0, xdot0] will use F'[x0] * xdot0; thus the definition of F in force at the time of execution will be used, so that if F is changed at some point, the value of ``Fdot[x0, xdot0]` will automatically be change, too.

Here is a general function that creates a function to evaluate a differential expression (i.e. in terms of x, Dt[x], Dt[Dt[x]] etc.) at inputs of the form {x0, dx0, ddx0,...}, similar to the way one lists the values of a function and its derivatives in Interpolation. The expression to be evaluated is stored explicitly, so any dependence on external symbols is clear.

ClearAll[dFunction];
dFunction[df_, var: _Symbol] := dFunction[df, {var}];
dFunction[df_, vars: {__Symbol}][vals__] /; Length[{vals}] == Length@Flatten[{vars}] :=
  df /. Flatten @ MapThread[
     Thread[NestList[Dt, #1, Length[#2] - 1] -> #2] &,
     {Flatten[{vars}], Flatten @* List /@ {vals}}];
(* optional formatting *)
Format[dFunction[df_, vars: {__Symbol}]] := 
 HoldForm[dFunction][
  Union @ DeleteCases[
     Cases[Hold[df], s_Symbol /; Context[s] === "Global`", Infinity, Heads -> True],
     Alternatives @@ vars],
  vars]

The Format value, which is optional and shown below, might take a long time on a large expression df. If that is a concern, delete it, delete just the Union @..., or wrap the Union in TimeConstrained:

TimeConstrained[Union@ ..., 0.01] /. $Aborted -> "\[LeftSkeleton]\[RightSkeleton]"

Examples and further utilities:

Undefined function F:

Clear[F];
Fdot2 = dFunction[Dt@F[x], x]
Fdotdot = dFunction[Dt@Dt@F[x, y], {x, y}]

Mathematica graphics

Fdot2[{2, 3}]
(*  3 F'[2]  *)

Fdotdot[{2, 3, 5}, {1, 7, 11}]

Mathematica graphics

Defining F causes Fdot to have the corresponding value:

F[x_] := Cos[x];
Fdot2[{2, 3}]
(*  -3 Sin[2]  *)

Using a previously defined function U:

ClearAll[U, G, M, m, x, y, z];
U[x, y, z] := -G M m/z;
energy = dFunction[U[x, y, z] + (1/2) m (Dt[x]^2 + Dt[y]^2 + Dt[z]^2), {x, y, z}]

Mathematica graphics

One can get the expression stored in the dFunction with First:

First @ energy
(*  -((G m M)/z) + 1/2 m (Dt[x]^2 + Dt[y]^2 + Dt[z]^2)  *)

Or one could add methods to the definition so that

energy["Expression"]

yields the expression above. One might also want to put the code from the Format into its own method, to inspect a complicated expression for parameters.

dFunction[df_, vars : {__Symbol}]["Expression"] := df;
dFunction[df_, vars : {__Symbol}]["IndependentVariables"] := vars;
dFunction[df_, vars : {__Symbol}]["Parameters"] := 
  dFunction[df, vars]["Parameters"] = 
   Union@DeleteCases[
     Cases[Hold[df], s_Symbol /; Context[s] === "Global`", Infinity, Heads -> True],
     Alternatives @@ vars];
dFunction[df_, vars : {__Symbol}]["Properties"] :=
 {"Expression", "IndependentVariables", "Parameters"};

With

TimeConstrained[dFunction[df, vars]["Parameters"], 0.01] /.
  $Aborted -> "\[LeftSkeleton]\[RightSkeleton]"

in the Format value:

d10 = dFunction[Nest[Dt, Sin[a x^2], 10], {x}]
d20 = dFunction[Nest[Dt, Sin[a x^2], 20], {x}]

Mathematica graphics

Since the "Parameters" property method is cached above, one can compute it explicitly and then it will be displayed.

d20["Parameters"]
d20

Mathematica graphics

On the other hand, cacheing the value does store the differential expression df in the SubValues (What is the distinction between DownValues, UpValues, SubValues, and OwnValues?) of dFunction. In the case of d20, that adds about 200K to the memory footprint of dFunction, whose basic definitions take up only 6240 bytes.

[Original attempt can be seen in the edit history.]

$\endgroup$
  • $\begingroup$ If I could do something like dxvec = {a, b}; dyvec = {c, d}; Dt@Dt[x Sin[y]] Fdd[x_,y_,a_,b_,c_,d_]:=% /. dt_Dt :> With[{levels = Level[dt, -1]}, Switch[First@levels, x, dxvec[[Length@levels]], y, dyvec[[Length@levels]], _, dt] /; MatchQ[levels, {_Symbol, ___Dt}]] Then I think I would have it. Ultimatly I want a function defined with variables replacing the Dt[x] $\endgroup$ – Michael Apr 28 '15 at 16:41
  • $\begingroup$ This does let me copy and paste the answer in to a function definition easily, but if I change the function at the top it won't rerun easily. $\endgroup$ – Michael Apr 28 '15 at 16:46
  • $\begingroup$ @Michael I added another guess. See if I'm closer. $\endgroup$ – Michael E2 Apr 28 '15 at 18:06
  • $\begingroup$ This seems to be exactly what I was looking for. But I am confused why this works, in particular why is an equal sign used instead of colon-equal? $\endgroup$ – Michael Apr 28 '15 at 18:58
  • $\begingroup$ @Michael Set (=) evaluates the right-hand side before making the definition; SetDelayed (:=) does not. When I have time later, I'll update my answer to make it more complete. I didn't want to spend a lot of time on it until I knew I was on the right track. Try ?Fdot with both definitions and see if that helps you figure it out. $\endgroup$ – Michael E2 Apr 28 '15 at 19:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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