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..a5c237d60 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. */ @@ -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 @@ -845,6 +846,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 +970,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 +1272,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; } @@ -1459,10 +1494,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++) @@ -1474,25 +1508,28 @@ 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; } } } -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 @@ -1561,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); @@ -1625,8 +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; - 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); @@ -1649,10 +1690,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; @@ -1669,15 +1715,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. @@ -1686,6 +1726,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++) @@ -1697,20 +1742,18 @@ 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); + 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; - 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)] - } + 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); @@ -1751,6 +1794,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 +1878,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 +1899,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_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_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 diff --git a/shared/lib_pv_io_manager.cpp b/shared/lib_pv_io_manager.cpp index 3b7534a60..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)); @@ -1136,6 +1143,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 +1184,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/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 38f007da4..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,23 +213,29 @@ void diffuse_reduce( } reduced_skydiff = Fskydiff * poa_sky; - double solalt = 90 - solzen; +// 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) diff --git a/ssc/cmod_pvsamv1.cpp b/ssc/cmod_pvsamv1.cpp index fa713fcf9..dfe54f837 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), 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)", "*", "", "" }, @@ -1133,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; @@ -1141,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); @@ -1511,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); } @@ -1526,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); @@ -1543,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; @@ -1589,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, 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, @@ -1628,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, 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, @@ -1745,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;