Nodes of different colours represent the following:
Solid arrows point from a parent (sub)module to the submodule which is descended from it. Dashed arrows point from a module being used to the module or program unit using it. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer, | intent(in) | :: | PVNum | |||
logical, | intent(in) | :: | RunFlag |
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed arrows point from an interface to procedures which implement that interface. This could include the module procedures in a generic interface or the implementation in a submodule of an interface in a parent module. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed arrows point from an interface to procedures which implement that interface. This could include the module procedures in a generic interface or the implementation in a submodule of an interface in a parent module. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
SUBROUTINE CalcTRNSYSPV(PVNum,RunFlag)
! SUBROUTINE INFORMATION:
! AUTHOR D. Bradley
! DATE WRITTEN April 2003
! MODIFIED B. Griffith, February 2008-- added support for inverter
! multipliers, and building integrated heat transfer
! B. Griffith, Aug. 2008 reworked for new, single-PV-generator data structure
! RE-ENGINEERED na
! PURPOSE OF THIS SUBROUTINE:
! This subroutine simulates the PV performance.
! METHODOLOGY EMPLOYED:
! na
! REFERENCES:
! na
! USE STATEMENTS:
USE DataGlobals, ONLY:SecInHour,MinutesPerTimeStep
USE DataSurfaces, ONLY: Surface
! USE DataPhotovoltaics, ONLY:CellTemp,LastCellTemp
USE DataHeatBalSurface, ONLY: TempSurfOut
USE TranspiredCollector, ONLY: GetUTSCTsColl
USE DataHeatBalance , ONLY: Zone
IMPLICIT NONE ! Enforce explicit typing of all variables in this routine
! SUBROUTINE FUNCTION DECLARATIONS:
! SUBROUTINE ARGUMENT DEFINITIONS:
INTEGER, INTENT(IN) :: PVNum !BTG added intent
LOGICAL, INTENT(IN) :: RunFlag !BTG added intent !flag tells whether the PV is ON or OFF
! SUBROUTINE PARAMETER DEFINITIONS:
REAL(r64), PARAMETER :: EPS=0.001d0
REAL(r64), PARAMETER :: ERR=0.001d0
REAL(r64), PARAMETER :: MinInsolation=30.0d0
INTEGER, PARAMETER :: CCMAX=10
INTEGER, PARAMETER :: KMAX=100
REAL(r64), PARAMETER :: EtaIni = 0.10d0 !initial value of eta
! INTERFACE BLOCK SPECIFICATIONS:
! na
! DERIVED TYPE DEFINITIONS:
! na
! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
REAL(r64),SAVE :: PVTimeStep !internal timestep (in seconds) for cell temperature mode 3
REAL(r64) :: DummyErr !
REAL(r64) :: ETA,Tambient,EtaOld,ILRef,AARef,IORef,SeriesResistance,IL,AA,IO,ISCG1,ISC,VOCG1,VOC
REAL(r64) :: VLEFT,VRIGHT,VM,IM,PM,IA,ISCA,VA,VOCA,PA
INTEGER :: CC,K
REAL(r64) :: CellTemp ! cell temperature in Kelvin
REAL(r64) :: CellTempC !cell temperature in degrees C
LOGICAL, SAVE :: FirstTime=.true.
!unused1208 INTEGER :: thisZone
! if the cell temperature mode is 2, convert the timestep to seconds
IF(FirstTime .and. PVarray(PVNum)%CellIntegrationMode == iDecoupledUllebergDynamicCellIntegration) THEN
PVTimeStep = REAL(MinutesPerTimeStep,r64)*60.0d0 !Seconds per time step
ENDIF
FirstTime=.false.
! place the shunt resistance into its common block
ShuntResistance = PVarray(PVNum)%TRNSYSPVModule%ShuntResistance
! convert ambient temperature from C to K
Tambient = Surface(PVarray(PVNum)%SurfacePtr)%OutDryBulbTemp + KelvinConv
IF ((PVarray(PVNum)%TRNSYSPVcalc%Insolation .GT. MinInsolation).AND.(RunFlag)) THEN
! set initial values for eta iteration loop
DummyErr = 2.0d0*ERR
CC = 1
EtaOld = EtaIni
! Begin DO WHILE loop - until the error tolerance is reached.
ETA = 0.0d0
DO WHILE (DummyErr .GT. ERR)
SELECT CASE (PVarray(PVNum)%CellIntegrationMode)
CASE (iDecoupledCellIntegration)
! cell temperature based on energy balance
PVarray(PVNum)%TRNSYSPVModule%HeatLossCoef = PVarray(PVNum)%TRNSYSPVModule%TauAlpha* &
PVarray(PVNum)%TRNSYSPVModule%NOCTInsolation/ &
(PVarray(PVNum)%TRNSYSPVModule%NOCTCellTemp-PVarray(PVNum)%TRNSYSPVModule%NOCTAmbTemp)
CellTemp = Tambient+(PVarray(PVNum)%TRNSYSPVcalc%Insolation*PVarray(PVNum)%TRNSYSPVModule%TauAlpha/ &
PVarray(PVNum)%TRNSYSPVModule%HeatLossCoef)*(1.0d0-ETA/PVarray(PVNum)%TRNSYSPVModule%TauAlpha)
CASE (iDecoupledUllebergDynamicCellIntegration)
! cell temperature based on energy balance with thermal capacity effects
CellTemp = Tambient+(PVarray(PVNum)%TRNSYSPVcalc%LastCellTempK-Tambient)* &
EXP(-PVarray(PVNum)%TRNSYSPVModule%HeatLossCoef/PVarray(PVNum)%TRNSYSPVModule%HeatCapacity*PVTimeStep) + &
(PVarray(PVNum)%TRNSYSPVModule%TauAlpha-ETA)*PVarray(PVNum)%TRNSYSPVcalc%Insolation / &
PVarray(PVNum)%TRNSYSPVModule%HeatLossCoef*(1.0d0-EXP(-PVarray(PVNum)%TRNSYSPVModule%HeatLossCoef / &
PVarray(PVNum)%TRNSYSPVModule%HeatCapacity*PVTimeStep))
CASE (iSurfaceOutsideFaceCellIntegration)
CellTemp = TempSurfOut(PVArray(PVNum)%SurfacePtr) + KelvinConv
CASE (iTranspiredCollectorCellIntegration)
CAll GetUTSCTsColl(PVArray(PVNum)%UTSCPtr, CellTemp)
CellTemp = CellTemp + KelvinConv
CASE (iExteriorVentedCavityCellIntegration)
CALL GetExtVentedCavityTsColl(PVArray(PVNum)%ExtVentCavPtr, CellTemp )
CellTemp = CellTemp + KelvinConv
CASE (iPVTSolarCollectorCellIntegration)
! get PVT model result for cell temp..
END SELECT
! reference parameters
ILRef = PVarray(PVNum)%TRNSYSPVModule%RefIsc
AARef = (PVarray(PVNum)%TRNSYSPVModule%TempCoefVoc*PVarray(PVNum)%TRNSYSPVModule%RefTemperature- &
PVarray(PVNum)%TRNSYSPVModule%RefVoc+PVarray(PVNum)%TRNSYSPVModule%SemiConductorBandgap* &
PVarray(PVNum)%TRNSYSPVModule%CellsInSeries)/(PVarray(PVNum)%TRNSYSPVModule%TempCoefIsc * &
PVarray(PVNum)%TRNSYSPVModule%RefTemperature/ILRef-3.0d0)
IORef = ILRef*EXP(-PVarray(PVNum)%TRNSYSPVModule%RefVoc/AARef)
! series resistance
SeriesResistance = (AARef*LOG(1.0d0-PVarray(PVNum)%TRNSYSPVModule%Imp/ILRef)- &
PVarray(PVNum)%TRNSYSPVModule%Vmp+PVarray(PVNum)%TRNSYSPVModule%RefVoc) / &
PVarray(PVNum)%TRNSYSPVModule%Imp
! temperature depencence
IL = PVarray(PVNum)%TRNSYSPVcalc%Insolation/PVarray(PVNum)%TRNSYSPVModule%RefInsolation* &
(ILRef+PVarray(PVNum)%TRNSYSPVModule%TempCoefIsc*(CellTemp-PVarray(PVNum)%TRNSYSPVModule%RefTemperature))
AA = AARef*CellTemp/PVarray(PVNum)%TRNSYSPVModule%RefTemperature
IO = IORef*(CellTemp/PVarray(PVNum)%TRNSYSPVModule%RefTemperature)**3* &
EXP(PVarray(PVNum)%TRNSYSPVModule%SemiConductorBandgap* &
PVarray(PVNum)%TRNSYSPVModule%CellsInSeries/AARef*(1.0d0-PVarray(PVNum)%TRNSYSPVModule%RefTemperature/CellTemp))
! compute short curcuit current and open circuit voltage
! NEWTON --> ISC (STARTVALUE: ISCG1 - BASED ON IL=ISC)
ISCG1 = IL
CALL NEWTON(ISC,FUN,FI,ISC,constant_zero,IO,IL,SeriesResistance,AA,ISCG1,EPS)
! NEWTON --> VOC (STARTVALUE: VOCG1 - BASED ON IM=0.0)
VOCG1 = (LOG(IL/IO)+1.0d0)*AA
CALL NEWTON(VOC,FUN,FV,constant_zero,VOC,IO,IL,SeriesResistance,AA,VOCG1,EPS)
! maximum power point tracking
! SEARCH --> VM AT MAXIMUM POWER POINT
VLEFT = 0.0d0
VRIGHT = VOC
CALL SEARCH(VLEFT,VRIGHT,VM,K,IO,IL,SeriesResistance,AA,EPS,KMAX)
! POWER --> IM & PM AT MAXIMUM POWER POINT
CALL POWER(IO,IL,SeriesResistance,AA,EPS,IM,VM,PM)
! calculate overall PV module efficiency
ETA = PM/PVarray(PVNum)%TRNSYSPVcalc%Insolation/PVarray(PVNum)%TRNSYSPVModule%Area
DummyErr = ABS((ETA-EtaOld)/EtaOld)
ETAOLD = ETA
CC=CC+1
END DO
! end of DO WHILE loop.
ELSE
! if there is no incident radiation or if the control switch is 'Off'
Select Case (PVarray(PVNum)%CellIntegrationMode)
Case (iDecoupledCellIntegration)
CellTemp = Tambient
CASE (iDecoupledUllebergDynamicCellIntegration)
CellTemp = Tambient+(PVarray(PVNum)%TRNSYSPVcalc%LastCellTempK-Tambient) &
*EXP(-PVarray(PVNum)%TRNSYSPVModule%HeatLossCoef/PVarray(PVNum)%TRNSYSPVModule%HeatCapacity*PVTimeStep)
CASE (iSurfaceOutsideFaceCellIntegration)
CellTemp = TempSurfOut(PVarray(PVNum)%SurfacePtr)+ KelvinConv
CASE (iTranspiredCollectorCellIntegration)
CAll GetUTSCTsColl(PVarray(PVNum)%UTSCPtr, CellTemp)
CellTemp = CellTemp + KelvinConv
CASE (iExteriorVentedCavityCellIntegration)
CALL GetExtVentedCavityTsColl(PVarray(PVNum)%ExtVentCavPtr, CellTemp )
CellTemp = CellTemp + KelvinConv
CASE (iPVTSolarCollectorCellIntegration)
! get PVT model result for cell temp..
END SELECT
PVarray(PVNum)%TRNSYSPVcalc%Insolation = 0.0d0
IM = 0.0d0 !module current
VM = 0.0d0 !module voltage
PM = 0.0d0 !module power
ETA = 0.0d0 !module efficiency
ISC = 0.0d0
VOC = 0.0d0
END IF
! convert cell temperature back to C
CellTempC = CellTemp - KelvinConv
! calculate array based outputs (so far, the outputs are module based
IA = PVarray(PVNum)%NumSeriesNParall*IM
ISCA = PVarray(PVNum)%NumSeriesNParall*ISC
VA = PVarray(PVNum)%NumModNSeries*VM
VOCA = PVarray(PVNum)%NumModNSeries*VOC
PA = IA*VA
! Place local variables into the reporting structure
PVarray(PVNum)%TRNSYSPVcalc%ArrayCurrent = IA
PVarray(PVNum)%TRNSYSPVcalc%ArrayVoltage = VA
PVarray(PVNum)%TRNSYSPVcalc%ArrayPower = PA
PVarray(PVNum)%Report%DCPower = PA
PVarray(PVNum)%TRNSYSPVcalc%ArrayEfficiency = ETA
PVarray(PVNum)%Report%ArrayEfficiency = ETA
PVarray(PVNum)%TRNSYSPVcalc%CellTemp = CellTempC
PVarray(PVNum)%Report%CellTemp = CellTempC
PVarray(PVNum)%TRNSYSPVcalc%CellTempK = CellTemp
PVarray(PVNum)%TRNSYSPVcalc%ArrayIsc = ISCA
PVarray(PVNum)%Report%ArrayIsc = ISCA
PVarray(PVNum)%TRNSYSPVcalc%ArrayVoc = VOCA
PVarray(PVNum)%Report%ArrayVoc = VOCA
PVarray(PVNum)%SurfaceSink = PA
CONTINUE
RETURN
END SUBROUTINE CalcTRNSYSPV