solar 0.0.2 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []