From 3943c1a1c7075e0b4fe8c074097de9ac29bbe0a8 Mon Sep 17 00:00:00 2001 From: Casey Zak Date: Tue, 20 Aug 2019 09:39:58 -0700 Subject: [PATCH 1/7] feat(): Expose bifacial model for mlm and iec module models --- shared/lib_iec61853.cpp | 56 +++++++++++++----------- shared/lib_irradproc.cpp | 22 +++++----- shared/lib_mlmodel.cpp | 28 +++++++----- shared/lib_pv_io_manager.cpp | 8 ++++ ssc/cmod_pvsamv1.cpp | 83 ++++++++++++++++++++---------------- 5 files changed, 112 insertions(+), 85 deletions(-) diff --git a/shared/lib_iec61853.cpp b/shared/lib_iec61853.cpp index 6f0f1f924..471f953cf 100644 --- a/shared/lib_iec61853.cpp +++ b/shared/lib_iec61853.cpp @@ -1,22 +1,22 @@ /** BSD-3-Clause Copyright 2019 Alliance for Sustainable Energy, LLC -Redistribution and use in source and binary forms, with or without modification, are permitted provided +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met : -1. Redistributions of source code must retain the above copyright notice, this list of conditions +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER, CONTRIBUTORS, UNITED STATES GOVERNMENT OR UNITED STATES -DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER, CONTRIBUTORS, UNITED STATES GOVERNMENT OR UNITED STATES +DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -858,47 +858,51 @@ bool iec61853_module_t::operator() ( pvinput_t &input, double TcellC, double opv /* initialize output first */ out.Power = out.Voltage = out.Current = out.Efficiency = out.Voc_oper = out.Isc_oper = 0.0; - double poa, tpoa, iamf; + double iamf; iamf = 1; - if( input.radmode != 3 ){ // Skip module cover effects if using POA reference cell data + double poa_front, poa_total, poa_eff_front, poa_eff_total; + if( input.radmode != 3 ){ // Skip module cover effects if using POA reference cell data // plane of array irradiance, W/m2 - poa = input.Ibeam + input.Idiff + input.Ignd; + poa_front = input.Ibeam + input.Idiff + input.Ignd; + poa_total = poa_front + input.Irear; // Note the rear irradiance has already taken bifaciality into consideration // transmitted poa through module cover - tpoa = poa; + poa_eff_front = poa_front; if ( input.IncAng > AOI_MIN && input.IncAng < AOI_MAX ) { iamf = iam( input.IncAng, GlassAR ); - tpoa = poa - ( 1.0 - iamf )*input.Ibeam*cos(input.IncAng*3.1415926/180.0); - if( tpoa < 0.0 ) tpoa = 0.0; - if( tpoa > poa ) tpoa = poa; + poa_eff_front = poa_front - ( 1.0 - iamf )*input.Ibeam*cos(input.IncAng*3.1415926/180.0); + if( poa_eff_front < 0.0 ) poa_eff_front = 0.0; + if( poa_eff_front > poa_front ) poa_eff_front = poa_front; } // spectral effect via AM modifier double ama = air_mass_modifier( input.Zenith, input.Elev, AMA ); - tpoa *= ama; + poa_eff_front *= ama; + poa_eff_total = poa_eff_front + input.Irear * ama; } else if(input.usePOAFromWF){ // Check if decomposed POA is required, if not use weather file POA directly - tpoa = poa = input.poaIrr; + poa_total = poa_eff_total = input.poaIrr; } else { // Otherwise use decomposed POA - tpoa = poa = input.Ibeam + input.Idiff + input.Ignd; + poa_total = input.poaIrr; + poa_eff_total = input.Ibeam + input.Idiff + input.Ignd + input.Irear; } double Tc = input.Tdry + 273.15; - if ( tpoa >= 1.0 ) + if ( poa_eff_total >= 1.0 ) { Tc = TcellC + 273.15; double q = 1.6e-19; double k = 1.38e-23; double aop = NcellSer*n*k*Tc/q; - double Ilop = tpoa/1000*(Il + alphaIsc*(Tc-298.15)); + double Ilop = poa_eff_total/1000*(Il + alphaIsc*(Tc-298.15)); double Egop = (1-0.0002677*(Tc-298.15))*Egref; double Ioop = Io*pow(Tc/298.15,3.0)*exp( 11600 * (Egref/298.15 - Egop/Tc)); - double Rsop = D1 + D2*(Tc-298.15) + D3*( 1-tpoa/1000.0)*pow(1000.0/poa,2.0); - double Rshop = C1 + C2*( pow(1000.0/tpoa,C3)-1 ); + double Rsop = D1 + D2*(Tc-298.15) + D3*( 1-poa_eff_total/1000.0)*pow(1000.0/poa_total,2.0); + double Rshop = C1 + C2*( pow(1000.0/poa_eff_total,C3)-1 ); // at some very low irradiances, these parameters can blow up due to @@ -929,7 +933,7 @@ bool iec61853_module_t::operator() ( pvinput_t &input, double TcellC, double opv out.Power = P; out.Voltage = V; out.Current = I; - out.Efficiency = P/(Area*poa); + out.Efficiency = P/(Area*poa_total); out.Voc_oper = V_oc; out.Isc_oper = I_sc; out.CellTemp = Tc - 273.15; diff --git a/shared/lib_irradproc.cpp b/shared/lib_irradproc.cpp index d60c301f8..01d57c977 100644 --- a/shared/lib_irradproc.cpp +++ b/shared/lib_irradproc.cpp @@ -1,22 +1,22 @@ /** BSD-3-Clause Copyright 2019 Alliance for Sustainable Energy, LLC -Redistribution and use in source and binary forms, with or without modification, are permitted provided +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met : -1. Redistributions of source code must retain the above copyright notice, this list of conditions +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER, CONTRIBUTORS, UNITED STATES GOVERNMENT OR UNITED STATES -DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER, CONTRIBUTORS, UNITED STATES GOVERNMENT OR UNITED STATES +DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ diff --git a/shared/lib_mlmodel.cpp b/shared/lib_mlmodel.cpp index 0d480d875..054f81c0a 100644 --- a/shared/lib_mlmodel.cpp +++ b/shared/lib_mlmodel.cpp @@ -214,19 +214,26 @@ bool mlmodel_module_t::operator() (pvinput_t &input, double T_C, double opvoltag } // Total effective irradiance - double S; + double S_front, S_total, S_eff_front, S_eff_total; if(input.radmode != 3){ // Skip module cover effects if using POA reference cell data - S = (f_IAM_beam * input.Ibeam + f_IAM_diff * input.Idiff + groundRelfectionFraction * f_IAM_gnd * input.Ignd) * f_AM; + S_front = input.Ibeam + input.Idiff + input.Ignd; + S_total = S_front + input.Irear; // Note the rear irradiance has already taken bifaciality into consideration + S_eff_front = (f_IAM_beam * input.Ibeam + f_IAM_diff * input.Idiff + groundRelfectionFraction * f_IAM_gnd * input.Ignd) * f_AM; + S_eff_total = S_eff_front + input.Irear * f_AM; + out.AOIModifier = S_eff_front / S_front; } else if(input.usePOAFromWF){ // Check if decomposed POA is required, if not use weather file POA directly - S = input.poaIrr; + S_total = S_eff_total = input.poaIrr; + out.AOIModifier = 1.0; } else { // Otherwise use decomposed POA - S = (f_IAM_beam * input.Ibeam + f_IAM_diff * input.Idiff + groundRelfectionFraction * f_IAM_gnd * input.Ignd) * f_AM; + S_total = input.poaIrr; + S_eff_total = input.Ibeam + input.Idiff + input.Ignd + input.Irear; + out.AOIModifier = 1.0; } // Single diode model acc. to [1] - if (S >= 1) + if (S_eff_total >= 1) { double n=0.0, a=0.0, I_L=0.0, I_0=0.0, R_sh=0.0, I_sc=0.0; double V_oc = V_oc_ref; // V_oc_ref as initial guess @@ -245,16 +252,16 @@ bool mlmodel_module_t::operator() (pvinput_t &input, double T_C, double opvoltag for (int i = 1; i <= iterations; i = i + 1) { if (T_mode == T_MODE_FAIMAN) { // T_cell = input.Tdry + (T_c_fa_alpha * G_total * (1 - eff)) / (T_c_fa_U0 + input.Wspd * T_c_fa_U1); - T_cell = input.Tdry + (T_c_fa_alpha * S * (1 - eff)) / (T_c_fa_U0 + input.Wspd * T_c_fa_U1); + T_cell = input.Tdry + (T_c_fa_alpha * S_eff_total* (1 - eff)) / (T_c_fa_U0 + input.Wspd * T_c_fa_U1); } n = n_0 + mu_n * (T_cell - T_ref); a = N_series * k * (T_cell + T_0) * n / q; - I_L = (S / S_ref) * (I_Lref + alpha_isc * (T_cell - T_ref)); - //I_L = (S / S_ref) * (I_Lref + alpha_isc / N_parallel * (T_cell - T_ref)); + I_L = (S_eff_total/ S_ref) * (I_Lref + alpha_isc * (T_cell - T_ref)); + //I_L = (S_eff_total/ S_ref) * (I_Lref + alpha_isc / N_parallel * (T_cell - T_ref)); I_0 = I_0ref * pow(((T_cell + T_0) / (T_ref + T_0)), 3) * exp((q * E_g) / (n * k) * (1 / (T_ref + T_0) - 1 / (T_cell + T_0))); - R_sh = R_shref + (R_sh0 - R_shref) * exp(-R_shexp * (S / S_ref)); + R_sh = R_shref + (R_sh0 - R_shref) * exp(-R_shexp * (S_eff_total/ S_ref)); V_oc = openvoltage_5par_rec(V_oc, a, I_L, I_0, R_sh, D2MuTau, Vbi); I_sc = I_L / (1 + R_s / R_sh); @@ -271,7 +278,7 @@ bool mlmodel_module_t::operator() (pvinput_t &input, double T_C, double opvoltag else I = current_5par_rec(V, 0.9*I_L, a, I_L, I_0, R_s, R_sh, D2MuTau, Vbi); P = V*I; } - eff = P / ((Width * Length) * (input.Ibeam + input.Idiff + input.Ignd)); + eff = P / ((Width * Length) * S_total); } out.Power = P; @@ -281,7 +288,6 @@ bool mlmodel_module_t::operator() (pvinput_t &input, double T_C, double opvoltag out.Voc_oper = V_oc; out.Isc_oper = I_sc; out.CellTemp = T_cell; - out.AOIModifier = S / (input.Ibeam + input.Idiff + input.Ignd); } return out.Power >= 0; diff --git a/shared/lib_pv_io_manager.cpp b/shared/lib_pv_io_manager.cpp index 3b7534a60..a17f365f3 100644 --- a/shared/lib_pv_io_manager.cpp +++ b/shared/lib_pv_io_manager.cpp @@ -1136,6 +1136,10 @@ Module_IO::Module_IO(compute_module* cm, std::string cmName, double dcLoss) else if (modulePowerModel == MODULE_IEC61853) { // IEC 61853 model + isBifacial = cm->as_boolean("sd11par_is_bifacial"); + bifaciality = cm->as_double("sd11par_bifaciality"); + bifacialTransmissionFactor = cm->as_double("sd11par_bifacial_transmission_factor"); + groundClearanceHeight = cm->as_double("sd11par_bifacial_ground_clearance_height"); elevenParamSingleDiodeModel.NcellSer = cm->as_integer("sd11par_nser"); elevenParamSingleDiodeModel.Area = cm->as_double("sd11par_area"); elevenParamSingleDiodeModel.AMA[0] = cm->as_double("sd11par_AMa0"); @@ -1173,6 +1177,10 @@ Module_IO::Module_IO(compute_module* cm, std::string cmName, double dcLoss) else if (modulePowerModel == MODULE_PVYIELD) { // Mermoud/Lejeune single-diode model + isBifacial = cm->as_boolean("mlm_is_bifacial"); + bifaciality = cm->as_double("mlm_bifaciality"); + bifacialTransmissionFactor = cm->as_double("mlm_bifacial_transmission_factor"); + groundClearanceHeight = cm->as_double("mlm_bifacial_ground_clearance_height"); size_t elementCount1 = 0; size_t elementCount2 = 0; ssc_number_t *arrayIncAngle = 0; diff --git a/ssc/cmod_pvsamv1.cpp b/ssc/cmod_pvsamv1.cpp index fa713fcf9..fc6897981 100644 --- a/ssc/cmod_pvsamv1.cpp +++ b/ssc/cmod_pvsamv1.cpp @@ -1,22 +1,22 @@ /** BSD-3-Clause Copyright 2019 Alliance for Sustainable Energy, LLC -Redistribution and use in source and binary forms, with or without modification, are permitted provided +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met : -1. Redistributions of source code must retain the above copyright notice, this list of conditions +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER, CONTRIBUTORS, UNITED STATES GOVERNMENT OR UNITED STATES -DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER, CONTRIBUTORS, UNITED STATES GOVERNMENT OR UNITED STATES +DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -30,11 +30,11 @@ static var_info _cm_vtab_pvsamv1[] = { /* VARTYPE DATATYPE NAME LABEL UNITS META GROUP REQUIRED_IF CONSTRAINTS UI_HINTS*/ {SSC_INPUT, SSC_STRING, "solar_resource_file", "Weather file in TMY2, TMY3, EPW, or SAM CSV", "", "", "Solar Resource", "?", "", "" }, {SSC_INPUT, SSC_TABLE, "solar_resource_data", "Weather data", "", "lat,lon,tz,elev,year,month,hour,minute,gh,dn,df,poa,tdry,twet,tdew,rhum,pres,Snow,alb,aod,wspd,wdir", "Solar Resource", "?", "", "" }, - + // transformer model percent of rated ac output {SSC_INPUT, SSC_NUMBER, "transformer_no_load_loss", "Power transformer no load loss", "%", "", "Losses", "?=0", "", "" }, {SSC_INPUT, SSC_NUMBER, "transformer_load_loss", "Power transformer load loss", "%", "", "Losses", "?=0", "", "" }, - + // optional for lifetime analysis {SSC_INPUT, SSC_NUMBER, "system_use_lifetime_output", "PV lifetime simulation", "0/1", "", "Lifetime", "?=0", "INTEGER,MIN=0,MAX=1", "" }, {SSC_INPUT, SSC_NUMBER, "analysis_period", "Lifetime analysis period", "years", "", "Lifetime", "system_use_lifetime_output=1", "", "" }, @@ -44,7 +44,7 @@ static var_info _cm_vtab_pvsamv1[] = { {SSC_INPUT, SSC_ARRAY, "dc_lifetime_losses", "Lifetime daily DC losses", "%", "", "Lifetime", "en_dc_lifetime_losses=1", "", "" }, {SSC_INPUT, SSC_NUMBER, "en_ac_lifetime_losses", "Enable lifetime daily AC losses", "0/1", "", "Lifetime", "?=0", "INTEGER,MIN=0,MAX=1", "" }, {SSC_INPUT, SSC_ARRAY, "ac_lifetime_losses", "Lifetime daily AC losses", "%", "", "Lifetime", "en_ac_lifetime_losses=1", "", "" }, - + // misc inputs {SSC_INPUT, SSC_NUMBER, "en_snow_model", "Toggle snow loss estimation", "0/1", "", "Losses", "?=0", "BOOLEAN", "" }, {SSC_INPUT, SSC_NUMBER, "system_capacity", "DC Nameplate capacity", "kWdc", "", "System Design", "*", "", "" }, @@ -54,7 +54,7 @@ static var_info _cm_vtab_pvsamv1[] = { {SSC_INPUT, SSC_NUMBER, "sky_model", "Diffuse sky model", "", "0=isotropic,1=hkdr,2=perez", "Solar Resource", "?=2", "INTEGER,MIN=0,MAX=2", "" }, {SSC_INPUT, SSC_NUMBER, "inverter_count", "Number of inverters", "", "", "System Design", "*", "INTEGER,POSITIVE", "" }, {SSC_INPUT, SSC_NUMBER, "enable_mismatch_vmax_calc", "Enable mismatched subarray Vmax calculation", "", "", "System Design", "?=0", "BOOLEAN", "" }, - + // subarray 1 {SSC_INPUT, SSC_NUMBER, "subarray1_nstrings", "Sub-array 1 Number of parallel strings", "", "", "System Design", "", "INTEGER", "" }, {SSC_INPUT, SSC_NUMBER, "subarray1_modules_per_string", "Sub-array 1 Modules per string", "", "", "System Design", "*", "INTEGER,POSITIVE", "" }, @@ -73,7 +73,7 @@ static var_info _cm_vtab_pvsamv1[] = { {SSC_INPUT, SSC_MATRIX, "subarray1_shading:azal", "Sub-array 1 Azimuth x altitude beam shading losses", "%", "", "Shading", "?", "", "" }, {SSC_INPUT, SSC_NUMBER, "subarray1_shading:diff", "Sub-array 1 Diffuse shading loss", "%", "", "Shading", "?", "", "" }, {SSC_INPUT, SSC_ARRAY, "subarray1_soiling", "Sub-array 1 Monthly soiling loss", "%", "", "Losses", "*", "LENGTH=12", "" }, - + // loss diagram outputs, also used to calculate total dc derate {SSC_INPUT, SSC_NUMBER, "subarray1_rear_irradiance_loss", "Sub-array 1 rear irradiance loss", "%", "", "Losses", "*", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray1_mismatch_loss", "Sub-array 1 DC mismatch loss", "%", "", "Losses", "*", "MIN=0,MAX=100", "" }, @@ -81,39 +81,39 @@ static var_info _cm_vtab_pvsamv1[] = { {SSC_INPUT, SSC_NUMBER, "subarray1_dcwiring_loss", "Sub-array 1 DC wiring loss", "%", "", "Losses", "*", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray1_tracking_loss", "Sub-array 1 DC tracking error loss", "%", "", "Losses", "*", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray1_nameplate_loss", "Sub-array 1 DC nameplate loss", "%", "", "Losses", "*", "MIN=-5,MAX=100", "" }, - + {SSC_INPUT, SSC_NUMBER, "subarray2_rear_irradiance_loss", "Sub-array 2 rear irradiance loss", "%", "", "Losses", "subarray2_enable=1", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray2_mismatch_loss", "Sub-array 2 DC mismatch loss", "%", "", "Losses", "?", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray2_diodeconn_loss", "Sub-array 2 DC diodes and connections loss", "%", "", "Losses", "?", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray2_dcwiring_loss", "Sub-array 2 DC wiring loss", "%", "", "Losses", "?", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray2_tracking_loss", "Sub-array 2 DC tracking error loss", "%", "", "Losses", "?", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray2_nameplate_loss", "Sub-array 2 DC nameplate loss", "%", "", "Losses", "?", "MIN=-5,MAX=100", "" }, - + {SSC_INPUT, SSC_NUMBER, "subarray3_rear_irradiance_loss", "Sub-array 3 rear irradiance loss", "%", "", "Losses", "subarray3_enable=1", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray3_mismatch_loss", "Sub-array 3 DC mismatch loss", "%", "", "Losses", "?", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray3_diodeconn_loss", "Sub-array 3 DC diodes and connections loss", "%", "", "Losses", "?", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray3_dcwiring_loss", "Sub-array 3 DC wiring loss", "%", "", "Losses", "?", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray3_tracking_loss", "Sub-array 3 DC tracking error loss", "%", "", "Losses", "?", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray3_nameplate_loss", "Sub-array 3 DC nameplate loss", "%", "", "Losses", "?", "MIN=-5,MAX=100", "" }, - + {SSC_INPUT, SSC_NUMBER, "subarray4_rear_irradiance_loss", "Sub-array 4 rear irradiance loss", "%", "", "Losses", "subarray4_enable=1", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray4_mismatch_loss", "Sub-array 4 DC mismatch loss", "%", "", "Losses", "?", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray4_diodeconn_loss", "Sub-array 4 DC diodes and connections loss", "%", "?", "Losses", "?", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray4_dcwiring_loss", "Sub-array 4 DC wiring loss", "%", "", "Losses", "?", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray4_tracking_loss", "Sub-array 4 DC tracking error loss", "%", "", "Losses", "?", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "subarray4_nameplate_loss", "Sub-array 4 DC nameplate loss", "%", "", "Losses", "?", "MIN=-5,MAX=100", "" }, - + //losses that are applied uniformly to all subarrays {SSC_INPUT, SSC_NUMBER, "dcoptimizer_loss", "DC power optimizer loss", "%", "", "Losses", "*", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "acwiring_loss", "AC wiring loss", "%", "", "Losses", "*", "MIN=0,MAX=100", "" }, {SSC_INPUT, SSC_NUMBER, "transmission_loss", "Transmission loss", "%", "", "Losses", "*", "MIN=0,MAX=100", "" }, - + //system design inputs {SSC_INPUT, SSC_NUMBER, "subarray1_mod_orient", "Sub-array 1 Module orientation", "0/1", "0=portrait,1=landscape", "Layout", "*", "INTEGER,MIN=0,MAX=1", "" }, {SSC_INPUT, SSC_NUMBER, "subarray1_nmodx", "Sub-array 1 Number of modules along bottom of row", "", "", "Layout", "*", "INTEGER,POSITIVE", "" }, {SSC_INPUT, SSC_NUMBER, "subarray1_nmody", "Sub-array 1 Number of modules along side of row", "", "", "Layout", "*", "INTEGER,POSITIVE", "" }, {SSC_INPUT, SSC_NUMBER, "subarray1_backtrack", "Sub-array 1 Backtracking enabled", "", "0=no backtracking,1=backtrack", "System Design", "subarray1_track_mode=1", "BOOLEAN", "" }, - + // subarray 2 {SSC_INPUT, SSC_NUMBER, "subarray2_enable", "Sub-array 2 Enable", "0/1", "0=disabled,1=enabled", "System Design", "?=0", "BOOLEAN", "" }, {SSC_INPUT, SSC_NUMBER, "subarray2_modules_per_string", "Sub-array 2 Modules per string", "", "", "System Design", "subarray2_enable=1", "INTEGER,MIN=1", "" }, @@ -137,7 +137,7 @@ static var_info _cm_vtab_pvsamv1[] = { {SSC_INPUT, SSC_NUMBER, "subarray2_nmodx", "Sub-array 2 Number of modules along bottom of row", "", "", "Layout", "subarray2_enable=1", "INTEGER,POSITIVE", "" }, {SSC_INPUT, SSC_NUMBER, "subarray2_nmody", "Sub-array 2 Number of modules along side of row", "", "", "Layout", "subarray2_enable=1", "INTEGER,POSITIVE", "" }, {SSC_INPUT, SSC_NUMBER, "subarray2_backtrack", "Sub-array 2 Backtracking enabled", "", "0=no backtracking,1=backtrack", "System Design", "", "BOOLEAN", "" }, - + // subarray 3 { SSC_INPUT, SSC_NUMBER, "subarray3_enable", "Sub-array 3 Enable", "0/1", "0=disabled,1=enabled", "System Design", "?=0", "BOOLEAN", "" }, { SSC_INPUT, SSC_NUMBER, "subarray3_modules_per_string", "Sub-array 3 Modules per string", "", "", "System Design", "subarray3_enable=1", "INTEGER,MIN=1", "" }, @@ -161,7 +161,7 @@ static var_info _cm_vtab_pvsamv1[] = { { SSC_INPUT, SSC_NUMBER, "subarray3_nmodx", "Sub-array 3 Number of modules along bottom of row", "", "", "Layout", "subarray3_enable=1", "INTEGER,POSITIVE", "" }, { SSC_INPUT, SSC_NUMBER, "subarray3_nmody", "Sub-array 3 Number of modules along side of row", "", "", "Layout", "subarray3_enable=1", "INTEGER,POSITIVE", "" }, { SSC_INPUT, SSC_NUMBER, "subarray3_backtrack", "Sub-array 3 Backtracking enabled", "", "0=no backtracking,1=backtrack", "System Design", "", "BOOLEAN", "" }, - + // subarray 4 { SSC_INPUT, SSC_NUMBER, "subarray4_enable", "Sub-array 4 Enable", "0/1", "0=disabled,1=enabled", "System Design", "?=0", "BOOLEAN", "" }, { SSC_INPUT, SSC_NUMBER, "subarray4_modules_per_string", "Sub-array 4 Modules per string", "", "", "System Design", "subarray4_enable=1", "INTEGER,MIN=1", "" }, @@ -185,11 +185,11 @@ static var_info _cm_vtab_pvsamv1[] = { { SSC_INPUT, SSC_NUMBER, "subarray4_nmodx", "Sub-array 4 Number of modules along bottom of row", "", "", "Layout", "subarray4_enable=1", "INTEGER,POSITIVE", "" }, { SSC_INPUT, SSC_NUMBER, "subarray4_nmody", "Sub-array 4 Number of modules along side of row", "", "", "Layout", "subarray4_enable=1", "INTEGER,POSITIVE", "" }, { SSC_INPUT, SSC_NUMBER, "subarray4_backtrack", "Sub-array 4 Backtracking enabled", "", "0=no backtracking,1=backtrack", "System Design", "", "BOOLEAN", "" }, - + // module { SSC_INPUT, SSC_NUMBER, "module_model", "Photovoltaic module model specifier", "", "0=spe,1=cec,2=6par_user,3=snl,4=sd11-iec61853,5=PVYield", "Module", "*", "INTEGER,MIN=0,MAX=5", "" }, { SSC_INPUT, SSC_NUMBER, "module_aspect_ratio", "Module aspect ratio", "", "", "Layout", "?=1.7", "POSITIVE", "" }, - + // spe model { SSC_INPUT, SSC_NUMBER, "spe_area", "Module area", "m2", "", "Simple Efficiency Module Model", "module_model=0", "", "" }, { SSC_INPUT, SSC_NUMBER, "spe_rad0", "Irradiance level 0", "W/m2", "", "Simple Efficiency Module Model", "module_model=0", "", "" }, @@ -215,7 +215,7 @@ static var_info _cm_vtab_pvsamv1[] = { { SSC_INPUT, SSC_NUMBER, "spe_bifacial_transmission_factor", "Bifacial transmission factor", "0-1", "", "Simple Efficiency Module Model", "module_model=0", "", "" }, { SSC_INPUT, SSC_NUMBER, "spe_bifaciality", "Bifaciality factor", "%", "", "Simple Efficiency Module Model", "module_model=0", "", "" }, { SSC_INPUT, SSC_NUMBER, "spe_bifacial_ground_clearance_height", "Module ground clearance height", "m", "", "Simple Efficiency Module Model", "module_model=0", "", "" }, - + // cec model { SSC_INPUT, SSC_NUMBER, "cec_area", "Module area", "m2", "", "CEC Performance Model with Module Database", "module_model=1", "", "" }, { SSC_INPUT, SSC_NUMBER, "cec_a_ref", "Nonideality factor a", "", "", "CEC Performance Model with Module Database", "module_model=1", "", "" }, @@ -249,7 +249,7 @@ static var_info _cm_vtab_pvsamv1[] = { { SSC_INPUT, SSC_NUMBER, "cec_array_rows", "Rows of modules in array", "", "", "CEC Performance Model with Module Database", "module_model=1&cec_temp_corr_mode=1","", "" }, { SSC_INPUT, SSC_NUMBER, "cec_array_cols", "Columns of modules in array", "", "", "CEC Performance Model with Module Database", "module_model=1&cec_temp_corr_mode=1","", "" }, { SSC_INPUT, SSC_NUMBER, "cec_backside_temp", "Module backside temperature", "C", "", "CEC Performance Model with Module Database", "module_model=1&cec_temp_corr_mode=1","POSITIVE", "" }, - + // 6 par model { SSC_INPUT, SSC_NUMBER, "6par_celltech", "Solar cell technology type", "", "monoSi=0,multiSi=1,CdTe=2,CIS=3,CIGS=4,Amorphous=5", "CEC Performance Model with User Entered Specifications","module_model=2", "INTEGER,MIN=0,MAX=5", "" }, { SSC_INPUT, SSC_NUMBER, "6par_vmp", "Maximum power point voltage", "V", "", "CEC Performance Model with User Entered Specifications","module_model=2", "", "" }, @@ -268,7 +268,7 @@ static var_info _cm_vtab_pvsamv1[] = { { SSC_INPUT, SSC_NUMBER, "6par_bifacial_transmission_factor", "Bifacial transmission factor", "0-1", "", "CEC Performance Model with User Entered Specifications","module_model=2", "", "" }, { SSC_INPUT, SSC_NUMBER, "6par_bifaciality", "Bifaciality factor", "%", "", "CEC Performance Model with User Entered Specifications","module_model=2", "", "" }, { SSC_INPUT, SSC_NUMBER, "6par_bifacial_ground_clearance_height","Module ground clearance height", "m", "", "CEC Performance Model with User Entered Specifications","module_model=2", "", "" }, - + // snl module model { SSC_INPUT, SSC_NUMBER, "snl_module_structure", "Module and mounting structure configuration", "", "0=Use Database Values,1=glass/cell/polymer sheet-open rack,2=glass/cell/glass-open rack,3=polymer/thin film/steel-open rack,4=Insulated back BIPV,5=close roof mount,6=user-defined", "Sandia PV Array Performance Model with Module Database","module_model=3", "INTEGER,MIN=0,MAX=6", "" }, { SSC_INPUT, SSC_NUMBER, "snl_a", "Temperature coefficient a", "", "", "Sandia PV Array Performance Model with Module Database","module_model=3", "", "" }, @@ -312,7 +312,7 @@ static var_info _cm_vtab_pvsamv1[] = { { SSC_INPUT, SSC_NUMBER, "snl_series_cells", "Number of cells in series", "", "", "Sandia PV Array Performance Model with Module Database","module_model=3", "INTEGER", "" }, { SSC_INPUT, SSC_NUMBER, "snl_vmpo", "Max power point voltage", "", "", "Sandia PV Array Performance Model with Module Database","module_model=3", "", "" }, { SSC_INPUT, SSC_NUMBER, "snl_voco", "Open circuit voltage", "", "", "Sandia PV Array Performance Model with Module Database","module_model=3", "", "" }, - + // 11 parameter model { SSC_INPUT, SSC_NUMBER, "sd11par_nser", "Nseries", "", "", "IEC61853 Single Diode Model", "module_model=4", "INTEGER,POSITIVE", "" }, { SSC_INPUT, SSC_NUMBER, "sd11par_area", "Module area", "m2", "", "IEC61853 Single Diode Model", "module_model=4", "", "" }, @@ -340,7 +340,12 @@ static var_info _cm_vtab_pvsamv1[] = { { SSC_INPUT, SSC_NUMBER, "sd11par_c1", "Rsh fit parameter 1", "", "", "IEC61853 Single Diode Model", "module_model=4", "", "" }, { SSC_INPUT, SSC_NUMBER, "sd11par_c2", "Rsh fit parameter 2", "", "", "IEC61853 Single Diode Model", "module_model=4", "", "" }, { SSC_INPUT, SSC_NUMBER, "sd11par_c3", "Rsh fit parameter 3", "", "", "IEC61853 Single Diode Model", "module_model=4", "", "" }, - + { SSC_INPUT, SSC_NUMBER, "sd11par_is_bifacial", "Modules are bifacial", "0/1", "", "IEC61853 Single Diode Model", "module_model=4", "", "" }, + { SSC_INPUT, SSC_NUMBER, "sd11par_bifacial_transmission_factor", "Bifacial transmission factor", "0-1", "", "IEC61853 Single Diode Model", "module_model=4", "", "" }, + { SSC_INPUT, SSC_NUMBER, "sd11par_bifaciality", "Bifaciality factor", "%", "", "IEC61853 Single Diode Model", "module_model=4", "", "" }, + { SSC_INPUT, SSC_NUMBER, "sd11par_bifacial_ground_clearance_height", "Module ground clearance height", "m", "", "IEC61853 Single Diode Model", "module_model=4", "", "" }, + + // mlm model { SSC_INPUT, SSC_NUMBER, "mlm_N_series", "Number of cells in series", "-", "", "Mermoud Lejeune Single Diode Model", "module_model=5", "", "" }, { SSC_INPUT, SSC_NUMBER, "mlm_N_parallel", "Number of cells in parallel", "-", "", "Mermoud Lejeune Single Diode Model", "module_model=5", "", "" }, @@ -393,13 +398,17 @@ static var_info _cm_vtab_pvsamv1[] = { { SSC_INPUT, SSC_ARRAY, "mlm_IAM_c_cs_incAngle", "Spline IAM - Incidence angles", "deg", "", "Mermoud Lejeune Single Diode Model", "module_model=5", "", "" }, { SSC_INPUT, SSC_ARRAY, "mlm_IAM_c_cs_iamValue", "Spline IAM - IAM values", "-", "", "Mermoud Lejeune Single Diode Model", "module_model=5", "", "" }, { SSC_INPUT, SSC_NUMBER, "mlm_groundRelfectionFraction", "Ground reflection fraction", "-", "", "Mermoud Lejeune Single Diode Model", "module_model=5", "", "" }, - + { SSC_INPUT, SSC_NUMBER, "mlm_is_bifacial", "Modules are bifacial", "0/1", "", "Mermoud Lejeune Single Diode Model", "module_model=5", "", "" }, + { SSC_INPUT, SSC_NUMBER, "mlm_bifacial_transmission_factor", "Bifacial transmission factor", "0-1", "", "Mermoud Lejeune Single Diode Model", "module_model=5", "", "" }, + { SSC_INPUT, SSC_NUMBER, "mlm_bifaciality", "Bifaciality factor", "%", "", "Mermoud Lejeune Single Diode Model", "module_model=5", "", "" }, + { SSC_INPUT, SSC_NUMBER, "mlm_bifacial_ground_clearance_height", "Module ground clearance height", "m", "", "Mermoud Lejeune Single Diode Model", "module_model=5", "", "" }, + // inverter model { SSC_INPUT, SSC_NUMBER, "inverter_model", "Inverter model specifier", "", "0=cec,1=datasheet,2=partload,3=coefficientgenerator,4=PVYield", "Inverter", "*", "INTEGER,MIN=0,MAX=4", "" }, { SSC_INPUT, SSC_NUMBER, "mppt_low_inverter", "Minimum inverter MPPT voltage window", "Vdc", "", "Inverter", "?=0", "", "" }, { SSC_INPUT, SSC_NUMBER, "mppt_hi_inverter", "Maximum inverter MPPT voltage window", "Vdc", "", "Inverter", "?=0", "", "" }, { SSC_INPUT, SSC_NUMBER, "inv_num_mppt", "Number of MPPT inputs", "", "", "Inverter", "?=1", "INTEGER,MIN=0,MAX=4", "" }, - + { SSC_INPUT, SSC_NUMBER, "inv_snl_c0", "Curvature between AC power and DC power at ref", "1/W", "", "Inverter CEC Database", "inverter_model=0", "", "" }, { SSC_INPUT, SSC_NUMBER, "inv_snl_c1", "Coefficient of Pdco variation with DC input voltage", "1/V", "", "Inverter CEC Database", "inverter_model=0", "", "" }, { SSC_INPUT, SSC_NUMBER, "inv_snl_c2", "Coefficient of Pso variation with DC input voltage", "1/V", "", "Inverter CEC Database", "inverter_model=0", "", "" }, @@ -526,8 +535,8 @@ static var_info _cm_vtab_pvsamv1[] = { { SSC_OUTPUT, SSC_ARRAY, "subarray1_poa_shaded", "Subarray 1 POA front total irradiance after shading only", "W/m2", "", "Time Series (Subarray 1)", "*", "", "" }, { SSC_OUTPUT, SSC_ARRAY, "subarray1_poa_shaded_soiled", "Subarray 1 POA front total irradiance after shading and soiling", "W/m2", "", "Time Series (Subarray 1)", "*", "", "" }, { SSC_OUTPUT, SSC_ARRAY, "subarray1_poa_front", "Subarray 1 POA front total irradiance after reflection (IAM)", "W/m2", "", "Time Series (Subarray 1)", "*", "", "" }, - { SSC_OUTPUT, SSC_ARRAY, "subarray1_poa_rear", "Subarray 1 POA rear total irradiance after reflection (IAM)", "W/m2", "", "Time Series (Subarray 1)", "*", "", "" }, - { SSC_OUTPUT, SSC_ARRAY, "subarray1_poa_eff", "Subarray 1 POA total irradiance after reflection (IAM)", "W/m2", "", "Time Series (Subarray 1)", "*", "", "" }, + { SSC_OUTPUT, SSC_ARRAY, "subarray1_poa_rear", "Subarray 1 POA rear total irradiance after reflection (IAM) and losses","W/m2", "", "Time Series (Subarray 1)", "*", "", "" }, + { SSC_OUTPUT, SSC_ARRAY, "subarray1_poa_eff", "Subarray 1 POA total irradiance after reflection (IAM) and bifaciality","W/m2", "", "Time Series (Subarray 1)", "*", "", "" }, { SSC_OUTPUT, SSC_ARRAY, "subarray1_soiling_derate", "Subarray 1 Soiling beam irradiance factor", "frac", "", "Time Series (Subarray 1)", "*", "", "" }, { SSC_OUTPUT, SSC_ARRAY, "subarray1_beam_shading_factor", "Subarray 1 External shading and soiling beam irradiance factor", "frac", "", "Time Series (Subarray 1)", "*", "", "" }, { SSC_OUTPUT, SSC_ARRAY, "subarray1_linear_derate", "Subarray 1 Self-shading linear beam irradiance factor", "frac", "", "Time Series (Subarray 1)", "*", "", "" }, @@ -1589,7 +1598,7 @@ void cm_pvsamv1::exec( ) throw (compute_module::general_error) double V = stringV / (double)Subarrays[nn]->nModulesPerString; //voltage of an individual module on a string on this subarray //initalize pvinput and pvoutput structures for the model - pvinput_t in(Subarrays[nn]->poa.poaBeamFront, Subarrays[nn]->poa.poaDiffuseFront, Subarrays[nn]->poa.poaGroundFront, Subarrays[nn]->poa.poaRear, Subarrays[nn]->poa.poaTotal, + pvinput_t in(Subarrays[nn]->poa.poaBeamFront, Subarrays[nn]->poa.poaDiffuseFront, Subarrays[nn]->poa.poaGroundFront, Subarrays[nn]->poa.poaRear * bifaciality, Subarrays[nn]->poa.poaTotal, wf.tdry, wf.tdew, wf.wspd, wf.wdir, wf.pres, solzen, Subarrays[nn]->poa.angleOfIncidenceDegrees, hdr.elev, Subarrays[nn]->poa.surfaceTiltDegrees, Subarrays[nn]->poa.surfaceAzimuthDegrees, @@ -1628,7 +1637,7 @@ void cm_pvsamv1::exec( ) throw (compute_module::general_error) { int nn = SubarraysOnMpptInput[nSubarray]; //get the index of the subarray we're checking here //initalize pvinput and pvoutput structures for the model - pvinput_t in_temp(Subarrays[nn]->poa.poaBeamFront, Subarrays[nn]->poa.poaDiffuseFront, Subarrays[nn]->poa.poaGroundFront, Subarrays[nn]->poa.poaRear, Subarrays[nn]->poa.poaTotal, + pvinput_t in_temp(Subarrays[nn]->poa.poaBeamFront, Subarrays[nn]->poa.poaDiffuseFront, Subarrays[nn]->poa.poaGroundFront, Subarrays[nn]->poa.poaRear * bifaciality, Subarrays[nn]->poa.poaTotal, wf.tdry, wf.tdew, wf.wspd, wf.wdir, wf.pres, solzen, Subarrays[nn]->poa.angleOfIncidenceDegrees, hdr.elev, Subarrays[nn]->poa.surfaceTiltDegrees, Subarrays[nn]->poa.surfaceAzimuthDegrees, From 4185c90792b2ca1d61b24f5b30406ea585f0aed0 Mon Sep 17 00:00:00 2001 From: Casey Zak Date: Thu, 22 Aug 2019 17:15:24 -0700 Subject: [PATCH 2/7] dev(lib_pvshade): Change poa_ground shade derate to match PVsyst It seems like the right way to do it is how SAM currently does it, but using the PVsyst approach means better agreement as well as more simplicity when you do the full analysis for the bifacial scenario --- shared/lib_pvshade.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/shared/lib_pvshade.cpp b/shared/lib_pvshade.cpp index 38f007da4..7f1124cd2 100644 --- a/shared/lib_pvshade.cpp +++ b/shared/lib_pvshade.cpp @@ -215,21 +215,27 @@ void diffuse_reduce( double solalt = 90 - solzen; - // ground reflected reduction + // ground reflected reduction + // simplified to match PVsyst's approach except for in bifacial scenarios CZ 8/2019 double F1 = alb * pow(sind(stilt / 2.0), 2); - double Y1 = R - B * sind(180.0 - solalt - stilt) / sind(solalt); - Y1 = fmax(0.00001, Y1); // constraint per Chris 4/23/12 - double F2 = 0.5 * (1.0 + Y1 / B - sqrt(pow(Y1, 2) / pow(B, 2) - 2 * Y1 / B * cosd(180 - stilt) + 1.0)); - double F3 = 0.5 * (1.0 + R / B - sqrt(pow(R, 2) / pow(B, 2) - 2 * R / B * cosd(180 - stilt) + 1.0)); +// double Y1 = R - B * sind(180.0 - solalt - stilt) / sind(solalt); +// Y1 = fmax(0.00001, Y1); // constraint per Chris 4/23/12 +// double F2 = 0.5 * (1.0 + Y1 / B - sqrt(pow(Y1, 2) / pow(B, 2) - 2 * Y1 / B * cosd(180 - stilt) + 1.0)); +// double F3 = 0.5 * (1.0 + R / B - sqrt(pow(R, 2) / pow(B, 2) - 2 * R / B * cosd(180 - stilt) + 1.0)); double Gr1 = F1 * (Gbh + Gdh); - double reduced_gnddiff_iso = ((F1 + (nrows - 1) * F1 * F2) / nrows) * Gbh - + ((F1 + (nrows - 1) * F1 * F3) / nrows) * Gdh; +// double reduced_gnddiff_iso = ((F1 + (nrows - 1) * F1 * F2) / nrows) * Gbh +// + ((F1 + (nrows - 1) * F1 * F3) / nrows) * Gdh; + +// Fgnddiff = 1.0; +// if (Gr1 > 0) +// Fgnddiff = reduced_gnddiff_iso / Gr1; +// reduced_gnddiff = Fgnddiff * reduced_gnddiff_iso; Fgnddiff = 1.0; if (Gr1 > 0) - Fgnddiff = reduced_gnddiff_iso / Gr1; - reduced_gnddiff = Fgnddiff * reduced_gnddiff_iso; + Fgnddiff = 1.0 / nrows; + reduced_gnddiff = Fgnddiff * poa_gnd; } double selfshade_dc_derate(double X, double S, double FF0, double dbh_ratio, double m_d, double Vmp) From 7b39ff9687eca7303d538d4a1892f271ea1d1d69 Mon Sep 17 00:00:00 2001 From: Casey Zak Date: Thu, 22 Aug 2019 18:08:40 -0700 Subject: [PATCH 3/7] dev(): Account for frontside ground irradiance from bifacial model and add rearside irradiance component outputs To bring model into alignment with PVsyst. Also added a commented out section for tweak the rearside irradiance if it's eventually needed --- shared/lib_irradproc.cpp | 75 ++++++++++++++++++++++++++++++++---- shared/lib_irradproc.h | 20 ++++++++-- shared/lib_pv_io_manager.cpp | 9 ++++- shared/lib_pv_io_manager.h | 9 ++++- shared/lib_pvshade.cpp | 6 +-- ssc/cmod_pvsamv1.cpp | 49 ++++++++++++++++++----- 6 files changed, 141 insertions(+), 27 deletions(-) diff --git a/shared/lib_irradproc.cpp b/shared/lib_irradproc.cpp index 01d57c977..cafb66b3b 100644 --- a/shared/lib_irradproc.cpp +++ b/shared/lib_irradproc.cpp @@ -845,6 +845,13 @@ void irrad::setup() planeOfArrayIrradianceRear[0] = planeOfArrayIrradianceRear[1] = planeOfArrayIrradianceRear[2] = diffuseIrradianceRear[0] = diffuseIrradianceRear[1] = diffuseIrradianceRear[2] = std::numeric_limits::quiet_NaN(); timeStepSunPosition[0] = timeStepSunPosition[1] = timeStepSunPosition[2] = -999; planeOfArrayIrradianceRearAverage = 0; + planeOfArrayIrradianceFrontAverageFromGroundBiFa = 0; + groundIrradianceRearAverage = 0; + planeOfArrayIrradianceFrontAverageBiFa = 0; + planeOfArrayIrradianceRearBeam = 0; + planeOfArrayIrradianceRearSky = 0; + planeOfArrayIrradianceRearGround = 0; + planeOfArrayIrradianceRearReflected = 0; calculatedDirectNormal = directNormal; calculatedDiffuseHorizontal = 0.0; @@ -962,9 +969,18 @@ void irrad::get_poa( double *beam, double *skydiff, double *gnddiff, if ( horizon != 0 ) *horizon = diffuseIrradianceFront[2]; } -double irrad::get_poa_rear() +void irrad::get_poa_rear(double *poa_rear, double *poa_front_ground, double *ghi_interrow, double *poa_front_bifacial, + double *poa_rear_beam, double *poa_rear_sky_diff, double *poa_rear_ground, double *poa_rear_reflected) { - return planeOfArrayIrradianceRearAverage; + *poa_rear = planeOfArrayIrradianceRearAverage; + *poa_front_ground = planeOfArrayIrradianceFrontAverageFromGroundBiFa; + *ghi_interrow = groundIrradianceRearAverage; + *poa_front_bifacial = planeOfArrayIrradianceFrontAverageBiFa; + *poa_rear_beam = planeOfArrayIrradianceRearBeam; + *poa_rear_sky_diff = planeOfArrayIrradianceRearSky; + *poa_rear_ground = planeOfArrayIrradianceRearGround; + *poa_rear_reflected = planeOfArrayIrradianceRearReflected; +// return planeOfArrayIrradianceRearAverage; } void irrad::get_irrad (double *ghi, double *dni, double *dhi){ @@ -1255,18 +1271,36 @@ int irrad::calc_rear_side(double transmissionFactor, double groundClearanceHeigh // Get the rear ground GHI std::vector rearGroundGHI, frontGroundGHI; + double averageGroundGHI = 0.0; this->getGroundGHI(transmissionFactor, rearSkyConfigFactors, frontSkyConfigFactors, rearGroundShade, frontGroundShade, rearGroundGHI, frontGroundGHI); + for (size_t i = 0; i != rearGroundGHI.size(); i++) + averageGroundGHI += rearGroundGHI[i] / rearGroundGHI.size(); + groundIrradianceRearAverage = averageGroundGHI; // Calculate the irradiance on the front of the PV module (to get front reflected) - std::vector frontIrradiancePerCellrow, frontReflected; + std::vector frontIrradiancePerCellrow, frontReflected, frontIrradianceFromGroundPerCellRow; double frontAverageIrradiance = 0; - getFrontSurfaceIrradiances(pvFrontShadeFraction, rowToRow, verticalHeight, clearanceGround, distanceBetweenRows, horizontalLength, frontGroundGHI, frontIrradiancePerCellrow, frontAverageIrradiance, frontReflected); - + double frontAverageIrradianceFromGround = 0; + getFrontSurfaceIrradiances(pvFrontShadeFraction, rowToRow, verticalHeight, clearanceGround, distanceBetweenRows, horizontalLength, frontGroundGHI, + frontIrradiancePerCellrow, frontAverageIrradiance, frontReflected, frontIrradianceFromGroundPerCellRow, frontAverageIrradianceFromGround); + planeOfArrayIrradianceFrontAverageFromGroundBiFa = frontAverageIrradianceFromGround; + planeOfArrayIrradianceFrontAverageBiFa = frontAverageIrradiance; // Calculate the irradiance on the back of the PV module std::vector rearIrradiancePerCellrow; double rearAverageIrradiance = 0; - getBackSurfaceIrradiances(pvBackShadeFraction, rowToRow, verticalHeight, clearanceGround, distanceBetweenRows, horizontalLength, rearGroundGHI, frontGroundGHI, frontReflected, rearIrradiancePerCellrow, rearAverageIrradiance); + double rearAverageIrradianceBeam = 0; + double rearAverageIrradianceSky = 0; + double rearAverageIrradianceGround = 0; + double rearAverageIrradianceReflected = 0; + getBackSurfaceIrradiances(pvBackShadeFraction, rowToRow, verticalHeight, clearanceGround, distanceBetweenRows, + horizontalLength, rearGroundGHI, frontGroundGHI, frontReflected, rearIrradiancePerCellrow, + rearAverageIrradiance, rearAverageIrradianceBeam, rearAverageIrradianceSky, rearAverageIrradianceGround, rearAverageIrradianceReflected); planeOfArrayIrradianceRearAverage = rearAverageIrradiance; + planeOfArrayIrradianceRearBeam = rearAverageIrradianceBeam; + planeOfArrayIrradianceRearSky = rearAverageIrradianceSky; + planeOfArrayIrradianceRearGround = rearAverageIrradianceGround; + planeOfArrayIrradianceRearReflected = rearAverageIrradianceReflected; + } return true; } @@ -1492,7 +1526,10 @@ void irrad::getGroundGHI(double transmissionFactor, std::vector rearSkyC } } -void irrad::getFrontSurfaceIrradiances(double pvFrontShadeFraction, double rowToRow, double verticalHeight, double clearanceGround, double distanceBetweenRows, double horizontalLength, std::vector frontGroundGHI, std::vector & frontIrradiance, double & frontAverageIrradiance, std::vector & frontReflected) +void irrad::getFrontSurfaceIrradiances(double pvFrontShadeFraction, double rowToRow, double verticalHeight, double clearanceGround, + double distanceBetweenRows, double horizontalLength, std::vector frontGroundGHI, + std::vector & frontIrradiance, double & frontAverageIrradiance, std::vector & frontReflected, + std::vector & frontIrradianceFromGround, double & frontAverageIrradianceFromGround) { // front surface assumed to be glass double n2 = 1.526; @@ -1544,6 +1581,7 @@ void irrad::getFrontSurfaceIrradiances(double pvFrontShadeFraction, double rowTo frontIrradiance.push_back(0.); frontReflected.push_back(0.); + frontIrradianceFromGround.push_back(0.); double reflectanceNormalIncidence = pow((n2 - 1.0) / (n2 + 1.0), 2.0); // Add sky diffuse component and horizon brightening if present @@ -1626,6 +1664,7 @@ void irrad::getFrontSurfaceIrradiances(double pvFrontShadeFraction, double rowTo } } frontIrradiance[i] += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * MarionAOICorrectionFactorsGlass[j] * actualGroundGHI * this->albedo; + frontIrradianceFromGround[i] += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * MarionAOICorrectionFactorsGlass[j] * actualGroundGHI * this->albedo; frontReflected[i] += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * actualGroundGHI * this->albedo * (1.0 - MarionAOICorrectionFactorsGlass[j] * (1.0 - reflectanceNormalIncidence)); } // Calculate and add direct and circumsolar irradiance components @@ -1649,10 +1688,15 @@ void irrad::getFrontSurfaceIrradiances(double pvFrontShadeFraction, double rowTo frontIrradiance[i] += (1.0 - cellShade) * (poa[0] + diffc[1]) * cor; } frontAverageIrradiance += frontIrradiance[i] / cellRows; + frontAverageIrradianceFromGround += frontIrradianceFromGround[i] / cellRows; } } -void irrad::getBackSurfaceIrradiances(double pvBackShadeFraction, double rowToRow, double verticalHeight, double clearanceGround, double , double horizontalLength, std::vector rearGroundGHI, std::vector frontGroundGHI, std::vector frontReflected, std::vector & rearIrradiance, double & rearAverageIrradiance) +void irrad::getBackSurfaceIrradiances(double pvBackShadeFraction, double rowToRow, double verticalHeight, + double clearanceGround, double , double horizontalLength, std::vector rearGroundGHI, std::vector frontGroundGHI, + std::vector frontReflected, std::vector & rearIrradiance, + double & rearAverageIrradiance, double & rearAverageIrradianceBeam, double & rearAverageIrradianceSky, + double & rearAverageIrradianceGround, double & rearAverageIrradianceReflected) { // front surface assumed to be glass double n2 = 1.526; @@ -1686,6 +1730,11 @@ void irrad::getBackSurfaceIrradiances(double pvBackShadeFraction, double rowToRo double PtopX = rowToRow + horizontalLength; // x value for point on top edge of PV module/panel of row in back of (in PV panel slope lengths) double PtopY = verticalHeight + clearanceGround; // y value for point on top edge of PV module/panel of row in back of (in PV panel slope lengths) + rearAverageIrradianceBeam = 0; + rearAverageIrradianceSky = 0; + rearAverageIrradianceGround = 0; + rearAverageIrradianceReflected = 0; + // Calculate diffuse and direct component irradiances for each cell row (assuming 6 rows) size_t cellRows = 6; for (size_t i = 0; i != cellRows; i++) @@ -1704,9 +1753,11 @@ void irrad::getBackSurfaceIrradiances(double pvBackShadeFraction, double rowToRo for (size_t j = 0; j != iStopIso; j++) { rearIrradiance[i] += 0.5 * (cos(j * DTOR) - cos((j + 1)*DTOR)) * MarionAOICorrectionFactorsGlass[j]* isotropicSkyDiffuse; + rearAverageIrradianceSky += 0.5 * (cos(j * DTOR) - cos((j + 1)*DTOR)) * MarionAOICorrectionFactorsGlass[j]* isotropicSkyDiffuse; if ((iStopIso - j) <= iHorBright) { rearIrradiance[i] += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * MarionAOICorrectionFactorsGlass[j]* horizonDiffuse / 0.052264; // 0.052246 = 0.5 * [cos(84) - cos(90)] + rearAverageIrradianceSky += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * MarionAOICorrectionFactorsGlass[j]* horizonDiffuse / 0.052264; } } @@ -1751,6 +1802,7 @@ void irrad::getBackSurfaceIrradiances(double pvBackShadeFraction, double rowToRo } PVreflectedIrradiance /= projectedX2 - projectedX1; rearIrradiance[i] += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * MarionAOICorrectionFactorsGlass[j] * PVreflectedIrradiance; + rearAverageIrradianceReflected += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * MarionAOICorrectionFactorsGlass[j] * PVreflectedIrradiance; } @@ -1834,6 +1886,7 @@ void irrad::getBackSurfaceIrradiances(double pvBackShadeFraction, double rowToRo } } rearIrradiance[i] += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * MarionAOICorrectionFactorsGlass[j] * actualGroundGHI * this->albedo; + rearAverageIrradianceGround += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * MarionAOICorrectionFactorsGlass[j] * actualGroundGHI * this->albedo; } // Calculate and add direct and circumsolar irradiance components incidence(0, 180.0 - tiltRadians * RTOD, (surfaceAzimuthRadians * RTOD - 180.0), 45.0, solarZenithRadians, solarAzimuthRadians, this->enableBacktrack, this->groundCoverageRatio, surfaceAnglesRadians); @@ -1854,9 +1907,15 @@ void irrad::getBackSurfaceIrradiances(double pvBackShadeFraction, double rowToRo { double iamMod = iamSjerpsKoomen(n2, surfaceAnglesRadians[0]); rearIrradiance[i] += (1.0 - cellShade) * (planeOfArrayIrradianceRear[0] + diffuseIrradianceRear[1]) * iamMod; + rearAverageIrradianceGround += (1.0 - cellShade) * (planeOfArrayIrradianceRear[0] + diffuseIrradianceRear[1]) * iamMod; } rearAverageIrradiance += rearIrradiance[i] / cellRows; } + rearAverageIrradianceBeam /= cellRows; + rearAverageIrradianceSky /= cellRows; + rearAverageIrradianceGround /= cellRows; + rearAverageIrradianceReflected /= cellRows; + } static double vec_dot(double a[3], double b[3]) diff --git a/shared/lib_irradproc.h b/shared/lib_irradproc.h index f8a119e6f..ff56d3129 100644 --- a/shared/lib_irradproc.h +++ b/shared/lib_irradproc.h @@ -328,7 +328,13 @@ class irrad double diffuseIrradianceRear[3]; ///< Rear-side diffuse irradiance for isotropic, circumsolar, and horizon (W/m2) int timeStepSunPosition[3]; ///< [0] effective hour of day used for sun position, [1] effective minute of hour used for sun position, [2] is sun up? (0=no, 1=midday, 2=sunup, 3=sundown) double planeOfArrayIrradianceRearAverage; ///< Average rear side plane-of-array irradiance (W/m2) - + double planeOfArrayIrradianceFrontAverageFromGroundBiFa; ///< Average front side plane-of-array irradiance that comes from ground reflection according to bifacial analysis (W/m2) + double groundIrradianceRearAverage; ///< Average irradiance hitting the ground between leading edge of one row to leading edge of next row according to bifacial analysis (W/m2) + double planeOfArrayIrradianceFrontAverageBiFa; ///< Average total irradiance hitting the front of the row according to bifacial analysis (W/m2) + double planeOfArrayIrradianceRearBeam; ///< Average rear side irradiance contribution from direct beam and circumsolar components + double planeOfArrayIrradianceRearSky; ///< Average rear side irradiance contribution from diffuse sky components + double planeOfArrayIrradianceRearGround; ///< Average rear side irradiance contribution from interrow ground component + double planeOfArrayIrradianceRearReflected; ///< Average rear side irradiance contribution from component reflected from row behind public: /// Directive to indicate that if delt_hr is less than zero, do not interpolate sunrise and sunset hours @@ -417,7 +423,8 @@ class irrad double *isotrop, double *circum, double *horizon ); /// Return the rear-side average total plane-of-array irradiance - double get_poa_rear(); + void get_poa_rear(double *poa_rear, double *poa_front_ground, double *ghi_interrow, double *poa_front_bifacial, + double *poa_rear_beam, double *poa_rear_sky_diff, double *poa_rear_ground, double *poa_rear_reflected); /// Return the front-side irradiance components void get_irrad (double *ghi, double *dni, double *dhi); @@ -438,10 +445,15 @@ class irrad void getGroundGHI(double transmissionFactor, std::vector rearSkyConfigFactors, std::vector frontSkyConfigFactors, std::vector rearGroundShadeFactors, std::vector frontGroundShadeFactors, std::vector & rearGroundGHI, std::vector & frontGroundGHI); /// Return the back surface irradiances, used by \link calc_rear_side() - void getBackSurfaceIrradiances(double pvBackShadeFraction, double rowToRow, double verticalHeight, double clearanceGround, double distanceBetweenRows, double horizontalLength, std::vector rearGroundGHI, std::vector frontGroundGHI, std::vector frontReflected, std::vector & rearIrradiance, double & rearAverageIrradiance); + void getBackSurfaceIrradiances(double pvBackShadeFraction, double rowToRow, double verticalHeight, double clearanceGround, + double distanceBetweenRows, double horizontalLength, std::vector rearGroundGHI, + std::vector frontGroundGHI, std::vector frontReflected, std::vector & rearIrradiance, + double & rearAverageIrradiance, double & rearAverageIrradianceBeam, double & rearAverageIrradianceSky, + double & rearAverageIrradianceGround, double & rearAverageIrradianceReflected); /// Return the front surface irradiances, used by \link calc_rear_side() - void getFrontSurfaceIrradiances(double pvBackShadeFraction, double rowToRow, double verticalHeight, double clearanceGround, double distanceBetweenRows, double horizontalLength, std::vector frontGroundGHI, std::vector & frontIrradiance, double & frontAverageIrradiance, std::vector & frontReflected); + void getFrontSurfaceIrradiances(double pvBackShadeFraction, double rowToRow, double verticalHeight, double clearanceGround, double distanceBetweenRows, double horizontalLength, std::vector frontGroundGHI, std::vector & frontIrradiance, double & frontAverageIrradiance, std::vector & frontReflected, + std::vector & frontIrradianceFromGround, double & frontAverageIrradianceFromGround); enum RADMODE { DN_DF, DN_GH, GH_DF, POA_R, POA_P }; enum SKYMODEL { ISOTROPIC, HDKR, PEREZ }; diff --git a/shared/lib_pv_io_manager.cpp b/shared/lib_pv_io_manager.cpp index a17f365f3..b441457dc 100644 --- a/shared/lib_pv_io_manager.cpp +++ b/shared/lib_pv_io_manager.cpp @@ -747,7 +747,14 @@ void PVSystem_IO::AllocateOutputs(compute_module* cm) p_poaTotal.push_back(cm->allocate(prefix + "poa_eff", numberOfWeatherFileRecords)); p_poaRear.push_back(cm->allocate(prefix + "poa_rear", numberOfWeatherFileRecords)); p_poaFront.push_back(cm->allocate(prefix + "poa_front", numberOfWeatherFileRecords)); - p_derateSoiling.push_back(cm->allocate(prefix + "soiling_derate", numberOfWeatherFileRecords)); + p_ghiInterrow.push_back(cm->allocate(prefix + "bifacial_interrow_ghi", numberOfWeatherFileRecords)); // + p_poaFrontFromInterrowGround.push_back(cm->allocate(prefix + "poa_front_interrow_ground", numberOfWeatherFileRecords)); // + p_poaFrontBifacialCalculation.push_back(cm->allocate(prefix + "poa_front_bifacial", numberOfWeatherFileRecords)); + p_poaRearBeamCircum.push_back(cm->allocate(prefix + "poa_rear_beam_circum", numberOfWeatherFileRecords)); + p_poaRearSkyDiff.push_back(cm->allocate(prefix + "poa_rear_sky_diff", numberOfWeatherFileRecords)); + p_poaRearGround.push_back(cm->allocate(prefix + "poa_rear_ground", numberOfWeatherFileRecords)); + p_poaRearRowReflected.push_back(cm->allocate(prefix + "poa_rear_row_reflected", numberOfWeatherFileRecords)); + p_derateSoiling.push_back(cm->allocate(prefix + "soiling_derate", numberOfWeatherFileRecords)); p_beamShadingFactor.push_back(cm->allocate(prefix + "beam_shading_factor", numberOfWeatherFileRecords)); p_temperatureCell.push_back(cm->allocate(prefix + "celltemp", numberOfWeatherFileRecords)); p_moduleEfficiency.push_back(cm->allocate(prefix + "modeff", numberOfWeatherFileRecords)); diff --git a/shared/lib_pv_io_manager.h b/shared/lib_pv_io_manager.h index 6a81d0a1d..2433627fb 100644 --- a/shared/lib_pv_io_manager.h +++ b/shared/lib_pv_io_manager.h @@ -290,7 +290,14 @@ struct PVSystem_IO std::vector p_poaDiffuseFront; std::vector p_poaFront; std::vector p_poaTotal; - std::vector p_poaRear; + std::vector p_poaRear; + std::vector p_ghiInterrow; + std::vector p_poaFrontFromInterrowGround; + std::vector p_poaFrontBifacialCalculation; + std::vector p_poaRearBeamCircum; + std::vector p_poaRearSkyDiff; + std::vector p_poaRearGround; + std::vector p_poaRearRowReflected; std::vector p_derateSoiling; std::vector p_beamShadingFactor; std::vector p_temperatureCell; diff --git a/shared/lib_pvshade.cpp b/shared/lib_pvshade.cpp index 7f1124cd2..9ebd1677f 100644 --- a/shared/lib_pvshade.cpp +++ b/shared/lib_pvshade.cpp @@ -186,8 +186,8 @@ void diffuse_reduce( double Gbh = Gb_nor * cosd(solzen); // beam irradiance on horizontal surface // double poa_sky_iso = Gdh * (1 + cosd(stilt)) / 2; - double B = 1.0; - double R = B / gcr; +// double B = 1.0; +// double R = B / gcr; // sky diffuse reduction double step = 1.0 / 1000.0; @@ -213,7 +213,7 @@ void diffuse_reduce( } reduced_skydiff = Fskydiff * poa_sky; - double solalt = 90 - solzen; +// double solalt = 90 - solzen; // ground reflected reduction // simplified to match PVsyst's approach except for in bifacial scenarios CZ 8/2019 diff --git a/ssc/cmod_pvsamv1.cpp b/ssc/cmod_pvsamv1.cpp index fc6897981..dfe54f837 100644 --- a/ssc/cmod_pvsamv1.cpp +++ b/ssc/cmod_pvsamv1.cpp @@ -536,7 +536,7 @@ static var_info _cm_vtab_pvsamv1[] = { { SSC_OUTPUT, SSC_ARRAY, "subarray1_poa_shaded_soiled", "Subarray 1 POA front total irradiance after shading and soiling", "W/m2", "", "Time Series (Subarray 1)", "*", "", "" }, { SSC_OUTPUT, SSC_ARRAY, "subarray1_poa_front", "Subarray 1 POA front total irradiance after reflection (IAM)", "W/m2", "", "Time Series (Subarray 1)", "*", "", "" }, { SSC_OUTPUT, SSC_ARRAY, "subarray1_poa_rear", "Subarray 1 POA rear total irradiance after reflection (IAM) and losses","W/m2", "", "Time Series (Subarray 1)", "*", "", "" }, - { SSC_OUTPUT, SSC_ARRAY, "subarray1_poa_eff", "Subarray 1 POA total irradiance after reflection (IAM) and bifaciality","W/m2", "", "Time Series (Subarray 1)", "*", "", "" }, + { SSC_OUTPUT, SSC_ARRAY, "subarray1_poa_eff", "Subarray 1 POA total irradiance after reflection (IAM), backside losses, bifaciality and additional frontside","W/m2", "", "Time Series (Subarray 1)", "*", "", "" }, { SSC_OUTPUT, SSC_ARRAY, "subarray1_soiling_derate", "Subarray 1 Soiling beam irradiance factor", "frac", "", "Time Series (Subarray 1)", "*", "", "" }, { SSC_OUTPUT, SSC_ARRAY, "subarray1_beam_shading_factor", "Subarray 1 External shading and soiling beam irradiance factor", "frac", "", "Time Series (Subarray 1)", "*", "", "" }, { SSC_OUTPUT, SSC_ARRAY, "subarray1_linear_derate", "Subarray 1 Self-shading linear beam irradiance factor", "frac", "", "Time Series (Subarray 1)", "*", "", "" }, @@ -1142,7 +1142,7 @@ void cm_pvsamv1::exec( ) throw (compute_module::general_error) double ts_accum_poa_front_beam_eff = 0.0; // calculate incident irradiance on each subarray - std::vector ipoa_rear, ipoa_rear_after_losses, ipoa_front, ipoa; + std::vector ipoa_rear, ipoa_rear_after_losses, ipoa_front, ipoa, ipoa_front_ground, ighi_interrow, ipoa_front_bifacial, ipoa_rear_beam, ipoa_rear_sky_diff, ipoa_rear_ground, ipoa_rear_reflected; double alb; alb = 0; @@ -1150,6 +1150,13 @@ void cm_pvsamv1::exec( ) throw (compute_module::general_error) { ipoa_rear.push_back(0); ipoa_rear_after_losses.push_back(0); + ipoa_front_ground.push_back(0); + ighi_interrow.push_back(0); + ipoa_front_bifacial.push_back(0); + ipoa_rear_beam.push_back(0); + ipoa_rear_sky_diff.push_back(0); + ipoa_rear_ground.push_back(0); + ipoa_rear_reflected.push_back(0); ipoa_front.push_back(0); ipoa.push_back(0); @@ -1520,7 +1527,20 @@ void cm_pvsamv1::exec( ) throw (compute_module::general_error) slopeLength = Subarrays[nn]->selfShadingInputs.width * Subarrays[nn]->selfShadingInputs.nmody; } irr.calc_rear_side(Subarrays[0]->Module->bifacialTransmissionFactor, Subarrays[0]->Module->groundClearanceHeight, slopeLength); - ipoa_rear[nn] = irr.get_poa_rear(); + double poa_rear_, poa_front_ground_, ghi_interrow_, poa_front_bifacial_, poa_rear_beam_, poa_rear_sky_diff_, poa_rear_ground_, poa_rear_reflected_; + irr.get_poa_rear(&poa_rear_, &poa_front_ground_, &ghi_interrow_, &poa_front_bifacial_, &poa_rear_beam_, &poa_rear_sky_diff_, &poa_rear_ground_, &poa_rear_reflected_); + // empirically determined correction factors to bring rearside irradiance calc into alignment with PVsyst +// if (Subarrays[nn]->trackMode == 0){poa_rear_ *= 1.03;} // fixed tilt +// else if (Subarrays[nn]->trackMode == 1){poa_rear_ *= 1.08;} // single axis tracking +// else {poa_rear_ *= 1.0;} // no correction for other racking scenarios + ipoa_rear[nn] = poa_rear_; + ipoa_front_ground[nn] = poa_front_ground_; + ighi_interrow[nn] = ghi_interrow_; + ipoa_front_bifacial[nn] = poa_front_bifacial_; + ipoa_rear_beam[nn] = poa_rear_beam_; + ipoa_rear_sky_diff[nn] = poa_rear_sky_diff_; + ipoa_rear_ground[nn] = poa_rear_ground_; + ipoa_rear_reflected[nn] = poa_rear_reflected_; ipoa_rear_after_losses[nn] = ipoa_rear[nn] * (1 - Subarrays[nn]->rearIrradianceLossPercent); } @@ -1535,6 +1555,13 @@ void cm_pvsamv1::exec( ) throw (compute_module::general_error) PVSystem->p_poaBeamFront[nn][idx] = (ssc_number_t)ibeam; PVSystem->p_poaDiffuseFront[nn][idx] = (ssc_number_t)(iskydiff + ignddiff); PVSystem->p_poaRear[nn][idx] = (ssc_number_t)(ipoa_rear_after_losses[nn]); + PVSystem->p_poaFrontFromInterrowGround[nn][idx] = (ssc_number_t)(ipoa_front_ground[nn]); + PVSystem->p_ghiInterrow[nn][idx] = (ssc_number_t)(ighi_interrow[nn]); + PVSystem->p_poaFrontBifacialCalculation[nn][idx] = (ssc_number_t)(ipoa_front_bifacial[nn]); + PVSystem->p_poaRearBeamCircum[nn][idx] = (ssc_number_t)(ipoa_rear_beam[nn]); + PVSystem->p_poaRearSkyDiff[nn][idx] = (ssc_number_t)(ipoa_rear_sky_diff[nn]); + PVSystem->p_poaRearGround[nn][idx] = (ssc_number_t)(ipoa_rear_ground[nn]); + PVSystem->p_poaRearRowReflected[nn][idx] = (ssc_number_t)(ipoa_rear_reflected[nn]); PVSystem->p_beamShadingFactor[nn][idx] = (ssc_number_t)beam_shading_factor; PVSystem->p_axisRotation[nn][idx] = (ssc_number_t)rot; PVSystem->p_idealRotation[nn][idx] = (ssc_number_t)(rot - btd); @@ -1552,7 +1579,7 @@ void cm_pvsamv1::exec( ) throw (compute_module::general_error) Subarrays[nn]->poa.poaDiffuseFront = iskydiff; Subarrays[nn]->poa.poaGroundFront = ignddiff; Subarrays[nn]->poa.poaRear = ipoa_rear_after_losses[nn]; - Subarrays[nn]->poa.poaTotal = (radmode == irrad::POA_R) ? ipoa[nn] :(ipoa_front[nn] + ipoa_rear_after_losses[nn] * bifaciality); + Subarrays[nn]->poa.poaTotal = (radmode == irrad::POA_R) ? ipoa[nn] :(ipoa_front[nn] + ipoa_rear_after_losses[nn] * bifaciality + ipoa_front_ground[nn]); Subarrays[nn]->poa.angleOfIncidenceDegrees = aoi; Subarrays[nn]->poa.sunUp = sunup; Subarrays[nn]->poa.surfaceTiltDegrees = stilt; @@ -1598,7 +1625,8 @@ void cm_pvsamv1::exec( ) throw (compute_module::general_error) double V = stringV / (double)Subarrays[nn]->nModulesPerString; //voltage of an individual module on a string on this subarray //initalize pvinput and pvoutput structures for the model - pvinput_t in(Subarrays[nn]->poa.poaBeamFront, Subarrays[nn]->poa.poaDiffuseFront, Subarrays[nn]->poa.poaGroundFront, Subarrays[nn]->poa.poaRear * bifaciality, Subarrays[nn]->poa.poaTotal, + double bifa_contrib = Subarrays[nn]->poa.poaRear * bifaciality + ipoa_front_ground[nn]; + pvinput_t in(Subarrays[nn]->poa.poaBeamFront, Subarrays[nn]->poa.poaDiffuseFront, Subarrays[nn]->poa.poaGroundFront, bifa_contrib, Subarrays[nn]->poa.poaTotal, wf.tdry, wf.tdew, wf.wspd, wf.wdir, wf.pres, solzen, Subarrays[nn]->poa.angleOfIncidenceDegrees, hdr.elev, Subarrays[nn]->poa.surfaceTiltDegrees, Subarrays[nn]->poa.surfaceAzimuthDegrees, @@ -1637,7 +1665,8 @@ void cm_pvsamv1::exec( ) throw (compute_module::general_error) { int nn = SubarraysOnMpptInput[nSubarray]; //get the index of the subarray we're checking here //initalize pvinput and pvoutput structures for the model - pvinput_t in_temp(Subarrays[nn]->poa.poaBeamFront, Subarrays[nn]->poa.poaDiffuseFront, Subarrays[nn]->poa.poaGroundFront, Subarrays[nn]->poa.poaRear * bifaciality, Subarrays[nn]->poa.poaTotal, + double bifa_contrib = Subarrays[nn]->poa.poaRear * bifaciality + ipoa_front_ground[nn]; + pvinput_t in_temp(Subarrays[nn]->poa.poaBeamFront, Subarrays[nn]->poa.poaDiffuseFront, Subarrays[nn]->poa.poaGroundFront, bifa_contrib, Subarrays[nn]->poa.poaTotal, wf.tdry, wf.tdew, wf.wspd, wf.wdir, wf.pres, solzen, Subarrays[nn]->poa.angleOfIncidenceDegrees, hdr.elev, Subarrays[nn]->poa.surfaceTiltDegrees, Subarrays[nn]->poa.surfaceAzimuthDegrees, @@ -1754,11 +1783,11 @@ void cm_pvsamv1::exec( ) throw (compute_module::general_error) if (iyear == 0) { ipoa_front[nn] *= out[nn].AOIModifier; - PVSystem->p_poaFront[nn][idx] = (radmode == irrad::POA_R) ? (ssc_number_t)ipoa[nn] : (ssc_number_t)(ipoa_front[nn]); - PVSystem->p_poaTotal[nn][idx] = (radmode == irrad::POA_R) ? (ssc_number_t)ipoa[nn] : (ssc_number_t)(ipoa_front[nn] + ipoa_rear_after_losses[nn] * bifaciality); + PVSystem->p_poaFront[nn][idx] = (radmode == irrad::POA_R) ? (ssc_number_t)ipoa[nn] : (ssc_number_t)(ipoa_front[nn] + ipoa_front_ground[nn]); + PVSystem->p_poaTotal[nn][idx] = (radmode == irrad::POA_R) ? (ssc_number_t)ipoa[nn] : (ssc_number_t)(ipoa_front[nn] + ipoa_rear_after_losses[nn] * bifaciality + ipoa_front_ground[nn]); - ts_accum_poa_front_total += ipoa_front[nn] * ref_area_m2 * Subarrays[nn]->nModulesPerString * Subarrays[nn]->nStrings; - ts_accum_poa_total_eff += ((radmode == irrad::POA_R) ? ipoa[nn] : (ipoa_front[nn] + ipoa_rear_after_losses[nn] * bifaciality)) * ref_area_m2 * Subarrays[nn]->nModulesPerString * Subarrays[nn]->nStrings; + ts_accum_poa_front_total += (ipoa_front[nn] + ipoa_front_ground[nn])* ref_area_m2 * Subarrays[nn]->nModulesPerString * Subarrays[nn]->nStrings; + ts_accum_poa_total_eff += ((radmode == irrad::POA_R) ? ipoa[nn] : (ipoa_front[nn] + ipoa_rear_after_losses[nn] * bifaciality + ipoa_front_ground[nn])) * ref_area_m2 * Subarrays[nn]->nModulesPerString * Subarrays[nn]->nStrings; //assign final string voltage output PVSystem->p_dcStringVoltage[nn][idx] = (ssc_number_t)Subarrays[nn]->Module->dcVoltage * Subarrays[nn]->nModulesPerString; From 1e1a7d70786b150eed021c6abb1c910795b795ac Mon Sep 17 00:00:00 2001 From: Casey Zak Date: Sun, 25 Aug 2019 15:43:38 -0700 Subject: [PATCH 4/7] dev(lib_irradproc.cpp): Change transp model in getGroundGHI from perez to isotropic --- shared/lib_irradproc.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/shared/lib_irradproc.cpp b/shared/lib_irradproc.cpp index cafb66b3b..5d1d81902 100644 --- a/shared/lib_irradproc.cpp +++ b/shared/lib_irradproc.cpp @@ -1493,10 +1493,9 @@ void irrad::getGroundShadeFactors(double rowToRow, double verticalHeight, double void irrad::getGroundGHI(double transmissionFactor, std::vector rearSkyConfigFactors, std::vector frontSkyConfigFactors, std::vector rearGroundShade, std::vector frontGroundShade, std::vector & rearGroundGHI, std::vector & frontGroundGHI) { // Calculate the diffuse components of irradiance - perez(0, calculatedDirectNormal, calculatedDiffuseHorizontal,albedo, sunAnglesRadians[1], 0.0, sunAnglesRadians[1], planeOfArrayIrradianceRear, diffuseIrradianceRear); + isotropic(0, calculatedDirectNormal, calculatedDiffuseHorizontal,albedo, sunAnglesRadians[1], 0.0, sunAnglesRadians[1], planeOfArrayIrradianceRear, diffuseIrradianceRear); double incidentBeam = planeOfArrayIrradianceRear[0]; double isotropicDiffuse = diffuseIrradianceRear[0]; - double circumsolarDiffuse = diffuseIrradianceRear[1]; // Sum the irradiance components for each of the ground segments to the front and rear of the front of the PV row for (size_t i = 0; i != 100; i++) @@ -1508,20 +1507,20 @@ void irrad::getGroundGHI(double transmissionFactor, std::vector rearSkyC if (rearGroundShade[i] == 0) { // Add beam and circumsolar component if not shaded - rearGroundGHI[i] += incidentBeam + circumsolarDiffuse; + rearGroundGHI[i] += incidentBeam; } else { // Add beam and circumsolar component transmitted thru module spacing if shaded - rearGroundGHI[i] += (incidentBeam + circumsolarDiffuse) * transmissionFactor; + rearGroundGHI[i] += incidentBeam * transmissionFactor; } if (frontGroundShade[i] == 0) { - frontGroundGHI[i] += incidentBeam + circumsolarDiffuse; + frontGroundGHI[i] += incidentBeam; } else { - frontGroundGHI[i] += (incidentBeam + circumsolarDiffuse) * transmissionFactor; + frontGroundGHI[i] += incidentBeam * transmissionFactor; } } } From b8b9b75a1fbb40fbd1459d7097ae9fead5ebd14e Mon Sep 17 00:00:00 2001 From: Casey Zak Date: Sun, 25 Aug 2019 16:05:17 -0700 Subject: [PATCH 5/7] dev(lib_irradproc.cpp): Change transpo model used in getBackSurfaceIrradiances from perez to isotropic --- shared/lib_irradproc.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/shared/lib_irradproc.cpp b/shared/lib_irradproc.cpp index 5d1d81902..6471bfe0c 100644 --- a/shared/lib_irradproc.cpp +++ b/shared/lib_irradproc.cpp @@ -1712,15 +1712,9 @@ void irrad::getBackSurfaceIrradiances(double pvBackShadeFraction, double rowToRo averageGroundGHI += rearGroundGHI[i] / rearGroundGHI.size(); // Calculate diffuse isotropic irradiance for a horizontal surface - perez(0, calculatedDirectNormal, calculatedDiffuseHorizontal, albedo, solarZenithRadians, 0, solarZenithRadians, planeOfArrayIrradianceRear, diffuseIrradianceRear); + isotropic(0, calculatedDirectNormal, calculatedDiffuseHorizontal, albedo, solarZenithRadians, 0, solarZenithRadians, planeOfArrayIrradianceRear, diffuseIrradianceRear); double isotropicSkyDiffuse = diffuseIrradianceRear[0]; - // Calculate components for a 90 degree tilt - double surfaceAnglesRadians90[5] = { 0,0,0,0,0 }; - incidence(0, 90.0, 180.0, 45.0, solarZenithRadians, solarAzimuthRadians, this->enableBacktrack, this->groundCoverageRatio, surfaceAnglesRadians90); - perez(0, calculatedDirectNormal, calculatedDiffuseHorizontal, albedo, surfaceAnglesRadians90[0], surfaceAnglesRadians90[1], solarZenithRadians, planeOfArrayIrradianceRear, diffuseIrradianceRear); - double horizonDiffuse = diffuseIrradianceRear[2]; - // Calculate x,y coordinates of bottom and top edges of PV row in back of desired PV row so that portions of sky and ground viewed by the // PV cell may be determined. Origin of x-y axis is the ground point below the lower front edge of the desired PV row. The row in back of // the desired row is in the positive x direction. @@ -1745,7 +1739,6 @@ void irrad::getBackSurfaceIrradiances(double pvBackShadeFraction, double rowToRo double elevationAngleUp = atan((PtopY - PcellY) / (PtopX - PcellX)); // Elevation angle up from PV cell to top of PV module/panel, radians double elevationAngleDown = atan((PcellY - PbotY) / (PbotX - PcellX)); // Elevation angle down from PV cell to bottom of PV module/panel, radians size_t iStopIso = (size_t)round((tiltRadians - elevationAngleUp) / DTOR); // Last whole degree in arc range that sees sky, first is 0 - size_t iHorBright = (size_t)round(fmax(0.0, 6.0 - elevationAngleUp / DTOR)); // Number of whole degrees for which horizon brightening occurs size_t iStartGrd = (size_t)round((tiltRadians + elevationAngleDown) / DTOR); // First whole degree in arc range that sees ground, last is 180 rearIrradiance.push_back(0); @@ -1753,11 +1746,6 @@ void irrad::getBackSurfaceIrradiances(double pvBackShadeFraction, double rowToRo { rearIrradiance[i] += 0.5 * (cos(j * DTOR) - cos((j + 1)*DTOR)) * MarionAOICorrectionFactorsGlass[j]* isotropicSkyDiffuse; rearAverageIrradianceSky += 0.5 * (cos(j * DTOR) - cos((j + 1)*DTOR)) * MarionAOICorrectionFactorsGlass[j]* isotropicSkyDiffuse; - if ((iStopIso - j) <= iHorBright) - { - rearIrradiance[i] += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * MarionAOICorrectionFactorsGlass[j]* horizonDiffuse / 0.052264; // 0.052246 = 0.5 * [cos(84) - cos(90)] - rearAverageIrradianceSky += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * MarionAOICorrectionFactorsGlass[j]* horizonDiffuse / 0.052264; - } } // Add relections from PV module front surfaces From 9173869e522a24d37e4fd2851d588d0f505b2864 Mon Sep 17 00:00:00 2001 From: Casey Zak Date: Sun, 25 Aug 2019 17:30:27 -0700 Subject: [PATCH 6/7] dev(): Convert iam model for sky diffuse component in getBackSurfaceIrradiances from MARION to ashrae --- shared/lib_irradproc.cpp | 9 ++++++--- shared/lib_pv_incidence_modifier.cpp | 7 +++++++ shared/lib_pv_incidence_modifier.h | 3 +++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/shared/lib_irradproc.cpp b/shared/lib_irradproc.cpp index 6471bfe0c..fb3dd724e 100644 --- a/shared/lib_irradproc.cpp +++ b/shared/lib_irradproc.cpp @@ -24,6 +24,7 @@ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include #include @@ -1742,13 +1743,15 @@ void irrad::getBackSurfaceIrradiances(double pvBackShadeFraction, double rowToRo size_t iStartGrd = (size_t)round((tiltRadians + elevationAngleDown) / DTOR); // First whole degree in arc range that sees ground, last is 180 rearIrradiance.push_back(0); + double theta = 0; for (size_t j = 0; j != iStopIso; j++) { - rearIrradiance[i] += 0.5 * (cos(j * DTOR) - cos((j + 1)*DTOR)) * MarionAOICorrectionFactorsGlass[j]* isotropicSkyDiffuse; - rearAverageIrradianceSky += 0.5 * (cos(j * DTOR) - cos((j + 1)*DTOR)) * MarionAOICorrectionFactorsGlass[j]* isotropicSkyDiffuse; + theta = 90.0 - j; + rearIrradiance[i] += 0.5 * (cos(j * DTOR) - cos((j + 1)*DTOR)) * iamASHRAE(0.04, theta * DTOR) * isotropicSkyDiffuse; + rearAverageIrradianceSky += 0.5 * (cos(j * DTOR) - cos((j + 1)*DTOR)) * iamASHRAE(0.04, theta * DTOR) * isotropicSkyDiffuse; } - // Add relections from PV module front surfaces + // Add reflections from PV module front surfaces for (size_t j = iStopIso; j < iStartGrd; j++) { double diagonalDistance = (PbotX - PcellX) / cos(elevationAngleDown); diff --git a/shared/lib_pv_incidence_modifier.cpp b/shared/lib_pv_incidence_modifier.cpp index 42c4493b5..6675aaf9f 100644 --- a/shared/lib_pv_incidence_modifier.cpp +++ b/shared/lib_pv_incidence_modifier.cpp @@ -121,3 +121,10 @@ double calculateIrradianceThroughCoverDeSoto(double theta, double theta_z, doubl return Geff_total; } + +double iamASHRAE(double b0, double theta) +{ + double factor = (1 - b0 * (1 / cos(theta) - 1)); + if (factor < 0.0) return 0.0; + return factor; +} diff --git a/shared/lib_pv_incidence_modifier.h b/shared/lib_pv_incidence_modifier.h index 92a66d2c1..4c1105d51 100644 --- a/shared/lib_pv_incidence_modifier.h +++ b/shared/lib_pv_incidence_modifier.h @@ -35,6 +35,9 @@ double iam_nonorm(double theta_deg, bool ar_glass); // non-normalized cover los * * */ + +double iamASHRAE(double b0, double theta); + double iamSjerpsKoomen(double n, double incidenceAngleRadians); /// Calculate Irradiance through the cover using the DeSoto model From 15a59d7efb0a875658e6c85d3a87107b2180d531 Mon Sep 17 00:00:00 2001 From: Casey Zak Date: Tue, 27 Aug 2019 12:12:46 -0700 Subject: [PATCH 7/7] dev(lib_irradproc.cpp): Change iam model for front ground contribution from MarionAOICorrection to ashrae with b0=0.04 --- shared/lib_irradproc.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/shared/lib_irradproc.cpp b/shared/lib_irradproc.cpp index fb3dd724e..a5c237d60 100644 --- a/shared/lib_irradproc.cpp +++ b/shared/lib_irradproc.cpp @@ -1599,8 +1599,10 @@ void irrad::getFrontSurfaceIrradiances(double pvFrontShadeFraction, double rowTo // Add ground reflected component + double theta = 0; // angle of incidence defined relative to surface normal for (size_t j = iStartGrd; j < 180; j++) { + theta = 90.0 - j; double startElevationDown = (j - iStartGrd) * DTOR + elevationAngleDown; double stopElevationDown = (j + 1 - iStartGrd) * DTOR + elevationAngleDown; double projectedX1 = PcellX - PcellY / tan(startElevationDown); @@ -1663,9 +1665,9 @@ void irrad::getFrontSurfaceIrradiances(double pvFrontShadeFraction, double rowTo actualGroundGHI /= projectedX2 - projectedX1; } } - frontIrradiance[i] += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * MarionAOICorrectionFactorsGlass[j] * actualGroundGHI * this->albedo; - frontIrradianceFromGround[i] += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * MarionAOICorrectionFactorsGlass[j] * actualGroundGHI * this->albedo; - frontReflected[i] += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * actualGroundGHI * this->albedo * (1.0 - MarionAOICorrectionFactorsGlass[j] * (1.0 - reflectanceNormalIncidence)); + frontIrradiance[i] += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * iamASHRAE(0.04, theta * DTOR) * actualGroundGHI * this->albedo; + frontIrradianceFromGround[i] += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * iamASHRAE(0.04, theta * DTOR) * actualGroundGHI * this->albedo; + frontReflected[i] += 0.5 * (cos(j * DTOR) - cos((j + 1) * DTOR)) * actualGroundGHI * this->albedo * (1.0 - iamASHRAE(0.04, theta * DTOR) * (1.0 - reflectanceNormalIncidence)); } // Calculate and add direct and circumsolar irradiance components incidence(0, tiltRadians * RTOD, surfaceAzimuthRadians * RTOD, 45.0, solarZenithRadians, solarAzimuthRadians, this->enableBacktrack, this->groundCoverageRatio, surfaceAnglesRadians);