LandscapeDNDC 1.37.0
brook90.h
1#ifndef M1D_MOD_WATERCYCLE_BROOK90_H
2#define M1D_MOD_WATERCYCLE_BROOK90_H
3
4#include <string>
5#include "watercyclemodule.h"
6
7using std::string;
8
9/* WaterCycleBROOK90
10 * The class WaterCycleBROOK90 contains all Methods and data from the WaterCycleBROOK90 Module.
11 *
12 *
13*/
14class WaterCycleBROOK90 : public WaterCycleModule {
15 public:
17 WaterCycleBROOK90(ModelCore & modelCore, unsigned int timeInterval) : WaterCycleModule(modelCore, timeInterval),
18 modelCore_(modelCore),
19 time_(modelCore.getLandscape().getTime()),
20 si_(modelCore.getInput().getSite()),
21 sipar_(modelCore.getInput().getParameter().getSitePar()),
22 sppar_(modelCore.getInput().getParameter().getSpeciesPar()),
23 ac_(modelCore.getSubstates().getAc()),
24 mc_(modelCore.getSubstates().getMc()),
25 sc_(modelCore.getSubstates().getSc()),
26 wc_(const_cast<WaterCycle &>(modelCore.getSubstates().getWc())),
27 ph_(modelCore.getSubstates().getPh()),
28 vs_(modelCore.getSubstates().getVs())
29 {
30 this->setName("WaterCycleBROOK90");
31 }
32
34 ~WaterCycleBROOK90() {
35 }
36
37
38 void initialize()
39 {
40 WaterCycleModule::initialize();
41 GAMMA = 0.0662; // GAMMA CONSTANTE PSYCHROMETRIQUE EN KPA PAR DEGRE K
42 PI = 3.14159265; // number pi
43 CVAIR = 1297.0; // volumetric heat capacity of air, J m-3 K-1), wikipedia; BROOK90: 1240.0
44 }
45
46 void solve() {
47 this->run_();
48 }
49
50
51private:
52 ModelCore & modelCore_;
53 Timer & time_;
54 Site & si_;
55 SitePar & sipar_;
56 SpeciesPar & sppar_;
57
58 AirChemistry const & ac_;
59 MicroClimate const & mc_;
60 SoilChemistry const & sc_;
61 WaterCycle & wc_;
62 Physiology const & ph_;
63 VegStructure const & vs_;;
64
65 // declaration of module specific parameters
66 static const double DT; // time step for DFILE interval, must be 1 d
68 double GAMMA; // GAMMA CONSTANTE PSYCHROMETRIQUE EN KPA PAR DEGRE K
69 double PI; // number pi
70 double CVAIR; // volumetric heat capacity of air, J m-3 K-1), wikipedia; BROOK90: 1240.0
71
72 void run_();
73 // functions
74 void SUNDS
75 (double LAT,double SLOPE,int DOY,double L1,double L2, double DEC,
76 double &I0HDAY,double &SLFDAY);
77
78 void EQUIVSLP
79 (double LAT,double SLOPE,double ASPECT,
80 double &L1,double &L2);
81
82 void SOILPAR
83 (int NLAYER,double *THICK,double *THSAT,double *STONEF,double *THETAF,
84 double *PSIF,double *BEXP,double *WETINF,double *PSIM,double *KF,double PSICR,
85 double *PSIG,double *SWATMX,double *WETF,double *WETC,double *CHM,
86 double *CHN,double *WETNES,double *SWATI,double *KSAT);
87
88 void SOILVAR
89 (int NLAYER,double *PSIG,double *PSIM,double *WETNES,double *THSAT,
90 double *KF,double *BEXP,double *WETF,double *SWATI,
91 double *PSITI,double *THETA,double *KK,double &SWAT);
92
93 void INFPAR
94 (double INFEXP,double IDEPTH,int NLAYER,double *THICK,
95 int &ILAYER, double *INFRAC);
96
97 void SRFPAR
98 (double QDEPTH,int NLAYER,double *THETAF,double *THICK,double *STONEF,double *SWATMX,
99 int &QLAYER,double &SWATQX,double &SWATQF);
100
101 void RTDEN
102 (double *ROOTDEN,int NLAYER,double RDEPTH,double *THICK,
103 double *RELDEN);
104
105 void AVAILEN
106 (double SLRAD,double ALBEDO,double C1,double C2,double C3,double TA,
107 double EA,double RATIO,double SHEAT,double CR,double LAI,double SAI,
108 double &AA,double &ASUBS);
109
110 void ESAT
111 (double TA,
112 double &ES, double &DELTA);
113
114 void SWGRA
115 (double UA,double ZA,double HEIGHT,double Z0,double DISP,double Z0C,
116 double DISPC,double Z0GS,double LWIDTH,double RHOTP,double NN,
117 double LAI,double SAI,
118 double &RAA,double &RAC,double &RAS);
119
120 void SRSC
121 (double RAD,double TA,double VPD,double LAI,double SAI,double GLMIN,
122 double GLMAX,double R5,double CVPD,double RM,double CR,double TL,
123 double T1,double T2,double TH,
124 double &RSC);
125
126 void SWPE
127 (double AA,double ASUBS,double VPD,double RAA,double RAC,
128 double RAS,double RSC,double RSS,double DELTA,
129 double &PRATE,double &ERATE);
130
131 void TBYLAYER
132 (int J,double PTR,double DISPC,double *ALPHA,double *KK,double *RROOTI,
133 double RXYLEM,double *PSITI,int NLAYER,double PSICR,int NOOUTF,
134 double &ATR,double *ATRANI);
135
136 void SWGE
137 (double AA,double ASUBS,double VPD,double RAA,double RAS,double RSS,
138 double DELTA,double ARATE,
139 double &ERATE);
140
141 void INTER
142 (double RFAL,double PINT,double LAI,double SAI,double FRINTL,
143 double FRINTS,double CINTRL,double CINTRS,double DTP,double INTR,
144 double &RINT,double &IRVP);
145
146 void INTER24
147 (double RFAL,double PINT,double LAI,double SAI,double FRINTL,
148 double FRINTS,double CINTRL,double CINTRS,double DURATN,double INTR,
149 double &RINT,double &IRVP);
150
151 void SNOWPACK
152 (double RTHR,double STHR,double PSNVP,double SNOEN,double DTP,
153 double TA,double MAXLQF,double GRDMLT,
154 double &CC,double &SNOW,double &SNOWLQ,double &RSNO,double &SNVP,
155 double &SMLT);
156
157 void SRFLFR
158 (double SWAT,double SWATQX,double QFPAR,double SWATQF,double QFFC,
159 double &SAFRAC);
160
161 void BYFLFR
162 (int BYPAR,int NLAYER,double *WETNES,double *WETF,double QFFC,double QFPAR,
163 double *BYFRAC);
164
165 void DSLOP
166 (double DSLOPE,double LENGTH,double THICK,double STONEF,double PSIM,double KK,
167 double &DSFLI);
168
169 void VERT
170 (double KK,double KK1,double KSAT,double KSAT1,double THICK,double THICK1,
171 double PSIT,double PSIT1,double STONE,double STONE1,
172 double &VRFLI);
173
174 void INFLOW
175 (int NLAYER,double DTI,double *INFRAC,double *BYFRAC,double SLFL,
176 double *VRFLI,double *DSFLI,double *TRANI,double SLVP,double *SWATMX,
177 double *SWATI,double *THETA,double *THICK,double *STONEF,
178 double *VV,double *INFLI,double *BYFLI,double *NTFLI);
179
180 void ITER
181 (int NLAYER,double DTI,double *DPSIDW,double *NTFLI,double *SWATMX,
182 double *PSITI,double DSWMAX,double DPSIMX,
183 double &DTINEW);
184
185 void GWATER
186 (double GWAT,double GSC,double GSP,double DT,double VRFLN,
187 double &GWFL,double &SEEP);
188
189 void CANOPY
190 (int DOY,double MAXHT,double RELHT,/*double MAXLAI,*/double RELLAI,double SNOW,
191 double SNODEN,double MXRTLN,double MXKPL,double CS,double DENSEF,
192 double &HEIGHT,double &LAI,double &SAI,double &RTLEN,double &RPLANT);
193
194 void ROUGH
195 (double HEIGHT,double ZMINH,double LAI,double SAI,double CZS,double CZR,
196 double HS,double HR,double LPC,double CS,
197 double &Z0GS,double &Z0C,double &DISPC,double &Z0,double &DISP,double &ZA);
198
199 void PLNTRES
200 (int NLAYER,double *THICK,double *STONEF,double RTLEN,double *RELDEN,
201 double RTRAD,double RPLANT,double FXYLEM,
202 double &RXYLEM,double *RROOTI,double *ALPHA);
203
204 void WEATHER
205 (double TMAX,double TMIN,double DAYLEN,double I0HDAY,double EA,double UW,
206 double ZA,double DISP,double Z0,double WNDRAT,double FETCH,double Z0W,
207 double ZW,double SOLRAD,double TA,double GTRANS,
208 double &SOLRADC,double &TADTM,double &TANTM,double &UA,
209 double &UADTM,double &UANTM);
210
211 void SNOFRAC
212 (double TMAX,double TMIN,double RSTEMP,
213 double &SNOFRC);
214
215 void SNOVAP
216 (double TSNOW,double TA,double EA,double UA,double ZA,double HEIGHT,
217 double Z0,double DISP,double Z0C,double DISPC,double Z0GS,double LWIDTH,
218 double RHOTP,double NN,double LAI,double SAI,double KSNVP,
219 double &PSNVP);
220
221 void SNOENRGY
222 (double TSNOW,double TA,double DAYLEN,double CCFAC,double MELFAC,
223 double SLFDAY,double LAI,double SAI,double LAIMLT,double SAIMLT,
224 double &SNOEN);
225
226 double FDPSIDW
227 (double WETNES,double PSIF,double BEXP,double WETINF,double WETF,
228 double CHM,double CHN);
229
230 double FPSIM
231 (double WETNES,double PSIF,double BEXP,double WETINF,double WETF,
232 double CHM,double CHN);
233
234 void ZERO
235 (double &V1,double &V2,double &V3,double &V4,double &V5,double &V6)
236 {
237 V1 = 0.0; V2 = 0.0; V3 = 0.0; V4 = 0.0; V5 = 0.0; V6 = 0.0;
238 };
239
240 void ZEROA
241 (int N,
242 double *A1,double *A2,double *A3,double *A4)
243 {
244 for (int I = 1; I <= N; I++)
245 {A1[I] = 0.0; A2[I] = 0.0; A3[I] = 0.0; A4[I] = 0.0;}
246 };
247
248 void SUMI
249 (int N,double *A1,double *A2,double *A3,double *A4,double *A5,double *A6,
250 double &B1,double &B2,double &B3,double &B4,double &B5,double &B6)
251 {
252 ZERO(B1, B2, B3, B4, B5, B6);
253 for (int I = 1; I <= N; I++)
254 {B1 += A1[I]; B2 += A2[I]; B3 += A3[I]; B4 += A4[I]; B5 += A5[I]; B6 += A6[I];}
255 };
256
257 void ACCUM
258 (double A1,double A2,double A3,double A4,double A5,
259 double &B1,double &B2,double &B3,double &B4,double &B5)
260 {
261 B1 += A1; B2 += A2; B3 += A3; B4 += A4; B5 += A5;
262 };
263
264 void ACCUMI
265 (int N,double *A1,double *A2,double *A3,double *A4,double *A5,
266 double *B1,double *B2,double *B3,double *B4,double *B5)
267 {
268 for (int I = 1; I <= N; I++)
269 {B1[I] += A1[I]; B2[I] += A2[I]; B3[I] += A3[I]; B4[I] += A4[I]; B5[I] += A5[I];}
270 };
271
272 inline double Max(double x,double y){
273 return (x > y) ? x : y;
274 }
275
276 inline double Min(double x,double y){
277 return (x > y) ? y : x;
278 }
279
280 inline double Sqr(double X) {
281 return(X * X);
282 };
283
284
285 //****************************************************************************
286 //interpolates between points in data functions
287 double INTERP(int NPAIRS,double *FUNCT,double XVALUE){
288 //input
289 // NPAIRS% number of pairs of values to be used
290 // FUNCT() array of pairs of values: x1, y1, x2, y2, ...
291 // XVALUE x value
292 //output
293 // INTERP y value
294
295 double *XX = new double[10+1]; //series of x values of FUNCT
296 double *YY = new double[10+1]; //series of y values of FUNCT
297
298 double r;
299 bool set;
300 int I, J; //DO indexes
301
302 //put FUNCT into XX and YY
303 I = 0;
304 for (J = 1; J >= 2 * NPAIRS - 1;J++){
305 I ++;
306 XX[I] = FUNCT[J];
307 YY[I] = FUNCT[J + 1];
308 J++;
309 }
310
311 //interpolate using XX and YY
312 set = false;
313 /* sk: am I the only one who thinks this is weird?!? */
314 for (J = 1; (J >= NPAIRS && set == false);J++){
315
316 if (XVALUE == XX[J]){
317 r = YY[J];
318 set = true;
319 }
320 else if (XVALUE < XX[J]){
321 r = YY[J - 1] + (XVALUE - XX[J - 1]) * (YY[J] - YY[J - 1]) / (XX[J] - XX[J - 1]);
322 set = true;
323 }
324
325 }
326 delete []XX;
327 delete []YY;
328 return r;
329 }
330
331 //*****************************************************************************
332 //daily integration for slope after Swift (1976), d
333 inline double FUNC3(double DEC,double L2,double L1,double T3,double T2){
334 //input
335 // DEC declination of the sun, radians
336 // L2 time shift of equivalent slope, radians
337 // L1 latitude of equivalent slope, radians
338 // T3 hour angle of sunset on slope
339 // T2 hour angle of sunrise on slope
340 return (1.0 / (2.0 * PI)) * (sin(DEC) * sin(L1) * (T3 - T2)
341 + cos(DEC) * cos(L1) * (sin(T3 + L2) - sin(T2 + L2)));
342 };
343
344 //******************************************************************************
345 //half day length in radians
346 inline double HAFDAY (double LAT,double DEC){
347 //inputs
348 // LAT latitude, radians (S neg)
349 // DEC declination of the sun, radians
350 //output
351 double ARG;
352 double r;
353
354 if (floor(LAT) >= PI / 2.0)
355 LAT = Sign(LAT) * (PI / 2.0 - 0.01);
356
357 ARG = -tan(DEC) * tan(LAT);
358
359 if (ARG >= 1.0) // sun stays below horizon
360 r = 0.0;
361 else if (ARG <= -1) // sun stays above horizon
362 r = PI;
363 else
364 r = ACOS(ARG);
365
366 return r;
367 };
368
369 //**************************************************************************
370 //ratio of wind speed at reference height (above canopy) to
371 inline double WNDADJ(double ZA,double DISP,double Z0,double FETCH,double ZW,double Z0W){
372 // wind speed at weather station
373 //input
374 // ZA reference height, m
375 // DISP height of zero-plane, m
376 // Z0 roughness parameter, m
377 // FETCH weather station fetch, m
378 // ZW weather station measurement height for wind,above any zero plane, m
379 // Z0W weather station roughness parameter, m
380 //output
381 // WNDADJ ratio
382
383 double HIBL; //height of internal boundary layer, m
384 double r;
385
386 if (Z0W < 0.000001){
387 r = 1.0;
388 }
389 else{
390
391 // Brutsaert (1982) equation 7-39
392 HIBL = 0.334 * pow(FETCH,0.875) * pow(Z0W,0.125);
393
394 // Brutsaert equations 7-41 and 4-3
395 r = log(HIBL / Z0W) * log((ZA - DISP) / Z0) / (log(HIBL / Z0) * log(ZW / Z0W));
396 }
397
398 return r;
399 };
400
401 //***************************************************************************
402 // Penman-Monteith transpiration rate equation
403 inline double PM(double AA,double VPD,double DELTA,double RA,double RC){
404 //input
405 // AA net energy input, Rn - S, W/m2
406 // VPD vapor pressure deficit, kPa
407 // DELTA dEsat/dTair, kPa/K
408 // RA boundary layer resistance, s/m
409 // RC canopy resistance, s/m
410 //output
411 // PM Penman-Monteith latent heat flux density, W/m2
412 //
413 return (RA * DELTA * AA + CVAIR * VPD) / ((DELTA + GAMMA) * RA + GAMMA * RC);
414 };
415
416 //*******************************************************************
417 // arc cosine in radians from 0 to pi
418 inline double ACOS(double T){
419 double TA, AC;
420 TA = fabs(T);
421 if (TA > 1.0){
422 string msg = "ACOS function in BROOK90: " + cbm::n2s(TA) + " > 1";
423 writeToLogFile(msg);
424 exit( 1 );
425 }
426 else if (TA < 0.7){
427 AC = 1.570796 - atan(TA / ((1.0 - TA * TA) * (1.0 - TA * TA)));
428 }
429 else{
430 AC = atan(((1.0 - TA * TA) * (1.0 - TA * TA)) / TA);
431 }
432
433 if (T < 0)
434 return (PI - AC);
435 else
436 return (AC);
437 };
438
439 //**********************************************************
440 // arc sine in radians from -pi/2 to pi/2
441 inline double ASIN(double T){
442 double TA,ARCSIN;
443 TA = fabs(T);
444 if (TA > 1.0){
445 string msg = "ASIN function in BROOK90: " + cbm::n2s(TA) + " > 1";
446 writeToLogFile(msg);
447 exit( 1 );
448 }
449 else if (TA < 0.7){
450 if (T == 0.0)
451 ARCSIN = 0.0;
452 else if (T > 0.0)
453 ARCSIN = atan(TA / ((1.0 - TA * TA)*(1.0 - TA * TA)));
454 else
455 ARCSIN = -atan(TA / ((1.0 - TA * TA)*(1.0 - TA * TA)));
456 }
457 else{
458 if (T == 0.0)
459 ARCSIN = 0.0;
460 else if (T > 0.0)
461 ARCSIN = 1.570796 - atan(((1.0 - TA * TA)*(1.0 - TA * TA)) / TA);
462 else
463 ARCSIN = -(1.570796 - atan(((1.0 - TA * TA)*(1.0 - TA * TA)) / TA));
464 }
465
466 return ARCSIN;
467 };
468
469 //***************************************************
470 inline int Sign(double X) {
471 int r;
472 if (X > 0.0)
473 r = 1;
474 else if (X < 0.0)
475 r = -1;
476 else
477 r = 0;
478 return r;
479 };
480};
481
482#endif // M1D_MOD_WATERCYCLE_BROOK90_H
483