agwx_biophys 0.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f9f340d516a0d61d5d391d7f346540c6af7e38e3
4
+ data.tar.gz: 29dd22ef00cc3ec68b4a9aff760b7324fdb624a2
5
+ SHA512:
6
+ metadata.gz: 991e2c2afbeb889135e0c71344c2fdd6de0a53b339e969d5984c7f89d223b5ce41f8177c97afec6354e0b84adf8ce5b95a3ae9a5e579bf86ad5773ad3dbf6efc
7
+ data.tar.gz: 8abb2837d359283f91762f624c31f63a1b94d7d559ee524b894cbda52db001b8a95ebe1199c29f353869d03029a0a82bf31b51490073bbe2550fa12999ceab85
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ test/.~lock.TestValues.xls#
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in agwx_biophys.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 RickWayne
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # AgwxBiophys
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'agwx_biophys'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install agwx_biophys
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ end
7
+
8
+ desc "Run tests"
9
+ task default: :test
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'agwx_biophys/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "agwx_biophys"
8
+ spec.version = AgwxBiophys::VERSION
9
+ spec.authors = ["RickWayne"]
10
+ spec.email = ["fewayne@wisc.edu"]
11
+ spec.description = %q{Biophysical calculators primarily useful in agriculture and land management}
12
+ spec.summary = %q{So far, just an ET calculator (Priestly-Taylor)}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ end
@@ -0,0 +1,149 @@
1
+ module AgwxBiophys
2
+ module ET
3
+ SOLCON = 1367.0
4
+ STEFAN = (0.0864*0.0000000567)
5
+ SFCEMISS = 0.96
6
+ ALBEDO = 0.25
7
+ KELVIN = 273.15
8
+
9
+ def rad_lat(lat); lat * Math::PI / 180.0;end
10
+
11
+ def daily_to_sol(total_sol); 0.0864 * total_sol; end
12
+
13
+ def declin(doy)
14
+ 0.41 *
15
+ Math::cos(
16
+ 2 * Math::PI * ( doy - 172.0 ) / 365.0
17
+ )
18
+ end
19
+
20
+ def sunrise_angle(doy,lat)
21
+ Math.acos(
22
+ -1 *
23
+ Math.tan(declin(doy)) *
24
+ Math.tan(rad_lat(lat))
25
+ )
26
+ end
27
+
28
+ def sunrise_hour(doy,lat); 12 - ( 12 / Math::PI ) * sunrise_angle(doy,lat); end
29
+
30
+ def day_hours(doy,lat); 24 - 2 * sunrise_hour(doy,lat); end
31
+
32
+ def av_eir(doy)
33
+ SOLCON * ( 1 + 0.035 * Math.cos( 2 * Math::PI * doy / 365.0 ) )
34
+ end
35
+
36
+ def to_eir(doy,lat)
37
+ ( 0.0864 / Math::PI ) * av_eir(doy) *
38
+
39
+ (
40
+ sunrise_angle(doy,lat) *
41
+ Math.sin( declin(doy) ) *
42
+ Math.sin( rad_lat(lat) ) +
43
+
44
+ Math.cos( declin(doy) ) *
45
+ Math.cos( rad_lat(lat) ) *
46
+ Math.sin( sunrise_angle(doy,lat) )
47
+ )
48
+ end
49
+
50
+ def to_clr(doy,lat)
51
+ to_eir(doy,lat) * (-0.7 + 0.86*day_hours(doy,lat)) / day_hours(doy,lat)
52
+ end
53
+
54
+ def c_to_k(temperature); temperature + KELVIN; end
55
+
56
+ # Temps are in Deg C
57
+
58
+ def lwu(min_temp,max_temp)
59
+ avg = (min_temp+max_temp) / 2.0
60
+ SFCEMISS * STEFAN * (273.15+avg) ** 4
61
+ end
62
+
63
+ def sfactor(min_temp,max_temp)
64
+ avg = (min_temp+max_temp) / 2.0
65
+ 0.398 + 0.0171 * avg - 0.000142 * avg * avg
66
+ end
67
+
68
+ def sky_emiss(avg_v_press,min_temp,max_temp,avg_temp)
69
+
70
+ if ( avg_v_press > 0.5)
71
+ 0.7 + (5.95e-4) * avg_v_press * Math.exp( 1500/(273+avg_temp) )
72
+ else
73
+ avg_t = (min_temp+max_temp) / 2.0
74
+ (1 - 0.261*Math.exp(-0.000777*avg_t*avg_t))
75
+ end
76
+ end
77
+
78
+ def angstrom(avg_v_press,min_temp,max_temp,avg_temp)
79
+ 1.0 - sky_emiss(avg_v_press,min_temp,max_temp,avg_temp) / SFCEMISS
80
+ end
81
+
82
+ def clr_ratio(d_to_sol,doy,lat)
83
+ dts = daily_to_sol(d_to_sol)
84
+ tc = to_clr(doy,lat)
85
+ # Never return higher than 1
86
+ [dts/tc,1.0].min
87
+ end
88
+
89
+ def lwnet(avg_v_press,min_temp,max_temp,avg_temp,d_to_sol,doy,lat)
90
+ angstrom(avg_v_press,min_temp,max_temp,avg_temp) * lwu(min_temp,max_temp) * clr_ratio(d_to_sol,doy,lat)
91
+ end
92
+
93
+ def et(max_temp,min_temp,avg_temp,avg_v_press,d_to_sol,doy,lat)
94
+ lwnet = lwnet(avg_v_press,min_temp,max_temp,avg_temp,d_to_sol,doy,lat )
95
+ lwd = lwu(min_temp,max_temp) - lwnet
96
+ r_net_1 = (1.0 - ALBEDO) * daily_to_sol(d_to_sol) - lwnet
97
+ ret1 = 1.28 * sfactor(min_temp,max_temp) * r_net_1
98
+ # puts "lwnet #{lwnet}, lwd #{lwd}, r_net_1 #{r_net_1}, ret1 #{ret1} refet #{ret1 / 62.3}"
99
+ [ret1 / 62.3,clr_ratio(d_to_sol,doy,lat) * 100.0]
100
+ end
101
+ # double LWD = LWU - LWnet;
102
+ # double Rnet1 = ( 1-ALBEDO ) * DailyToSol - LWnet; /* ;(RESULTANT ET)=MJ/M2/DY
103
+ # ;(RESULTANT ET)=REFN ET IN/DY */
104
+ # double RET1 = 1.28 * Sfactor * Rnet1;
105
+ # DRefET = RET1 / 62.3;
106
+ # DClrRatio = ClrRatio*100;
107
+
108
+ # Here's the old Java code
109
+ # double rad_lat = lat *Math.PI/180.0;
110
+ # double DailyToSol = 0.0864 * DToSol;
111
+ # double Declin = 0.41 *Math.cos( 2 * Math.PI * ( dayOfYear -172. ) / 365. );
112
+ # double Sunrise_Angle = Math.acos( -1*Math.tan(Declin) * Math.tan(rad_lat));
113
+ # double Sunrise_Hour = 12 - ( 12 / Math.PI ) * Sunrise_Angle;
114
+ # double Day_Hours = 24 - 2 * Sunrise_Hour;
115
+
116
+ # double AvEIR = SOLCON * ( 1 + 0.035 * Math.cos( 2 * Math.PI * dayOfYear / 365. ) );
117
+ # double ToEIR = ( 0.0864 / Math.PI ) * AvEIR *
118
+ # ( Sunrise_Angle * Math.sin( Declin ) * Math.sin( rad_lat )
119
+ # + Math.cos( Declin ) * Math.cos( rad_lat ) * Math.sin( Sunrise_Angle ) );
120
+ # /* MJ/SQM/DY */
121
+ #
122
+ # double ToClr = ToEIR * (-.7 + 0.86*Day_Hours) / Day_Hours ;
123
+ #
124
+ # double T = ( DMxTAir + DMnTAir ) / 2;
125
+ # double LWU = SFCEMISS * STEFAN * Math.pow( 273.15+T,4 ); /*LONG WAVE RAD
126
+ # EMITTED OUT */
127
+ # double Sfactor = 0.398 + 0.0171 * T - 0.000142 * T * T;
128
+ #
129
+ # double Angstrom = 1 - SkyEmiss / SFCEMISS;
130
+ #
131
+ # double ClrRatio;
132
+ # if (DailyToSol <= ToClr) { /*CLRRATIO = PCTCLR, < 100%
133
+ # 100 added to relieve problem */
134
+ # ClrRatio = DailyToSol / ToClr;
135
+ # }
136
+ # else {
137
+ # ClrRatio = 1.0;
138
+ # }
139
+ #
140
+ # double LWnet = Angstrom * LWU * ClrRatio;
141
+ # double LWD = LWU - LWnet;
142
+ # double Rnet1 = ( 1-ALBEDO ) * DailyToSol - LWnet; /* ;(RESULTANT ET)=MJ/M2/DY
143
+ # ;(RESULTANT ET)=REFN ET IN/DY */
144
+ # double RET1 = 1.28 * Sfactor * Rnet1;
145
+ # DRefET = RET1 / 62.3;
146
+ # DClrRatio = ClrRatio*100;
147
+
148
+ end # module ET
149
+ end # AgwxBiophys
@@ -0,0 +1,3 @@
1
+ module AgwxBiophys
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,6 @@
1
+ require "agwx_biophys/version"
2
+ require "agwx_biophys/et"
3
+
4
+
5
+ module AgwxBiophys
6
+ end
@@ -0,0 +1,117 @@
1
+ public class Et_testing {
2
+
3
+ static final double SOLCON = 1367.0;
4
+ static final double STEFAN = (0.0864*0.0000000567);
5
+ static final double SFCEMISS = 0.96;
6
+ static final double ALBEDO = 0.25;
7
+
8
+ double DRefET, DClrRatio;
9
+
10
+ public Et_testing() {
11
+ DRefET = -1.0;
12
+ DClrRatio = -1.0;
13
+ }
14
+ public Et_testing(double DToSol, int dayOfYear, double DMnTAir, double DMxTAir,
15
+ double DAvVPre, double DAvTAir, double lat) {
16
+ this();
17
+ if (lat < 1.0 || lat > 90.0) /* Dont use this in Indonesia!!! */
18
+ return;
19
+ // wha***k?
20
+ /*
21
+ if ( ( dayOfYear >= 91 ) && ( dayOfYear <= 273 ) )
22
+ return;
23
+ */
24
+
25
+ double rad_lat = lat *Math.PI/180.0;
26
+ double DailyToSol = 0.0864 * DToSol;
27
+ double Declin = 0.41 *Math.cos( 2 * Math.PI * ( dayOfYear -172. ) / 365. );
28
+
29
+ /*-----
30
+ * The Old sunrise angle was given by
31
+ * Sunrise_Angle=acos(tan(Declin)*tan(rad_lat);formula used for ET days
32
+ * + 0.0145/(cos(Declin)*cos(rad_lat))) ;other than months ?? (4-9)
33
+ */
34
+
35
+ double Sunrise_Angle = Math.acos( -1*Math.tan(Declin) * Math.tan(rad_lat));
36
+ double Sunrise_Hour = 12 - ( 12 / Math.PI ) * Sunrise_Angle;
37
+ double Day_Hours = 24 - 2 * Sunrise_Hour;
38
+ double AvEIR = SOLCON * ( 1 + 0.035 * Math.cos( 2 * Math.PI * dayOfYear / 365. ) );
39
+ double ToEIR = ( 0.0864 / Math.PI ) * AvEIR *
40
+ ( Sunrise_Angle * Math.sin( Declin ) * Math.sin( rad_lat )
41
+ + Math.cos( Declin ) * Math.cos( rad_lat ) * Math.sin( Sunrise_Angle ) );
42
+ /* MJ/SQM/DY */
43
+
44
+ double ToClr = ToEIR * (-.7 + 0.86*Day_Hours) / Day_Hours ;
45
+
46
+ double T = ( DMxTAir + DMnTAir ) / 2;
47
+ double LWU = SFCEMISS * STEFAN * Math.pow( 273.15+T,4 ); /*LONG WAVE RAD
48
+ EMITTED OUT */
49
+ double Sfactor = 0.398 + 0.0171 * T - 0.000142 * T * T;
50
+ /*-------
51
+ * Old Sky Emiss equation
52
+ * SkyEmiss = ( 1 - 0.261 * Exp ( -0.000777 * T * T ) )
53
+ */ double SkyEmiss;
54
+ if ( DAvVPre > 0.5) {
55
+ SkyEmiss = 0.7 + (5.95e-4)*DAvVPre*
56
+ Math.exp(1500/(273+DAvTAir));
57
+ }
58
+ else {
59
+ SkyEmiss = (1-0.261*Math.exp(-0.000777*T*T));
60
+ }
61
+ double Angstrom = 1 - SkyEmiss / SFCEMISS;
62
+
63
+ double ClrRatio;
64
+ if (DailyToSol <= ToClr) { /*CLRRATIO = PCTCLR, < 100%
65
+ 100 added to relieve problem */
66
+ ClrRatio = DailyToSol / ToClr;
67
+ }
68
+ else {
69
+ ClrRatio = 1.0;
70
+ }
71
+
72
+ double LWnet = Angstrom * LWU * ClrRatio;
73
+ double LWD = LWU - LWnet;
74
+ double Rnet1 = ( 1-ALBEDO ) * DailyToSol - LWnet; /* ;(RESULTANT ET)=MJ/M2/DY
75
+ ;(RESULTANT ET)=REFN ET IN/DY */
76
+ double RET1 = 1.28 * Sfactor * Rnet1;
77
+ System.out.print("ToEIR: "); System.out.println(ToEIR);
78
+ System.out.print("AvEIR: "); System.out.println(AvEIR);
79
+ System.out.print("SkyEmiss: "); System.out.println(SkyEmiss);
80
+ System.out.print("LWnet: "); System.out.println(LWnet);
81
+ System.out.print("Angstrom: "); System.out.println(Angstrom);
82
+ System.out.print("LWU: "); System.out.println(LWU);
83
+ System.out.print("ClrRatio: "); System.out.println(ClrRatio);
84
+ System.out.print("LWD: "); System.out.println(LWD);
85
+ System.out.print("Rnet1: "); System.out.println(Rnet1);
86
+ System.out.print("RET1: "); System.out.println(RET1);
87
+ DRefET = RET1 / 62.3;
88
+ DClrRatio = ClrRatio*100;
89
+ } // ET ctor
90
+
91
+ public double getET() {
92
+ return DRefET;
93
+ }
94
+ public double getPctClr() {
95
+ return DClrRatio;
96
+ }
97
+
98
+ public static void main(String[] args) {
99
+ // public Et_testing(double DToSol, int dayOfYear, double DMnTAir, double DMxTAir,
100
+ // double DAvVPre, double DAvTAir, float lat) {
101
+ Et_testing eT = new Et_testing(336.0,172,16.0,24.0,1.0,(16.0+24.0)/2.0,45.0);
102
+ System.out.println(eT.getET());
103
+ System.out.println();
104
+ System.out.println();
105
+ System.out.println();
106
+ // double[] et_obs1 = {244.40,10.80,24.88,1.49,152,44.12,0.18,63.05};
107
+ eT = new Et_testing(285.40,153,5.23,15.91,0.86,10.60,44.12);
108
+ System.out.println(eT.getET());
109
+ System.out.println(eT.getET() - 0.18);
110
+ double[] et_obs2 = {285.40,5.23,15.91,0.86,153,44.12,0.17,73.49};
111
+ double[] et_obs3 = {319.60,3.63,21.95,0.92,154,44.12,0.20,82.15};
112
+ double[] et_obs4 = {45.76,9.95,13.56,1.25,155,44.12,0.03,11.74};
113
+
114
+ eT.invokedStandalone = true;
115
+ }
116
+ private boolean invokedStandalone = false;
117
+ }
Binary file
data/test/test_et.rb ADDED
@@ -0,0 +1,232 @@
1
+ require 'test/unit'
2
+ require 'agwx_biophys'
3
+
4
+ class TestET < Test::Unit::TestCase
5
+ include AgwxBiophys::ET
6
+ def test_rad_lat
7
+ [
8
+ [0,0],
9
+ [30,0.5235983333],
10
+ [45,0.7853975],
11
+ [60,1.0471966667],
12
+ [90,1.570795],
13
+ [180,3.14159]
14
+ ].each do |lat,radians|
15
+ assert_in_delta(radians, rad_lat(lat), 0.00001)
16
+ end
17
+ assert_equal(0, rad_lat(0.0))
18
+ assert_equal(Math::PI, rad_lat(180.0))
19
+ assert_equal(Math::PI/2.0, rad_lat(90.0))
20
+ end
21
+
22
+ def test_daily_to_sol
23
+ assert_equal(0.0864, daily_to_sol(1.0))
24
+ end
25
+
26
+ def test_declin
27
+ [
28
+ [1,-0.4019921553],
29
+ [150,0.3809480272],
30
+ [172,0.41],
31
+ [200,0.3632890322],
32
+ [250,0.092707884]
33
+ ].each do |doy,declination|
34
+ assert_in_delta(declination, declin(doy), 2 ** -20)
35
+ end
36
+ end
37
+
38
+ def test_sunrise_angle
39
+ [
40
+ [1,0,1.5707963268],
41
+ [150,30,1.8041439502],
42
+ [172,45,2.020424427],
43
+ [200,60,2.2895663737],
44
+ [1,60,0.7431090864],
45
+ [150,45,1.9828717405],
46
+ [172,30,1.8244415261],
47
+ [200,0,1.5707963268]
48
+
49
+ ].each do |doy,latitude,sun_angle|
50
+ assert_in_delta(sun_angle, sunrise_angle(doy,latitude), 0.00001)
51
+ end
52
+ end
53
+
54
+ def test_sunrise_hour
55
+ [
56
+ [1,0,5.999994932],
57
+ [150,30,5.1086719137],
58
+ [172,45,4.2825406486],
59
+ [200,60,3.254493271]
60
+ ].each do |doy,latitude,sun_hour|
61
+ assert_in_delta(sun_hour, sunrise_hour(doy,latitude), 0.00001)
62
+ end
63
+ end
64
+
65
+ def test_day_hours
66
+ [
67
+ [1,0,12.0],
68
+ [150,30,13.7826561727],
69
+ [172,45,15.4349187028],
70
+ [200,60,17.491013458]
71
+ ].each do |doy,latitude,day_hrs|
72
+ assert_in_delta(day_hrs, day_hours(doy,latitude), 0.00002)
73
+ end
74
+ end
75
+ def test_av_eir
76
+ [
77
+ [1,1414.8379112589],
78
+ [150,1326.4494599268],
79
+ [172,1319.9344503498],
80
+ [200,1321.3095743309]
81
+ ].each do |doy,aveir|
82
+ assert_in_delta(aveir, av_eir(doy), 0.00006)
83
+ end
84
+ end
85
+
86
+ def test_to_eir
87
+ [
88
+ [1,0,35.8090258247],
89
+ [150,30,40.7680366801],
90
+ [172,45,41.8737911],
91
+ [200,60,38.3861488725]
92
+ ].each do |doy,latitude,total_eir|
93
+ assert_in_delta(total_eir, to_eir(doy,latitude), 0.00005)
94
+ end
95
+ end
96
+
97
+ def test_to_clr
98
+ [
99
+ [1,0,28.7069041338],
100
+ [150,30,32.9899653948],
101
+ [172,45,34.1124418882],
102
+ [200,60,31.4758531933]
103
+ ].each { |doy,lat,clr| assert_in_delta(clr, to_clr(doy,lat), 0.0003) }
104
+ end
105
+
106
+ def test_lwu
107
+ [
108
+ [5,15,30.2297320891],
109
+ [16,24,34.73182695],
110
+ [18,27,35.9318491504],
111
+ [16,24,34.7318269495]
112
+ ].each do |min,max,exp_lwu|
113
+ assert_in_delta(exp_lwu, lwu(min,max), 0.000001)
114
+ end
115
+ end
116
+
117
+ def test_sfactor
118
+ [
119
+ [5,15,0.5548],
120
+ [16,24,0.6832],
121
+ [18,27,0.7108625]
122
+ ].each do |min,max,exp_sfactor|
123
+ assert_in_delta(exp_sfactor, sfactor(min,max), 2 ** -20)
124
+ end
125
+ end
126
+
127
+ def test_exponentiation
128
+ assert_in_delta(2.71828182845904, Math.exp(1), 2 ** -20)
129
+ assert_in_delta(148.4131591026, Math.exp(5), 2 ** -20)
130
+ [
131
+ [5 ,15,10 ,283.0, 0.9252419575,200.4076128756],
132
+ [16,24,20 ,293.0, 0.7328604333,167.2440168899],
133
+ [18,27,22.5,295.5, 0.6747883114,160.1550057145]
134
+ ].each do |min,max,avg,avg_kelvin,lo,hi|
135
+ avg_temp = (min+max) / 2.0
136
+ assert_in_delta(avg, avg_temp, 2 ** -20)
137
+ assert_in_delta(avg_temp + 273.0, avg_kelvin, 2 ** -20)
138
+ avg_kelvin = avg_temp + 273
139
+ lo_exp = Math.exp(-0.000777*avg_temp*avg_temp)
140
+ hi_exp = Math.exp( 1500.0/(273.0+avg_temp))
141
+ assert_in_delta(hi, hi_exp, 2 ** -20)
142
+ assert_in_delta(lo, lo_exp, 2 ** -20)
143
+ end
144
+ end
145
+
146
+ def test_sky_emiss
147
+ [
148
+ [0.1,5,15 ,0.7585118491],
149
+ [0.2,16,24 ,0.8087234269],
150
+ [0.499,18,27 ,0.8238802507],
151
+ [0.51,5,15 ,0.7608136901],
152
+ [1,16,24 ,0.79951019],
153
+ [2,18,27 ,0.8905844568],
154
+ [1.0,16.0,24.0,0.79951019]
155
+ ].each do |vp,min,max,sky|
156
+ assert_in_delta(sky, sky_emiss(vp,min,max,(min+max)/2.0), 0.000001,"Out of range for vp #{vp} min #{min} max #{max}")
157
+ end
158
+ end
159
+
160
+ def test_angstrom
161
+ [
162
+ [0.1,5,15 ,0.2098834905],
163
+ [0.2,16,24 ,0.1575797636],
164
+ [0.499,18,27 ,0.1417914055],
165
+ [0.51,5,15 ,0.2074857395],
166
+ [1,16,24 ,0.1671768854],
167
+ [2,18,27 ,0.0723078575],
168
+ [1.0,16.0,24.0,0.16718]
169
+ ].each { |vp,min,max,angs| assert_in_delta(angs, angstrom(vp,min,max,(min+max)/2.0), 0.000004) }
170
+
171
+ end
172
+ def test_clr_ratio
173
+ [
174
+ [62,1,0,0.186603194],
175
+ [142,150,30,0.3718949036],
176
+ [336,172,45,0.8510208708],
177
+ [62,200,60,0.1701876028]
178
+ ].each { |dAvSol,doy,lat,clr_ratio| assert_in_delta(clr_ratio, clr_ratio(dAvSol,doy,lat), 2 ** -20) }
179
+ end
180
+
181
+ def test_lwnet
182
+ [
183
+ [0.1,5,15,142,150,30 ,2.35957],
184
+ [0.2,16,24,336,172,45 ,4.65767],
185
+ [0.499,18,27,62,200,60 ,0.86708],
186
+ [1.0,16.0,24.0,336.0,172,45.0,4.94133]
187
+ ].each do |vp,min,max,sol,doy,lat,lwnet|
188
+ assert_in_delta(lwnet, lwnet(vp,min,max,(min+max)/2.0,sol,doy,lat), 0.000025,"lwnet for #{vp}")
189
+ end
190
+ end
191
+
192
+ def test_ets_with_obs
193
+ # DAvSol,DMnTAir,DMxTAir,DAvTAir,DAvVPre,theDate,latitude,DRefET,DPctClr
194
+
195
+ et_obs = [
196
+ [336.0,16.0,24.0,20.0,1.0,'2013-06-21',45.0,0.24,85.10],
197
+ [244.40,10.80,24.88,18.32,1.49,'2013-06-01',44.12,0.18,63.05],
198
+ [285.40,5.23,15.91,10.60,0.86,'2013-06-02',44.12,0.17,73.49],
199
+ [319.60,3.63,21.95,13.82,0.92,'2013-06-03',44.12,0.20,82.15],
200
+ [45.76,9.95,13.56,11.41,1.25,'2013-06-04',44.12,0.03,11.74],
201
+ [97.60,9.88,15.20,11.28,1.27,'2013-06-05',44.12,0.07,25.01],
202
+ [62.95,9.55,13.01,11.00,1.26,'2013-06-06',44.12,0.04,16.10],
203
+ [176.90,8.48,19.95,13.43,1.28,'2013-06-07',44.12,0.12,45.20],
204
+ [131.80,9.21,19.31,14.57,1.35,'2013-06-08',44.12,0.09,33.63],
205
+ [158.40,11.08,23.55,17.22,1.51,'2013-06-09',44.12,0.12,40.37],
206
+ [234.00,14.20,26.73,20.02,1.78,'2013-06-10',44.12,0.19,59.58],
207
+ [220.00,12.74,26.06,20.13,1.84,'2013-06-11',44.12,0.18,55.96],
208
+ [142.00,13.74,25.72,18.78,1.86,'2013-06-12',44.12,0.12,36.09],
209
+ [329.10,13.61,24.73,19.16,1.46,'2013-06-13',44.12,0.25,83.57],
210
+ [336.40,11.01,24.85,18.69,1.34,'2013-06-14',44.12,0.24,85.37],
211
+ [190.20,14.12,26.06,18.89,1.93,'2013-06-15',44.12,0.16,48.24],
212
+ [349.00,13.27,27.64,20.92,1.52,'2013-06-16',44.12,0.27,88.48],
213
+ [297.40,13.74,27.97,20.09,1.55,'2013-06-17',44.12,0.23,75.37],
214
+ [345.90,9.55,22.27,15.83,1.14,'2013-06-18',44.12,0.24,87.64],
215
+ [348.00,6.63,25.58,17.61,1.24,'2013-06-19',44.12,0.24,88.16],
216
+ [331.50,14.34,29.81,22.59,1.52,'2013-06-20',44.12,0.26,83.98],
217
+ [130.30,16.84,25.53,20.66,2.06,'2013-06-21',44.12,0.11,33.01],
218
+ [134.30,18.37,25.59,20.98,2.23,'2013-06-22',44.12,0.12,34.03],
219
+ [297.30,17.58,29.69,23.44,2.24,'2013-06-23',44.12,0.26,75.35],
220
+ [198.10,19.17,28.10,22.58,2.27,'2013-06-24',44.12,0.18,50.23],
221
+ [195.10,17.85,25.98,21.67,2.30,'2013-06-25',44.12,0.17,49.49],
222
+ [235.70,20.29,28.08,23.26,2.37,'2013-06-26',44.12,0.22,59.82],
223
+ ].each { |arr| arr[5] = Date.parse(arr[5]).yday }
224
+
225
+ et_obs.each do |sol,min,max,avg,vapr,yday,lat,et,pct|
226
+ # max_temp,min_temp,avg_v_press,d_to_sol,doy,lat
227
+ ref_et,pct_clr = et(max,min,avg,vapr,sol,yday,lat)
228
+ assert_in_delta(et, ref_et.round(2), 0.00001,"ET bludgered for #{Date.civil(2013,1,1)+yday-1}")
229
+ assert_in_delta(pct, pct_clr.round(2), 0.00001,"PctClr bludgered for #{Date.civil(2013,1,1)+yday-1}")
230
+ end
231
+ end
232
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: agwx_biophys
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - RickWayne
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Biophysical calculators primarily useful in agriculture and land management
42
+ email:
43
+ - fewayne@wisc.edu
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - agwx_biophys.gemspec
54
+ - lib/agwx_biophys.rb
55
+ - lib/agwx_biophys/et.rb
56
+ - lib/agwx_biophys/version.rb
57
+ - test/Et_testing.java
58
+ - test/TestValues.xls
59
+ - test/test_et.rb
60
+ homepage: ''
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.0.6
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: So far, just an ET calculator (Priestly-Taylor)
84
+ test_files:
85
+ - test/Et_testing.java
86
+ - test/TestValues.xls
87
+ - test/test_et.rb