solar 0.0.2 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,228 @@
1
+ module Solar
2
+
3
+ ALTITUDES = {
4
+ official: -50/60.0,
5
+ civil: -6.0,
6
+ nautical: -12.0,
7
+ astronomical: -18.0
8
+ }
9
+
10
+ class <<self
11
+ private
12
+
13
+ # Julian Day as Rational
14
+ def jd_r(t)
15
+ if false
16
+ # This computes JD with precision of seconds and yields smaller denominators
17
+ t = t.utc
18
+ t.to_date.ajd + Rational(t.hour,24) + Rational(t.min,1440) + Rational(t.sec,86_400)
19
+ else
20
+ # This preserves the internal precision of t (which we probably don't need)
21
+ # and produces larger denominators in general
22
+ t.to_datetime.utc.ajd
23
+ end
24
+ end
25
+
26
+ # Julian Day as Float
27
+ def jd_f(t)
28
+ # t.to_date.ajd.to_f + t.hour/24.0 + t.min/1440.0 + t.sec/86400.0
29
+ t.to_datetime.utc.ajd.to_f
30
+ end
31
+
32
+ def to_rad(deg)
33
+ deg*Math::PI/180.0
34
+ end
35
+
36
+ def to_deg(rad)
37
+ rad*180.0/Math::PI
38
+ end
39
+
40
+ def to_h(deg)
41
+ deg/15.0
42
+ end
43
+
44
+ # Julian day to Julian Centuries since J2000.0
45
+ def to_jc(jd)
46
+ (jd - 2_451_545)/36_525
47
+ end
48
+
49
+ def polynomial(coefficients, x)
50
+ coefficients.inject(0.0) { |p, a| p*x + a }
51
+ end
52
+
53
+ # Conversion of Float to Rational preserving the exact value of the number
54
+ def to_r(x)
55
+ x = x.to_f
56
+ return Rational(x.to_i,1) if x.modulo(1) == 0
57
+ if !x.finite?
58
+ return Rational(0,0) if x.nan?
59
+ return x < 0 ? Rational(-1,0) : Rational(1,0)
60
+ end
61
+
62
+ f,e = Math.frexp(x)
63
+
64
+ if e < Float::MIN_EXP
65
+ bits = e + Float::MANT_DIG - Float::MIN_EXP
66
+ else
67
+ bits = [Float::MANT_DIG, e].max
68
+ # return Rational(x.to_i, 1) if bits < e
69
+ end
70
+ p = Math.ldexp(f,bits)
71
+ e = bits - e
72
+ if e<Float::MAX_EXP
73
+ q = Math.ldexp(1, e)
74
+ else
75
+ q = Float::RADIX**e
76
+ end
77
+ Rational(p.to_i, q.to_i)
78
+ end
79
+
80
+ # time to dynamical time
81
+ def to_td(t)
82
+ t = t.utc
83
+ t + to_r(delta_t(t))/86_400
84
+ end
85
+
86
+ # dynamical_time to utc
87
+ def to_utc(td)
88
+ raise 'Invalid dynamical time (should be utc)' unless td.utc?
89
+ td - to_r(delta_t(td))/86_400
90
+ end
91
+
92
+ # Compute difference between dynamical time and UTC in seconds.
93
+ #
94
+ # See http://sunearth.gsfc.nasa.gov/eclipse/SEcat5/deltatpoly.html.
95
+ #
96
+ # Good from -1999 to +3000.
97
+ #
98
+ def delta_t(date)
99
+ year = date.year.to_f
100
+ y = year + (date.month.to_f - 0.5) / 12.0
101
+
102
+ case
103
+ when year < -500.0
104
+ u = (year - 1820.0) / 100.0
105
+ -20.0 + 32.0*u*u
106
+ when year < 500.0
107
+ u = y / 100.0
108
+ polynomial [0.0090316521, 0.022174192, -0.1798452, -5.952053, 33.78311, -1014.41, 10583.6], u
109
+ when year < 1600.0
110
+ u = (y - 1000.0) / 100.0
111
+ polynomial [0.0083572073, -0.005050998, -0.8503463, 0.319781, 71.23472, -556.01, 1574.2], u
112
+ when year < 1700.0
113
+ t = y - 1600.0
114
+ polynomial [1.0/7129.0, -0.01532, -0.9808, 120.0], t
115
+ when year < 1800.0
116
+ t = y - 1700.0
117
+ polynomial [-1.0/1174000.0, 0.00013336, -0.0059285, 0.1603, 8.83], t
118
+ when year < 1860.0
119
+ t = y - 1800.0
120
+ polynomial [0.000000000875, -0.0000001699, 0.0000121272, -0.00037436, 0.0041116, 0.0068612, -0.332447, 13.72], t
121
+ when year < 1900.0
122
+ t = y - 1860.0
123
+ polynomial [1.0/233174.0, -0.0004473624, 0.01680668, -0.251754, 0.5737, 7.62], t
124
+ when year < 1920.0
125
+ t = y - 1900.0
126
+ polynomial [-0.000197, 0.0061966, -0.0598939, 1.494119, -2.79], t
127
+ when year < 1941.0
128
+ t = y - 1920.0
129
+ polynomial [0.0020936, -0.076100, 0.84493, 21.20], t
130
+ when year < 1961.0
131
+ t = y - 1950.0
132
+ polynomial [1.0/2547.0, -1.0/233.0, 0.407, 29.07], t
133
+ when year < 1986.0
134
+ t = y - 1975.0
135
+ polynomial [-1.0/718.0, -1.0/260.0, 1.067, 45.45], t
136
+ when year < 2005.0
137
+ t = y - 2000.0
138
+ polynomial [0.00002373599, 0.000651814, 0.0017275, -0.060374, 0.3345, 63.86], t
139
+ when year < 2050.0
140
+ t = y - 2000.0
141
+ polynomial [0.005589, 0.32217, 62.92], t
142
+ when year < 2150.0
143
+ -20.0 + 32.0*((y - 1820.0)/100.0)**2 - 0.5628*(2150.0 - y)
144
+ else
145
+ u = (year - 1820.0) / 100.0
146
+ -20.0 + 32*u*u
147
+ end
148
+ end
149
+
150
+ # Solar equatorial coordinates / Low accuracy : Meeus pg 151
151
+ # returns [declination in radians, right ascension in radians]
152
+ def equatorial_position_rad(t)
153
+ # t as Julian centuries of 36525 ephemeris days form the epoch J2000.0
154
+ if false
155
+ # Float
156
+ jd = jd_f(to_td(t))
157
+ else
158
+ # Rational
159
+ jd = jd_r(to_td(t))
160
+ end
161
+ t = to_jc(jd)
162
+
163
+ # Geometric mean longitude of the Sun, referred to the mean equinox of the date
164
+ l = 280.46645 + (36_000.76983 + 0.0003032*t)*t
165
+
166
+ # Mean anomaly of the Sun
167
+ m_deg = 357.52910 + (35_999.05030 - (0.0001559 + 0.00000048*t)*t)*t
168
+ m_rad = to_rad(m_deg)
169
+
170
+ # Eccentricity of the Earth's orbit
171
+ e = 0.016708617 - (0.000042037 + 0.0000001236*t)*t
172
+
173
+ # Sun's Equation of the center
174
+ c = (1.914600 - (0.004817 + 0.000014*t)*t)*Math.sin(m_rad) +
175
+ (0.019993 - 0.000101*t)*Math.sin(2*m_rad) +
176
+ 0.000290*Math.sin(3*m_rad)
177
+
178
+ # Sun's true longitude
179
+ o = l + c
180
+
181
+ # Reduce magnitude to minimize errors
182
+ o %= 360
183
+
184
+ # Sun's apparent Longitude
185
+ omega_deg = 125.04 - 1934.136*t
186
+ omega_rad = to_rad(omega_deg)
187
+ lambda_deg = o - 0.00569 - 0.00478 * Math.sin(omega_rad)
188
+
189
+ # Reduce magnitude to minimize errors
190
+ lambda_deg %= 360
191
+
192
+ lambda_rad = to_rad(lambda_deg)
193
+
194
+ # Obliquity of the ecliptic
195
+ epsilon_deg = 23.4392966666667 -
196
+ (0.012777777777777778 + (0.00059/60 - 0.00059/60*t)*t)*t +
197
+ 0.00256*Math.cos(omega_rad)
198
+ epsilon_rad = to_rad(epsilon_deg)
199
+
200
+ # Sun's declination
201
+ delta_rad = Math.asin(Math.sin(epsilon_rad)*Math.sin(lambda_rad))
202
+
203
+ # Sun's right ascension
204
+ alpha_rad = Math.atan2(
205
+ Math.cos(epsilon_rad) * Math.sin(lambda_rad),
206
+ Math.cos(lambda_rad)
207
+ )
208
+
209
+ [delta_rad, alpha_rad]
210
+ end
211
+
212
+ def altitude_from_options(options)
213
+ if options.has_key?(:zenith)
214
+ zenith = options[:zenith]
215
+ if Symbol===zenith
216
+ altitude = ALTITUDES[zenith]
217
+ else
218
+ altitude = 90.0 - zenith
219
+ end
220
+ else
221
+ altitude = options[:altitude] || :official
222
+ altitude = ALTITUDES[altitude] if Symbol===altitude
223
+ end
224
+ altitude
225
+ end
226
+ end
227
+
228
+ end
@@ -2,14 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: solar 0.1.1 ruby lib
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = "solar"
8
- s.version = "0.0.2"
9
+ s.version = "0.1.1"
9
10
 
10
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
11
13
  s.authors = ["Javier Goizueta"]
12
- s.date = "2012-10-08"
14
+ s.date = "2015-07-23"
13
15
  s.description = "# Calculation of solar position, rise & set times for a given position & time."
14
16
  s.email = "jgoizueta@gmail.com"
15
17
  s.extra_rdoc_files = [
@@ -25,38 +27,43 @@ Gem::Specification.new do |s|
25
27
  "Rakefile",
26
28
  "VERSION",
27
29
  "lib/solar.rb",
30
+ "lib/solar/day_night.rb",
31
+ "lib/solar/lambert.rb",
32
+ "lib/solar/passages.rb",
33
+ "lib/solar/position.rb",
34
+ "lib/solar/radiation.rb",
35
+ "lib/solar/support.rb",
28
36
  "solar.gemspec",
29
37
  "test/helper.rb",
30
38
  "test/test_solar.rb"
31
39
  ]
32
40
  s.homepage = "http://github.com/jgoizueta/solar"
33
41
  s.licenses = ["MIT"]
34
- s.require_paths = ["lib"]
35
- s.rubygems_version = "1.8.23"
42
+ s.rubygems_version = "2.2.2"
36
43
  s.summary = "# Calculation of solar position, rise & set times"
37
44
 
38
45
  if s.respond_to? :specification_version then
39
- s.specification_version = 3
46
+ s.specification_version = 4
40
47
 
41
48
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
42
49
  s.add_runtime_dependency(%q<activesupport>, [">= 0"])
43
50
  s.add_development_dependency(%q<shoulda>, [">= 0"])
44
51
  s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
45
52
  s.add_development_dependency(%q<bundler>, ["~> 1"])
46
- s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
53
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
47
54
  else
48
55
  s.add_dependency(%q<activesupport>, [">= 0"])
49
56
  s.add_dependency(%q<shoulda>, [">= 0"])
50
57
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
51
58
  s.add_dependency(%q<bundler>, ["~> 1"])
52
- s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
59
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
53
60
  end
54
61
  else
55
62
  s.add_dependency(%q<activesupport>, [">= 0"])
56
63
  s.add_dependency(%q<shoulda>, [">= 0"])
57
64
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
58
65
  s.add_dependency(%q<bundler>, ["~> 1"])
59
- s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
66
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
60
67
  end
61
68
  end
62
69
 
@@ -26,4 +26,15 @@ class TestSolar < Test::Unit::TestCase
26
26
  assert_equal :day, Solar.day_or_night(Time.utc(2012,10,7,9,0,0), 0, -89)
27
27
  end
28
28
 
29
+ should "compute radiation accurately" do
30
+ # from [Duffie-1991] Example 1.10.1
31
+ dt = 600.0 # integrate in 10-minute steps
32
+ r = 0.0
33
+ (0...24*3600.0).step(dt) do |h|
34
+ t = Date.new(1991, 4, 15).to_time + h
35
+ r += dt*Solar.radiation(t, 0.0, 43.0, clearness_index: 1.0)*1E-6
36
+ end
37
+ assert_in_delta 33.8, r, 33.8*1E-3
38
+ end
39
+
29
40
  end
metadata CHANGED
@@ -1,98 +1,87 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
5
- prerelease:
4
+ version: 0.1.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Javier Goizueta
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-10-08 00:00:00.000000000 Z
11
+ date: 2015-07-23 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: activesupport
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: shoulda
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rdoc
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ~>
45
+ - - "~>"
52
46
  - !ruby/object:Gem::Version
53
47
  version: '3.12'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ~>
52
+ - - "~>"
60
53
  - !ruby/object:Gem::Version
61
54
  version: '3.12'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: bundler
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ~>
59
+ - - "~>"
68
60
  - !ruby/object:Gem::Version
69
61
  version: '1'
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ~>
66
+ - - "~>"
76
67
  - !ruby/object:Gem::Version
77
68
  version: '1'
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: jeweler
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ~>
73
+ - - "~>"
84
74
  - !ruby/object:Gem::Version
85
- version: 1.8.4
75
+ version: 2.0.1
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ~>
80
+ - - "~>"
92
81
  - !ruby/object:Gem::Version
93
- version: 1.8.4
94
- description: ! '# Calculation of solar position, rise & set times for a given position
95
- & time.'
82
+ version: 2.0.1
83
+ description: "# Calculation of solar position, rise & set times for a given position
84
+ & time."
96
85
  email: jgoizueta@gmail.com
97
86
  executables: []
98
87
  extensions: []
@@ -100,7 +89,7 @@ extra_rdoc_files:
100
89
  - LICENSE.txt
101
90
  - README.rdoc
102
91
  files:
103
- - .document
92
+ - ".document"
104
93
  - Gemfile
105
94
  - Gemfile.lock
106
95
  - LICENSE.txt
@@ -108,35 +97,37 @@ files:
108
97
  - Rakefile
109
98
  - VERSION
110
99
  - lib/solar.rb
100
+ - lib/solar/day_night.rb
101
+ - lib/solar/lambert.rb
102
+ - lib/solar/passages.rb
103
+ - lib/solar/position.rb
104
+ - lib/solar/radiation.rb
105
+ - lib/solar/support.rb
111
106
  - solar.gemspec
112
107
  - test/helper.rb
113
108
  - test/test_solar.rb
114
109
  homepage: http://github.com/jgoizueta/solar
115
110
  licenses:
116
111
  - MIT
112
+ metadata: {}
117
113
  post_install_message:
118
114
  rdoc_options: []
119
115
  require_paths:
120
116
  - lib
121
117
  required_ruby_version: !ruby/object:Gem::Requirement
122
- none: false
123
118
  requirements:
124
- - - ! '>='
119
+ - - ">="
125
120
  - !ruby/object:Gem::Version
126
121
  version: '0'
127
- segments:
128
- - 0
129
- hash: -3223580498560321012
130
122
  required_rubygems_version: !ruby/object:Gem::Requirement
131
- none: false
132
123
  requirements:
133
- - - ! '>='
124
+ - - ">="
134
125
  - !ruby/object:Gem::Version
135
126
  version: '0'
136
127
  requirements: []
137
128
  rubyforge_project:
138
- rubygems_version: 1.8.23
129
+ rubygems_version: 2.2.2
139
130
  signing_key:
140
- specification_version: 3
141
- summary: ! '# Calculation of solar position, rise & set times'
131
+ specification_version: 4
132
+ summary: "# Calculation of solar position, rise & set times"
142
133
  test_files: []