Closed srlightfoote closed 4 years ago
I agree, this enhancement would be valuable. There isn't an elegant way to supply poa_global
in place of GHI, etc., in the ModelChain
methods. #478 wrestled with this issue.
A question for @srlightfoote : in your use case, does poa_global
already account for either spectral content or reflection loss? I can foresee use cases where poa_global
is sourced from different measurement devices (reference cell, photodiode, pyranometer) where the adjustments to poa_global
from spectrum and reflections may already be accounted for in the measurement.
Not sure I’m qualified to answer the question other than to say that the use case would be for a Pyranometer (secondary standard or other) at a typical operational solar plant installed at the POA of the modules, either at a fixed tilt, or mounted on a tracker array.
OK, if it's a pyranometer then we should anticipate the POA irradiance is broadband without either spectral adjustment or reflection losses. I just wanted to confirm this use case is of interest before we consider the ModelChain
design changes.
I believe that using poa as input is the goal of the gti dirint changes in #400 and #396
@mikofski They are certainly related ideas, but I wrote #400 because it was useful for some parameter fitting algorithms, not because I wanted to integrate the output with ModelChain
. I don't expect to explicitly support the combination in pvlib.
@mikofski I don't think that starting with POA, translating to GHI, then transposing back to POA to provide input to a power simulation is wise. I doubt that the POA-GHI-POA circle closes to the same values.
I think that we can enhance the prepare_inputs
convenience function to accept poa
as a column of input data. While we're at it, we could also allow prepare_inputs
to accept 2 of GHI, DHI, or DNI, and calculate the missing component by closure.
@cwhanse I agree wholeheartedly with your assessment that an expansion of the prepare_inputs
function is probably a good way to go and also that we probably don't want to include additional uncertainties / biases in doing the roundabout POA --> GHI --> POA method. If we have POA, we should use it. That said, wouldn't there be a conflict with the defaults of the ModelChain
creation function which by default applies a transposition algorithm? If the disabling of a transposition algorithm isn't done until the run_model
function is executed this could be an unexpected result for the user. Obviously the user could modify the ModelChain
transposition algorithm choice to None
or False
when calling it in the first place, but that isn't currently the default. Ideally, the weather
data would be an input to Model Chain
itself whereby the code logic used to define the transposition method would default to 'None' or False
if a poa_global
column of data was included. Perhaps the simplest update, other than just allowing the ability to input poa_global
into weather
and disabling the transposition algorithm step in run_model
would be to have the transposition algorithm be overwritten to "None" or "False" upon execution of "run_model" if poa_global
is detected in the weather
data and a simple warning is printed to the command line indicating that this was done. I suppose run_model
could also just error as well if poa_global
is detected along with a defined transposition algorithm.
Thanks all for your interest in this update. Let me know if I can be of further help. I'm afraid my python skills are probably insufficient at this point to contribute to the package, but hopefully in the future I'll be able to lend a hand.
@cwhanse, @wholmgren, @srlightfoote, I'm sorry, I was confused, you are correct, POA if measured and matching spectral and IAM of panels, then should be used directly.
I was thinking about shading, then you might need the components individually for shade and unshaded areas, but correct also that roundabout process will introduce uncertainties.
Although, if POA measurements are not matched spectrally or have different IAM, then I don't see what other choice you would have than go the roundabout way, right?
I'm not too excited about making ModelChain.prepare_inputs
do more than it already does. Maybe it would be ok if some of the existing functionality is refactored into other methods. Perhaps we should think about a new method such as run_model_from_poa
. Maybe also rename the existing run_model
to something like run_model_from_weather
(not sure about this name, but hopefully it gets the idea across).
If we did both of the above, the transposition
argument could be used to map the generic name run_model
to the relevant specific method. Other options (as discussed in #478) could come into play in that mapping as well. I'm not sure if that's a good idea, just brainstorming.
While we're at it, we could also allow prepare_inputs to accept 2 of GHI, DHI, or DNI, and calculate the missing component by closure.
In #239 we decided to make a new method, ModelChain.complete_irradiance
, and expected the user to call this method first if necessary. I still think this is a good design choice. Also relevant to my point of view here is that I think that we should remove the "use clear sky by default" behavior of run_model
/prepare_inputs
.
@cwhanse As far as use-cases go, it would be handy to be able to specify either pyranometer or reference cell as the sensor type when supplying measured POA data (SAM has this toggle). Though if the scope is limited to only allowing one of them, I would agree that assuming pyranometer is preferable.
Additionally, for what it's worth about POA-GHI-POA: SAM will decompose measured POA into constituent direct/diffuse components for shading calculation purposes, and in my experience the recombined POA is pretty close to the original (within a W/m2 or two). But I have no hard data to show for this.
Sorry, I did not see this until just now.
Is there any way that we can abstract these three lines in [ModelChain.run_model]():
self.aoi_model()
self.spectral_model()
self.effective_irradiance_model()
into a single self.compute_irradiance()
method that complements the single temperature method self.compute_temperature()
? The interface for this method is "simply" to compute whatever irradiance input is needed to the DC model whose parameters are in the PVSystem
member and whose implementation is in ModelChain.dc_model
. (Also, this self.compute_irradiance()
's output may need to inform the subsequent self.compute_temperature()
call.) Implementing self.compute_irradiance()
generally for existing and future/custom dc_model
s is where the (potentially disruptive) refactor presumably occurs.
@srlightfoote PVfit can use measurements of an IEC 61853-1 calibrated reference PV device (say, a matched reference module at the same orientation as the array) and directly produce an "effective irradiance ratio" F := Isc/Isc0 and a cell temperature, T, which is then passed to a single-diode performance model that is parameterized directly in terms of F (as opposed to G with various corrections). I can even envision a F-measurement scheme that computes F using a module's T-dependent irradiance-mode spectral response, a conventional module temperature model, and some sort of global tilted spectrometer. Thus, in #478, I was trying to accommodate these possibilities, while "falling back" to a variant of the SAPM to compute F and T from "conventional" MET-station-based weather data when a reference PV device is not available.
@markcampanelli are you suggesting to replace the three separate calculations with a single call to a new method? What would the new method do that the current methods don't?
@cwhanse Yes. Actually, for the main use case I have at hand, the new single method will do less than those three methods put together. With a "matched" reference PV device and an "F-formulation" of a single-diode model, there is no need for the AOI or Spectral Correction computations to determine F. In the simplest case, the weather data are merely a time series of F's and T's, which are directly input to the single-diode model. (An example use case here would be for a capacity acceptance test where one compares measured array power to the model prediction over a period of time, where a reference device monitors F and T directly. See the discussion at https://github.com/pvcaptest/pvcaptest/issues/33.)
However, most folks don't seem to work with such reference devices, so after inspecting the weather
input and seeing that F's are missing, my envisioned compute_irradiance()
method would fall back to a variant of the SAPM effective irradiance computation that "undoes" the Isc0 temperature correction (thus, also introspecting the PVSystem
object for the required subset of SAPM module parameters). This SAPM effective irradiance computation (I think) uses all of those three functions, but instead they would be computed inside the single compute_irradiance()
method that is still the single entry point for the interface.
Granted, I don't understand all the pvlib-python
internals here, so I'm worried that things are already too highly coupled to easily realize this vision. For one, the irradiance computation should not be hard coded like it is now.
ModelChain
was designed to explicitly set (or infer from previously set PVSystem
parameters) the sequence of models that are needed to take a time series of GHI/DHI/DNI to AC power. Once the ModelChain
is successfully instantiated, the code path is completely determined.
It seems that we're discussing some additional switches that make the model configuration depend on the input time series data. This is very much counter to the intent of ModelChain
.
One solution could be refactoring ModelChain
into a smaller base class and a couple of additional class like MetChain
, POAChain
, FTChain
. Or maybe ModelChain
is fundamentally flawed and can't be easily and cleanly adapted into what the discussion in this thread requires. Happy to discuss those alternatives elsewhere.
@wholmgren I'm game for having ModelChain
as a base class that abstracts the modeling procedure, if that procedure can be suitably abstracted/generalized. This is partly why I stopped working on #478, because I seemed to be hacking in an anti-pattern. I note that, based on the very "flexible" nature of model implementation in the single PVSystem
class, I was under the impression that a similar "flexibility" was in mind for ModelChain
, such that one might expect to be able to swap in a custom irradiance function.
Along these lines, should PVSystem
also become a base class that is sub-classed to implement different AC+DC models, as opposed to having a bunch of pre-defined models with "auto-detection" built into a single class, but which can also be overridden by assigning custom functions to PVSystem.dc_model
and/or PVSystem.ac_model
?
This also circles back to the discussion of a "plugin/entrypoint" architecture for the "computational graph" that defines the model chain, and I think it's a real question as to whether this project has the intent and resources to design, enforce, and support such flexible higher-level interfaces.
I really love the concept of the ModelChain in pvlib. However, I would like to be able to use the ModelChain to model DC and AC output of a given system (more than one module and inverter) using Plane of Array irradiance as the weather input, rather than inputting the GHI, DNI and DHI components (which I don't have measurements of) and then specifying a transposition model as part of the ModelChain. Could this functionality of being able to specify:
mc=pvlib.modelchain.ModelChain(transposition_model='None')
and then inputing
poa_global
data as an input toweather
data frame inmc.run_model
?