<jupyter_start><jupyter_text>Tutorial 3 - Module TemperatureThis notebook shows how to use pvlib to estimate PV cell temperature, a secondary driver that affects the PV conversion efficiency.![Overview](images/tutorial_3_overview.PNG)  PV Concepts in this lesson: Python concepts in this lesson:  What affects module temperature?If PV modules were 100% efficient, they would convert 100% of collected irradiance into electrical energy.  However, today's PV modules are on the order of 20% efficient, meaning the other 80% of sunlight is converted to thermal enregy.  This thermal energy causes the temperature of the module to rise above ambient conditions, eventually reaching a steady state defined by a heat balance of power in (solar irradiance) vs power out (thermal radiation, convective cooling, etc).  With that in mind, the primary drivers of module temperature are POA irradiance, ambient temperature, and wind speed. A distinction that is often ignored is the difference between module temperature and cell temperature.  In theory, the temperature of the P-N junction inside the cell is what affects conversion efficiency, but this is difficult to measure.  In practice, the temperature of the module backsheet is often a usable approximation, though it is often 1-2 degrees Celsius cooler than the junction temperature. Modeling module temperatureSome PV thermal models go to the trouble of modeling the entire heat balance equation, but much simpler models are available and are often accurate enough.  Here we will use the thermal model from the Sandia Array Performance Model (SAPM) to estimate cell temperature from ambient conditions.  The SAPM thermal model takes only POA irradiance, ambient temperature, and wind speed as weather inputs, but it also requires a set of parameters that characterize the thermal properties of the module of interest.  More on that later.First, let's use the procedure of previous tutorials to get the relevant inputs for a tracking array:<jupyter_code>import pvlib
import pandas as pd  # for data wrangling
import matplotlib.pyplot as plt  # for visualization
import pathlib  # for finding the example dataset

print(pvlib.__version__)
DATA_DIR = pathlib.Path(pvlib.__file__).parent / 'data'
df_tmy, metadata = pvlib.iotools.read_tmy3(DATA_DIR / '723170TYA.CSV', coerce_year=1990)

location = pvlib.location.Location(latitude=metadata['latitude'],
                                   longitude=metadata['longitude'])

times = df_tmy.index - pd.Timedelta('30min')
solar_position = location.get_solarposition(times)
solar_position.index += pd.Timedelta('30min')

tracker_data = pvlib.tracking.singleaxis(solar_position['apparent_zenith'],
                                         solar_position['azimuth'],
                                         axis_azimuth=180,
                                         )
tilt = tracker_data['surface_tilt'].fillna(0)
azimuth = tracker_data['surface_azimuth'].fillna(0)

df_poa_tracker = pvlib.irradiance.get_total_irradiance(surface_tilt=tilt,
                                                       surface_azimuth=azimuth,
                                                       dni=df_tmy['DNI'],
                                                       ghi=df_tmy['GHI'],
                                                       dhi=df_tmy['DHI'],
                                                       solar_zenith=solar_position['apparent_zenith'],
                                                       solar_azimuth=solar_position['azimuth'])
tracker_poa = df_poa_tracker['poa_global']<jupyter_output><empty_output><jupyter_text>Now that we have the necessary weather inputs, all that is left are the thermal parameters.  These characterize the thermal properties of the module as well as the module's mounting configuration.  Parameter values covering the common system designs are provided with pvlib:<jupyter_code>all_parameters = pvlib.temperature.TEMPERATURE_MODEL_PARAMETERS['sapm']
list(all_parameters.keys())<jupyter_output><empty_output><jupyter_text>`open_rack_glass_polymer` is appropriate for many large-scale systems (polymer backsheet; open racking), so we will use it here:<jupyter_code>parameters = all_parameters['open_rack_glass_polymer']
cell_temperature = pvlib.temperature.sapm_cell(tracker_poa,
                                               df_tmy['DryBulb'],
                                               df_tmy['Wspd'],
                                               **parameters)<jupyter_output><empty_output><jupyter_text>Now let's compare ambient temperature with cell temperature.  Notice how our modeled cell temperature rises significantly above ambient temperature during the day, especially on sunny days:<jupyter_code>df_tmy['DryBulb'].head(24*7).plot()
cell_temperature.head(24*7).plot()
plt.ylabel('Temperature [°C]');<jupyter_output><empty_output><jupyter_text>Wind speed also has an effect, but it's harder to see in a time series plot like this.  To make it clearer, let's make a scatter plot:<jupyter_code>temperature_difference = cell_temperature - df_tmy['DryBulb']
plt.scatter(tracker_poa, temperature_difference, c=df_tmy['Wspd'])
plt.colorbar()
plt.ylabel('Temperature rise above ambient [°C]')
plt.xlabel('POA Irradiance [W/m^2]');
plt.title('Cell temperature rise, colored by wind speed');<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.06873365707881958, 'fraction_numerical': 0.007657825924542398, 'mean_word_length': 3.3501218521527214, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '171888', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 1440, 'n_tokens_neox': 1336, 'n_words': 493, 'path': 'Tutorial 3 - Module Temperature.ipynb', 'repo_name': 'jdnewmil/PVSC48-Python-Tutorial', 'size': '5354'}