From 7c5084cfa3cea3f8878d7030631f6a9e0000fc7e Mon Sep 17 00:00:00 2001 From: Matt Prilliman Date: Mon, 2 Oct 2023 12:15:41 -0500 Subject: [PATCH] Expose clear sky calcs to walker method calculations --- shared/lib_irradproc.cpp | 4 +-- shared/lib_pv_io_manager.cpp | 2 +- shared/lib_shared_inverter.cpp | 50 +--------------------------------- ssc/cmod_pvsamv1.cpp | 42 ++++++++++++++++------------ 4 files changed, 27 insertions(+), 71 deletions(-) diff --git a/shared/lib_irradproc.cpp b/shared/lib_irradproc.cpp index 35db1295a..4046507c2 100644 --- a/shared/lib_irradproc.cpp +++ b/shared/lib_irradproc.cpp @@ -2159,9 +2159,7 @@ int irrad::calc() { } //clearsky - if (enableSubhourlyClipping) { - ineichen(clearskyIrradiance, RTOD * sunAnglesRadians[1], 1.5, 1.0, elevation); - } + ineichen(clearskyIrradiance, RTOD * sunAnglesRadians[1], 1.5, 1.0, elevation); planeOfArrayIrradianceFront[0] = planeOfArrayIrradianceFront[1] = planeOfArrayIrradianceFront[2] = 0; diff --git a/shared/lib_pv_io_manager.cpp b/shared/lib_pv_io_manager.cpp index e9a778870..534b5927a 100644 --- a/shared/lib_pv_io_manager.cpp +++ b/shared/lib_pv_io_manager.cpp @@ -941,7 +941,7 @@ void PVSystem_IO::AllocateOutputs(compute_module* cm) p_systemDCPowerCS = cm->allocate("dc_net_clearsky", numberOfLifetimeRecords); p_subhourlyClippingLoss = cm->allocate("subhourly_clipping_loss", numberOfLifetimeRecords); - p_subhourlyClippingLossFactor = cm->allocate("subhourly_clipping_loss_factor", numberOfLifetimeRecords); + //p_subhourlyClippingLossFactor = cm->allocate("subhourly_clipping_loss_factor", numberOfLifetimeRecords); p_DistributionClippingLoss = cm->allocate("distribution_clipping_loss", numberOfLifetimeRecords); diff --git a/shared/lib_shared_inverter.cpp b/shared/lib_shared_inverter.cpp index b973555b2..099064de4 100644 --- a/shared/lib_shared_inverter.cpp +++ b/shared/lib_shared_inverter.cpp @@ -229,7 +229,7 @@ void SharedInverter::calculateTempDerate(double V, double tempC, double& p_dc_ra double SharedInverter::getInverterDCMaxPower(double p_dc_rated) { - double inv_dc_max_power; + double inv_dc_max_power = p_dc_rated * util::kilowatt_to_watt; if (m_inverterType == SANDIA_INVERTER || m_inverterType == DATASHEET_INVERTER || m_inverterType == COEFFICIENT_GENERATOR) //m_sandiaInverter->acpower(std::fabs(powerDC_Watts) / m_numInverters, DCStringVoltage, &powerAC_Watts, &P_par, &P_lr, &efficiencyAC, &powerClipLoss_kW, &powerConsumptionLoss_kW, &powerNightLoss_kW); inv_dc_max_power = m_sandiaInverter->Pdco; @@ -353,54 +353,6 @@ void SharedInverter::calculateACPower(const double powerDC_kW_in, const double D } } -void SharedInverter::calculateACPower(const double powerDC_kW_in, const double powerDC_kW_in_max, const double powerDC_kW_in_min, const double DCStringVoltage, double tempC) -{ - double P_par, P_lr; - double P_par_clipping, P_lr_clipping; - double efficiencyAC_clipping, powerClipLoss_kW_clipping, powerConsumptionLoss_kW_clipping, powerNightLoss_kW_clipping = 0; - bool negativePower = powerDC_kW_in < 0 ? true : false; - - - dcWiringLoss_ond_kW = 0.0; - acWiringLoss_ond_kW = 0.0; - - // Power quantities go in and come out in units of W - double powerDC_Watts = powerDC_kW_in * util::kilowatt_to_watt; - double powerAC_Watts = 0.0; - double powerAC_Watts_clipping = 0.0; - Tdry_C = tempC; - StringV = DCStringVoltage; - double tempLoss = 0.0; - double power_ratio = 1.0; - if (m_tempEnabled) { - calculateTempDerate(DCStringVoltage, tempC, powerDC_Watts, power_ratio, tempLoss); - } - - m_sandiaInverter->acpower(std::abs(powerDC_Watts) / m_numInvertersClipping, DCStringVoltage, &powerAC_Watts_clipping, &P_par_clipping, &P_lr_clipping, &efficiencyAC_clipping, &powerClipLoss_kW_clipping, &powerConsumptionLoss_kW_clipping, &powerNightLoss_kW_clipping); - - - if (m_inverterType == SANDIA_INVERTER || m_inverterType == DATASHEET_INVERTER || m_inverterType == COEFFICIENT_GENERATOR) - m_sandiaInverter->acpower(std::abs(powerDC_Watts) / m_numInverters, DCStringVoltage, &powerAC_Watts, &P_par, &P_lr, &efficiencyAC, &powerClipLoss_kW, &powerConsumptionLoss_kW, &powerNightLoss_kW); - else if (m_inverterType == PARTLOAD_INVERTER) - m_partloadInverter->acpower(std::abs(powerDC_Watts) / m_numInverters, &powerAC_Watts, &P_lr, &P_par, &efficiencyAC, &powerClipLoss_kW, &powerNightLoss_kW); - else if (m_inverterType == OND_INVERTER) - m_ondInverter->acpower(std::abs(powerDC_Watts) / m_numInverters, DCStringVoltage, tempC, &powerAC_Watts, &P_par, &P_lr, &efficiencyAC, &powerClipLoss_kW, &powerConsumptionLoss_kW, &powerNightLoss_kW, &dcWiringLoss_ond_kW, &acWiringLoss_ond_kW); - else if (m_inverterType == NONE) { - powerClipLoss_kW = 0.; - powerConsumptionLoss_kW = 0.; - powerNightLoss_kW = 0.; - efficiencyAC = NONE_INVERTER_EFF; - powerAC_Watts = powerDC_Watts * efficiencyAC; - } - - - - m_subhourlyClippingEnabled = true; - powerAC_kW_clipping = powerAC_Watts_clipping * m_numInvertersClipping * util::watt_to_kilowatt; - return; - -} - /* This function takes input inverter DC power (kW) per MPPT input for a SINGLE multi-mppt inverter, DC voltage (V) per input, and ambient temperature (deg C), and calculates output for the total number of inverters in the system */ void SharedInverter::calculateACPower(const std::vector powerDC_kW_in, const std::vector DCStringVoltage, double tempC) { diff --git a/ssc/cmod_pvsamv1.cpp b/ssc/cmod_pvsamv1.cpp index a2f8c5adb..7070741d3 100644 --- a/ssc/cmod_pvsamv1.cpp +++ b/ssc/cmod_pvsamv1.cpp @@ -1508,7 +1508,7 @@ void cm_pvsamv1::exec() Irradiance->dtHour, Subarrays[nn]->tiltDegrees, Subarrays[nn]->azimuthDegrees, Subarrays[nn]->trackerRotationLimitDegrees, 0.0, Subarrays[nn]->groundCoverageRatio, Subarrays[nn]->slopeTilt, Subarrays[nn]->slopeAzm, Subarrays[nn]->monthlyTiltDegrees, Irradiance->userSpecifiedMonthlyAlbedo, Subarrays[nn]->poa.poaAll.get(), - Irradiance->useSpatialAlbedos, &Irradiance->userSpecifiedMonthlySpatialAlbedos, as_boolean("enable_subhourly_clipping")); + Irradiance->useSpatialAlbedos, &Irradiance->userSpecifiedMonthlySpatialAlbedos, (as_boolean("enable_subhourly_clipping") || as_boolean("enable_subinterval_distribution"))); int code = irr.calc(); @@ -2553,11 +2553,11 @@ void cm_pvsamv1::exec() } for (size_t inrec = 0; inrec < nrec; inrec++) { idx = inrec; - double dcPower_kW_csky = PVSystem->p_systemDCPowerCS[idx]; + double dcPower_kWcsky = PVSystem->p_systemDCPowerCS[idx]; //Calculate DNI clearness index (time step basis) double dni_clearness_index = PVSystem->p_DNIIndex[0][idx]; //Calculate Clipping Potential ((P_dc,dryclean - P_ac,0) / P_ac,0) (time step basis) - sharedInverter->calculateACPower(dcPower_kW_csky, dcVoltagePerMppt[0], Irradiance->weatherRecord.tdry, as_boolean("enable_subhourly_clipping")); //DC batteries not allowed with multiple MPPT, so can just use MPPT 1's voltage + sharedInverter->calculateACPower(dcPower_kWcsky, dcVoltagePerMppt[0], Irradiance->weatherRecord.tdry, as_boolean("enable_subhourly_clipping")); //DC batteries not allowed with multiple MPPT, so can just use MPPT 1's voltage nominal_annual_clipping_output += sharedInverter->powerAC_kW_clipping; /* double clip_pot = (dcPower_kW_csky - sharedInverter->powerAC_kW_clipping) / sharedInverter->powerAC_kW_clipping; @@ -2619,9 +2619,7 @@ void cm_pvsamv1::exec() double dcPower_kW = PVSystem->p_systemDCPower[idx]; double dcPower_kW_csky = PVSystem->p_systemDCPowerCS[idx]; - double dcPower_kW_max = dcPower_kW_csky; - double dcPower_kW_min = dcPower_kW_max * 0.045 / 1.5; //AM? - double dcPower_kW_avg = dcPower_kW; + // Battery replacement if (en_batt && (batt_topology == ChargeController::DC_CONNECTED)) { @@ -2657,43 +2655,51 @@ void cm_pvsamv1::exec() } } - if (as_boolean("enable_subinterval_distribution")) { - if (dcPower_kW > 0) { + if (as_integer("enable_subinterval_distribution")==1) { + if (dcPower_kW > 0.0) { double dcPower_kW_max = dcPower_kW_csky; + log(util::format("dcPower max is %lg", dcPower_kW_max), SSC_NOTICE); double dcPower_kW_min = dcPower_kW_max * 0.045 / 1.5; //AM? + log(util::format("dcPower min is %lg", dcPower_kW_min), SSC_NOTICE); double dcPower_kW_avg = dcPower_kW; double CF = (dcPower_kW_avg - dcPower_kW_min) / (dcPower_kW_max - dcPower_kW_min); double n = CF / (1 - CF); - int inverter_count = as_integer("inverter_count"); + log(util::format("n is %lg", n), SSC_NOTICE); + //int inverter_count = as_integer("inverter_count"); + int inverter_count = 99; //sharedInverter->calculateACPower(dcPower_kW_csky, dcVoltagePerMppt[0], Irradiance->weatherRecord.tdry, as_boolean("enable_subhourly_clipping")); - double inv_dc_max = sharedInverter->getInverterDCMaxPower(0.0) / 1000.0 * inverter_count; + double inv_dc_max = sharedInverter->getInverterDCMaxPower(nameplate_kw) / 1000.0 * inverter_count; + //log(util::format("Inverter DC Max is %lg kW", inv_dc_max), SSC_NOTICE); double T = 1.0; - double log_test = 1 - (inv_dc_max - dcPower_kW_min) / (dcPower_kW_max - dcPower_kW_min); - double t_lm = 0.0; - if (log_test > 0.0) { - t_lm = T * exp(std::log(1 - (inv_dc_max - dcPower_kW_min) / (dcPower_kW_max - dcPower_kW_min)) / n); //fraction of hours + double log_test = 1.0 - (inv_dc_max - dcPower_kW_min) / (dcPower_kW_max - dcPower_kW_min); + log(util::format("log_test is %lg", log_test), SSC_NOTICE); + ssc_number_t t_lm = 0.0; + if (log_test > 0.0 && n > 0.0) { + t_lm = T * std::exp(std::log(1.0 - (inv_dc_max - dcPower_kW_min) / (dcPower_kW_max - dcPower_kW_min)) / n); //fraction of hours } + log(util::format("t_lm is %lg", t_lm), SSC_NOTICE); double E_clipped = dcPower_kW_max * t_lm - ((dcPower_kW_max - dcPower_kW_min) * pow(t_lm, n + 1) / ((n + 1) * pow(T, n))) - inv_dc_max * t_lm; + log(util::format("E_clipped is %lg kW", E_clipped), SSC_NOTICE); double E_remaining = (inv_dc_max - dcPower_kW_max) * T + ((dcPower_kW_max - dcPower_kW_min) * pow(T, n + 1) / ((n + 1) * pow(T, n))) - (inv_dc_max - dcPower_kW_max) * t_lm - ((dcPower_kW_max - dcPower_kW_min) * pow(t_lm, n + 1) / ((n + 1) * pow(T, n))); double subinterval_clipping_loss = E_clipped; - if (E_clipped > 0) { + if (E_clipped > 0.0) { for (size_t m = 0; m < PVSystem->Inverter->nMpptInputs; m++) { dcPowerNetPerMppt_kW[m] -= E_clipped * dcPowerNetPerMppt_kW[m] / dcPower_kW; } dcPower_kW -= E_clipped; - PVSystem->p_DistributionClippingLoss[idx] = E_clipped; + PVSystem->p_DistributionClippingLoss[idx] = (ssc_number_t)E_clipped; if (iyear == 0) { annual_distribution_clipping_loss += E_clipped; } } else { - PVSystem->p_DistributionClippingLoss[idx] = 0.0; + PVSystem->p_DistributionClippingLoss[idx] = (ssc_number_t)1; } } else { - PVSystem->p_DistributionClippingLoss[idx] = 0.0; + PVSystem->p_DistributionClippingLoss[idx] = (ssc_number_t)2; } }