I need to take the derivative of a function that have a numerical integration on it. The variable in which the integration will be taken is not the same as the one in which the derivative will be taken, so I can take the derivative before integrating the expression. I have tried the following:
nfun[x1_?NumericQ, x2_?NumericQ] := NIntegrate[Cos[x1^x/x2], {x, 2, 3}]
tvar = {x1 -> 0.1, x2 -> 0.3};
D[nfun[x1, x2], x1] /. tvar
And it worked pretty fine. But my real expression has multiple variables and multiple numerical integrations, so I would like to take a list of arguments as input. I also have to take one derivative for each variable. So I tried the following:
nfun1[arg : {_?NumericQ ..}] := NIntegrate[Cos[#1^x/#2], {x, 2, 3}] & @@ arg
But when I try:
D[nfun1[x1, x2], x1] /. tvar
It doesn't work...
I have tried what is proposed in here: Derivative after numerical Integration (2nd answer), but I couldn't get it to work Do you have any sugestions?
I hope I could express myself correctly
Edit: As Mark and Myke showed, the syntax in the second try is wrong, it should be:
D[nfun1[{x1, x2}], x1] /. tvar
But still not working :(
Answer
First note that your first solution generates a spurious complex part.
nfun[x1_?NumericQ, x2_?NumericQ] := NIntegrate[Cos[x1^x/x2], {x, 2, 3}]
tvar = {x1 -> 0.1, x2 -> 0.3};
D[nfun[x1, x2], x1] /. tvar // RepeatedTiming
(* {0.17, -0.00527135 - 9.7792*10^-9 I} *)
We will also see that it's rather slow to differentiate, too. This is because Mathematica is computing the derivative numerically, which causes the integral to be computed many times. This integral has a symbolic derivative, which can be used to speed up the calculation of the derivative.
Using If
is an easy way to get the protection of NumericQ
but still be able to differentiate the expression. (Update: I did have ConditionalExpression
, which for some reason was working in my original session, but shouldn't have. It doesn't hold its arguments.)
nfun1[arg_List] := If[arg ∈ Reals, NIntegrate[Cos[#1^x/#2], {x, 2, 3}]] & @@ arg
There is no spurious imaginary part to the derivative and it is almost 50 times faster, too. (The Reals
can be replaced with the Complexes
.)
nfun1[{x1, x2}]
D[%, x1] /. tvar // RepeatedTiming
(*
If[(x1 | x2) ∈ Reals, NIntegrate[Cos[x1^x/x2], {x, 2, 3}]]
{0.0045, -0.00527132}
*)
Update: I had a function NEval
was considerably faster than the ConditionalExpression
"solution." The arguments to NEval
consisted an expression expr
to be evaluated when the rest of the arguments are numeric. There is also a special derivative rule, so that differentiating NEval
simply differentiates expr
. While one is naturally initially fond of all one's creations, there seems little need for it in this case. See edit history, if curious.
Comments
Post a Comment