Sunteți pe pagina 1din 25

Funciile procesului solar

Option Private Module


' Funciile procesului solar
'*****************************************************************************************************************
' Constante
Public Const SOLAR_CONST = 1367#
Public Const Pi = 3.14159265359
Public Const MEGA = 1000000#
Public Const DTOR = Pi / 180#
Public Const RTOD = 180# / Pi

' constanta solar [W/m2]


' pi
' un milion
' factor de conversie grade n radiani
' factor de conversie radiani n grade

' Moduri de urmrire


Private Const TR_NONE = 0
Private Const TR_1_AXIS = 1
Private Const TR_2_AXIS = 2
Private Const TR_AZIMUTH = 3
'*****************************************************************************************************************
' arc cosinus
Function Acos(x)
If (x > 0.9999995) Then
Acos = 0
ElseIf (x < -0.9999995) Then
Acos = Pi

Else
Acos = Atn(-x / Sqr(-x * x + 1)) + 1.5708
End If
End Function
'*****************************************************************************************************************
' arc tangent 2 - returneaz arc tangent de y/x, n domeniul [-pi,pi]
Function Atan2(x, y)
' Calcul arc tangent
If (Abs(x) < 0.0000005) Then
If (y > 0) Then
Atan2 = Pi / 2#
Else
Atan2 = -Pi / 2#
End If
Else
Atan2 = Atn(y / x)
' Calcul cadran
If (x < 0) Then
If (y < 0) Then
Atan2 = Atan2 - Pi
Else
Atan2 = Atan2 + Pi
End If
End If
End If
End Function

'*****************************************************************************************************************
1. Y12=GetDeclination(X12) apelul funciei

Declinaie [radiani]
284 n

23,45 sin 2

365

' nDay
= X12 // (i) ziua anului
Function GetDeclination(nDay)
GetDeclination = DTOR * 23.45 * Sin(2# * Pi * (284# + nDay) / 365#)
End Function
'*****************************************************************************************************************
2. Z12=GetAlbedo(H12) apelul funciei

Calcul albedo pe baza temperaturii medii

min Tmax T max T Tmin


Tmax Tmin

' Adoptam pentru albedo valoarea 0.7 daca temperatura < -5C si 0.2 peste 0 si o interpolare lineara intre aceste valori
Temp
= H12
Function GetAlbedo(Temp)
Const LowTemp = -5
Const LowAlbedo = 0.7
Const HighTemp = 0

Const HighAlbedo = 0.2


If (Temp < LowTemp) Then
GetAlbedo = LowAlbedo
ElseIf (Temp > HighTemp) Then
GetAlbedo = HighAlbedo
Else
GetAlbedo = (LowAlbedo * (HighTemp - Temp) + HighAlbedo * (Temp - LowTemp)) / (HighTemp - LowTemp)
End If
End Function
'*****************************************************************************************************************
3. AA12=getsunsethourangle(Lat_rad;Y12) apelul funciei

' Unghiul orei apusului s [radiani]


S arc cos tan tan
' Lat
= Lat_rad
// (i) latitudinea staiei [radian]
' Decl
= Y12
// (i) declinaia staiei [radian]
Function GetSunsetHourAngle(Lat, Decl)
CosSunset = -Tan(Lat) * Tan(Decl)
If (CosSunset > 1#) Then
GetSunsetHourAngle = 0#
ElseIf (CosSunset < -1#) Then
GetSunsetHourAngle = Pi
Else
GetSunsetHourAngle = Acos(CosSunset)

End If
End Function

'*****************************************************************************************************************
4.1 AC12=GetNExtra(X12)/1000 apelul funciei

' Iradiaia extraterestr normal [W/m2]


' nDay
// (i) ziua anului
Function GetNExtra(nDay)
GetNExtra = SOLAR_CONST * (1# + 0.033 * Cos(2# * Pi * nDay / 365#))
End Function
'*****************************************************************************************************************
4. AD12=GetHExtra_integ(AA12; Lat_rad; Y12; GetNExtra(X12))/1000000 apelul funciei

' H0 Iradiaia extraterestr pe o suprafa orizontal integrat de la unghiul orar -w la unghiul orar w.
H0

86400 G sc

1 0,033 cos 2

365

cos cos sin s s sin sin

w
= AA12
// unghiul orar al apusului
Lat
= Lat_rad
// latitudinea
Decl = Y12
// declianatia
Nextra = GetNExtra(X12)/1000000
Function GetHExtra_integ (w, Lat, Decl, NExtra)
HExtra = Sin(Decl) * Sin(Lat) * w + Cos(Decl) * Cos(Lat) * Sin(w)

HExtra = HExtra * NExtra * 86400# / 2# / Pi


GetHExtra_integ = 2# * HExtra
End Function

'*****************************************************************************************************************
5.1 Call CalcSunPositionHourAngle(SunZenith, SunAzimuth, Decl, HAngle, Lat) apelul procedurii
' Poziia soarelui: zenit i azimut funcie de declinaie i unghiul orar
' Not: n Braun i Mitchell, convenia pentru unghiul azimutului solar este:
' punctele aproape de ecuator si pozitiv spre vest. Pentru un punct
' aflat la ecuator 0 points south. In emisfera nordica aceasta
' conventie este echivalenta cu cea din SCL. In emisfera sudica
' Azimuth_SCL = PI - Azimuth_BM (modulo 2*PI), prin urmare sinAzimuth este
' acelasi cosAzimuth isi schimba semnul
'
' void CalcSunPositionHourAngle
' double *Zenith
= SunZenith
/* (o) unghiul zenital solar [radian] */
' double *Azimuth
= SunAzimuth /* (o) unghiul azimutal solar [radian] */
' double Decl
= Decl
/* (i) declinaie [radian] */
' double HourAngle
= HAngle
/* (i) unghiul orar [radian] */
' double Lat
= Lat
/* (i) latitudine [radian] */
Sub CalcSunPositionHourAngle (Zenith As Double, Azimuth As Double, Decl As Double, HourAngle As Double, Lat As Double)
' Declaraii
Dim cosZenith As Double, sinAzimuth As Double, cosAzimuth As Double
' Calcul unghi zenital
cos Z sin sin cos cos cos
cosZenith = Cos(Lat) * Cos(Decl) * Cos(HourAngle) + Sin(Lat) * Sin(Decl)
If (cosZenith > 1#) Then cosZenith = 1#
If (cosZenith < -1#) Then cosZenith = -1#
Zenith = Acos(cosZenith)

' Calcul unghi azimutal


sin sin cos

cos cos cos sin sin cos

sinAzimuth = Sin(HourAngle) * Cos(Decl)


cosAzimuth = Cos(HourAngle) * Cos(Decl) * Sin(Lat) - Sin(Decl) * Cos(Lat)
Azimuth = Atan2(cosAzimuth, sinAzimuth)
End Sub
'*****************************************************************************************************************
5.2.1 BMAzimuth(SunAzimuth, Lat) sau BMAzimuth(TrackAzimuth, Lat) apelul funciei
' Aceast funcie convertete unghiurile din convenia SCL convention n convenia Braun and Mitchell
' Reversul conversiei este identic cu conversia direct
Function BMAzimuth(Azimuth As Double, Lat As Double) As Double
Azimutul dup Braun i Mitchell este egal cu azimutul SCL n nord, pi minus azimutul SCL n sud
If (Lat >= 0) Then
BMAzimuth = Azimuth
Else
BMAzimuth = Pi - Azimuth
End If
' Azimutul trebuie s fie ntre -pi i pi
While (BMAzimuth < -Pi)
BMAzimuth = BMAzimuth + 2# * Pi

Wend
While (BMAzimuth > Pi)
BMAzimuth = BMAzimuth - 2# * Pi
Wend
End Function
'*****************************************************************************************************************
5.2.2 GetCosIncidenceAngle(SunZenith, SunAzimuth, SurfSlope, SurfAzimuth) apelul funciei
' Cosinusul unghiului de inciden pe o suprafa nclinat cu orice orientare
cos cos Z cos sin Z sin cos sur

Function GetCosIncidenceAngle (SunZenith, SunAzimuth, SurfaceSlope, SurfaceAzimuth)


CosInc = Cos(SunZenith) * Cos(SurfaceSlope) + Sin(SunZenith) * Sin(SurfaceSlope) * Cos(SunAzimuth - SurfaceAzimuth)
CosInc = Application.Min(CosInc, 1#)
CosInc = Application.Max(CosInc, -1#)
GetCosIncidenceAngle = CosInc
End Function
'*****************************************************************************************************************
5.2 Call Track(SurfSlope, SurfAzimuth, cosIncidenceAngle, SunZenith, SunAzimuth, Mode, TrackSlope, TrackAzim, Lat)
' Calculul pantei suprafeei, azimutul i unghiul de inciden pentru diferite suprafae fixe sau de urmrire
' double SurfSlope
/* (o) Panta suprafeei de urmrire */
' double SurfAzimuth
/* (o) Azimutul suprafeei de urmrire */

' double cosIncidenceAngle


' double SunZenith
' double SunAzimuth
' int Mode
' double TrackSlope
' double TrackAzimuth

/* (o) Cosinusul unghiului de inciden al radiaiei directe pe suprafaa de urmrire */


/* (i) Unghiul zenital solar [radian] */
/* (i) Unghiul azimutal slar [radian] */
/* (i) Modul de urmrire */
/* (i) Panta axei de urmrire [radian] */
/* (i) Azimutul axei de urmrire [radian] */

Sub Track (SurfSlope As Double, SurfAzimuth As Double, cosIncidenceAngle As Double, SunZenith As Double, SunAzimuth _
As Double, Mode As Integer, TrackSlope As Double, TrackAzimuth As Double, Lat As Double)
' Conversie a azimutului n convenia Braun i Mitchell
Dim BMSurfAzimuth As Double, BMSunAzimuth As Double, BMTrackAzimuth As Double
BMSunAzimuth = BMAzimuth(SunAzimuth, Lat)
BMTrackAzimuth = BMAzimuth(TrackAzimuth, Lat)
Select Case Mode
' Fr urmrire
Case TR_NONE:
SurfSlope = TrackSlope
BMSurfAzimuth = BMTrackAzimuth
' O singur ax urmrit
Case TR_1_AXIS:
' Axa orizontal
If (TrackSlope = 0#) Then
' Prima dat se convertete unghiul pentru valori ntre -pi/2 i pi/2
While (BMTrackAzimuth < -Pi / 2#)
BMTrackAzimuth = BMTrackAzimuth + Pi

Wend
While (BMTrackAzimuth > Pi / 2#)
BMTrackAzimuth = BMTrackAzimuth - Pi
Wend
If (BMSunAzimuth >= BMTrackAzimuth) Then
BMSurfAzimuth = BMTrackAzimuth + Pi / 2
Else
BMSurfAzimuth = BMTrackAzimuth - Pi / 2
End If
SurfSlope = Atn(Tan(SunZenith) * Cos(BMSurfAzimuth - BMSunAzimuth))
If (SurfSlope < 0#) Then
' SurfSlope = SurfSlope + Pi
SurfSlope = -SurfSlope
End If
' Ax nclinat, suprafaa paralel cu axa
Else
Dim Aux As Double
Aux = GetCosIncidenceAngle(SunZenith, BMSunAzimuth, TrackSlope, BMTrackAzimuth)
BMSurfAzimuth = BMTrackAzimuth + Atn(Sin(SunZenith) * Sin(BMSunAzimuth - BMTrackAzimuth) / Aux / Sin(TrackSlope))
If ((BMSurfAzimuth - BMTrackAzimuth) * (BMSunAzimuth - BMTrackAzimuth) < 0) Then
If (BMSunAzimuth >= BMTrackAzimuth) Then
BMSurfAzimuth = BMSurfAzimuth + Pi
Else
BMBMSurfAzimuth = BMSurfAzimuth - Pi
End If

End If
SurfSlope = Atn(Tan(TrackSlope) / Cos(BMSurfAzimuth - BMTrackAzimuth))
If (SurfSlope < 0#) Then
SurfSlope = SurfSlope + Pi
End If
End If
' Azimutul urmriri (axa vartical)
Case TR_AZIMUTH:
SurfSlope = TrackSlope
BMSurfAzimuth = BMSunAzimuth
' Urmarire n doua axe
Case TR_2_AXIS:
SurfSlope = SunZenith
BMSurfAzimuth = BMSunAzimuth
' n caz de eroare
Case Else:
MsgBox "Error: invalid tracking value"
End Select
' Conversie la convenia SCL
SurfAzimuth = BMAzimuth(BMSurfAzimuth, Lat)
' Calculul unghiului de inciden
cosIncidenceAngle = GetCosIncidenceAngle(SunZenith, SunAzimuth, SurfSlope, SurfAzimuth)

End Sub
'*****************************************************************************************************************
5. AG12=GetMonthlyTrackingRadiation(Lat_rad;TrackModeIndex;Slope_rad;Azim_rad;X12;AE12*1000000;Z12) /1000000
1 cos
1 - cos
H

2
2

Ht HbRb Hd

' Calculul mediei lunare a radiaiei zilnice pe o suprafa nclinat, given the monthly mean
' se dau media lunar a radiaiei zilnice pe o suprafa orizontal, numrul de luni,
' albedo, modul de urmrire i orientara suprafeei de urmrire
' GetMonthlyTrackingRadiation
/* media lunar a radiaiei zilnice pe o suprafa de urmrire [J] */
' double Lat
= Lat_rad
/* latitudine [radian] */
' int Mode
= TrackModeIndex
/* mod de urmrire */
' double TrackSlope
= Slope_rad
/* panta urmririi [radian] */
' double TrackAzim
= Azim_rad
/* azimutul urmririi [radian] */
' int Day
= X12
/* ziua medie a lunii */
' double Hglobar
= AE12*1000000
/* media lunar a radiaiei zilnice pe o suprafa [J] */
' double Albedobar
= Z12
/* medie lunar a albedo [0-1] */
Function GetMonthlyTrackingRadiation (Lat As Double, Mode As Integer, TrackSlope As Double, TrackAzim As Double, Day As _
Integer, Hglobar As Double, Albedobar As Double)
' Calcul declinaie
Dim Decl As Double
Decl = GetDeclination(Day)
' s Calcul unghi orar apus [radian]
Dim Sunset As Double
Sunset = GetSunsetHourAngle(Lat, Decl)

' H0 Calcul Hextra radiaie extraterestr zilnic


H0

86400 G sc

1 0,033 cos 2

365

cos cos sin s s sin sin

Dim HExtra As Double


HExtra = GetNExtra(Day) * 24 * 3600# / Pi * (Cos(Lat) * Cos(Decl) * Sin(Sunset) + Sunset * Sin(Lat) * Sin(Decl))
' K T Calcul Ktbar medie lunar a indicelui de luminozitate
KT

H
H0

Dim KTbar As Double


If (HExtra > 0#) Then
KTbar = Hglobar / HExtra
Else
KTbar = 0.8
End If
' Algoritm de corecie empiric, cnd (KTbar) este n afara domeniului [0.3,0.8]:
' Calcul (Hdirbar) presupunnd Hbar = HExtra*KTbar, apoi Hdifbar ca Hbar - Hdirbar.
' Aceast corecie este necesar pentru lunile apropiate de noaptea polar deasupra cercului polar, unde metoda zilei medii nu poate prezice
o valoare destul de mare a (HExtra), prin urmare conduce spre valori foarte mari ale lui (KTbar)
' Corecia lui Ktbar pentru valori n afara domeniului
If (KTbar > 0.8) Then KTbar = 0.8
If (KTbar < 0.3) Then KTbar = 0.3

' Calcul Hdirbar radiaia direct orizontal corespunzatoare lui KTbar, apoi radiaia difuz = radiaia global - radiaia direct
Hd
1,391 3,560 K T 4,189 K T2 2,137 K T3
H

pentru s < 81,40

Hd
1,311 3,022 K T 3,427 K T2 1,821 K T3
H

pentru s > 81,40

Dim Hdifbar As Double, Hdirbar As Double


If (Sunset <= 81.4 * DTOR) Then
Hdifbar = HExtra * KTbar * (1.391 + KTbar * (-3.56 + KTbar * (4.189 + KTbar * -2.137)))
Else
Hdifbar = HExtra * KTbar * (1.311 + KTbar * (-3.022 + KTbar * (3.427 + KTbar * -1.821)))
End If
' Calculul radiaiei directe orizontale corespunzatoare lui KTbar, apoi radiaia difuz ca global minus direct
Hdirbar = HExtra * KTbar - Hdifbar
Hdifbar = Hglobar - Hdirbar
' Calculul matricelor celor 24 de valori ale radiaiei globale i difuze zilnice
rt

a b cos cos - cos s


24
sin s s cos s

a 0,409 0,5016 sin s


3

b 0,6609 0,4767 sin s


3

rd

cos cos s

24 sin s s cos s

Pentru aceasta se declar variabilele ca matrici


Dim Hglo(0 To 23) As Double, Hdif(0 To 23) As Double, Hdir(0 To 23) As Double
Dim Den As Double
Dim CosSunset As Double
CosSunset = Cos(Sunset)
Den = Sin(Sunset) - Sunset * CosSunset
Dim Aux As Double
Aux = Sin(Sunset - Pi / 3#)
Dim a As Double, b As Double
a = 0.409 + 0.5016 * Aux
b = 0.6609 - 0.4767 * Aux
Dim h As Integer
Dim rttot As Double, rdtot As Double
rttot = 0#
rdtot = 0#
Calculul unghiului orar pentru cele 24 de ore (calculul se realizeaz pentru mijlocul fiecrei ore)
For h = 0 To 23
Dim HAngle As Double, cosHAngle As Double
HAngle = DTOR * 15# * (h + 0.5 - 12#)
cosHAngle = Cos(HAngle)
If (Abs(HAngle) < Sunset And Den > 0#) Then
Dim rd As Double, rt As Double
rd = Pi / 24# * (cosHAngle - CosSunset) / Den

rt = rd * (a + b * cosHAngle)
Hglo(h) = rt
Hdif(h) = rd
rttot = rttot + rt
rdtot = rdtot + rd
Else
Hglo(h) = 0#
Hdif(h) = 0#
End If
Next h
' Calculul matricelor celor 24 de valori ale radiaiei globale, difuze i directe zilnice
H rt H

H d rd H d

Hb H Hd

For h = 0 To 23
If (rttot > 0#) Then Hglo(h) = Hglo(h) * Hglobar / rttot
If (rdtot > 0#) Then Hdif(h) = Hdif(h) * Hdifbar / rdtot
Hdir(h) = Hglo(h) - Hdif(h)
Next h
Dim Tglobar As Double
Tglobar = 0#
' Calculul celor 24 de valori ale radiaiei pe planul nclinat i nsumarea acestora

1 cos
1 - cos
H

2
2

Ht HbRb Hd

For h = 0 To 23
' Calculul poziiei soarelui
Dim SunZenith As Double, SunAzimuth As Double
HAngle = DTOR * 15# * (h + 0.5 - 12#)
Call CalcSunPositionHourAngle(SunZenith, SunAzimuth, Decl, HAngle, Lat)
' Cazul n care Soarele este sub orizont
If (SunZenith < Pi / 2#) Then
' Calculul orientrii suprafeei
Dim SurfSlope As Double, SurfAzimuth As Double, cosIncidenceAngle As Double
Call Track(SurfSlope, SurfAzimuth, cosIncidenceAngle, SunZenith, SunAzimuth, Mode, TrackSlope, TrackAzim, Lat)
' Calcul Rbbar
Rb

cos
cos z

Dim rb As Double
rb = cosIncidenceAngle / Cos(SunZenith)
If (rb < 0#) Then rb = 0#
' Calculul radiaiei pe planul nclinat
Tglobar = Tglobar + Hdir(h) * rb + Hdif(h) * (1# + Cos(SurfSlope)) / 2# + Albedobar * Hglo(h) * (1# - Cos(SurfSlope)) / 2#
End If
Next h

' Cazul nopii polare: Tglobar = 0


If (Tglobar = 0#) Then
Tglobar = Hglobar
End If
' ntoarce valoarea
GetMonthlyTrackingRadiation = Tglobar
End Function

'*****************************************************************************************************************
6. AH12=GetDailyDiffuseFraction(AF12)
' Calculul fraciuni de radiaie difuz zilnic, cunoscnd indicele de luminozitate zilnic
Function GetDailyDiffuseFraction(DailyClearnessIndex)
kt = DailyClearnessIndex
If (kt <= 0.17) Then
kd = 0.99
ElseIf (kt < 0.75) Then
kd = 1.188 + kt * (-2.272 + kt * (9.473 + kt * (-21.865 + kt * 14.648)))
ElseIf (kt < 0.8) Then
kd = -0.54 * kt + 0.632
Else
kd = 0.2
End If
GetDailyDiffuseFraction = kd
End Function
'*****************************************************************************************************************
7. AI12=SurfSlopeNoon(Lat_rad;Y12;TrackModeIndex;Slope_rad; Azim_rad)
Function SurfSlopeNoon (Lat As Double, Decl As Double, Mode As Integer, TrackSlope As Double, TrackAzimuth As Double _
) As Double
Dim SunZenithNoon As Double, SunAzimuthNoon As Double
Dim SurfAzimuthNoon As Double, cosIncidenceAngle As Double

Call CalcSunPositionHourAngle(SunZenithNoon, SunAzimuthNoon, Decl, 0#, Lat)


Call Track(SurfSlopeNoon, SurfAzimuthNoon, cosIncidenceAngle, SunZenithNoon, SunAzimuthNoon, Mode, TrackSlope, _
TrackAzimuth, Lat)
End Function
'*****************************************************************************************************************
8. AJ12=CosIncidenceAngleNoon(Lat_rad;Y12;TrackModeIndex;Slope_rad; Azim_rad)
Function cosIncidenceAngleNoon (Lat As Double, Decl As Double, Mode As Integer, TrackSlope As Double, TrackAzimuth As _
Double) As Double
Dim SunZenithNoon As Double, SunAzimuthNoon As Double
Dim SurfSlope As Double, SurfAzimuth As Double
Call CalcSunPositionHourAngle(SunZenithNoon, SunAzimuthNoon, Decl, 0#, Lat)
Call Track(SurfSlope, SurfAzimuth, cosIncidenceAngleNoon, SunZenithNoon, SunAzimuthNoon, Mode, TrackSlope, TrackAzimuth, Lat)
End Function
'*****************************************************************************************************************

9. AX12=getcoszenithangle(Y12;0;Lat_rad)
' s Unghiul solar zenital [radiani]

cos Z sin sin cos cos cos

Function GetCosZenithAngle(Decl, HourAngle, Lat)


cosZenith = Cos(Lat) * Cos(Decl) * Cos(HourAngle) + Sin(Lat) * Sin(Decl)

cosZenith = Application.Min(cosZenith, 1#)


cosZenith = Application.Max(cosZenith, -1#)
GetCosZenithAngle = cosZenith
End Function

'*****************************************************************************************************************

10. BA12=GetHourlyToDailyTotalRadRatio(0;AA12)
' rt,n Calcularea raportului dintre radiaia total orar i zilnic
rt ,n

a b cos cos - cos s


24
sin s s cos s

Function GetHourlyToDailyTotalRadRatio(HourAngle, SunsetHourAngle)


SinSunset60 = Sin(SunsetHourAngle - DTOR * 60)
a = 0.409 + 0.5016 * SinSunset60
b = 0.6609 - 0.4767 * SinSunset60
GetHourlyToDailyTotalRadRatio = (a + b * Cos(HourAngle)) * GetHourlyToDailyDiffuseRadRatio(HourAngle, SunsetHourAngle)
If (GetHourlyToDailyTotalRadRatio > 1#) Then GetHourlyToDailyTotalRadRatio = 1#
End Function
'*****************************************************************************************************************

11. BB12=GetHourlyToDailyDiffuseRadRatio(0;AA12)
' rd,n Calculul raportului dintre radiaia difuz orar i zilnic (cnd soarle este la amiaz, = 0)
rd ,n

cos cos s

24 sin s s cos s

Function GetHourlyToDailyDiffuseRadRatio(HourAngle, SunsetHourAngle)

If (HourAngle < SunsetHourAngle) Then


sinSunset = Sin(SunsetHourAngle)
CosSunset = Cos(SunsetHourAngle)
cosHAngle = Cos(HourAngle)
GetHourlyToDailyDiffuseRadRatio = Pi / 24 * (cosHAngle - CosSunset) / (sinSunset - SunsetHourAngle * CosSunset)
If (GetHourlyToDailyDiffuseRadRatio > 1#) Then GetHourlyToDailyDiffuseRadRatio = 1#
Else
GetHourlyToDailyDiffuseRadRatio = 1#
End If
End Function
'*****************************************************************************************************************

S-ar putea să vă placă și