@@ -175,17 +175,8 @@ def vd_from_brent(voc, v, iph, isat, rs, rsh, gamma):
175
175
vd = vd_from_brent_vectorized (voc_est , voltage , * args )
176
176
elif method .lower () == 'newton' :
177
177
# make sure all args are numpy arrays if max size > 1
178
- size , shape = _get_size_and_shape ((voltage ,) + args )
179
- if size > 1 :
180
- args = [np .asarray (arg ) for arg in args ]
181
- # newton uses initial guess for the output shape
182
- # copy v0 to a new array and broadcast it to the shape of max size
183
- if shape is not None :
184
- v0 = np .broadcast_to (voltage , shape ).copy ()
185
- else :
186
- v0 = voltage
187
- # x0 and x in func are the same reference! DO NOT set x0 to voltage!
188
- # voltage in fv(x, voltage, *a) MUST BE CONSTANT!
178
+ # if voltage is an array, then make a copy to use for initial guess, v0
179
+ args , v0 = _prepare_newton_inputs ((voltage ,), args , voltage )
189
180
vd = newton (func = lambda x , * a : fv (x , voltage , * a ), x0 = v0 ,
190
181
fprime = lambda x , * a : bishop88 (x , * a , gradients = True )[4 ],
191
182
args = args )
@@ -248,17 +239,8 @@ def vd_from_brent(voc, i, iph, isat, rs, rsh, gamma):
248
239
vd = vd_from_brent_vectorized (voc_est , current , * args )
249
240
elif method .lower () == 'newton' :
250
241
# make sure all args are numpy arrays if max size > 1
251
- size , shape = _get_size_and_shape ((current ,) + args )
252
- if size > 1 :
253
- args = [np .asarray (arg ) for arg in args ]
254
- # newton uses initial guess for the output shape
255
- # copy v0 to a new array and broadcast it to the shape of max size
256
- if shape is not None :
257
- v0 = np .broadcast_to (voc_est , shape ).copy ()
258
- else :
259
- v0 = voc_est
260
- # x0 and x in func are the same reference! DO NOT set x0 to current!
261
- # voltage in fi(x, current, *a) MUST BE CONSTANT!
242
+ # if voc_est is an array, then make a copy to use for initial guess, v0
243
+ args , v0 = _prepare_newton_inputs ((current ,), args , voc_est )
262
244
vd = newton (func = lambda x , * a : fi (x , current , * a ), x0 = v0 ,
263
245
fprime = lambda x , * a : bishop88 (x , * a , gradients = True )[3 ],
264
246
args = args )
@@ -315,17 +297,8 @@ def fmpp(x, *a):
315
297
vd = vec_fun (voc_est , * args )
316
298
elif method .lower () == 'newton' :
317
299
# make sure all args are numpy arrays if max size > 1
318
- size , shape = _get_size_and_shape (args )
319
- if size > 1 :
320
- args = [np .asarray (arg ) for arg in args ]
321
- # newton uses initial guess for the output shape
322
- # copy v0 to a new array and broadcast it to the shape of max size
323
- if shape is not None :
324
- v0 = np .broadcast_to (voc_est , shape ).copy ()
325
- else :
326
- v0 = voc_est
327
- # x0 and x in func are the same reference! DO NOT set x0 to current!
328
- # voltage in fi(x, current, *a) MUST BE CONSTANT!
300
+ # if voc_est is an array, then make a copy to use for initial guess, v0
301
+ args , v0 = _prepare_newton_inputs ((), args , voc_est )
329
302
vd = newton (
330
303
func = fmpp , x0 = v0 ,
331
304
fprime = lambda x , * a : bishop88 (x , * a , gradients = True )[7 ], args = args
@@ -359,6 +332,19 @@ def _get_size_and_shape(args):
359
332
return size , shape
360
333
361
334
335
+ def _prepare_newton_inputs (i_or_v_tup , args , v0 ):
336
+ # broadcast arguments for newton method
337
+ # the first argument should be a tuple, eg: (i,), (v,) or ()
338
+ size , shape = _get_size_and_shape (i_or_v_tup + args )
339
+ if size > 1 :
340
+ args = [np .asarray (arg ) for arg in args ]
341
+ # newton uses initial guess for the output shape
342
+ # copy v0 to a new array and broadcast it to the shape of max size
343
+ if shape is not None :
344
+ v0 = np .broadcast_to (v0 , shape ).copy ()
345
+ return args , v0
346
+
347
+
362
348
def _lambertw_v_from_i (resistance_shunt , resistance_series , nNsVth , current ,
363
349
saturation_current , photocurrent ):
364
350
try :
0 commit comments