graph TD
A[Start: What result is needed?] --> B{Need physical IV behavior?}
B -- No --> C[Use PVWATTS_LOSSES for loss stack]
B -- Yes --> D{Have SAPM coefficients?}
D -- Yes --> E[Run SAPM_EFF_IRRAD]
E --> F[Run SAPM]
D -- No --> G{Have De Soto or PVsyst params?}
G -- De Soto --> H[Run CALCPARAMS_DESOTO]
G -- PVsyst --> I[Run CALCPARAMS_PVSYST]
H --> J[Run SINGLEDIODE or MAX_POWER_POINT]
I --> J
J --> K{Need voltage at fixed current?}
K -- Yes --> L[Run V_FROM_I]
K -- No --> M[Use MPP/IV outputs directly]
Module Models
Overview
Introduction PV module models are mathematical representations of how a photovoltaic module converts irradiance and temperature into electrical output (current, voltage, and power). In practical system modeling, the module model is the layer that connects weather and geometry inputs to AC energy estimates, clipping risk, degradation analysis, and financial forecasts. The most common physical framework is the single-diode model, which approximates PV cell behavior with a current source, a diode, and parasitic resistances. In production workflows, these equations are widely implemented through pvlib-python, and this category exposes key pvlib methods in spreadsheet-friendly form.
This category is especially important because small modeling choices can produce large annual-energy and revenue differences. A mismatch between parameter-extraction assumptions and solver assumptions can bias maximum-power predictions. A simplified loss stack can either understate or overstate net production, especially when portfolio comparisons rely on one number like performance ratio or P50 yield. Teams that need defensible results typically separate the problem into layers: derive physically consistent model parameters, solve operating points robustly, and then apply bankable system-level derates.
The calculators in this category align to exactly that workflow. CALCPARAMS_DESOTO and CALCPARAMS_PVSYST translate irradiance and temperature into single-diode coefficients. SINGLEDIODE solves the equation to produce IV key points. MAX_POWER_POINT focuses directly on the optimal operating point, while V_FROM_I solves for voltage at a specified current. In parallel, the Sandia path uses SAPM_EFF_IRRAD to form effective irradiance and SAPM to compute key IV outputs using SAPM coefficients. Finally, PVWATTS_LOSSES converts component-level derates into a total system loss percentage. Together, these tools support both engineering-grade physical modeling and decision-grade portfolio analysis.
From a business perspective, this category supports three high-value objectives: improving forecast credibility, accelerating scenario analysis, and increasing auditability. Forecast credibility improves when assumptions are explicit and physically coherent. Scenario analysis accelerates because the calculators are modular and can be chained in tabular models. Auditability improves because each output can be traced to a specific equation family and parameter set, which is essential in lender technical reviews and internal investment committees.
When to Use It Use this category when the job is to convert irradiance and temperature into realistic module power outputs, not just to apply a single blanket derate. A typical signal that these functions are needed is when project decisions depend on thermal sensitivity, low-light behavior, row-level mismatch assumptions, or technology-specific model choices.
One common job is utility-scale yield forecasting with technology-specific detail. An analyst receives TMY weather data and module datasheet/test parameters and must estimate annual DC production under different module options (for example, mono-PERC versus thin-film). The De Soto or PVsyst parameter route is used first: CALCPARAMS_DESOTO for De Soto assumptions, or CALCPARAMS_PVSYST when PVsyst-style parameterization is preferred. Then SINGLEDIODE or MAX_POWER_POINT provides operating points for each timestep. If inverter loading ratio studies require current-constrained evaluations, V_FROM_I is used for voltage-at-current checks. This path is ideal when the question is “Which module and DC/AC configuration gives better annual and shoulder-hour performance?”
Another common job is portfolio screening where speed and comparability matter more than deep device physics. Early-stage developers often need fast, consistent assumptions across many sites before committing to detailed simulation. In that case, PVWATTS_LOSSES is used to build standardized loss stacks (soiling, wiring, mismatch, availability, and age) that are directly comparable across opportunities. This does not replace IV modeling, but it provides a normalized “net-loss layer” that supports quick go/no-go ranking and sensitivity sweeps.
A third frequent job is operations and performance diagnostics. During underperformance investigations, teams often need to test whether measured string behavior is physically plausible under current weather conditions. CALCPARAMS_DESOTO or CALCPARAMS_PVSYST computes expected single-diode parameters at the observed irradiance/temperature; SINGLEDIODE then yields expected IV landmarks. If SCADA provides operating current but not module-level voltage certainty, V_FROM_I helps estimate expected voltage behavior at that current. MAX_POWER_POINT helps isolate whether MPP tracking appears consistent with modeled capability.
This category is also used when teams adopt the Sandia modeling pathway for modules with known SAPM coefficients. SAPM_EFF_IRRAD maps POA direct/diffuse irradiance, airmass, and AOI to effective irradiance at the cell level; SAPM then computes key IV points and power. This is valuable when spectral and angle-of-incidence effects need to be captured with coefficient-based empirical detail.
In short, use this category when decisions depend on either physical consistency or transparent model decomposition. Avoid relying on a single simplified loss percentage alone when choices hinge on temperature response, recombination effects, or electrical operating constraints.
How It Works The category combines two major modeling families from pvlib: single-diode equation methods and Sandia empirical methods, plus a system-loss aggregation model. Core references are in pvlib.pvsystem.
At the center is the single-diode equation, commonly expressed as
I = I_L - I_0\left[\exp\left(\frac{V + I R_s}{nN_sV_{th}}\right)-1\right] - \frac{V + I R_s}{R_{sh}},
where I_L is photocurrent, I_0 is diode saturation current, R_s is series resistance, R_{sh} is shunt resistance, and nN_sV_{th} is the thermal/ideality term. This equation is implicit in I and V, so practical modeling requires stable numerical or semi-analytic solvers.
CALCPARAMS_DESOTO and CALCPARAMS_PVSYST do not solve the IV curve by themselves; they compute the five coefficients needed by downstream solvers at each irradiance-temperature condition. The key distinction is parameterization philosophy:
- De Soto route (CALCPARAMS_DESOTO): widely used for physically motivated translation from reference-condition parameters to operating conditions, including bandgap temperature dependencies.
- PVsyst route (CALCPARAMS_PVSYST): follows PVsyst-oriented assumptions, including shunt-resistance behavior and optional recombination-related terms often relevant to some thin-film behaviors.
After coefficients are known, SINGLEDIODE computes canonical IV landmarks such as I_{sc}, V_{oc}, I_{mp}, V_{mp}, and P_{mp}. MAX_POWER_POINT directly finds (I_{mp},V_{mp},P_{mp}) and can use solver options such as Brent methods for robustness. V_FROM_I inverts the relation at a specified current to retrieve voltage, useful in string-operating diagnostics and controller constraints.
For maximum power specifically, the conceptual optimization target is
P(V)=V\,I(V),\qquad V_{mp}=\arg\max_V P(V),\qquad I_{mp}=I(V_{mp}).
Because I(V) itself is governed by the implicit single-diode equation, stable root-finding is central to numerical reliability. In practice, solver choice can affect runtime and edge-case behavior more than central-case results.
The Sandia path is structured differently. SAPM_EFF_IRRAD first constructs effective irradiance from direct and diffuse POA components adjusted by spectral and incidence-angle modifiers. A simplified conceptual form is
E_e = E_b\,f_2(\text{AOI})\,f_1(AM_a) + f_d\,E_d,
where E_b and E_d are beam and diffuse POA irradiance, AM_a is absolute airmass, and the functions are coefficient-based correction terms. SAPM then uses E_e, temperature, and module coefficients to compute key IV quantities and maximum power. This coefficient-driven approach can be very effective when reliable SAPM parameter sets are available.
PVWATTS_LOSSES is not an IV solver; it is a multiplicative derate combiner used in NREL PVWatts-style workflows. If losses are L_i in percent, total retained fraction is
f_{\text{retained}}=\prod_i\left(1-\frac{L_i}{100}\right),
and total losses are
L_{\text{total}}=100\,(1-f_{\text{retained}}).
This matters because simply summing percentages can overstate losses when multiple derates are sequentially applied.
Important assumptions and checks for this category:
- Units must remain consistent: irradiance in W/m², temperature in °C where expected by interface wrappers, and resistances in ohms.
- Parameter provenance matters: De Soto inputs, PVsyst inputs, and SAPM coefficient sets are not interchangeable without conversion.
- Solver settings can influence convergence speed and sometimes edge behavior near extreme operating points.
- Loss modeling scope should be explicit: PVWATTS_LOSSES captures system-level derates, not internal IV physics.
The practical strength of this category is composability: one can chain parameter calculation, IV solving, MPP extraction, and final derating in a transparent pipeline that remains aligned with pvlib’s reference implementations.
Practical Example Consider a developer evaluating a 75 MWdc project with two module options and a financing deadline. The team needs a decision in one week: select the module that maximizes annual net revenue while controlling uncertainty in shoulder-hour performance.
Step 1: Build weather-to-module inputs. The team starts with site POA irradiance components, cell temperature estimates, and airmass series. They define module reference parameters for both candidates, including whichever parameter family is available from vendor data and third-party tests.
Step 2: Run two parallel physical pathways for cross-checking. For each hourly point, they compute single-diode coefficients via CALCPARAMS_DESOTO for one baseline and CALCPARAMS_PVSYST for a sensitivity case. This allows comparison of model-family dependence, which is useful when lenders ask about methodology robustness.
Step 3: Solve electrical operating points. They run SINGLEDIODE to obtain IV key points and MAX_POWER_POINT to verify MPP consistency in a direct solver-focused path. If a subset of hours has current-constrained conditions from plant controls, V_FROM_I computes expected voltage at those currents and flags any unrealistic operating regions.
Step 4: Execute Sandia coefficient pathway for modules with validated SAPM sets. They compute effective irradiance using SAPM_EFF_IRRAD, then derive IV/power outputs with SAPM. This creates an empirical counterpart to the single-diode route and helps determine whether module ranking is stable across modeling approaches.
Step 5: Apply system derates consistently across scenarios. The team sets a shared loss stack (soiling, mismatch, wiring, availability, and age assumptions) and computes total loss with PVWATTS_LOSSES. This ensures that differences between module scenarios are driven by module behavior rather than inconsistent derating arithmetic.
Step 6: Aggregate decision metrics. They summarize annual DC energy, clipped energy sensitivity, quarterly shoulder-hour contribution, and downside cases under high-temperature weeks. Because all pathways are modular, they can quickly isolate why one candidate outperforms: lower thermal penalty, better low-light effective irradiance response, or superior MPP stability.
Step 7: Present decision narrative. The selected module is the one that wins net-revenue weighted metrics and remains robust across De Soto/PVsyst/SAPM comparisons. The team can document assumptions at each stage and defend them in technical due diligence.
This workflow demonstrates Boardflare’s dual pillar strategy in action: physically grounded engineering calculators for model fidelity and spreadsheet-operable structures for fast commercial decision-making.
How to Choose The most reliable selection method is to choose by modeling task, then by available parameter set, then by required output granularity. The table below maps each function to its best-fit job.
| Decision Need | Recommended Function | Best Input Context | Main Output | Strengths | Limits / Cautions |
|---|---|---|---|---|---|
| Convert irradiance + temperature into single-diode coefficients using De Soto assumptions | CALCPARAMS_DESOTO | Reference single-diode parameters with De Soto-compatible terms | I_L, I_0, R_s, R_{sh}, nN_sV_{th} | Physically interpretable, widely used in PV modeling chains | Requires consistent reference parameters; wrong provenance can bias results |
| Convert irradiance + temperature into single-diode coefficients using PVsyst assumptions | CALCPARAMS_PVSYST | PVsyst-style module parameter sets | I_L, I_0, R_s, R_{sh}, nN_sV_{th} | Aligns with PVsyst-oriented assumptions and variants | Not interchangeable with De Soto inputs without care |
| Solve full IV key points from single-diode coefficients | SINGLEDIODE | Coefficients already computed at operating condition | I_{sc},V_{oc},I_{mp},V_{mp},P_{mp},I_x,I_{xx} | Complete electrical snapshot in one call | Solver choice and numeric conditions matter in edge cases |
| Extract only maximum-power operating point | MAX_POWER_POINT | Single-diode coefficients with optional recombination terms | I_{mp},V_{mp},P_{mp} | Focused MPP solution; useful for dispatch and clipping studies | Less comprehensive than full IV landmark output |
| Compute voltage for a known operating current | V_FROM_I | Current target + single-diode coefficients | Voltage at specified current | Ideal for diagnostics and controller-constrained states | Depends on realistic coefficient values and solver behavior |
| Convert POA components to effective irradiance in SAPM framework | SAPM_EFF_IRRAD | POA direct/diffuse, airmass, AOI, SAPM coefficients | Effective irradiance | Captures spectral and AOI modifiers in empirical form | Needs credible SAPM coefficients |
| Compute SAPM IV points and power | SAPM | Effective irradiance, temperature, SAPM module coefficients | IV key points and power | Strong empirical pathway with established parameter sets | Coefficient quality determines reliability |
| Combine system-level loss percentages | PVWATTS_LOSSES | Derate assumptions by loss component | Total percent loss | Fast, transparent, portfolio-comparable | Not a replacement for physical IV modeling |
Use this decision flow for most projects:
Practical selection guidance:
- Choose SINGLEDIODE when complete IV landmarks are required for engineering reports.
- Choose MAX_POWER_POINT when optimization and dispatch analysis center on P_{mp} rather than full curve descriptors.
- Choose V_FROM_I when current is known from controls or measurements and voltage must be inferred.
- Choose SAPM_EFF_IRRAD + SAPM when a validated SAPM coefficient set exists and spectral/AOI treatment is desired.
- Choose PVWATTS_LOSSES as a standardized derate layer, not as a substitute for module physics.
Teams usually get the best results by using both pillars together: physical model pathways for technical fidelity and standardized loss aggregation for comparability across business scenarios.
CALCPARAMS_DESOTO
This function translates reference single-diode parameters to operating conditions using the De Soto photovoltaic module model. It adjusts the light-generated current, diode saturation current, shunt resistance, and thermal-voltage term for the supplied irradiance and cell temperature while preserving the series resistance reference value.
A key relationship in the model is the irradiance and temperature adjustment of photocurrent:
I_L = \frac{G}{G_{ref}} \left(I_{L,ref} + \alpha_{sc}(T_c - T_{ref})\right)
The returned values are ordered as photocurrent, saturation current, series resistance, shunt resistance, and nN_sV_{th}. These outputs are intended to be passed directly into the single-diode solvers such as singlediode or max_power_point.
Excel Usage
=CALCPARAMS_DESOTO(effective_irradiance, temp_cell, alpha_sc, a_ref, I_L_ref, I_o_ref, R_sh_ref, R_s, EgRef, dEgdT, irrad_ref, temp_ref)
effective_irradiance(float, required): Irradiance converted to photocurrent (W/m^2).temp_cell(float, required): Average cell temperature (C).alpha_sc(float, required): Short-circuit current temp coefficient (A/C).a_ref(float, required): Modified diode ideality factor term at reference (V).I_L_ref(float, required): Light-generated current at reference (A).I_o_ref(float, required): Diode saturation current at reference (A).R_sh_ref(float, required): Shunt resistance at reference (ohms).R_s(float, required): Series resistance at reference (ohms).EgRef(float, optional, default: 1.121): Energy bandgap at reference temperature (eV).dEgdT(float, optional, default: -0.0002677): Temperature dependence of energy bandgap (1/K).irrad_ref(float, optional, default: 1000): Reference irradiance (W/m^2).temp_ref(float, optional, default: 25): Reference cell temperature (C).
Returns (list[list]): 2D list containing [[photocurrent, saturation_current, resistance_series, resistance_shunt, nNsVth]], or an error string.
Example 1: Standard test conditions
Inputs:
| effective_irradiance | temp_cell | alpha_sc | a_ref | I_L_ref | I_o_ref | R_sh_ref | R_s | EgRef | dEgdT | irrad_ref | temp_ref |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1000 | 25 | 0.004 | 1.5 | 5.5 | 2e-10 | 300 | 0.5 | 1.121 | -0.0002677 | 1000 | 25 |
Excel formula:
=CALCPARAMS_DESOTO(1000, 25, 0.004, 1.5, 5.5, 2e-10, 300, 0.5, 1.121, -0.0002677, 1000, 25)
Expected output:
| Result | ||||
|---|---|---|---|---|
| 5.5 | 2e-10 | 0.5 | 300 | 1.5 |
Example 2: Default reference constants
Inputs:
| effective_irradiance | temp_cell | alpha_sc | a_ref | I_L_ref | I_o_ref | R_sh_ref | R_s |
|---|---|---|---|---|---|---|---|
| 1000 | 25 | 0.004 | 1.5 | 5.5 | 2e-10 | 300 | 0.5 |
Excel formula:
=CALCPARAMS_DESOTO(1000, 25, 0.004, 1.5, 5.5, 2e-10, 300, 0.5)
Expected output:
| Result | ||||
|---|---|---|---|---|
| 5.5 | 2e-10 | 0.5 | 300 | 1.5 |
Example 3: Reduced irradiance and warmer cell
Inputs:
| effective_irradiance | temp_cell | alpha_sc | a_ref | I_L_ref | I_o_ref | R_sh_ref | R_s | EgRef | dEgdT | irrad_ref | temp_ref |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 800 | 45 | 0.004 | 1.5 | 5.5 | 2e-10 | 300 | 0.5 | 1.121 | -0.0002677 | 1000 | 25 |
Excel formula:
=CALCPARAMS_DESOTO(800, 45, 0.004, 1.5, 5.5, 2e-10, 300, 0.5, 1.121, -0.0002677, 1000, 25)
Expected output:
| Result | ||||
|---|---|---|---|---|
| 4.464 | 4.69768e-9 | 0.5 | 375 | 1.60062 |
Example 4: Cool cell at elevated irradiance
Inputs:
| effective_irradiance | temp_cell | alpha_sc | a_ref | I_L_ref | I_o_ref | R_sh_ref | R_s | EgRef | dEgdT | irrad_ref | temp_ref |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1100 | 10 | 0.004 | 1.5 | 5.5 | 2e-10 | 300 | 0.5 | 1.121 | -0.0002677 | 1000 | 25 |
Excel formula:
=CALCPARAMS_DESOTO(1100, 10, 0.004, 1.5, 5.5, 2e-10, 300, 0.5, 1.121, -0.0002677, 1000, 25)
Expected output:
| Result | ||||
|---|---|---|---|---|
| 5.984 | 1.41199e-11 | 0.5 | 272.727 | 1.42453 |
Python Code
Show Code
from pvlib.pvsystem import calcparams_desoto as result_func
def calcparams_desoto(effective_irradiance, temp_cell, alpha_sc, a_ref, I_L_ref, I_o_ref, R_sh_ref, R_s, EgRef=1.121, dEgdT=-0.0002677, irrad_ref=1000, temp_ref=25):
"""
Calculate five single-diode model parameter values using the De Soto model.
See: https://pvlib-python.readthedocs.io/en/stable/reference/generated/pvlib.pvsystem.calcparams_desoto.html
This example function is provided as-is without any representation of accuracy.
Args:
effective_irradiance (float): Irradiance converted to photocurrent (W/m^2).
temp_cell (float): Average cell temperature (C).
alpha_sc (float): Short-circuit current temp coefficient (A/C).
a_ref (float): Modified diode ideality factor term at reference (V).
I_L_ref (float): Light-generated current at reference (A).
I_o_ref (float): Diode saturation current at reference (A).
R_sh_ref (float): Shunt resistance at reference (ohms).
R_s (float): Series resistance at reference (ohms).
EgRef (float, optional): Energy bandgap at reference temperature (eV). Default is 1.121.
dEgdT (float, optional): Temperature dependence of energy bandgap (1/K). Default is -0.0002677.
irrad_ref (float, optional): Reference irradiance (W/m^2). Default is 1000.
temp_ref (float, optional): Reference cell temperature (C). Default is 25.
Returns:
list[list]: 2D list containing [[photocurrent, saturation_current, resistance_series, resistance_shunt, nNsVth]], or an error string.
"""
try:
irrad = float(effective_irradiance)
tc = float(temp_cell)
asc = float(alpha_sc)
ar = float(a_ref)
ilr = float(I_L_ref)
ior = float(I_o_ref)
rshr = float(R_sh_ref)
rs = float(R_s)
eg = float(EgRef) if EgRef is not None else 1.121
dt = float(dEgdT) if dEgdT is not None else -0.0002677
ir = float(irrad_ref) if irrad_ref is not None else 1000.0
tr = float(temp_ref) if temp_ref is not None else 25.0
# Returns tuple: photocurrent, saturation_current, resistance_series, resistance_shunt, nNsVth
res = result_func(
effective_irradiance=irrad,
temp_cell=tc,
alpha_sc=asc,
a_ref=ar,
I_L_ref=ilr,
I_o_ref=ior,
R_sh_ref=rshr,
R_s=rs,
EgRef=eg,
dEgdT=dt,
irrad_ref=ir,
temp_ref=tr
)
return [[float(v) for v in res]]
except Exception as e:
return f"Error: {str(e)}"Online Calculator
CALCPARAMS_PVSYST
This function converts PVsyst reference module parameters into the operating-condition coefficients required by the single-diode equation. It accounts for irradiance, cell temperature, the PVsyst diode-factor model, and the irradiance dependence of shunt resistance.
The thermal-voltage term returned by the model is based on the diode factor, cells in series, and cell temperature:
nN_sV_{th} = \gamma N_s \frac{k_B T_c}{q}
The five outputs are returned in the order photocurrent, saturation current, series resistance, shunt resistance, and nN_sV_{th}. These values are typically used as inputs to singlediode, max_power_point, or related IV-curve calculations.
Excel Usage
=CALCPARAMS_PVSYST(effective_irradiance, temp_cell, alpha_sc, gamma_ref, mu_gamma, I_L_ref, I_o_ref, R_sh_ref, R_sh_zero, R_s, cells_in_series, R_sh_exp, eg_ref, irrad_ref, temp_ref)
effective_irradiance(float, required): Irradiance converted to photocurrent (W/m^2).temp_cell(float, required): Average cell temperature (C).alpha_sc(float, required): Short-circuit current temp coefficient (A/C).gamma_ref(float, required): Diode ideality factor (unitless).mu_gamma(float, required): Temp coefficient for ideality factor (1/K).I_L_ref(float, required): Light-generated current at reference (A).I_o_ref(float, required): Diode saturation current at reference (A).R_sh_ref(float, required): Shunt resistance at reference (ohms).R_sh_zero(float, required): Shunt resistance at zero irradiance (ohms).R_s(float, required): Series resistance at reference (ohms).cells_in_series(int, required): Number of cells in series.R_sh_exp(float, optional, default: 5.5): Exponent for shunt resistance.eg_ref(float, optional, default: 1.121): Energy bandgap at reference temperature (eV).irrad_ref(float, optional, default: 1000): Reference irradiance (W/m^2).temp_ref(float, optional, default: 25): Reference cell temperature (C).
Returns (list[list]): 2D list containing [[photocurrent, saturation_current, resistance_series, resistance_shunt, nNsVth]], or an error string.
Example 1: PVsyst parameter calculation at standard conditions
Inputs:
| effective_irradiance | temp_cell | alpha_sc | gamma_ref | mu_gamma | I_L_ref | I_o_ref | R_sh_ref | R_sh_zero | R_s | cells_in_series | R_sh_exp | eg_ref | irrad_ref | temp_ref |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1000 | 25 | 0.005 | 1.1 | 0.001 | 6 | 1e-9 | 400 | 1000 | 0.3 | 60 | 5.5 | 1.121 | 1000 | 25 |
Excel formula:
=CALCPARAMS_PVSYST(1000, 25, 0.005, 1.1, 0.001, 6, 1e-9, 400, 1000, 0.3, 60, 5.5, 1.121, 1000, 25)
Expected output:
| Result | ||||
|---|---|---|---|---|
| 6 | 1e-9 | 0.3 | 400 | 1.69571 |
Example 2: Default optional PVsyst constants
Inputs:
| effective_irradiance | temp_cell | alpha_sc | gamma_ref | mu_gamma | I_L_ref | I_o_ref | R_sh_ref | R_sh_zero | R_s | cells_in_series |
|---|---|---|---|---|---|---|---|---|---|---|
| 1000 | 25 | 0.005 | 1.1 | 0.001 | 6 | 1e-9 | 400 | 1000 | 0.3 | 60 |
Excel formula:
=CALCPARAMS_PVSYST(1000, 25, 0.005, 1.1, 0.001, 6, 1e-9, 400, 1000, 0.3, 60)
Expected output:
| Result | ||||
|---|---|---|---|---|
| 6 | 1e-9 | 0.3 | 400 | 1.69571 |
Example 3: Warm cell with reduced irradiance
Inputs:
| effective_irradiance | temp_cell | alpha_sc | gamma_ref | mu_gamma | I_L_ref | I_o_ref | R_sh_ref | R_sh_zero | R_s | cells_in_series | R_sh_exp | eg_ref | irrad_ref | temp_ref |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 750 | 45 | 0.005 | 1.1 | 0.001 | 6 | 1e-9 | 400 | 1000 | 0.3 | 60 | 5.5 | 1.121 | 1000 | 25 |
Excel formula:
=CALCPARAMS_PVSYST(750, 45, 0.005, 1.1, 0.001, 6, 1e-9, 400, 1000, 0.3, 60, 5.5, 1.121, 1000, 25)
Expected output:
| Result | ||||
|---|---|---|---|---|
| 4.575 | 1.40654e-8 | 0.3 | 407.276 | 1.84236 |
Example 4: Cool cell at elevated irradiance
Inputs:
| effective_irradiance | temp_cell | alpha_sc | gamma_ref | mu_gamma | I_L_ref | I_o_ref | R_sh_ref | R_sh_zero | R_s | cells_in_series | R_sh_exp | eg_ref | irrad_ref | temp_ref |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1100 | 15 | 0.005 | 1.1 | 0.001 | 6 | 1e-9 | 400 | 1000 | 0.3 | 60 | 5.5 | 1.121 | 1000 | 25 |
Excel formula:
=CALCPARAMS_PVSYST(1100, 15, 0.005, 1.1, 0.001, 6, 1e-9, 400, 1000, 0.3, 60, 5.5, 1.121, 1000, 25)
Expected output:
| Result | ||||
|---|---|---|---|---|
| 6.545 | 2.25033e-10 | 0.3 | 398.958 | 1.62394 |
Python Code
Show Code
from pvlib.pvsystem import calcparams_pvsyst as result_func
def calcparams_pvsyst(effective_irradiance, temp_cell, alpha_sc, gamma_ref, mu_gamma, I_L_ref, I_o_ref, R_sh_ref, R_sh_zero, R_s, cells_in_series, R_sh_exp=5.5, eg_ref=1.121, irrad_ref=1000, temp_ref=25):
"""
Calculate five single-diode parameter values using the PVsyst v6 model.
See: https://pvlib-python.readthedocs.io/en/stable/reference/generated/pvlib.pvsystem.calcparams_pvsyst.html
This example function is provided as-is without any representation of accuracy.
Args:
effective_irradiance (float): Irradiance converted to photocurrent (W/m^2).
temp_cell (float): Average cell temperature (C).
alpha_sc (float): Short-circuit current temp coefficient (A/C).
gamma_ref (float): Diode ideality factor (unitless).
mu_gamma (float): Temp coefficient for ideality factor (1/K).
I_L_ref (float): Light-generated current at reference (A).
I_o_ref (float): Diode saturation current at reference (A).
R_sh_ref (float): Shunt resistance at reference (ohms).
R_sh_zero (float): Shunt resistance at zero irradiance (ohms).
R_s (float): Series resistance at reference (ohms).
cells_in_series (int): Number of cells in series.
R_sh_exp (float, optional): Exponent for shunt resistance. Default is 5.5.
eg_ref (float, optional): Energy bandgap at reference temperature (eV). Default is 1.121.
irrad_ref (float, optional): Reference irradiance (W/m^2). Default is 1000.
temp_ref (float, optional): Reference cell temperature (C). Default is 25.
Returns:
list[list]: 2D list containing [[photocurrent, saturation_current, resistance_series, resistance_shunt, nNsVth]], or an error string.
"""
try:
irrad = float(effective_irradiance)
tc = float(temp_cell)
asc = float(alpha_sc)
gr = float(gamma_ref)
mg = float(mu_gamma)
ilr = float(I_L_ref)
ior = float(I_o_ref)
rshr = float(R_sh_ref)
rs_v = float(R_s)
nc = int(cells_in_series)
rsh0 = float(R_sh_zero) if R_sh_zero is not None else 1000.0
rexp = float(R_sh_exp) if R_sh_exp is not None else 5.5
eg = float(eg_ref) if eg_ref is not None else 1.121
ir = float(irrad_ref) if irrad_ref is not None else 1000.0
tr = float(temp_ref) if temp_ref is not None else 25.0
res = result_func(
effective_irradiance=irrad,
temp_cell=tc,
alpha_sc=asc,
gamma_ref=gr,
mu_gamma=mg,
I_L_ref=ilr,
I_o_ref=ior,
R_sh_ref=rshr,
R_sh_0=rsh0,
R_s=rs_v,
cells_in_series=nc,
R_sh_exp=rexp,
EgRef=eg,
irrad_ref=ir,
temp_ref=tr
)
return [[float(v) for v in res]]
except Exception as e:
return f"Error: {str(e)}"Online Calculator
MAX_POWER_POINT
This function finds the point on a photovoltaic IV curve where electrical power is maximized for a given set of single-diode model coefficients. It is a focused alternative to singlediode when only the maximum-power operating point is needed.
The objective is to maximize electrical power along the curve:
P = I V
The function returns the current, voltage, and power at the maximum power point as [i_{mp}, v_{mp}, p_{mp}]. Optional thin-film parameters can be provided to account for recombination effects in CdTe and amorphous-silicon models.
Excel Usage
=MAX_POWER_POINT(photocurrent, saturation_current, resistance_series, resistance_shunt, nNsVth, d_mu_tau, ns_vbi, mpp_solver)
photocurrent(float, required): Photo-generated current (A).saturation_current(float, required): Diode reverse saturation current (A).resistance_series(float, required): Series resistance (ohms).resistance_shunt(float, required): Shunt resistance (ohms).nNsVth(float, required): Product of ideality factor, cells in series, and thermal voltage (V).d_mu_tau(float, optional, default: 0): PVsyst recombination parameter for thin-film modules (V).ns_vbi(float, optional, default: 1000000): PVsyst builtin voltage parameter for thin-film modules (V).mpp_solver(str, optional, default: “brentq”): Numerical solver method.
Returns (list[list]): 2D list [[i_mp, v_mp, p_mp]], or an error string.
Example 1: Standard MPP calculation
Inputs:
| photocurrent | saturation_current | resistance_series | resistance_shunt | nNsVth | mpp_solver |
|---|---|---|---|---|---|
| 5.5 | 2e-10 | 0.5 | 300 | 1.5 | brentq |
Excel formula:
=MAX_POWER_POINT(5.5, 2e-10, 0.5, 300, 1.5, "brentq")
Expected output:
| Result | ||
|---|---|---|
| 5.11038 | 29.057 | 148.492 |
Example 2: Standard MPP using Newton solver
Inputs:
| photocurrent | saturation_current | resistance_series | resistance_shunt | nNsVth | mpp_solver |
|---|---|---|---|---|---|
| 5.5 | 2e-10 | 0.5 | 300 | 1.5 | newton |
Excel formula:
=MAX_POWER_POINT(5.5, 2e-10, 0.5, 300, 1.5, "newton")
Expected output:
| Result | ||
|---|---|---|
| 5.11038 | 29.057 | 148.492 |
Example 3: Higher series resistance lowers power
Inputs:
| photocurrent | saturation_current | resistance_series | resistance_shunt | nNsVth | mpp_solver |
|---|---|---|---|---|---|
| 5.5 | 2e-10 | 0.9 | 300 | 1.5 | brentq |
Excel formula:
=MAX_POWER_POINT(5.5, 2e-10, 0.9, 300, 1.5, "brentq")
Expected output:
| Result | ||
|---|---|---|
| 5.06449 | 27.2753 | 138.135 |
Example 4: Lower shunt resistance case
Inputs:
| photocurrent | saturation_current | resistance_series | resistance_shunt | nNsVth | mpp_solver |
|---|---|---|---|---|---|
| 5.5 | 2e-10 | 0.5 | 150 | 1.5 | brentq |
Excel formula:
=MAX_POWER_POINT(5.5, 2e-10, 0.5, 150, 1.5, "brentq")
Expected output:
| Result | ||
|---|---|---|
| 5.01612 | 29.0464 | 145.7 |
Python Code
Show Code
from pvlib.pvsystem import max_power_point as result_func
import numpy as np
def max_power_point(photocurrent, saturation_current, resistance_series, resistance_shunt, nNsVth, d_mu_tau=0, ns_vbi=1000000, mpp_solver='brentq'):
"""
Calculate the maximum power point (MPP) from single-diode equation coefficients.
See: https://pvlib-python.readthedocs.io/en/stable/reference/generated/pvlib.pvsystem.max_power_point.html
This example function is provided as-is without any representation of accuracy.
Args:
photocurrent (float): Photo-generated current (A).
saturation_current (float): Diode reverse saturation current (A).
resistance_series (float): Series resistance (ohms).
resistance_shunt (float): Shunt resistance (ohms).
nNsVth (float): Product of ideality factor, cells in series, and thermal voltage (V).
d_mu_tau (float, optional): PVsyst recombination parameter for thin-film modules (V). Default is 0.
ns_vbi (float, optional): PVsyst builtin voltage parameter for thin-film modules (V). Default is 1000000.
mpp_solver (str, optional): Numerical solver method. Valid options: Newton, Brentq, Chandrupatla. Default is 'brentq'.
Returns:
list[list]: 2D list [[i_mp, v_mp, p_mp]], or an error string.
"""
try:
il = float(photocurrent)
i0 = float(saturation_current)
rs = float(resistance_series)
rsh = float(resistance_shunt)
nv = float(nNsVth)
d2mt = float(d_mu_tau) if d_mu_tau is not None else 0.0
nvb = float(ns_vbi) if ns_vbi is not None else np.inf
meth = str(mpp_solver) if mpp_solver is not None else "brentq"
res = result_func(
photocurrent=il,
saturation_current=i0,
resistance_series=rs,
resistance_shunt=rsh,
nNsVth=nv,
d2mutau=d2mt,
NsVbi=nvb,
method=meth
)
# res has keys: i_mp, v_mp, p_mp
out = [float(res['i_mp']), float(res['v_mp']), float(res['p_mp'])]
return [out]
except Exception as e:
return f"Error: {str(e)}"Online Calculator
PVWATTS_LOSSES
This function combines multiple PV system loss assumptions into a single total derate percentage using the PVWatts compounding-loss formulation. Each input is a percentage loss for one mechanism such as soiling, shading, mismatch, or equipment availability.
PVWatts multiplies the retained fractions for each loss component and converts the remaining derate back to a total loss percentage:
L_{total}(\%) = 100 \left[1 - \prod_i \left(1 - \frac{L_i}{100}\right)\right]
Because the model compounds retained performance, the total loss is not simply the arithmetic sum of the inputs except in very small-loss approximations.
Excel Usage
=PVWATTS_LOSSES(soiling, shading, snow, mismatch, wiring, connections, lid, nameplate_rating, age, availability)
soiling(float, optional, default: 2): Loss due to soiling (%).shading(float, optional, default: 3): Loss due to shading (%).snow(float, optional, default: 0): Loss due to snow (%).mismatch(float, optional, default: 2): Loss due to mismatch (%).wiring(float, optional, default: 2): Loss due to wiring (%).connections(float, optional, default: 0.5): Loss due to connections (%).lid(float, optional, default: 1.5): Light induced degradation (%).nameplate_rating(float, optional, default: 1): Nameplate rating loss (%).age(float, optional, default: 0): Loss due to age (%).availability(float, optional, default: 3): Loss due to availability (%).
Returns (float): Total system losses (%), or an error string.
Example 1: Standard PVWatts default losses
Inputs:
| soiling | shading | snow | mismatch | wiring | connections | lid | nameplate_rating | age | availability |
|---|---|---|---|---|---|---|---|---|---|
| 2 | 3 | 0 | 2 | 2 | 0.5 | 1.5 | 1 | 0 | 3 |
Excel formula:
=PVWATTS_LOSSES(2, 3, 0, 2, 2, 0.5, 1.5, 1, 0, 3)
Expected output:
14.0757
Example 2: No modeled losses
Inputs:
| soiling | shading | snow | mismatch | wiring | connections | lid | nameplate_rating | age | availability |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Excel formula:
=PVWATTS_LOSSES(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
Expected output:
0
Example 3: Single age loss component
Inputs:
| soiling | shading | snow | mismatch | wiring | connections | lid | nameplate_rating | age | availability |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 5 | 0 |
Excel formula:
=PVWATTS_LOSSES(0, 0, 0, 0, 0, 0, 0, 0, 5, 0)
Expected output:
5
Example 4: Higher aggregate project losses
Inputs:
| soiling | shading | snow | mismatch | wiring | connections | lid | nameplate_rating | age | availability |
|---|---|---|---|---|---|---|---|---|---|
| 5 | 8 | 1 | 3 | 2.5 | 1 | 2 | 1.5 | 1 | 4 |
Excel formula:
=PVWATTS_LOSSES(5, 8, 1, 3, 2.5, 1, 2, 1.5, 1, 4)
Expected output:
25.6764
Python Code
Show Code
from pvlib.pvsystem import pvwatts_losses as result_func
def pvwatts_losses(soiling=2, shading=3, snow=0, mismatch=2, wiring=2, connections=0.5, lid=1.5, nameplate_rating=1, age=0, availability=3):
"""
Implement NREL's PVWatts system loss model.
See: https://pvlib-python.readthedocs.io/en/stable/reference/generated/pvlib.pvsystem.pvwatts_losses.html
This example function is provided as-is without any representation of accuracy.
Args:
soiling (float, optional): Loss due to soiling (%). Default is 2.
shading (float, optional): Loss due to shading (%). Default is 3.
snow (float, optional): Loss due to snow (%). Default is 0.
mismatch (float, optional): Loss due to mismatch (%). Default is 2.
wiring (float, optional): Loss due to wiring (%). Default is 2.
connections (float, optional): Loss due to connections (%). Default is 0.5.
lid (float, optional): Light induced degradation (%). Default is 1.5.
nameplate_rating (float, optional): Nameplate rating loss (%). Default is 1.
age (float, optional): Loss due to age (%). Default is 0.
availability (float, optional): Loss due to availability (%). Default is 3.
Returns:
float: Total system losses (%), or an error string.
"""
try:
l_soiling = float(soiling) if soiling is not None else 2.0
l_shading = float(shading) if shading is not None else 3.0
l_snow = float(snow) if snow is not None else 0.0
l_mismatch = float(mismatch) if mismatch is not None else 2.0
l_wiring = float(wiring) if wiring is not None else 2.0
l_conn = float(connections) if connections is not None else 0.5
l_lid = float(lid) if lid is not None else 1.5
l_nameplate = float(nameplate_rating) if nameplate_rating is not None else 1.0
l_age = float(age) if age is not None else 0.0
l_avail = float(availability) if availability is not None else 3.0
res = result_func(
soiling=l_soiling,
shading=l_shading,
snow=l_snow,
mismatch=l_mismatch,
wiring=l_wiring,
connections=l_conn,
lid=l_lid,
nameplate_rating=l_nameplate,
age=l_age,
availability=l_avail
)
return float(res)
except Exception as e:
return f"Error: {str(e)}"Online Calculator
SAPM
This function evaluates the Sandia Photovoltaic Array Performance Model to generate the principal operating points of a module IV curve from effective irradiance, cell temperature, and a dictionary of SAPM module coefficients.
The result summarizes the curve with short-circuit current, maximum-power current and voltage, open-circuit voltage, and the auxiliary shape points I_x and I_{xx}. The peak electrical output is represented by:
P_{mp} = I_{mp} V_{mp}
Module coefficients must be supplied as a 2D list of key-value pairs, for example [["C0", 1.0], ["Isco", 6.0]]. The wrapper converts that list into the dict-like structure required by pvlib.
Excel Usage
=SAPM(effective_irradiance, temp_cell, module_params, temperature_ref, irradiance_ref)
effective_irradiance(float, required): Irradiance reaching the cells (W/m^2).temp_cell(float, required): Cell temperature (C).module_params(list[list], required): 2D list of SAPM parameters [[‘key’, value], …].temperature_ref(float, optional, default: 25): Reference temperature (C).irradiance_ref(float, optional, default: 1000): Reference irradiance (W/m^2).
Returns (list[list]): 2D list [[i_sc, i_mp, v_oc, v_mp, p_mp, i_x, i_xx]], or an error string.
Example 1: Standard SAPM points
Inputs:
| effective_irradiance | temp_cell | module_params | |
|---|---|---|---|
| 1000 | 25 | C0 | 1.012 |
| C1 | -0.012 | ||
| C2 | 0 | ||
| C3 | 0 | ||
| Isco | 6 | ||
| Impo | 5.5 | ||
| Voco | 36 | ||
| Vmpo | 30 | ||
| Aisc | 0.001 | ||
| Aimp | 0.0005 | ||
| Bvoco | -0.12 | ||
| Mbvoc | 0 | ||
| Bvmpo | -0.1 | ||
| Mbvmp | 0 | ||
| N | 1.2 | ||
| Cells_in_series | 60 | ||
| IXO | 5.8 | ||
| IXXO | 5.3 | ||
| C4 | 1 | ||
| C5 | 0 | ||
| C6 | 1 | ||
| C7 | 0 |
Excel formula:
=SAPM(1000, 25, {"C0",1.012;"C1",-0.012;"C2",0;"C3",0;"Isco",6;"Impo",5.5;"Voco",36;"Vmpo",30;"Aisc",0.001;"Aimp",0.0005;"Bvoco",-0.12;"Mbvoc",0;"Bvmpo",-0.1;"Mbvmp",0;"N",1.2;"Cells_in_series",60;"IXO",5.8;"IXXO",5.3;"C4",1;"C5",0;"C6",1;"C7",0})
Expected output:
| Result | ||||||
|---|---|---|---|---|---|---|
| 6 | 5.5 | 36 | 30 | 165 | 5.8 | 5.3 |
Example 2: Lower irradiance operating points
Inputs:
| effective_irradiance | temp_cell | module_params | |
|---|---|---|---|
| 800 | 25 | C0 | 1.012 |
| C1 | -0.012 | ||
| C2 | 0 | ||
| C3 | 0 | ||
| Isco | 6 | ||
| Impo | 5.5 | ||
| Voco | 36 | ||
| Vmpo | 30 | ||
| Aisc | 0.001 | ||
| Aimp | 0.0005 | ||
| Bvoco | -0.12 | ||
| Mbvoc | 0 | ||
| Bvmpo | -0.1 | ||
| Mbvmp | 0 | ||
| N | 1.2 | ||
| Cells_in_series | 60 | ||
| IXO | 5.8 | ||
| IXXO | 5.3 | ||
| C4 | 1 | ||
| C5 | 0 | ||
| C6 | 1 | ||
| C7 | 0 |
Excel formula:
=SAPM(800, 25, {"C0",1.012;"C1",-0.012;"C2",0;"C3",0;"Isco",6;"Impo",5.5;"Voco",36;"Vmpo",30;"Aisc",0.001;"Aimp",0.0005;"Bvoco",-0.12;"Mbvoc",0;"Bvmpo",-0.1;"Mbvmp",0;"N",1.2;"Cells_in_series",60;"IXO",5.8;"IXXO",5.3;"C4",1;"C5",0;"C6",1;"C7",0})
Expected output:
| Result | ||||||
|---|---|---|---|---|---|---|
| 4.8 | 4.41056 | 35.5872 | 30 | 132.317 | 4.64 | 4.24 |
Example 3: Warmer cell temperature case
Inputs:
| effective_irradiance | temp_cell | module_params | |
|---|---|---|---|
| 1000 | 45 | C0 | 1.012 |
| C1 | -0.012 | ||
| C2 | 0 | ||
| C3 | 0 | ||
| Isco | 6 | ||
| Impo | 5.5 | ||
| Voco | 36 | ||
| Vmpo | 30 | ||
| Aisc | 0.001 | ||
| Aimp | 0.0005 | ||
| Bvoco | -0.12 | ||
| Mbvoc | 0 | ||
| Bvmpo | -0.1 | ||
| Mbvmp | 0 | ||
| N | 1.2 | ||
| Cells_in_series | 60 | ||
| IXO | 5.8 | ||
| IXXO | 5.3 | ||
| C4 | 1 | ||
| C5 | 0 | ||
| C6 | 1 | ||
| C7 | 0 |
Excel formula:
=SAPM(1000, 45, {"C0",1.012;"C1",-0.012;"C2",0;"C3",0;"Isco",6;"Impo",5.5;"Voco",36;"Vmpo",30;"Aisc",0.001;"Aimp",0.0005;"Bvoco",-0.12;"Mbvoc",0;"Bvmpo",-0.1;"Mbvmp",0;"N",1.2;"Cells_in_series",60;"IXO",5.8;"IXXO",5.3;"C4",1;"C5",0;"C6",1;"C7",0})
Expected output:
| Result | ||||||
|---|---|---|---|---|---|---|
| 6.12 | 5.555 | 33.6 | 28 | 155.54 | 5.916 | 5.353 |
Example 4: Lowercase cell-series alias is accepted
Inputs:
| effective_irradiance | temp_cell | module_params | |
|---|---|---|---|
| 1000 | 25 | C0 | 1.012 |
| C1 | -0.012 | ||
| C2 | 0 | ||
| C3 | 0 | ||
| Isco | 6 | ||
| Impo | 5.5 | ||
| Voco | 36 | ||
| Vmpo | 30 | ||
| Aisc | 0.001 | ||
| Aimp | 0.0005 | ||
| Bvoco | -0.12 | ||
| Mbvoc | 0 | ||
| Bvmpo | -0.1 | ||
| Mbvmp | 0 | ||
| N | 1.2 | ||
| cells_in_series | 60 | ||
| IXO | 5.8 | ||
| IXXO | 5.3 | ||
| C4 | 1 | ||
| C5 | 0 | ||
| C6 | 1 | ||
| C7 | 0 |
Excel formula:
=SAPM(1000, 25, {"C0",1.012;"C1",-0.012;"C2",0;"C3",0;"Isco",6;"Impo",5.5;"Voco",36;"Vmpo",30;"Aisc",0.001;"Aimp",0.0005;"Bvoco",-0.12;"Mbvoc",0;"Bvmpo",-0.1;"Mbvmp",0;"N",1.2;"cells_in_series",60;"IXO",5.8;"IXXO",5.3;"C4",1;"C5",0;"C6",1;"C7",0})
Expected output:
| Result | ||||||
|---|---|---|---|---|---|---|
| 6 | 5.5 | 36 | 30 | 165 | 5.8 | 5.3 |
Python Code
Show Code
from pvlib.pvsystem import sapm as result_func
import pandas as pd
def sapm(effective_irradiance, temp_cell, module_params, temperature_ref=25, irradiance_ref=1000):
"""
Sandia Photovoltaic Array Performance Model (SAPM) solver.
See: https://pvlib-python.readthedocs.io/en/stable/reference/generated/pvlib.pvsystem.sapm.html
This example function is provided as-is without any representation of accuracy.
Args:
effective_irradiance (float): Irradiance reaching the cells (W/m^2).
temp_cell (float): Cell temperature (C).
module_params (list[list]): 2D list of SAPM parameters [['key', value], ...].
temperature_ref (float, optional): Reference temperature (C). Default is 25.
irradiance_ref (float, optional): Reference irradiance (W/m^2). Default is 1000.
Returns:
list[list]: 2D list [[i_sc, i_mp, v_oc, v_mp, p_mp, i_x, i_xx]], or an error string.
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
irrad = float(effective_irradiance)
tc = float(temp_cell)
module_params = to2d(module_params)
if not isinstance(module_params, list) or not all(isinstance(row, list) for row in module_params):
return "Error: module_params must be a 2D list of key-value pairs"
key_aliases = {
"cells_in_series": "Cells_in_Series",
"cells_in_Series": "Cells_in_Series",
"Cells_in_series": "Cells_in_Series"
}
mod_dict = {}
for row in module_params:
if len(row) >= 2:
key = str(row[0]).strip()
key = key_aliases.get(key, key)
val = row[1]
try:
val = float(val)
except (TypeError, ValueError):
pass
mod_dict[key] = val
t_ref = float(temperature_ref) if temperature_ref is not None else 25.0
i_ref = float(irradiance_ref) if irradiance_ref is not None else 1000.0
res = result_func(
effective_irradiance=irrad,
temp_cell=tc,
module=mod_dict,
temperature_ref=t_ref,
irradiance_ref=i_ref
)
if isinstance(res, pd.DataFrame):
row_res = res.iloc[0].to_dict()
elif isinstance(res, dict):
row_res = dict(res)
else:
# Some versions of pvlib return an OrderedDict or other mapping-like object
# which may not implement to_dict(). Fall back to dict() conversion.
if hasattr(res, "to_dict"):
row_res = res.to_dict()
else:
try:
row_res = dict(res)
except Exception:
row_res = {}
out = [
float(row_res.get('i_sc', 0)),
float(row_res.get('i_mp', 0)),
float(row_res.get('v_oc', 0)),
float(row_res.get('v_mp', 0)),
float(row_res.get('p_mp', 0)),
float(row_res.get('i_x', 0)),
float(row_res.get('i_xx', 0))
]
return [out]
except Exception as e:
return f"Error: {str(e)}"Online Calculator
SAPM_EFF_IRRAD
This function converts plane-of-array direct and diffuse irradiance into the effective irradiance actually absorbed by module cells under the Sandia model. It applies both a spectral adjustment based on absolute airmass and an incidence-angle modifier based on angle of incidence.
The SAPM effective irradiance relationship is:
E_e = f_1(AM_a) \left(E_b f_2(AOI) + f_d E_d\right)
Here f_1 is the spectral response polynomial, f_2 is the angle-of-incidence modifier, and f_d is the diffuse fraction coefficient. Supply the required coefficients as a 2D list of key-value pairs such as [["A0", 1.0], ["B0", 1.0], ["FD", 1.0]].
Excel Usage
=SAPM_EFF_IRRAD(poa_direct, poa_diffuse, airmass_absolute, aoi, module_params)
poa_direct(float, required): Direct irradiance on the plane of array (W/m^2).poa_diffuse(float, required): Diffuse irradiance on the plane of array (W/m^2).airmass_absolute(float, required): Absolute airmass (unitless).aoi(float, required): Angle of incidence (degrees).module_params(list[list], required): 2D list of SAPM coefficients [[‘key’, value], …].
Returns (float): Effective irradiance (W/m^2), or an error string.
Example 1: Standard Effective Irradiance
Inputs:
| poa_direct | poa_diffuse | airmass_absolute | aoi | module_params | |
|---|---|---|---|---|---|
| 800 | 100 | 1.5 | 30 | A0 | 1 |
| A1 | 0 | ||||
| A2 | 0 | ||||
| A3 | 0 | ||||
| A4 | 0 | ||||
| B0 | 1 | ||||
| B1 | 0 | ||||
| B2 | 0 | ||||
| B3 | 0 | ||||
| B4 | 0 | ||||
| B5 | 0 | ||||
| FD | 1 |
Excel formula:
=SAPM_EFF_IRRAD(800, 100, 1.5, 30, {"A0",1;"A1",0;"A2",0;"A3",0;"A4",0;"B0",1;"B1",0;"B2",0;"B3",0;"B4",0;"B5",0;"FD",1})
Expected output:
900
Example 2: Diffuse-only irradiance case
Inputs:
| poa_direct | poa_diffuse | airmass_absolute | aoi | module_params | |
|---|---|---|---|---|---|
| 0 | 200 | 1.5 | 30 | A0 | 1 |
| A1 | 0 | ||||
| A2 | 0 | ||||
| A3 | 0 | ||||
| A4 | 0 | ||||
| B0 | 1 | ||||
| B1 | 0 | ||||
| B2 | 0 | ||||
| B3 | 0 | ||||
| B4 | 0 | ||||
| B5 | 0 | ||||
| FD | 1 |
Excel formula:
=SAPM_EFF_IRRAD(0, 200, 1.5, 30, {"A0",1;"A1",0;"A2",0;"A3",0;"A4",0;"B0",1;"B1",0;"B2",0;"B3",0;"B4",0;"B5",0;"FD",1})
Expected output:
200
Example 3: Reduced diffuse fraction coefficient
Inputs:
| poa_direct | poa_diffuse | airmass_absolute | aoi | module_params | |
|---|---|---|---|---|---|
| 700 | 100 | 1.5 | 30 | A0 | 1 |
| A1 | 0 | ||||
| A2 | 0 | ||||
| A3 | 0 | ||||
| A4 | 0 | ||||
| B0 | 1 | ||||
| B1 | 0 | ||||
| B2 | 0 | ||||
| B3 | 0 | ||||
| B4 | 0 | ||||
| B5 | 0 | ||||
| FD | 0.8 |
Excel formula:
=SAPM_EFF_IRRAD(700, 100, 1.5, 30, {"A0",1;"A1",0;"A2",0;"A3",0;"A4",0;"B0",1;"B1",0;"B2",0;"B3",0;"B4",0;"B5",0;"FD",0.8})
Expected output:
780
Example 4: Spectral scaling below unity
Inputs:
| poa_direct | poa_diffuse | airmass_absolute | aoi | module_params | |
|---|---|---|---|---|---|
| 800 | 100 | 1.5 | 30 | A0 | 0.95 |
| A1 | 0 | ||||
| A2 | 0 | ||||
| A3 | 0 | ||||
| A4 | 0 | ||||
| B0 | 1 | ||||
| B1 | 0 | ||||
| B2 | 0 | ||||
| B3 | 0 | ||||
| B4 | 0 | ||||
| B5 | 0 | ||||
| FD | 1 |
Excel formula:
=SAPM_EFF_IRRAD(800, 100, 1.5, 30, {"A0",0.95;"A1",0;"A2",0;"A3",0;"A4",0;"B0",1;"B1",0;"B2",0;"B3",0;"B4",0;"B5",0;"FD",1})
Expected output:
855
Python Code
Show Code
from pvlib.pvsystem import sapm_effective_irradiance as result_func
def sapm_eff_irrad(poa_direct, poa_diffuse, airmass_absolute, aoi, module_params):
"""
Calculate SAPM effective irradiance accounting for spectral and incidence losses.
See: https://pvlib-python.readthedocs.io/en/stable/reference/generated/pvlib.pvsystem.sapm_effective_irradiance.html
This example function is provided as-is without any representation of accuracy.
Args:
poa_direct (float): Direct irradiance on the plane of array (W/m^2).
poa_diffuse (float): Diffuse irradiance on the plane of array (W/m^2).
airmass_absolute (float): Absolute airmass (unitless).
aoi (float): Angle of incidence (degrees).
module_params (list[list]): 2D list of SAPM coefficients [['key', value], ...].
Returns:
float: Effective irradiance (W/m^2), or an error string.
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
eb = float(poa_direct)
ed = float(poa_diffuse)
am = float(airmass_absolute)
ao = float(aoi)
module_params = to2d(module_params)
if not isinstance(module_params, list) or not all(isinstance(row, list) for row in module_params):
return "Error: module_params must be a 2D list of key-value pairs"
mod_dict = {}
for row in module_params:
if len(row) >= 2:
key = str(row[0]).strip()
val = row[1]
try:
val = float(val)
except (TypeError, ValueError):
pass
mod_dict[key] = val
res = result_func(
poa_direct=eb,
poa_diffuse=ed,
airmass_absolute=am,
aoi=ao,
module=mod_dict
)
return float(res)
except Exception as e:
return f"Error: {str(e)}"Online Calculator
SINGLEDIODE
This function solves the photovoltaic single-diode equation for the principal operating points on an IV curve. It is the core electrical model used after weather and module parameters have been translated into single-diode coefficients.
The governing equation is:
I = I_L - I_0 \left[\exp\left(\frac{V + I R_s}{n N_s V_{th}}\right) - 1\right] - \frac{V + I R_s}{R_{sh}}
From those coefficients the function returns i_{sc}, v_{oc}, i_{mp}, v_{mp}, p_{mp}, i_x, and i_{xx}. Different numerical methods can be selected depending on the tradeoff between speed and convergence robustness.
Excel Usage
=SINGLEDIODE(photocurrent, saturation_current, resistance_series, resistance_shunt, nNsVth, sd_solver)
photocurrent(float, required): Light-generated current (A). Must be >= 0.saturation_current(float, required): Diode saturation current (A). Must be > 0.resistance_series(float, required): Series resistance (ohms). Must be >= 0.resistance_shunt(float, required): Shunt resistance (ohms). Must be > 0.nNsVth(float, required): Product of ideality factor, cells in series, and thermal voltage (V). Must be > 0.sd_solver(str, optional, default: “lambertw”): Root-finding algorithm.
Returns (list[list]): 2D list [[i_sc, v_oc, i_mp, v_mp, p_mp, i_x, i_xx]], or an error string.
Example 1: Standard IV key points
Inputs:
| photocurrent | saturation_current | resistance_series | resistance_shunt | nNsVth | sd_solver |
|---|---|---|---|---|---|
| 5.5 | 2e-10 | 0.5 | 300 | 1.5 | lambertw |
Excel formula:
=SINGLEDIODE(5.5, 2e-10, 0.5, 300, 1.5, "lambertw")
Expected output:
| Result | ||||||
|---|---|---|---|---|---|---|
| 5.49085 | 36.0231 | 5.11038 | 29.057 | 148.492 | 5.43071 | 3.62124 |
Example 2: Standard IV key points using Newton solver
Inputs:
| photocurrent | saturation_current | resistance_series | resistance_shunt | nNsVth | sd_solver |
|---|---|---|---|---|---|
| 5.5 | 2e-10 | 0.5 | 300 | 1.5 | newton |
Excel formula:
=SINGLEDIODE(5.5, 2e-10, 0.5, 300, 1.5, "newton")
Expected output:
| Result | ||||||
|---|---|---|---|---|---|---|
| 5.49085 | 36.0231 | 5.11038 | 29.057 | 148.492 | 5.43071 | 3.62124 |
Example 3: Lower shunt resistance reduces fill factor
Inputs:
| photocurrent | saturation_current | resistance_series | resistance_shunt | nNsVth | sd_solver |
|---|---|---|---|---|---|
| 5.5 | 2e-10 | 0.5 | 150 | 1.5 | lambertw |
Excel formula:
=SINGLEDIODE(5.5, 2e-10, 0.5, 150, 1.5, "lambertw")
Expected output:
| Result | ||||||
|---|---|---|---|---|---|---|
| 5.48173 | 35.9893 | 5.01612 | 29.0464 | 145.7 | 5.36197 | 3.56516 |
Example 4: Higher series resistance case
Inputs:
| photocurrent | saturation_current | resistance_series | resistance_shunt | nNsVth | sd_solver |
|---|---|---|---|---|---|
| 5.5 | 2e-10 | 0.9 | 300 | 1.5 | lambertw |
Excel formula:
=SINGLEDIODE(5.5, 2e-10, 0.9, 300, 1.5, "lambertw")
Expected output:
| Result | ||||||
|---|---|---|---|---|---|---|
| 5.48355 | 36.0231 | 5.06449 | 27.2753 | 138.135 | 5.42284 | 3.28872 |
Python Code
Show Code
from pvlib.pvsystem import singlediode as result_func
def singlediode(photocurrent, saturation_current, resistance_series, resistance_shunt, nNsVth, sd_solver='lambertw'):
"""
Solve the single-diode equation to obtain a photovoltaic IV curve and its key operating points.
See: https://pvlib-python.readthedocs.io/en/stable/reference/generated/pvlib.pvsystem.singlediode.html
This example function is provided as-is without any representation of accuracy.
Args:
photocurrent (float): Light-generated current (A). Must be >= 0.
saturation_current (float): Diode saturation current (A). Must be > 0.
resistance_series (float): Series resistance (ohms). Must be >= 0.
resistance_shunt (float): Shunt resistance (ohms). Must be > 0.
nNsVth (float): Product of ideality factor, cells in series, and thermal voltage (V). Must be > 0.
sd_solver (str, optional): Root-finding algorithm. Valid options: Lambert W, Newton, Brentq, Chandrupatla. Default is 'lambertw'.
Returns:
list[list]: 2D list [[i_sc, v_oc, i_mp, v_mp, p_mp, i_x, i_xx]], or an error string.
"""
try:
il = float(photocurrent)
i0 = float(saturation_current)
rs = float(resistance_series)
rsh = float(resistance_shunt)
nv = float(nNsVth)
if il < 0: return "Error: photocurrent must be >= 0"
if i0 <= 0: return "Error: saturation_current must be > 0"
if rs < 0: return "Error: resistance_series must be >= 0"
if rsh <= 0: return "Error: resistance_shunt must be > 0"
if nv <= 0: return "Error: nNsVth must be > 0"
meth = str(sd_solver) if sd_solver is not None else "lambertw"
res = result_func(
photocurrent=il,
saturation_current=i0,
resistance_series=rs,
resistance_shunt=rsh,
nNsVth=nv,
method=meth
)
# res has keys: i_sc, v_oc, i_mp, v_mp, p_mp, i_x, i_xx
out = [
float(res['i_sc']),
float(res['v_oc']),
float(res['i_mp']),
float(res['v_mp']),
float(res['p_mp']),
float(res['i_x']),
float(res['i_xx'])
]
return [out]
except Exception as e:
return f"Error: {str(e)}"Online Calculator
V_FROM_I
This function computes the device voltage corresponding to a specified operating current under the single-diode model. It is useful when a current setpoint is already known and only the matching voltage on the IV curve is required.
The calculation inverts the single-diode relationship
I = I_L - I_0 \left[\exp\left(\frac{V + I R_s}{n N_s V_{th}}\right) - 1\right] - \frac{V + I R_s}{R_{sh}}
to solve for V at the requested current. When shunt resistance is effectively infinite the solution can simplify, while finite-shunt cases use the selected numerical method.
Excel Usage
=V_FROM_I(current, photocurrent, saturation_current, resistance_series, resistance_shunt, nNsVth, vfi_solver)
current(float, required): Operating current (A).photocurrent(float, required): Light-generated current (A).saturation_current(float, required): Diode saturation current (A).resistance_series(float, required): Series resistance (ohms).resistance_shunt(float, required): Shunt resistance (ohms). Use a large value for infinite.nNsVth(float, required): Product of ideality factor, cells in series, and thermal voltage (V).vfi_solver(str, optional, default: “lambertw”): Numerical solver method.
Returns (float): The device voltage (V), or an error string.
Example 1: Voltage at typical Imp
Inputs:
| current | photocurrent | saturation_current | resistance_series | resistance_shunt | nNsVth | vfi_solver |
|---|---|---|---|---|---|---|
| 5.09341 | 5.5 | 2e-10 | 0.5 | 300 | 1.5 | lambertw |
Excel formula:
=V_FROM_I(5.09341, 5.5, 2e-10, 0.5, 300, 1.5, "lambertw")
Expected output:
29.151
Example 2: Voltage at zero current approximates Voc
Inputs:
| current | photocurrent | saturation_current | resistance_series | resistance_shunt | nNsVth | vfi_solver |
|---|---|---|---|---|---|---|
| 0 | 5.5 | 2e-10 | 0.5 | 300 | 1.5 | lambertw |
Excel formula:
=V_FROM_I(0, 5.5, 2e-10, 0.5, 300, 1.5, "lambertw")
Expected output:
36.0231
Example 3: Voltage at typical Imp using Newton solver
Inputs:
| current | photocurrent | saturation_current | resistance_series | resistance_shunt | nNsVth | vfi_solver |
|---|---|---|---|---|---|---|
| 5.09341 | 5.5 | 2e-10 | 0.5 | 300 | 1.5 | newton |
Excel formula:
=V_FROM_I(5.09341, 5.5, 2e-10, 0.5, 300, 1.5, "newton")
Expected output:
29.151
Example 4: Voltage at operating current with higher series resistance
Inputs:
| current | photocurrent | saturation_current | resistance_series | resistance_shunt | nNsVth | vfi_solver |
|---|---|---|---|---|---|---|
| 5.09341 | 5.5 | 2e-10 | 0.9 | 300 | 1.5 | lambertw |
Excel formula:
=V_FROM_I(5.09341, 5.5, 2e-10, 0.9, 300, 1.5, "lambertw")
Expected output:
27.1137
Python Code
Show Code
from pvlib.pvsystem import v_from_i as result_func
def v_from_i(current, photocurrent, saturation_current, resistance_series, resistance_shunt, nNsVth, vfi_solver='lambertw'):
"""
Calculate device voltage at a given current for the single-diode model.
See: https://pvlib-python.readthedocs.io/en/stable/reference/generated/pvlib.pvsystem.v_from_i.html
This example function is provided as-is without any representation of accuracy.
Args:
current (float): Operating current (A).
photocurrent (float): Light-generated current (A).
saturation_current (float): Diode saturation current (A).
resistance_series (float): Series resistance (ohms).
resistance_shunt (float): Shunt resistance (ohms). Use a large value for infinite.
nNsVth (float): Product of ideality factor, cells in series, and thermal voltage (V).
vfi_solver (str, optional): Numerical solver method. Valid options: Lambert W, Newton, Brentq, Chandrupatla. Default is 'lambertw'.
Returns:
float: The device voltage (V), or an error string.
"""
try:
i = float(current)
il = float(photocurrent)
i0 = float(saturation_current)
rs_v = float(resistance_series)
rsh = float(resistance_shunt)
nv = float(nNsVth)
meth = str(vfi_solver) if vfi_solver is not None else "lambertw"
res = result_func(
current=i,
photocurrent=il,
saturation_current=i0,
resistance_series=rs_v,
resistance_shunt=rsh,
nNsVth=nv,
method=meth
)
return float(res)
except Exception as e:
return f"Error: {str(e)}"Online Calculator