-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsunearth.chpl
More file actions
295 lines (290 loc) · 13.4 KB
/
sunearth.chpl
File metadata and controls
295 lines (290 loc) · 13.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
const TwoPi = 2*pi;
// -----------------------------------------------------------------------------
// --> ddse: ddse: declination and distance sun-earth a funcion of (year, month,
// day)
//
// based on
//
// Van Flandern, T. C. and Pulkkinen, K. F. (1979) "Low Precision Formulae for
// Planetary Positions" - The Astronomical Journal Supplement Series,
// 41,391:411.
//
// 2019-05-04T13:46:15 fumbling around
//
// 2020-03-30T15:38:03 reverting to a faithful reproduction of my dear ddstx in
// weather.c
//
// 2021-04-06T13:56:56 translating from Python to Chapel
// -----------------------------------------------------------------------------
proc ddse(yea: int, mon: int, day: int): (real,real) {
// -----------------------------------------------------------------------------
// At GMT noon: this is done with purely integer arithmetic
// -----------------------------------------------------------------------------
var JD = 367 * yea - ( 7 * (yea + (mon + 9) / 12 ) / 4 )
+ ( 275 * mon / 9 + day ) + 1721014;
var tee = (JD - 2451545): real; // tee == thousands of Julian years from 2000
var TC = tee/36525.0 + 1.0; // TC == hundreds of Julian years from 1900
var LS = 0.779072 + 0.00273790931 * tee; // mean longitude, Sun
var GS = 0.993126 + 0.00273777850 * tee; // mean anomaly, Sun
var G5 = 0.056531 + 0.00023080893 * tee; // mean anomaly, Jupiter
var OM = 0.347343 - 0.00014709391 * tee; // long of lunar ascending mode
// -----------------------------------------------------------------------------
// extracts fractional part
// -----------------------------------------------------------------------------
LS = LS - trunc(LS);
GS = GS - trunc(GS);
G5 = G5 - trunc(G5);
OM = OM - trunc(OM);
// -----------------------------------------------------------------------------
// converts to radians
// -----------------------------------------------------------------------------
LS = LS * TwoPi;
GS = GS * TwoPi;
G5 = G5 * TwoPi;
OM = OM * TwoPi;
// -----------------------------------------------------------------------------
// obtains VS
// -----------------------------------------------------------------------------
var VS = + 0.39785 * sin( LS )
- 0.01000 * sin( LS - GS )
+ 0.00333 * sin( LS + GS )
- 0.00021 * TC * sin( LS )
+ 0.00004 * sin( LS + 2.0 * GS )
- 0.00004 * cos( LS )
- 0.00004 * sin( OM - LS )
+ 0.00003 * TC * sin( LS - GS );
// -----------------------------------------------------------------------------
// obtains US
// -----------------------------------------------------------------------------
var US = + 1.0
- 0.03349 * cos( GS )
- 0.00014 * cos( 2.0 * GS )
+ 0.00008 * TC * cos( GS )
- 0.00003 * sin( GS - G5 );
// -----------------------------------------------------------------------------
// Sun's declination
// -----------------------------------------------------------------------------
var delta = asin( VS / sqrt(US) ) ;
// -----------------------------------------------------------------------------
// distance Sun-Earth in the form (r/a) where a is the length of the largest
// semi-axis of the Earth's orbit, i.e.: the equivalent to one astronomical
// unit, and rr is the Sun-Earth distance
// -----------------------------------------------------------------------------
var rr = 1.00021 * sqrt( US );
return (delta,rr);
}
// -----------------------------------------------------------------------------
// -->sunman: only the sun mean anomaly a funcion of (year, month,day)
//
// based on
//
// Van Flandern, T. C. and Pulkkinen, K. F. (1979) "Low Precision Formulae for
// Planetary Positions" - The Astronomical Journal Supplement Series,
// 41,391:411.
//
// 2021-04-06T14:19:53 Translating to Chahpel
// -----------------------------------------------------------------------------
proc sunman(yea,mon,day,sec=0.0): real {
// -----------------------------------------------------------------------------
// At GMT noon: this is done with purely integer arithmetic
// -----------------------------------------------------------------------------
var IJD = 367 * yea
- 7*(yea + (mon + 9)/12)/4
- 3*((yea + (mon - 9)/7)/100 + 1)/4
+ 275*mon/9 + day + 1721029;
// -----------------------------------------------------------------------------
// trying to get more accuracy by calculating seconds
// -----------------------------------------------------------------------------
var JD = IJD + sec/86400.0;
// -----------------------------------------------------------------------------
// Obtains tee,
// -----------------------------------------------------------------------------
var tee = JD - 2451545.0;
// -----------------------------------------------------------------------------
// other variables
// -----------------------------------------------------------------------------
var GS = 0.993126 + 0.00273777850 * tee; // mean anomaly, Sun
GS = GS - trunc(GS); // fractional part
// -----------------------------------------------------------------------------
// converts to radians
// -----------------------------------------------------------------------------
GS = GS * TwoPi ;
return(GS);
}
// -----------------------------------------------------------------------------
// --> rsds: extra-atmospheric solar radiation and maximum number of hours of
// sunshine as a function of latitude, the Sun-Earth distance and the Sun's
// declination, where:
//
// lat -- latitude (radians)
// rr -- Sun-Earth distance in A.U.
// delta -- Sun's declination (radians)
//
// returns
//
// rsea -- extra-atmospheric solar radiation ( W/m2 )
// dsmax -- maximum sunshine duration (hours)
//
// References: Sellers, W.D. (1965) " Physical Climatology " . The University of
// Chicago Press / Chicago & London
//
// 2020-03-30T16:15:43 since my MSc thesis the solar constant has changed! Now
// it is 1361.5 (according to Wikipedia)
// -----------------------------------------------------------------------------
proc rsds(lat,rr,delta): (real,real) {
const rs0 = 1361.5; // solar constant
// -----------------------------------------------------------------------------
// calculates H = half-duration of a day in radians
// -----------------------------------------------------------------------------
var H = acos( - tan(lat) * tan(delta) );
// -----------------------------------------------------------------------------
// calculates dsmax in hours
// -----------------------------------------------------------------------------
var dsmax = 24.0 * H / pi;
// -----------------------------------------------------------------------------
// calculates rsea
// -----------------------------------------------------------------------------
var rsea = ( rs0 / pi ) * (1.0/rr**2) *
( H * sin(lat) * sin(delta) + cos(lat) * cos(delta) * sin(H) );
return (rsea,dsmax);
}
// -----------------------------------------------------------------------------
// --> rsdsZ: extra-atmospheric solar radiation and maximum number of hours of
// sunshine as a function of latitude, the Sun-Earth distance and the Sun's
// declination, where:
//
// lat -- latitude (radians)
// rr -- Sun-Earth distance in A.U.
// delta -- Sun's declination (radians)
//
// returns
//
// rsea -- extra-atmospheric solar radiation ( W/m2 )
// dsmax -- maximum sunshine duration (hours)
// Z -- zenith angle of the sun at solar noon
//
// References: Sellers, W.D. (1965) " Physical Climatology " . The University of
// Chicago Press / Chicago & London
//
// 2020-03-30T16:15:43 since my MSc thesis the solar constant has changed! Now
// it is 1361.5 (according to Wikipedia)
// -----------------------------------------------------------------------------
proc rsdsZ(lat,rr,delta): (real,real,real) {
const rs0 = 1361.5; // solar constant
// -----------------------------------------------------------------------------
// calculates H = half-duration of a day in radians
// -----------------------------------------------------------------------------
var H = acos( - tan(lat) * tan(delta) );
// -----------------------------------------------------------------------------
// calculates dsmax in hours
// -----------------------------------------------------------------------------
var dsmax = 24.0 * H / pi;
// -----------------------------------------------------------------------------
// calculates rsea
// -----------------------------------------------------------------------------
var rsea = ( rs0 / pi ) * (1.0/rr**2) *
( H * sin(lat) * sin(delta) + cos(lat) * cos(delta) * sin(H) );
// -----------------------------------------------------------------------------
// Zenith angle at solar noon
// -----------------------------------------------------------------------------
var Z = lat - delta;
// if lat < 0 then Z = -Z;
return (rsea,dsmax,Z);
}
// -----------------------------------------------------------------------------
// --> rseat: instantaneous extra-atmospheric solar radiation and maximum number
// of hours of sunshine as a function of latitude, the Sun-Earth distance and
// the Sun's declination, where:
//
// tnoon -- time of solar noon, in decimal hours
// t -- time, in decimal hours (9.47, etc.)
// lat -- latitude (radians)
// rr -- Sun-Earth distance in A.U.
// delta -- Sun's declination (radians)
//
// returns
//
// rsea -- extra-atmospheric solar radiation at time t ( W/m2 )
// cosZ -- cosine of Zenith angle of the Sun
//
// References: Sellers, W.D. (1965) " Physical Climatology " . The University of
// Chicago Press / Chicago & London 2020-08-13T15:01:51 since my MSc thesis the
// solar constant has changed! Now it is 1361.5 (according to Wikipedia)
//
// returns instantaneous values, adequate for hourly or sub-hourly time
// intervals
// -----------------------------------------------------------------------------
proc rseat(
tnoon: real,
t: real,
lat: real,
rr: real,
delta: real ): (real,real) {
const rs0 = 1361.5; // solar constant
// -----------------------------------------------------------------------------
// calculates H = half-duration of a day in radians
// -----------------------------------------------------------------------------
var H = acos( - tan(lat) * tan(delta) );
// -----------------------------------------------------------------------------
// the first thing we need to calculate is the hour angle!
// -----------------------------------------------------------------------------
var h = (pi/12.0)*(tnoon - t);
if ( h < -H) || (h > H) then { // control nightime periods
return(0.0,0.0);
} // daytime!
// -----------------------------------------------------------------------------
// cosine of Zenith angle
// -----------------------------------------------------------------------------
var cosZ = (sin(delta)*sin(lat)+cos(delta)*cos(lat)*cos(h));
// -----------------------------------------------------------------------------
// extra-terrestrial radiation at time t
// -----------------------------------------------------------------------------
var rsea = rs0*cosZ/(rr**2);
return (rsea,cosZ);
}
// -----------------------------------------------------------------------------
// --> rseac: calculates the instantaneous clear-sky solar radiation, following
//
// - Crawford, T. M. & Duchon, C. E. An improved parameterization for estimating
// effective atmospheric emissivity for use in calculating daytime downwelling
// longwave radiation J Appl Meteorol, 1999, 38, 474-480
//
// - Meyers, T. & Dale, R. Predicting daily insolation with hourly cloud height
// and coverage Journal of climate and applied meteorology, 1983, 22, 537-545
//
// - Smith, W. L. Note on the relationship between total precipitable water and
// surface dew point Journal of Applied Meteorology, 1966, 5, 726-727
//
// as a function of year, month, day, latitude (radians), local solar
// noon time and local time, Smith's lambda (Table 1), atmospheric
// pressure (Pa) and Dew Point temperature (K)
//
// Nelson Luís Dias
// 2020-08-13T16:05:54
// 2020-08-13T16:05:57
// -----------------------------------------------------------------------------
proc rseac(year,mon,day,lat,tnoon,t,slambda,pa,Td): real {
var (delta,rr) = ddse(year,mon,day); // sun's decl and sun-earth distance
// -----------------------------------------------------------------------------
// instantaneous extra-terrestrial solar radiation and Zenith angle
// -----------------------------------------------------------------------------
var (rsea,cosZ) = rseat(tnoon,t,lat,rr,delta);
if ( rsea == 0.0 ) then { // nighttime? return
return 0.0;
}
// -----------------------------------------------------------------------------
// optical air mass at 101325 Pa
// -----------------------------------------------------------------------------
var m = 35*(1224*cosZ**2 + 1)**(-0.5);
pa /= 1000.0; // use pressure in kPa in formulas
var TrTg = 1.021 - 0.084*(m*(949*pa*1.0e-5+0.051))**(0.5);
// -----------------------------------------------------------------------------
// Dew point temperature
// -----------------------------------------------------------------------------
Td = Td - 273.15; // from Kelvin to Celsius
Td = Td*9.0/5.0 + 32.0; // from Celsius to Fahrenheit
var u = exp(0.1133 - log(slambda + 1.0) + 0.0393*Td);
var Tw = 1 - 0.077*(u*m)**0.3;
var Ta = 0.935**m;
return rsea*(TrTg*Tw*Ta);
}