We can see that there is a 10^x
in the message, which shows that the call to GuessError[.., .., 10^x, etc.]
was evaluated with a symbolic x
. (NMinimize
is not HoldAll
or HoldFirst
.) This is a classic problem solved by _?NumericQ
, which is explained in this answer: What are the most common pitfalls awaiting new users?
One might add it to other variables except IVcurve
, which needs a ?(MatrixQ[#, NumericQ]&)
PatternTest
.
Gratuitous suggestions
Since NMinimize
can be slow, it might be good to speed up GuessError
. Depending on how large IVcurve
is, since it is static, it would be potentially much faster to construct the NearestFunction
just once for the optimization problem.
Next, since it is the position of the nearest point that is desired, it will be more efficient to use the form
Nearest[Vexp -> Automatic]
These two changes speed up NMinimize
35% in a test run on an IVcurve
of length 1000
, 20% on a curve of length 100
.
Further, one can do some more of the construction of the objective function by precomputing Jexp
and Vexp
which are constant (with respect to ni
). With these improvements, the same optimization runs almost 65% faster on a curve of length 1000 (and almost 50% faster on a curve of length 100).
Code:
ClearAll[GuessError, objGuessError];
(* No pattern tests - Returns an objective function, objGuessError *)
GuessError[IVcurve_, Area_, ni_, mue_, krec_, Jgen_, d_, T_] :=
objGuessError[
IVcurve[[All, 1]]/Area^2, IVcurve[[All, 2]],
Nearest[IVcurve[[All, 1]] -> Automatic],
Area, ni, mue, krec, Jgen, d, T];
objGuessError[Jexp_, Vexp_, iNF_, Area_, ni_?NumericQ, mue_, krec_, Jgen_, d_, T_] :=
Module[{Vext, q, Vt, Jsim, Vsup, Vinf, ninf, nsup, Jrange, Vrange,
Vint, imin, imax, JV}, Vt = 8.61733238 10^-5 (T + 273.15);
q = 1.6 10^-19;
Vint = Vt Log[(Jexp + Jgen)/(q d krec ni^2) + 1];
Vext = Vint + (d Jexp)/(2 q mue ni E^(Vint/(2 Vt)));
Vinf = Max[First[Vext], First[Vexp]];
ninf = First[iNF[Vinf]];
Vsup = Min[Last[Vext], Last[Vexp]];
nsup = First[iNF[Vsup]];
Vrange = Take[Vext, {ninf, nsup}];
Abs@Total[(Vrange - Take[Vexp, {ninf, nsup}])^2]]
Example optimization:
ivcurve = Table[{t, 10^t}, {t, 0, 10, 0.01}];
NMinimize[{GuessError[ivcurve, 1, 10^x, 1, 1, 1, 1, 1], {0.1 < x < 1.5}}, x]