Skip to content

Conversation

@dguittet
Copy link
Collaborator

@dguittet dguittet commented May 27, 2025

Run time for Mac w/ 8 processes

2025-05-28 09:19:45: Solving for 21598 Modules
2025-05-28 09:19:45: Starting First Pass Solve
2025-05-28 10:19:50: Solved 21439. 159 remaining.
2025-05-28 10:19:50: Starting Second Pass Solve
2025-05-28 10:20:05: Solved 21574. 24 remaining.
2025-05-28 10:20:05: Starting Final Pass Solve
2025-05-28 10:20:07: Solved 21576. 22 unsolved.

To test, install the dependencies listed in tests/requirements.txt and also conda install -c conda-forge ipopt to install the solver

iv_diff_cols = ['d_Isc', 'd_Imp', 'd_Vmp', 'd_Pmp']

# 6par_solve.h L 423
def current_at_voltage_cec(Vmodule, IL_ref, IO_ref, RS, A_ref, RSH_ref, I_mp_ref):
Copy link
Contributor

@cwhanse cwhanse May 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wondering if pvlib.pvsystem.i_from_v() would be suitable here. This solver iterates using a Newton's method, risking numerical overflow from the exponential term at high voltages, and exiting at rather low precision. The default solver behind pvlib's i_from_v should return 10 digits of precision and handles overflow.

And i_from_v is vectorized, if that doesn't conflict with what pyomo needs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Cliff, thanks for the suggestion. This current_at_voltage_cec function is only for plotting purposes and isn't used in the actual solving. I'm looking at i_from_v() and will run a comparison

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the doc string on the function:

    Solve for the current at the voltage Vmodule, given the single diode parameters which could have been modified for non-STC condition

    Used for plotting only, so numerical precision is only 1e-4. Adapted from ssc/shared/6par_solve.h L 423

    For better stability and precision, use pvlib.pvsystem.i_from_v(v, IL_oper, IO_oper, Rs, Rsh_oper, A_oper)


def cec_model_params_at_condition(model, Irr, T_cell_K):
"""
Get the single diode parameters at a given condition
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pvlib equivalent is pvlib.pvsystem.calcparams_cec. I'm guessing that casting to pyomo objects is necessary, though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take a look, but this function is again just for plotting purposes. Everything for the solve is via pyomo objects in create_model

Copy link
Collaborator Author

@dguittet dguittet May 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two differences I noticed:

  1. The calculation of IL in SAM has a modification using Adjust to the alpha coefficient that's not present in pvlib.
# pvlib L 1695
IL = effective_irradiance / irrad_ref * (I_L_ref + alpha_sc * (Tcell_K - Tref_K))
# sam
IL_oper = Irr/I_ref *( Il + alpha * (1-Adj/100)*(T_cell_K-Tc_ref) )
  1. The calculation of IO. SAM's plotting function had simplified the coefficients (probably to deal with numerical issues in LK), so I switched it back to the version using the Boltzmann coefficient in both the plotting function and in pyomo. The numerical impact was small, but in the precision requirement for pyomo, potentially impactful.
# b.Io_Tc = pyo.Expression(expr=m.par.Io* ( b.Tc/m.Tref)**3 * pyo.exp( 11600 * (m.Egref/m.Tref - b.Eg_Tc/b.Tc)))
b.Io_Tc = pyo.Expression(expr=m.par.Io* ( b.Tc/m.Tref)**3 * pyo.exp(b.Eg_Tc / (m.k*(m.Tref)) - (m.Egref / (m.k*(b.Tc)))))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

calcparams_cec calls calcparams_desoto with the modification to alpha_sc in the passed parameters: alpha_sc*(1.0 - Adjust/100)

The CEC and De Soto models only differ by the Adjust parameter so we re-use code here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I'd missed that! Thanks for pointing it out. Makes sense now

@dguittet
Copy link
Collaborator Author

@cwhanse Thanks for the review! I've addressed your comments, please let me know if you have other feedback

@cwhanse
Copy link
Contributor

cwhanse commented May 28, 2025

@cwhanse Thanks for the review! I've addressed your comments, please let me know if you have other feedback

Curious what solver is being used? Its been some time since I looked at pyomo but I recall that it isn't distributed with a solver.

@dguittet
Copy link
Collaborator Author

dguittet commented May 28, 2025

Curious what solver is being used? Its been some time since I looked at pyomo but I recall that it isn't distributed with a solver.

It's using IPOPT: conda install -c conda-forge ipopt. I'll add that information to the top of the file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants