Skip to content

Commit ce5b0f5

Browse files
committed
MAINT: replace boilerplate code for broadcasting newton array args
* closes pvlib#498 * adds _prepare_newton_inputs(i_or_v_tup, args, v0) * also replace verbose comment with more descriptive one to copy v0 if it's an array to use for initial guess
1 parent 337d7b4 commit ce5b0f5

File tree

1 file changed

+19
-33
lines changed

1 file changed

+19
-33
lines changed

pvlib/singlediode_methods.py

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -175,17 +175,8 @@ def vd_from_brent(voc, v, iph, isat, rs, rsh, gamma):
175175
vd = vd_from_brent_vectorized(voc_est, voltage, *args)
176176
elif method.lower() == 'newton':
177177
# 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)
189180
vd = newton(func=lambda x, *a: fv(x, voltage, *a), x0=v0,
190181
fprime=lambda x, *a: bishop88(x, *a, gradients=True)[4],
191182
args=args)
@@ -248,17 +239,8 @@ def vd_from_brent(voc, i, iph, isat, rs, rsh, gamma):
248239
vd = vd_from_brent_vectorized(voc_est, current, *args)
249240
elif method.lower() == 'newton':
250241
# 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)
262244
vd = newton(func=lambda x, *a: fi(x, current, *a), x0=v0,
263245
fprime=lambda x, *a: bishop88(x, *a, gradients=True)[3],
264246
args=args)
@@ -315,17 +297,8 @@ def fmpp(x, *a):
315297
vd = vec_fun(voc_est, *args)
316298
elif method.lower() == 'newton':
317299
# 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)
329302
vd = newton(
330303
func=fmpp, x0=v0,
331304
fprime=lambda x, *a: bishop88(x, *a, gradients=True)[7], args=args
@@ -359,6 +332,19 @@ def _get_size_and_shape(args):
359332
return size, shape
360333

361334

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+
362348
def _lambertw_v_from_i(resistance_shunt, resistance_series, nNsVth, current,
363349
saturation_current, photocurrent):
364350
try:

0 commit comments

Comments
 (0)