-
Notifications
You must be signed in to change notification settings - Fork 0
/
arno_evap.c
203 lines (174 loc) · 7.9 KB
/
arno_evap.c
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
#include <stdio.h>
#include <stdlib.h>
#include <vicNl.h>
static char vcid[] = "$Id$";
/****************************************************************************
ARNO/ARNO Model of Evaporation
Routine to compute evaporation based on the assumption that
evaporation is at the potential for the area which is saturated,
and at some percentage of the potential for the area which is partial
saturated.
Evaporation from bare soil calculated only from uppermost layer.
Evaporation is in mm/(time step) --> usually 1 day or 1 hour
modifications:
6-8-2000 modified to make use of spatially distributed frost KAC
2-24-03 moved unit conversion of moist_resid outside of distributed
precipitation loop. Moist_resid was being multiplied by
D1 * 1000 twice for the dry fraction. KAC
04-Jun-04 Moved unit conversion of moist_resid back inside distributed
precipitation loop in such a way that it does not get multiplied
by D1 * 1000 twice. TJB
04-Jun-04 Changed logic of evap limit check to avoid creating spurious
condensation. Previously, when liquid moisture < residual
moisture, (liquid moisture - residual moisture) would be
negative. Any non-negative evap would be greater than this,
resulting in evap getting set to (liquid moisture - residual
moisture), which would be negative (i.e. condensation).
This artificially created condensation in whatever amount
necessary to bring liquid moisture up to residual, causing
1) large latent heat flux, 2) incorrect surface temperatures,
3) occasional inability for calc_surf_energy_bal to converge
in root_brent, and 4) spuriously high runoff and baseflow.
Now there is an added condition that liquid moisture > residual
moisture for evap to be capped at (liquid moisture - residual
moisture). In addition, the previous logic for capping evap
involved an incorrect calculation of the soil's ice content.
Since the new logic doesn't require calculation of ice content,
this calculation has been removed altogether. TJB
2007-Apr-06 Modified to handle grid cell errors by returning ERROR
status that can be trapped by calling routines. GCT/KAC
2009-Mar-16 Modified to use min_liq (minimum allowable liquid water
content) instead of resid_moist. For unfrozen soil,
min_liq = resid_moist. TJB
2009-Jun-09 Moved computation of canopy resistance rc out of penman()
and into separate function calc_rc(). TJB
2009-Nov-15 Changed D1 to depth1 to avoid confusion with the D1 used in
func_surf_energy_bal() (the parent function), which refers
to the depth of the 1st soil thermal node in some cases. TJB
2009-Dec-11 Removed min_liq and options.MIN_LIQ. TJB
2010-Apr-28 Removed net_short, displacement, roughness, and ref_height from
arg list as they are no longer used. TJB
2012-Jan-16 Removed LINK_DEBUG code BN
2014-Mar-28 Removed DIST_PRCP option. TJB
****************************************************************************/
double arno_evap(layer_data_struct *layer,
double rad,
double air_temp,
double vpd,
double depth1,
double max_moist,
double elevation,
double b_infilt,
double ra,
double delta_t,
double moist_resid,
double *frost_fract)
{
extern option_struct options;
int num_term;
int i;
int frost_area;
double tmp,beta_asp,dummy;
double ratio,as;
double Epot; /* potential bare soil evaporation */
double moist;
double evap;
double max_infil;
double Evap;
double tmpsum;
Evap = 0;
/* moist = liquid soil moisture */
moist = 0;
for ( frost_area = 0; frost_area < options.Nfrost; frost_area++ ) {
moist += (layer[0].moist - layer[0].ice[frost_area]) * frost_fract[frost_area];
}
if ( moist > max_moist ) moist = max_moist;
/* Calculate the potential bare soil evaporation (mm/time step) */
Epot = penman(air_temp, elevation, rad, vpd, ra, 0.0, 0.0) * delta_t / SEC_PER_DAY;
/**********************************************************************/
/* Compute temporary infiltration rate based on given soil_moist. */
/**********************************************************************/
max_infil = (1.0 + b_infilt) * max_moist;
if(b_infilt == -1.0)
tmp = max_infil;
else {
ratio = 1.0 - (moist) / (max_moist);
/*****if(ratio < SMALL && ratio > -SMALL) ratio = 0.;*****/
if(ratio > 1.0) {
printf("\n ERROR: SOIL RATIO GREATER THAN 1.0\n");
printf("moisture %f max_moisture %f -> ratio = %f\n", moist,max_moist,ratio);
return( ERROR );
}
else {
if(ratio < 0.0) {
printf("\n ERROR: SOIL RATIO LESS THAN 0.0\n");
printf("moisture %f max_moisture %f -> ratio = %e\n", moist,max_moist,ratio);
return( ERROR );
}
else
ratio = pow(ratio,(1.0 / (b_infilt + 1.0)));
}
tmp = max_infil*(1.0 - ratio);
}
/**********************************************************************/
/* Evaporate at potential rate, i.e., Eq.(10) in Liang's derivation. */
/**********************************************************************/
if(tmp >= max_infil)
evap = Epot;
else {
/********************************************************************/
/* Compute As. 'As' is % area saturated, '1-As' is % area */
/* that is unsaturated. */
/********************************************************************/
ratio = tmp/max_infil;
ratio = 1.0 - ratio;
if(ratio > 1.0) {
printf("\n ARNO ERROR: EVAP RATIO GREATER THAN 1.0");
return ( ERROR );
}
else {
if(ratio < 0.0) {
printf("\n ARNO ERROR: EVAP RATIO LESS THAN 0.0");
return( ERROR );
}
else {
if(ratio != 0.0)
ratio = pow(ratio,b_infilt);
}
}
as = 1 - ratio;
/********************************************************************/
/* Compute the beta function in the ARNO evaporation model using */
/* the first 30 terms in the power expansion expression. */
/********************************************************************/
ratio = pow(ratio,(1.0/b_infilt));
dummy = 1.0;
for(num_term=1;num_term<=30;num_term++) {
tmpsum = ratio;
for ( i = 1; i < num_term; i++ ) tmpsum *= ratio;
dummy += b_infilt * tmpsum / (b_infilt + num_term);
}
beta_asp = as+(1.0-as)*(1.0-ratio)*dummy;
evap = Epot*beta_asp;
}
/***********************************************************************/
/* Evaporation cannot exceed available soil moisture. */
/* Evaporation second soil layer = 0.0 */
/***********************************************************************/
/* only consider positive evaporation; we won't put limits on condensation */
if (evap > 0.0) {
if (moist > moist_resid * depth1 * 1000.) {
/* there is liquid moisture available; cap evap at available liquid moisture */
if (evap > moist - moist_resid * depth1 * 1000.) {
evap = moist - moist_resid * depth1 * 1000.;
}
}
else {
/* no moisture available; cap evap at 0 */
evap = 0.0;
}
}
layer[0].evap = evap;
Evap += evap / 1000. / delta_t;
return(Evap);
}