Re: FindRoot[ NIntegrate[...] ...] works but generates "NIntegrate::nlim" limit error message!?
- To: mathgroup at smc.vnet.net
- Subject: [mg72507] Re: FindRoot[ NIntegrate[...] ...] works but generates "NIntegrate::nlim" limit error message!?
- From: "Ray Koopman" <koopman at sfu.ca>
- Date: Wed, 3 Jan 2007 01:43:13 -0500 (EST)
- References: <end7ko$iek$1@smc.vnet.net>
William McHargue wrote: > Hello, > > I wish to solve for an integration result to equal a given value while > varying the upper limit of the integration. It seems a straightforward > thing to do, and in fact it finds the numerical answer, but it > generates an error message at the beginning of the root solving > operation. I create a function to perform a numerical integration with > a passed upper limit of integration: > > In[1]:= integralFunction[upperLimit_] := NIntegrate[x, {x, 0, > upperLimit}] > > > Then I create a function to find a result of this integration that > equals a supplied value with the upper limit of integration as the > independent variable: > > In[2]:= rootOfIntegralFunction[solveForValue_] := > FindRoot[integralFunction[u] == solveForValue, {u, 1}, > EvaluationMonitor :> Print[u]] > > > (I use the EvaluationMonitor to print the value of "u" as it searches > for the solution.) > > When I execute the following I get an error message, yet it finds the > correct result: > > In[3]:= rootOfIntegralFunction[12.5] > > NIntegrate::nlim : x = u is not a valid limit of integration. > More... > > 1. > > 13. > > 2.2 > > 6.78182 > > 4.3982 > > 5.04117 > > 5.00017 > > 5. > > 5. > > Out[3]= {u->5.} > > > > If anyone has any insight into this behavior please let me know. Thank > you! > > Bill. Your code, with more precise output: In[1]:= integralFunction[upperLimit_] := NIntegrate[x, {x, 0, upperLimit}] In[2]:= rootOfIntegralFunction[solveForValue_] := FindRoot[integralFunction[u] == solveForValue, {u, 1}, EvaluationMonitor :> Print[InputForm@u]] In[3]:= rootOfIntegralFunction[12.5] //InputForm NIntegrate::nlim : x = u is not a valid limit of integration. More... 1. 13. 2.2 6.781818181818182 4.398197725857718 5.041172089084762 5.000168129642239 5.0000000028266625 4.999999999999999 Out[3]//InputForm= {u -> 4.999999999999999} Specifying ?NumericQ as the pattern of its argument makes integralFunqtion defined only for numeric arguments, so NIntegrate will no longer complain. However, more function evaluations are required because the FindRoot can no longer get analytic derivatives. In[4]:= integralFunqtion[upperLimit_?NumericQ] := NIntegrate[x, {x, 0, upperLimit}] In[5]:= rootOfIntegralFunqtion[solveForValue_] := FindRoot[integralFunqtion[u] == solveForValue, {u, 1}, EvaluationMonitor :> Print[InputForm@u]] In[6]:= rootOfIntegralFunqtion[12.5] //InputForm 1. 1. 1.0000000149011612 13. 2.2 2.2 2.2000000327825546 6.781818150220108 4.398197757391624 4.398197757391624 4.398197822929878 5.041172080620799 5.041172080620799 5.041172155740117 5.000168129897382 5.000168129897382 5.000168204405694 5.000000002828278 5.000000002828278 5.000000077334084 5. Out[6]//InputForm= {u -> 5.} To use analytic derivatives with a numeric-only function, you must tell FindRoot what the Jacobian is. In this case it is simply the upper bound of integration. In[7]:= rootOfIntegralFunktion[solveForValue_] := FindRoot[integralFunqtion[u] == solveForValue, {u, 1}, EvaluationMonitor :> Print[InputForm@u], Jacobian->{{u}}] In[8]:= rootOfIntegralFunktion[12.5] //InputForm 1. 13. 2.2 6.781818181818182 4.398197725857718 5.041172089084762 5.000168129642239 5.0000000028266625 4.999999999999999 Out[8]//InputForm= {u -> 4.999999999999999}