Do not evaluate function composition in total derivative

How to achieve that Dt[] does not touch certain function compositions, but still applies all the other derivative transformations. Example:

(* want *)
Dt[t f[x], t] = f[x] + t Dt[f[x], t]

(* get *)
Dt[t f[x], t] = f[x] + t Dt[x, t] f'[x]


Context: I am doing quantum field theory calculations and want to use Dt for derivatives of fields. For that I need the Conjugate[] of fields, which should be kept unevaluated by Dt[].

Bonus points: Make Conjugate[] commute with Dt[], i.e.

Conjugate[Dt[Conjugate[x], t]] = Dt[x, t]

• I assume the "want" line should be f[x] + t Dt[f[x], t]? Oct 27 '20 at 10:23
• I think the only easy way to get your desired output is by just leaving out the x dependence: Dt[t f, t] Oct 27 '20 at 10:25
• Mathematica can be given assumptions (via Assumptions or Assuming). Maybe telling Mathematica that x does not depend on t does the trick Oct 27 '20 at 12:19
• also, assuming that x is independent of t, shouldn't Dt[f[x],t] evaluate to zero? Oct 27 '20 at 12:37
• I think defining f more clearly would be helpful, i.e. what is its domain and codomain? Oct 27 '20 at 12:52

You can change a system option so that derivatives of Conjugate are not performed:

old = OptionValue[
SystemOptions[],
"DifferentiationOptions"->"ExcludedFunctions"
]

SetSystemOptions[
"DifferentiationOptions" -> "ExcludedFunctions" -> DeleteDuplicates[Append[old, Conjugate]]
]


{Hold, HoldComplete, Less, LessEqual, Greater, GreaterEqual, Inequality,
Unequal, Nand, Nor, Xor, Not, Element, Exists, ForAll, Implies, Positive,
Negative, NonPositive, NonNegative, Replace, ReplaceAll, ReplaceRepeated}

"DifferentiationOptions" -> {"AlwaysThreadGradients" -> False, "DifferentiateHeads" -> True, "DifferentiateIteratorIndexed" -> True, "DirectHighDerivatives" -> True, "DirectHighDerivativeThreshold" -> 10, "ExcludedFunctions" -> {Hold, HoldComplete, Less, LessEqual, Greater, GreaterEqual, Inequality, Unequal, Nand, Nor, Xor, Not, Element, Exists, ForAll, Implies, Positive, Negative, NonPositive, NonNegative, Replace, ReplaceAll, ReplaceRepeated, Conjugate}, "ExitOnFailure" -> False, "HighDerivativeMaxTerms" -> 1000, "SymbolicAutomaticDifferentiation" -> False}

Then, you can use UpValues to define how Dt should behave with Conjugate:

Unprotect[Conjugate];
Conjugate /: Dt[Conjugate[f_], d__] := Conjugate[Dt[f, d]]
Protect[Conjugate];


Then:

Dt[t Conjugate[x], t]


Conjugate[x] + t Conjugate[Dt[x, t]]

and:

Conjugate[Dt[Conjugate[x], t]]


Dt[x, t]

Resetting to defaults:

SetSystemOptions["DifferentiationOptions" -> "ExcludedFunctions" -> old]


"DifferentiationOptions" -> {"AlwaysThreadGradients" -> False, "DifferentiateHeads" -> True, "DifferentiateIteratorIndexed" -> True, "DirectHighDerivatives" -> True, "DirectHighDerivativeThreshold" -> 10, "ExcludedFunctions" -> {Hold, HoldComplete, Less, LessEqual, Greater, GreaterEqual, Inequality, Unequal, Nand, Nor, Xor, Not, Element, Exists, ForAll, Implies, Positive, Negative, NonPositive, NonNegative, Replace, ReplaceAll, ReplaceRepeated}, "ExitOnFailure" -> False, "HighDerivativeMaxTerms" -> 1000, "SymbolicAutomaticDifferentiation" -> False}

• @MichaelE2 I think f was just a stand-in for Conjugate. Oct 27 '20 at 20:47
• Carl Woll is right. Thanks, that's exactly the type of solution I was looking for :) Oct 28 '20 at 11:32

Getting system functions to behave different from the way they were designed is in general a rather difficult task. One option, I strongly advise against, would be unprotecting the function and adding custom definitions for special cases. For relatively simple tasks I found it easier (and much saver) to write my own function/wrappers. Depending on how much functionality of Dt OP really needs this could be a good starting point.

ClearAll[dt];

dt[f_[x_,y__],t_]:=f@@(dt[#,t]&/@{x,y})/;MemberQ[{Plus,List},f]
dt[Times[a_,b__],t_]:=dt[a,t]*b+a dt[Times[b],t]
dt[Conjugate[a_],t_]:=Conjugate[dt[a,t]]

dt[t f[x],t]
Conjugate[dt[Conjugate[x],t]]


returning the desired output

t dt[f[x], t] + f[x]
dt[x, t]


This code distributes dt over Plus and List, uses the product rule on Times, commutes with Conjugate (for those sweet bonus points OP is talking about) and then tries to use Dt. Dt is only applied if the resulting expression is free of derivatives (Derivative and Dt), which prevents partial derivatives like f'[x] but allows for e.g. dt[t^2 Sin[t], t] to evaluate (to t^2 Cos[t]+2 t Sin[t]) using the differentiation tools of Dt.

In terms of performance a manual implementation like this is slower then Dt but still very fast. If performance becomes a problem or such a custom implementation is unsuited using rules to eliminate f[x] in intermediate steps as suggested by Sjoerd Smit in the comment of OPs question might be the better option.