.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "_autogenerated_examples/300_module_efficiency/module_efficiency_demo.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr__autogenerated_examples_300_module_efficiency_module_efficiency_demo.py: Module efficiency models ======================== Fit seven models to sample measurements and find the best one. .. GENERATED FROM PYTHON SOURCE LINES 7-39 .. code-block:: Python from pvpltools.module_efficiency import ( adr, heydenreich, motherpv, pvgis, mpm5, mpm6, bilinear, ) from pvpltools.module_efficiency import fit_efficiency_model, fit_bilinear import numpy as np import pandas as pd import matplotlib import matplotlib.pyplot as plt from pathlib import Path import os # different current working directories for Sphinx-gallery / normal interpreter try: cwd = os.path.dirname(__file__) except NameError: cwd = os.getcwd() cwd = Path(cwd) matplotlib.style.use("classic") matplotlib.rcParams["figure.facecolor"] = "w" matplotlib.rcParams["axes.grid"] = True matplotlib.rcParams["lines.linewidth"] = 2 .. GENERATED FROM PYTHON SOURCE LINES 40-43 Now get some efficiency measurements to work with. A file containing module matrix measurements can be downloaded from the PVPMC website at https://pvpmc.sandia.gov/download/7701/. .. GENERATED FROM PYTHON SOURCE LINES 43-73 .. code-block:: Python # this is the filename of the data file under "examples/data" measurements_file = cwd.parent.joinpath( "data", "Sandia_PV_Module_P-Matrix-and-TempCo-Data_2019.xlsx" ) # The first sheet is for the Panasonic HIT module TYPE = "Panasonic HIT" matrix = pd.read_excel( measurements_file, sheet_name=0, usecols="B,C,H", header=None, skiprows=5, nrows=27, ) matrix.columns = ["temperature", "irradiance", "p_mp"] # calculate efficiency from power matrix = matrix.eval("eta = p_mp / irradiance") eta_stc = matrix.query("irradiance == 1000 and temperature == 25").eta matrix.eta /= eta_stc.values # just keep the columns that are needed matrix = matrix[["irradiance", "temperature", "eta"]] matrix .. raw:: html
irradiance temperature eta
0 100 15 0.935730
1 200 15 0.978227
2 400 15 1.007194
3 600 15 1.022552
4 800 15 1.027077
5 1000 15 1.026549
6 100 25 0.907523
7 200 25 0.948437
8 400 25 0.980789
9 600 25 0.994289
10 800 25 0.998903
11 1000 25 1.000000
12 1100 25 0.998982
13 100 50 0.833199
14 200 50 0.879565
15 400 50 0.908011
16 600 50 0.920241
17 800 50 0.925466
18 1000 50 0.927551
19 1100 50 0.926319
20 100 75 0.746943
21 200 75 0.792776
22 400 75 0.826435
23 600 75 0.842713
24 800 75 0.847741
25 1000 75 0.849045
26 1100 75 0.849035


.. GENERATED FROM PYTHON SOURCE LINES 74-76 it really is matrix data this becomes more obvious when you pivot it .. GENERATED FROM PYTHON SOURCE LINES 76-82 .. code-block:: Python grid = matrix.pivot(index="irradiance", columns="temperature", values="eta") grid .. raw:: html
temperature 15 25 50 75
irradiance
100 0.935730 0.907523 0.833199 0.746943
200 0.978227 0.948437 0.879565 0.792776
400 1.007194 0.980789 0.908011 0.826435
600 1.022552 0.994289 0.920241 0.842713
800 1.027077 0.998903 0.925466 0.847741
1000 1.026549 1.000000 0.927551 0.849045
1100 NaN 0.998982 0.926319 0.849035


.. GENERATED FROM PYTHON SOURCE LINES 83-84 now fit my favorite model .. GENERATED FROM PYTHON SOURCE LINES 84-94 .. code-block:: Python popt, pcov = fit_efficiency_model( matrix.irradiance, matrix.temperature, matrix.eta, adr, ) popt .. rst-class:: sphx-glr-script-out .. code-block:: none array([ 0.99879112, -5.85209308, 0.01939665, 0.0696307 , 0.21036569]) .. GENERATED FROM PYTHON SOURCE LINES 95-96 wait, it can't be that easy! .. GENERATED FROM PYTHON SOURCE LINES 96-100 .. code-block:: Python adr(600, 15, *popt) .. rst-class:: sphx-glr-script-out .. code-block:: none np.float64(1.022515949060066) .. GENERATED FROM PYTHON SOURCE LINES 101-102 yes it can .. GENERATED FROM PYTHON SOURCE LINES 105-106 define some ranges for plotting .. GENERATED FROM PYTHON SOURCE LINES 106-111 .. code-block:: Python ggg = np.logspace(-0.1, 3.1, 51) tt = np.array([0, 15, 25, 50, 75, 90]) .. GENERATED FROM PYTHON SOURCE LINES 112-113 Plot the results .. GENERATED FROM PYTHON SOURCE LINES 113-124 .. code-block:: Python plt.figure() for t in tt: plt.plot(ggg, adr(ggg, t, *popt)) plt.plot(grid, "ko") plt.title("Nice fit for model %s on module %s" % ("ADR", TYPE)) .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_001.png :alt: Nice fit for model ADR on module Panasonic HIT :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Text(0.5, 1.0, 'Nice fit for model ADR on module Panasonic HIT') .. GENERATED FROM PYTHON SOURCE LINES 125-126 Gather plotting commands into a convenient function .. GENERATED FROM PYTHON SOURCE LINES 126-154 .. code-block:: Python def plot_model(model, params): ggg = np.logspace(-0.1, 3.1, 51) tt = np.array([0, 15, 25, 50, 75, 90]) plt.figure() plt.gca().set_prop_cycle( "color", plt.cm.rainbow(np.linspace(0, 1, len(tt))) ) for t in tt: plt.plot(ggg, model(ggg, t, *params)) plt.xlim(-50, 1350) plt.ylim(0.45, 1.15) plt.xlabel("Irradiance [W/m²]") plt.ylabel("Relative efficiency") plt.legend(tt, title="Temperature", ncol=2, loc="best") plt.title(model.__name__.upper()) return plt.gca() ax = plot_model(adr, popt) ax.plot(grid, "ko") .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_002.png :alt: ADR :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none [, , , ] .. GENERATED FROM PYTHON SOURCE LINES 155-156 now run and plot all the available models .. GENERATED FROM PYTHON SOURCE LINES 156-170 .. code-block:: Python models = [bilinear, heydenreich, motherpv, pvgis, mpm5, mpm6, adr] for model in models: if model is bilinear: interpolator = fit_bilinear(**matrix) popt = [interpolator] else: popt, pcov = fit_efficiency_model(**matrix, model=model) plot_model(model, popt) plt.plot(grid, "ko") .. rst-class:: sphx-glr-horizontal * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_003.png :alt: BILINEAR :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_003.png :class: sphx-glr-multi-img * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_004.png :alt: HEYDENREICH :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_004.png :class: sphx-glr-multi-img * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_005.png :alt: MOTHERPV :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_005.png :class: sphx-glr-multi-img * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_006.png :alt: PVGIS :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_006.png :class: sphx-glr-multi-img * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_007.png :alt: MPM5 :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_007.png :class: sphx-glr-multi-img * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_008.png :alt: MPM6 :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_008.png :class: sphx-glr-multi-img * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_009.png :alt: ADR :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_009.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 171-172 make a function to calculate rms error .. GENERATED FROM PYTHON SOURCE LINES 172-190 .. code-block:: Python def efficiency_model_rmse(irradiance, temperature, eta, model, p): from numpy import sqrt as root, mean, square eta_hat = model(irradiance, temperature, *p) return root(mean(square(eta_hat - eta))) rmse = efficiency_model_rmse( matrix.irradiance, matrix.temperature, matrix.eta, model, popt ) print(TYPE, model.__name__.upper(), rmse) .. rst-class:: sphx-glr-script-out .. code-block:: none Panasonic HIT ADR 0.002028199009144769 .. GENERATED FROM PYTHON SOURCE LINES 191-192 compare the models .. GENERATED FROM PYTHON SOURCE LINES 192-206 .. code-block:: Python for model in models: if model is bilinear: interpolator = fit_bilinear(**matrix) popt = [interpolator] else: popt, pcov = fit_efficiency_model(**matrix, model=model) rmse = efficiency_model_rmse(**matrix, model=model, p=popt) print("%20s, %-20s %.5f" % (TYPE, model.__name__.upper(), rmse)) .. rst-class:: sphx-glr-script-out .. code-block:: none Panasonic HIT, BILINEAR 2.30300 Panasonic HIT, HEYDENREICH 0.00605 Panasonic HIT, MOTHERPV 0.00249 Panasonic HIT, PVGIS 0.00158 Panasonic HIT, MPM5 0.00291 Panasonic HIT, MPM6 0.00279 Panasonic HIT, ADR 0.00203 .. GENERATED FROM PYTHON SOURCE LINES 207-208 now run one of the harder tests: extrapolating to the low irradiance values .. GENERATED FROM PYTHON SOURCE LINES 208-225 .. code-block:: Python subset_fit = matrix.query("irradiance > 200") subset_err = matrix.query("irradiance <= 200") for model in models: if model is bilinear: interpolator = fit_bilinear(**subset_fit) popt = [interpolator] else: popt, pcov = fit_efficiency_model(**subset_fit, model=model) rmse = efficiency_model_rmse(**subset_err, model=model, p=popt) print("%20s, %-20s %.5f" % (TYPE, model.__name__.upper(), rmse)) .. rst-class:: sphx-glr-script-out .. code-block:: none Panasonic HIT, BILINEAR 0.40747 Panasonic HIT, HEYDENREICH 0.02965 Panasonic HIT, MOTHERPV 0.15097 Panasonic HIT, PVGIS 0.02889 Panasonic HIT, MPM5 0.00490 Panasonic HIT, MPM6 0.08156 Panasonic HIT, ADR 0.00401 .. GENERATED FROM PYTHON SOURCE LINES 226-227 the graphs make these differences more striking .. GENERATED FROM PYTHON SOURCE LINES 227-239 .. code-block:: Python for model in models: if model is bilinear: interpolator = fit_bilinear(**subset_fit) popt = [interpolator] else: popt, pcov = fit_efficiency_model(**subset_fit, model=model) plot_model(model, popt) plt.plot(grid, "ko") .. rst-class:: sphx-glr-horizontal * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_010.png :alt: BILINEAR :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_010.png :class: sphx-glr-multi-img * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_011.png :alt: HEYDENREICH :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_011.png :class: sphx-glr-multi-img * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_012.png :alt: MOTHERPV :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_012.png :class: sphx-glr-multi-img * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_013.png :alt: PVGIS :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_013.png :class: sphx-glr-multi-img * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_014.png :alt: MPM5 :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_014.png :class: sphx-glr-multi-img * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_015.png :alt: MPM6 :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_015.png :class: sphx-glr-multi-img * .. image-sg:: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_016.png :alt: ADR :srcset: /_autogenerated_examples/300_module_efficiency/images/sphx_glr_module_efficiency_demo_016.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 240-243 just one small detail missing: the last parameter of MPM6 should not be larger than zero so bounds need to be defined for all its parameters .. GENERATED FROM PYTHON SOURCE LINES 243-266 .. code-block:: Python MPM6_BOUNDS = ( [ -np.inf, -np.inf, -np.inf, -np.inf, -np.inf, ], [+np.inf, +np.inf, +np.inf, +np.inf, 0.0], ) model = mpm6 popt, pcov = fit_efficiency_model( **subset_fit, model=model, bounds=MPM6_BOUNDS ) rmse = efficiency_model_rmse(**subset_err, model=model, p=popt) print("%-20s %-20s RMSE = %.5f" % (TYPE, model.__name__.upper(), rmse)) print("popt =", popt) .. rst-class:: sphx-glr-script-out .. code-block:: none Panasonic HIT MPM6 RMSE = 0.08156 popt = [ 1.03574966 -0.00299249 -0.04758015 -0.00717004 -0.0290341 ] .. GENERATED FROM PYTHON SOURCE LINES 267-268 in this case the bounds did not influence the result .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.846 seconds) .. _sphx_glr_download__autogenerated_examples_300_module_efficiency_module_efficiency_demo.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: module_efficiency_demo.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: module_efficiency_demo.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: module_efficiency_demo.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_