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}]
Fdot2[{2, 3}]
(* 3 F'[2] *)
Fdotdot[{2, 3, 5}, {1, 7, 11}]
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}]
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}]
Since the "Parameters"
property method is cached above, one can compute it explicitly and then it will be displayed.
d20["Parameters"]
d20
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.]
{}
button above the edit window. The edit window help button?
is also useful for learning how to format your questions and answers. $\endgroup$Dt[x]
withxdot
, etc.? (That's my guess, anyway.) $\endgroup$