agwx_biophys 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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