using bifacial irradiance in pvlib

261 views
Skip to first unread message

Mike Johnson

unread,
Feb 24, 2020, 9:46:33 AM2/24/20
to pvlib-python
Hi all.

I'm wondering if there's a way to pass pvlib.bifacial into pvlib's modelchain.

Also, if I was to use pvlib.bifacial or pvfactors to directly estimate incident irradiance, is there a workflow I can use to turn incident irradiance into power generation for modules in the cec-module list? It seems like pvlib is better set up for Sandia modules, though the CEC module list has more recent modules, including newer bifacial modules.

Thanks.

cwh...@sandia.gov

unread,
Feb 24, 2020, 11:34:23 AM2/24/20
to pvlib-python
On Monday, February 24, 2020 at 7:46:33 AM UTC-7, Mike Johnson wrote:
Hi all.

I'm wondering if there's a way to pass pvlib.bifacial into pvlib's modelchain.

At present, not really.  ModelChain is set up to accept weather as input, containing GHI, DNI and DHI (or just GHI). ModelChain.prepare_inputs() will manipulate those values and assign attribute ModelChain.total_irrad, which is the plane of array irradiance passed to the module output models. One could set ModelChain.total_irrad directly using the output of pvlib.bifacial (more on that in a bit) but then ModelChain.run_model() will overwrite total_irrad.

One significant improvement to ModelChain would be to allow plane-of-array irradiance in the weather input. PR welcome.


Also, if I was to use pvlib.bifacial or pvfactors to directly estimate incident irradiance, is there a workflow I can use to turn incident irradiance into power generation for modules in the cec-module list? It seems like pvlib is better set up for Sandia modules, though the CEC module list has more recent modules, including newer bifacial modules.

Yes. The CEC module models e.g. pvlib.pvsystem.calcparams_cec(effective_irradiance=XXX, …) followed by pvlib.pvsystem.singlediode(…), need the effective irradiance, which is irradiance reaching the cells adjusted for spectrum. The output of pvlib.bifacial.pvfactors_timeseries is broadband irradiance on the front and rear surfaces, reduced by reflections, but not accounting for obstructions and aperture of the rear surface. In this case, one approach could be

effective_irradiance = f(AM, etc.) x (front_poa_irradiance + BF x rear_poa_irradiance) 

where f(AM, etc.) is a model to adjust irradiance for spectrum (e.g., pvlib.atmosphere.first_solar_spectral_correction) and BF is the fraction of irradiance on the rear surface that gets through to the cells. BF can be equated with the bifaciality factor, which is the ratio of back efficiency to front efficiency. Once you have effective_irradiance, the electrical performance of bifacial modules is similar enough to monofacial modules that the CEC model is fine, IMO. Cheers, Cliff


Thanks.

Mike Johnson

unread,
Feb 24, 2020, 12:21:07 PM2/24/20
to pvlib-python
Thanks for your response. :)

Also, I can't express enough how fantastic pvlib is. I'm relatively new at python, and find pvlib very useful and usable (modelchain FTW).

Brock Taute

unread,
Feb 25, 2020, 3:09:43 PM2/25/20
to pvlib-python
It's a little more involved, but I incorporated bifaciality into the ModelChain by making my own version of run_model().  In order to add this method to my ModelChain instance, I needed to import the "types" package.  An example of how this looks is:

def my_irradiance_model(self, weather):


   
# Basic ModelChain calls
   
self.prepare_inputs(weather.index, weather)
   
self.aoi_model()
   
self.spectral_model()
   
self.effective_irradiance_model()
   
self.temp_model()
   
   
# My custom bifacial implementation
    pvfactor
= pvlib.bifacial.pvfactors_timeseries(...)
   
# Save backside irradiance in the modelchain, filling in NaNs with 0s
    setattr
(self, 'back_irradiance', pvfactor[1].fillna(0))
    setattr
(self, 'bifacial_irradiance', self.effective_irradiance + self.back_irradiance * bifaciality)


   
return self


bifaciality is a variable I have that represents the back-to-front ratio Cliff describes.  It's the module bifaciality factor with some losses added to it.

I have similar methods for dc, ac, and plant models so as to incorporate my own custom losses.  There is then a final method:

def my_run_model(self, weather):
   
self.my_irradiance_model(weather)
   
self.my_dc_model()
   
self.my_ac_model()
   
self.my_plant_model()


   
return self


And finally, to assign these methods to my ModelChain instance (which I named mc):

mc.my_irradiance_model = types.MethodType(my_irradiance_model, mc)
# Repeat this code for each model ....
mc
.my_run_model = types.MethodType(my_run_model, mc)



Hopefully this work-around helps!

cwh...@sandia.gov

unread,
Feb 25, 2020, 5:04:11 PM2/25/20
to pvlib-python
Very cool, thanks Brock!


On Tuesday, February 25, 2020 at 1:09:43 PM UTC-7, Brock Taute wrote:
It's a little more involved, but I incorporated bifaciality into the ModelChain by making my own version of run_model().  In order to add this method to my ModelChain instance, I needed to import the "types" package.  An example of how this looks is:
Thanks.

yan gang

unread,
Jan 12, 2021, 7:43:12 AM1/12/21
to pvlib-python
Hi Tautebro , 

So appreciate that you share the example code for bifacial simulation. I can not simulate the fixed rack installation bifacial system by pvlib. Could you please explain more specific for your code (def my_irradiance_model(self, weather):....) ? Thanks a lot.

Gang

Brock Taute

unread,
Jan 19, 2021, 7:27:56 PM1/19/21
to yan gang, pvlib-python
Hello Gang,

My apologies for the delayed response, I was offline last week.  I'm happy to hear that code snippet is useful!

My goal with the code was to recreate the run_model method of the ModelChain class by incorporating bifacial irradiance, and custom loss models (dc, ac, and plant level losses).  It's simplest to ignore the loss models for now and only look at the function my_irradiance_model.  The first chunk of code is identical to the run_model method documented here.

The second chunk of code does as follows:
1. Call the pvlib.bifacial.pvfactors_timeseries function documented here.
2. With this bifacial timeseries, set the back irradiance as an attribute of my ModelChain class.
3. With this bifacial timeseries, set a total bifacial irradiance by combining the front irradiance with the back irradiance * the bifaciality factor of the module.

To make the my_irradiance_model method a part of my ModelChain class, I first created an instance of a ModelChain, which I named mc:
mc = ModelChain(...)  

Then I assign the method to mc using the "types" package:
mc.my_irradiance_model = types.MethodType(my_irradiance_model, mc)  

Now, I can call mc.my_irradiance_model(weather) to run a ModelChain method that includes bifaciality.

Sorry if that's a little difficult to follow, I might be better at answering some direct questions.  If it helps, here is the code in its entirety:  https://github.com/btaute/solar-models/blob/master/solar_functions.py.  It could certainly use some refactoring, but it successfully allowed me to run utility scale bifacial solar plant energy estimates in both R and Python when I first wrote it.

--
You received this message because you are subscribed to the Google Groups "pvlib-python" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pvlib-python...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pvlib-python/d4a1f435-5895-471d-99de-20cfbda7474en%40googlegroups.com.
Message has been deleted

yan gang

unread,
Jan 20, 2021, 8:05:23 AM1/20/21
to pvlib-python
Hi  Tautebro,

It is so appreciate for your help. I will read deeply and try your method these day, then give your feedback . Thanks a lot.

Best regards,

Gang 

Message has been deleted

yan gang

unread,
Feb 6, 2021, 9:13:56 AM2/6/21
to pvlib-python
Hi  Tautebro,

Thank you for your code. It is so appreciate. I finished the bifacial simulation by PVlib under your guidance.

Because I  want to compare PVsyst and PVlib for bifacial module of fixed-rack system, I change a little for the code. 

setattr(self, 'effective_irradiance', self.front_irradiance + self.back_irradiance * self.bifaciality)
And then, add 'self._run_from_effective_irrad(weather)' code for run_my_model function, due to I have to use 'pvsyst' dc model to simulation.
def run_my_model(self, weather):
      self.prepare_inputs(weather)
      self.aoi_model()
      self.spectral_model()
      self.get_effective_irradiance(weather)
      self._run_from_effective_irrad(weather)
      return self

It is glad that the comparison result (as attachment) is relative good, although the rear irradiance gap is a little bigger. It comes from difference of the rear irradiance model (as attachment). 

Thanks again for your help.

Best reagards,

Gang
monofacial_simulation (PVlib VS PVsyst).png
bifacial_simulation (PVlib VS PVsyst).png
pvsyst and pvfactors model difference _ reference paper.png

yan gang

unread,
Feb 22, 2021, 3:34:12 AM2/22/21
to pvlib-python
Hi Tautebro,

When use pvlib to simulate bifacial tracker system, I found that the dc_energy will increase as albedo decrease. However, if I use bifacial fixed rack system to simulate, the trendency is right (dc_energy will increase as albedo increase). I try to fix the bug for two days, but there is no clue, and I am not familiar with pvfacotor. What is the possible reason for that tendency? Hope you can give some bright suggestions. Thanks a lot.

Note: 
1. pvfactor version is V1.4.1, PVlib version is V0.8.0;
2. The tracker_theta result of pvlib is very closed as PVsyst result (as attachment).



Tracker theta.png

Gang
Reply all
Reply to author
Forward
0 new messages