Skip to content

Commit 0bc1087

Browse files
committed
contorted version using numpy's out parameter
1 parent 9bf9360 commit 0bc1087

File tree

3 files changed

+24
-32
lines changed

3 files changed

+24
-32
lines changed

pvlib/bifacial/infinite_sheds.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ def _vf_ground_sky_integ(surface_tilt, surface_azimuth, gcr, height,
5050
# The VFs to the sky will thus be symmetric around z=0.5
5151
z = np.linspace(0, 1, npoints)
5252
rotation = np.atleast_1d(surface_tilt)
53-
fz_sky, _ = utils._vf_ground_sky_2d(z, rotation, gcr, pitch, height,
54-
max_rows)
53+
fz_sky = utils._vf_ground_sky_2d(z, rotation, gcr, pitch, height, max_rows)
5554
# calculate the integrated view factor for all of the ground between rows
5655
return np.trapz(fz_sky, z, axis=0)
5756

pvlib/bifacial/utils.py

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,12 @@ def _vf_ground_sky_2d(x, rotation, gcr, pitch, height, max_rows=10):
122122
vf : array
123123
Fraction of sky dome visible from each point on the ground.
124124
Shape is (len(x), len(rotation)). [unitless]
125-
wedge_angles : array
126-
Angles defining each wedge of sky that is blocked by a row. Shape is
127-
(2, len(x), len(rotation), 2*max_rows+1). ``wedge_angles[0,:,:,:]``
128-
is the starting angle of each wedge, ``wedge_angles[1,:,:,:]`` is the
129-
end angle. [degree]
130125
"""
131126
# This function creates large float64 arrays of size
132127
# (2*len(x)*len(rotation)*len(max_rows)) or ~100 MB for
133-
# typical time series inputs. This function uses `del` to
134-
# allow python to recapture intermediate variables and
135-
# reduce peak memory usage.
128+
# typical time series inputs. This function makes heavy
129+
# use of numpy's out parameter to avoid allocating new
130+
# memory. Unfortunately that comes at the cost of readability.
136131

137132
# handle floats:
138133
x = np.atleast_1d(x)[:, np.newaxis, np.newaxis]
@@ -143,29 +138,27 @@ def _vf_ground_sky_2d(x, rotation, gcr, pitch, height, max_rows=10):
143138
dy = width * sind(rotation)
144139
dx = width * cosd(rotation)
145140

141+
phi = np.empty((2, x.shape[0], rotation.shape[1], len(all_k)))
142+
146143
# angles from x to right edge of each row
147144
a1 = height + dy
148-
b1 = distance_to_row_centers + dx
149-
phi_1 = np.arctan2(a1, b1) # dimensions: (x, rotation, row)
150-
del a1, b1 # reduce max memory usage
145+
phi[0] = distance_to_row_centers + dx
146+
np.arctan2(a1, phi[0], out=phi[0])
151147

152148
# angles from x to left edge of each row
153149
a2 = height - dy
154-
b2 = distance_to_row_centers - dx
155-
phi_2 = np.arctan2(a2, b2) # dimensions: (x, rotation, row)
156-
del a2, b2 # reduce max memory usage
157-
158-
phi = np.stack([phi_1, phi_2]) # dimensions: (row edge, x, rotation, row)
159-
swap = phi_1 > phi_2
160-
del phi_1, phi_2 # reduce max memory usage
150+
phi[1] = distance_to_row_centers - dx
151+
np.arctan2(a2, phi[1], out=phi[1])
161152

162-
# swap where phi_1 > phi_2 so that phi[0,:,:,:] is the lesser angle
163-
phi = np.where(swap, phi[::-1], phi)
164-
del swap # reduce max memory usage
153+
# swap angles so that phi[0,:,:,:] is the lesser angle
154+
phi.sort(axis=0)
165155

166156
# right edge of next row - left edge of previous row
167-
wedge_vfs = 0.5 * (np.cos(phi[1, :, :, 1:]) - np.cos(phi[0, :, :, :-1]))
168-
vf = np.sum(np.clip(wedge_vfs, a_min=0., a_max=None), axis=-1)
169-
del wedge_vfs # reduce max memory usage
170-
171-
return vf, np.degrees(phi)
157+
next_edge = phi[1, :, :, 1:]
158+
np.cos(next_edge, out=next_edge)
159+
prev_edge = phi[0, :, :, :-1]
160+
np.cos(prev_edge, out=prev_edge)
161+
np.subtract(next_edge, prev_edge, out=next_edge)
162+
np.clip(next_edge, a_min=0., a_max=None, out=next_edge)
163+
vf = np.sum(next_edge, axis=-1) / 2
164+
return vf

pvlib/tests/bifacial/test_utils.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ def test__unshaded_ground_fraction(
7979
def test__vf_ground_sky_2d(test_system_fixed_tilt):
8080
# vector input
8181
ts, pts, vfs_gnd_sky = test_system_fixed_tilt
82-
vfs, _ = utils._vf_ground_sky_2d(pts, ts['rotation'], ts['gcr'],
83-
ts['pitch'], ts['height'], max_rows=1)
82+
vfs = utils._vf_ground_sky_2d(pts, ts['rotation'], ts['gcr'],
83+
ts['pitch'], ts['height'], max_rows=1)
8484
assert np.allclose(vfs, vfs_gnd_sky, rtol=0.1) # middle point vf is off
8585
# test with singleton x
86-
vf, _ = utils._vf_ground_sky_2d(pts[0], ts['rotation'], ts['gcr'],
87-
ts['pitch'], ts['height'], max_rows=1)
86+
vf = utils._vf_ground_sky_2d(pts[0], ts['rotation'], ts['gcr'],
87+
ts['pitch'], ts['height'], max_rows=1)
8888
assert np.isclose(vf, vfs_gnd_sky[0])

0 commit comments

Comments
 (0)