|
9 | 9 |
|
10 | 10 | def pvfactors_timeseries( |
11 | 11 | solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, |
12 | | - axis_azimuth, |
13 | | - timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, |
14 | | - n_pvrows=3, index_observed_pvrow=1, |
| 12 | + axis_azimuth, timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, |
| 13 | + albedo, n_pvrows=3, index_observed_pvrow=1, |
15 | 14 | rho_front_pvrow=0.03, rho_back_pvrow=0.05, |
16 | | - horizon_band_angle=15., |
17 | | - run_parallel_calculations=True, n_workers_for_parallel_calcs=2): |
| 15 | + horizon_band_angle=15.): |
18 | 16 | """ |
19 | 17 | Calculate front and back surface plane-of-array irradiance on |
20 | 18 | a fixed tilt or single-axis tracker PV array configuration, and using |
@@ -62,127 +60,92 @@ def pvfactors_timeseries( |
62 | 60 | Back surface reflectivity of PV rows |
63 | 61 | horizon_band_angle: float, default 15 |
64 | 62 | Elevation angle of the sky dome's diffuse horizon band (deg) |
65 | | - run_parallel_calculations: bool, default True |
66 | | - pvfactors is capable of using multiprocessing. Use this flag to decide |
67 | | - to run calculations in parallel (recommended) or not. |
68 | | - n_workers_for_parallel_calcs: int, default 2 |
69 | | - Number of workers to use in the case of parallel calculations. The |
70 | | - '-1' value will lead to using a value equal to the number |
71 | | - of CPU's on the machine running the model. |
72 | 63 |
|
73 | 64 | Returns |
74 | 65 | ------- |
75 | | - front_poa_irradiance: numeric |
| 66 | + poa_front: numeric |
76 | 67 | Calculated incident irradiance on the front surface of the PV modules |
77 | 68 | (W/m2) |
78 | | - back_poa_irradiance: numeric |
| 69 | + poa_back: numeric |
79 | 70 | Calculated incident irradiance on the back surface of the PV modules |
80 | 71 | (W/m2) |
81 | | - df_registries: pandas DataFrame |
82 | | - DataFrame containing detailed outputs of the simulation; for |
83 | | - instance the shapely geometries, the irradiance components incident on |
84 | | - all surfaces of the PV array (for all timestamps), etc. |
85 | | - In the pvfactors documentation, this is refered to as the "surface |
86 | | - registry". |
| 72 | + poa_front_absorbed: numeric |
| 73 | + Calculated absorbed irradiance on the front surface of the PV modules |
| 74 | + (W/m2), after AOI losses |
| 75 | + poa_back_absorbed: numeric |
| 76 | + Calculated absorbed irradiance on the back surface of the PV modules |
| 77 | + (W/m2), after AOI losses |
87 | 78 |
|
88 | 79 | References |
89 | 80 | ---------- |
90 | 81 | .. [1] Anoma, Marc Abou, et al. "View Factor Model and Validation for |
91 | 82 | Bifacial PV and Diffuse Shade on Single-Axis Trackers." 44th IEEE |
92 | 83 | Photovoltaic Specialist Conference. 2017. |
93 | 84 | """ |
94 | | - |
95 | 85 | # Convert pandas Series inputs (and some lists) to numpy arrays |
96 | 86 | if isinstance(solar_azimuth, pd.Series): |
97 | 87 | solar_azimuth = solar_azimuth.values |
98 | 88 | elif isinstance(solar_azimuth, list): |
99 | 89 | solar_azimuth = np.array(solar_azimuth) |
100 | 90 | if isinstance(solar_zenith, pd.Series): |
101 | 91 | solar_zenith = solar_zenith.values |
| 92 | + elif isinstance(solar_zenith, list): |
| 93 | + solar_zenith = np.array(solar_zenith) |
102 | 94 | if isinstance(surface_azimuth, pd.Series): |
103 | 95 | surface_azimuth = surface_azimuth.values |
104 | 96 | elif isinstance(surface_azimuth, list): |
105 | 97 | surface_azimuth = np.array(surface_azimuth) |
106 | 98 | if isinstance(surface_tilt, pd.Series): |
107 | 99 | surface_tilt = surface_tilt.values |
| 100 | + elif isinstance(surface_tilt, list): |
| 101 | + surface_tilt = np.array(surface_tilt) |
108 | 102 | if isinstance(dni, pd.Series): |
109 | 103 | dni = dni.values |
| 104 | + elif isinstance(dni, list): |
| 105 | + dni = np.array(dni) |
110 | 106 | if isinstance(dhi, pd.Series): |
111 | 107 | dhi = dhi.values |
112 | | - if isinstance(solar_azimuth, list): |
113 | | - solar_azimuth = np.array(solar_azimuth) |
| 108 | + elif isinstance(dhi, list): |
| 109 | + dhi = np.array(dhi) |
114 | 110 |
|
115 | 111 | # Import pvfactors functions for timeseries calculations. |
116 | | - from pvfactors.run import (run_timeseries_engine, |
117 | | - run_parallel_engine) |
| 112 | + from pvfactors.run import run_timeseries_engine |
118 | 113 |
|
119 | 114 | # Build up pv array configuration parameters |
120 | 115 | pvarray_parameters = { |
121 | 116 | 'n_pvrows': n_pvrows, |
122 | 117 | 'axis_azimuth': axis_azimuth, |
123 | 118 | 'pvrow_height': pvrow_height, |
124 | 119 | 'pvrow_width': pvrow_width, |
125 | | - 'gcr': gcr, |
126 | | - 'rho_front_pvrow': rho_front_pvrow, |
127 | | - 'rho_back_pvrow': rho_back_pvrow, |
| 120 | + 'gcr': gcr |
| 121 | + } |
| 122 | + |
| 123 | + irradiance_model_params = { |
| 124 | + 'rho_front': rho_front_pvrow, |
| 125 | + 'rho_back': rho_back_pvrow, |
128 | 126 | 'horizon_band_angle': horizon_band_angle |
129 | 127 | } |
130 | 128 |
|
131 | | - # Run pvfactors calculations: either in parallel or serially |
132 | | - if run_parallel_calculations: |
133 | | - report = run_parallel_engine( |
134 | | - PVFactorsReportBuilder, pvarray_parameters, |
135 | | - timestamps, dni, dhi, |
136 | | - solar_zenith, solar_azimuth, |
137 | | - surface_tilt, surface_azimuth, |
138 | | - albedo, n_processes=n_workers_for_parallel_calcs) |
139 | | - else: |
140 | | - report = run_timeseries_engine( |
141 | | - PVFactorsReportBuilder.build, pvarray_parameters, |
142 | | - timestamps, dni, dhi, |
143 | | - solar_zenith, solar_azimuth, |
144 | | - surface_tilt, surface_azimuth, |
145 | | - albedo) |
| 129 | + # Create report function |
| 130 | + def fn_build_report(pvarray): |
| 131 | + return {'total_inc_back': pvarray.ts_pvrows[index_observed_pvrow] |
| 132 | + .back.get_param_weighted('qinc'), |
| 133 | + 'total_inc_front': pvarray.ts_pvrows[index_observed_pvrow] |
| 134 | + .front.get_param_weighted('qinc'), |
| 135 | + 'total_abs_back': pvarray.ts_pvrows[index_observed_pvrow] |
| 136 | + .back.get_param_weighted('qabs'), |
| 137 | + 'total_abs_front': pvarray.ts_pvrows[index_observed_pvrow] |
| 138 | + .front.get_param_weighted('qabs')} |
| 139 | + |
| 140 | + # Run pvfactors calculations |
| 141 | + report = run_timeseries_engine( |
| 142 | + fn_build_report, pvarray_parameters, |
| 143 | + timestamps, dni, dhi, solar_zenith, solar_azimuth, |
| 144 | + surface_tilt, surface_azimuth, albedo, |
| 145 | + irradiance_model_params=irradiance_model_params) |
146 | 146 |
|
147 | 147 | # Turn report into dataframe |
148 | 148 | df_report = pd.DataFrame(report, index=timestamps) |
149 | 149 |
|
150 | | - return df_report.total_inc_front, df_report.total_inc_back |
151 | | - |
152 | | - |
153 | | -class PVFactorsReportBuilder(object): |
154 | | - """In pvfactors, a class is required to build reports when running |
155 | | - calculations with multiprocessing because of python constraints""" |
156 | | - |
157 | | - @staticmethod |
158 | | - def build(report, pvarray): |
159 | | - """Reports will have total incident irradiance on front and |
160 | | - back surface of center pvrow (index=1)""" |
161 | | - # Initialize the report as a dictionary |
162 | | - if report is None: |
163 | | - report = {'total_inc_back': [], 'total_inc_front': []} |
164 | | - # Add elements to the report |
165 | | - if pvarray is not None: |
166 | | - pvrow = pvarray.pvrows[1] # use center pvrow |
167 | | - report['total_inc_back'].append( |
168 | | - pvrow.back.get_param_weighted('qinc')) |
169 | | - report['total_inc_front'].append( |
170 | | - pvrow.front.get_param_weighted('qinc')) |
171 | | - else: |
172 | | - # No calculation is performed when the sun is down |
173 | | - report['total_inc_back'].append(np.nan) |
174 | | - report['total_inc_front'].append(np.nan) |
175 | | - |
176 | | - return report |
177 | | - |
178 | | - @staticmethod |
179 | | - def merge(reports): |
180 | | - """Works for dictionary reports. Merges the reports list of |
181 | | - dictionaries in a single dictionary. The list of the first |
182 | | - dictionary are extended by those of all subsequent lists.""" |
183 | | - report = reports[0] |
184 | | - keys_report = list(report.keys()) |
185 | | - for other_report in reports[1:]: # loop won't run if len(reports) < 2 |
186 | | - for key in keys_report: |
187 | | - report[key] += other_report[key] |
188 | | - return report |
| 150 | + return (df_report.total_inc_front, df_report.total_inc_back, |
| 151 | + df_report.total_abs_front, df_report.total_abs_back) |
0 commit comments