-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vectorize geometry calculations #60
Conversation
* next is calculating shadows...!
* fixed tests accordingly
* because pvrows and ground can change, so it's hard to know if an update needs to be done or not
* the edge pts list was not re-initialized at every interation
* shaded length is somehow infinitesimally smaller than with previous class, but this has virtually no impact. To be investigated later * now surfaces have more logical indexing (from left to right, increasing index) in ground object, so matrices ordering got shifted a bit
@@ -14,9 +13,8 @@ class PVEngine(object): | |||
as a timeseries when the pvarrays can be build from dictionary parameters | |||
""" | |||
|
|||
def __init__(self, params, vf_calculator=VFCalculator(), | |||
def __init__(self, pvarray, vf_calculator=VFCalculator(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's meaningless to have pvarray=OrderedPVArray()
, because it will make something fail later.
It's better to initialize the PV array outside of the engine and then pass it in
self.vf_calculator = vf_calculator | ||
self.irradiance = irradiance_model | ||
self.cls_pvarray = cls_pvarray | ||
self.is_fast_mode = isinstance(fast_mode_pvrow_index, int) \ | ||
and fast_mode_pvrow_index < params['n_pvrows'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since params
is not passed anymore to the engine, we can't do this check for the user anymore
@@ -108,9 +104,11 @@ def fit(self, timestamps, DNI, DHI, solar_zenith, solar_azimuth, | |||
|
|||
# Fit irradiance model | |||
self.irradiance.fit(timestamps, DNI, DHI, solar_zenith, solar_azimuth, | |||
surface_tilt, surface_azimuth, | |||
self.params['rho_front_pvrow'], | |||
self.params['rho_back_pvrow'], albedo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now the rho
reflectivity values are passed to the irradiance models at initialization: it kind of makes more sense since they are not timeseries values, and bc the fit()
function is more or less for timeseries vectorized calculations
pvarray = self.pvarray | ||
|
||
# Transform pvarray to time step | ||
pvarray.transform(idx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now pvarray
is also using the "fit()/transform()" paradigm, just like the irradiance models
for idx, surface in geom_dict.items(): | ||
surface.update_params({'q0': q0[idx], 'qinc': qinc[idx], | ||
'isotropic': isotropic_vec[idx], | ||
'reflection': reflection_vec[idx]}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there was a non-impactful conflict between the idx
passed to run_timestep()
and the index of this for
loop
pvfactors/geometry/base.py
Outdated
x_center, y_center = xy_center | ||
radius = length / 2. | ||
# Get rotation | ||
rotation = get_rotation_from_tilt_azimuth(surface_azimuth, axis_azimuth, | ||
tilt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the fn get_rotation_from_tilt_azimuth
will be re-used in OrderedPVArray
.
The rotation
output here could actually be returned by this coords_from_center_tilt_length()
fn, but it would not really make sense...
self._surface_registry = None | ||
self._view_matrix = None | ||
self._obstr_matrix = None | ||
self._surfaces_indexed = False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these were used to cache the values of the class properties. But with the new OrderedPVArray
, the pv array attributes can change without notice and it doesn't make sense anymore to cache these values: so they are now recalculated every time the properties are called.
(so we try to call the properties only once, or save their values outside if need to be reused)
self.rho_front = None | ||
self.rho_back = None | ||
self.rho_front = rho_front | ||
self.rho_back = rho_back |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now reflectivity values are passed to the irradiance model at initialization, not in the fit()
function; which makes more sense since they are always floats
vf_calculator = cls_vf() | ||
eng = cls_engine(pvarray_parameters, cls_pvarray=cls_pvarray, | ||
irradiance_model=irradiance_model, | ||
eng = cls_engine(pvarray, irradiance_model=irradiance_model, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now the pvarray
needs to be initialized outside of the engine
[8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 4], | ||
[0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 10, 0, 5], | ||
[8, 8, 8, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 10, 0, 0, 4], | ||
[0, 0, 0, 0, 6, 6, 6, 0, 6, 6, 0, 0, 0, 0, 0, 0, 5], | ||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the same surfaces are created, but their indexing differs now with the new implementation.
So the matrices are slightly shifted
vf_left_cut_sum_axis_one_rounded = np.array( | ||
[0.009, 0.346, 0.359, 0.28, 0.268, 0.04, 0.001, 0.372, 0.387, | ||
0.346, 0.035, 0.046, 0.064, 0.966, 0.048, 0.976, 0.981, 0.026, | ||
0.977, 0.]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked that the values of this vector stayed consistent when I updated the matrix above (which was updated because of the new surface indexing of the new class implementation)
Hey @cedricleroy , I would really appreciate if you could take a quick look. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good @anomam! Just minor cosmetic comments.
- solar zenith > 90, ie the sun is down | ||
- DNI or DHI is negative, which does not make sense | ||
- DNI and DHI are both zero | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A little below in the Returns: It looks like None
can be returned as well.
"""Calculate ``shapely`` :py:class:`LineString` coordinate from | ||
center coords, surface tilt angle and length of line. | ||
"""Calculate ``shapely`` :py:class:`LineString` coordinates from | ||
center coords, surface angles and length of line. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is not on the doc, should it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it's a helper function I'll make it private! thx
positive, rotation angles can be negative. | ||
In pvfactors, positive rotation angles will indicate pvrows pointing to the | ||
left, and negative rotation angles will indicate pvrows pointing to the | ||
right (no matter what the the axis azimuth is). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not in the doc?
|
||
Parameters | ||
---------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parameters order to review.
pvfactors/engine.py
Outdated
self.is_fast_mode = isinstance(fast_mode_pvrow_index, int) \ | ||
and fast_mode_pvrow_index < params['n_pvrows'] | ||
self.pvarray = pvarray | ||
self.is_fast_mode = isinstance(fast_mode_pvrow_index, int) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would personally do this to avoid the type check:
self.is_fast_mode = False if fast_mode_pvrow_index is None else True
pvfactors/geometry/pvarray.py
Outdated
|
||
@classmethod | ||
def from_dict(cls, parameters, surface_params=[]): | ||
"""Create ordered PV array from dictionary of parameters | ||
def init_from_dict(cls, pvarray_params, surface_params=[]): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default list to be avoided.
pvfactors/geometry/pvarray.py
Outdated
surface_params=surface_params) | ||
|
||
@classmethod | ||
def transform_from_dict_of_scalars(cls, pvarray_params, surface_params=[]): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default list to be avoided.
@classmethod | ||
def from_ordered_shadow_and_cut_pt_coords( | ||
cls, x_min_max=None, y_ground=Y_GROUND, ordered_shadow_coords=[], | ||
cut_point_coords=[], surface_params=[]): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default list to be avoided.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok got it! thx!
pvfactors/geometry/pvground.py
Outdated
|
||
Parameters | ||
---------- | ||
list_shaded_surfaces : list |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the indent expected?
pvfactors/geometry/pvground.py
Outdated
|
||
Parameters | ||
---------- | ||
list_shaded_surfaces : list |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indent?
Vectorize geometry calculations of ordered PV arrays to improve computation time
In
OrderedPVArray
:PV row coordinates calculation can be vectorized
Ground shadows and cut points coordinates calculation can also be vectorized
This means that the class will be instantiated and used differently.
Update
OrderedPVArray
class to use a fit()/transform() approach, just like the irradiance modelsUpdate PVEngine to accept that change from PV arrays from now on
Update run function as necessary