What is the best way to define Wirtinger derivatives
Here is one idea for supporting derivatives with respect to $z$ and $z^*$. First
, we need to use SetSystemOptions
to avoid differentiating Conjugate
/Abs
. Something like:
old = "ExcludedFunctions" /.
("DifferentiationOptions" /. SystemOptions["DifferentiationOptions"]);
SetSystemOptions["DifferentiationOptions" ->
"ExcludedFunctions" -> Union@Join[old,{Abs, Conjugate}]
];
Then, we need to teach D
how to differentiate Conjugate
/Abs
the way we want. To do this we need to make use of the NonConstants
option of D
so that derivatives of functions with a hidden dependence on Conjugate[z]
with respect to Conjugate[z]
do not automatically evaluate to 0.
Unprotect[Conjugate, Abs];
Conjugate /: D[z, Conjugate[z], NonConstants->{z}] := 0;
Conjugate /: D[Conjugate[f_], w_, NonConstants->{z}] := Conjugate[D[f, Conjugate[w], NonConstants->{z}]];
Abs /: D[Abs[f_], w_, NonConstants->{z}] := 1/(2Abs[f]) D[Conjugate[f]f, w, NonConstants->{z}]
Without the NonConstants->{z}
option, something like D[Abs[z]^2, Conjugate[z]]
will evaluate to 0.
D[Abs[z]^2, Conjugate[z]]
D[Abs[z]^2, Conjugate[z], NonConstants->{z}]
0
z
Here are some examples:
D[z, z, NonConstants->{z}]
D[Conjugate[z], z, NonConstants->{z}]
D[Abs[z]^2, Conjugate[z],NonConstants->{z}]
D[(z+Conjugate[z])/2, z, NonConstants->{z}]
1
0
z
1/2
It might be convenient to create a function to package up everything up:
ComplexD[expr_, z__] := With[
{
v = Union @ Cases[{z}, s_Symbol | Conjugate[s_Symbol] | {s_Symbol | Conjugate[s_Symbol], _} :> s],
old = "ExcludedFunctions" /. ("DifferentiationOptions" /. SystemOptions["DifferentiationOptions"])
},
Internal`WithLocalSettings[
SetSystemOptions["DifferentiationOptions" -> "ExcludedFunctions" -> Join[old, {Abs, Conjugate}]];
Unprotect[Conjugate, Abs];
Conjugate /: D[w_, Conjugate[w_], NonConstants->v] := 0;
Conjugate /: D[Conjugate[f_], w_, NonConstants->v] := Conjugate[D[f, Conjugate[w], NonConstants->v]];
Abs /: D[Abs[f_], w_, NonConstants->v] := 1/(2Abs[f]) D[Conjugate[f]f, w, NonConstants->v],
D[expr, z, NonConstants->v],
SetSystemOptions["DifferentiationOptions" -> "ExcludedFunctions" -> old];
Conjugate /: D[w_, Conjugate[w_], NonConstants->v] =.;
Conjugate /: D[Conjugate[f_], w_, NonConstants->v] =.;
Abs /: D[Abs[f_], w_, NonConstants->v] =.;
Protect[Conjugate, Abs];
]
]
The function ComplexD
will temporarily change the system options and give Conjugate
/Abs
the desired D behavior. An example:
ComplexD[Conjugate@Sin[z Conjugate[z]^2], z]
ComplexD[Exp[Conjugate[w] z], Conjugate[w]]
2 z Conjugate[z] Cos[z^2 Conjugate[z]]
E^(z Conjugate[w]) z