pvlib / pvlib-python

A set of documented functions for simulating the performance of photovoltaic energy systems.
https://pvlib-python.readthedocs.io
BSD 3-Clause "New" or "Revised" License
1.22k stars 1.02k forks source link

Using ModelChain with Plane of Array (POA) as weather input #536

Closed srlightfoote closed 4 years ago

srlightfoote commented 6 years ago

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 to weather data frame in mc.run_model?

cwhanse commented 6 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.

srlightfoote commented 6 years ago

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.

cwhanse commented 6 years ago

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.

mikofski commented 6 years ago

I believe that using poa as input is the goal of the gti dirint changes in #400 and #396

wholmgren commented 6 years ago

@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.

cwhanse commented 6 years ago

@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.

srlightfoote commented 6 years ago

@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.

mikofski commented 6 years ago

@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?

wholmgren commented 6 years ago

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.

kevinsa5 commented 6 years ago

@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.

markcampanelli commented 5 years ago

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_models 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.

cwhanse commented 5 years ago

@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?

markcampanelli commented 5 years ago

@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.

wholmgren commented 5 years ago

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.

markcampanelli commented 5 years ago

@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.