infiltration.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include "global.h"
  2. /* The Green-and-Ampt Model */
  3. double get_f(double t, double R)
  4. {
  5. static double cumf = 0.0, f_ = 0.0;
  6. static char ponding = 0;
  7. double f, f1, f2, fc, R2, cnst, pt, psi_dtheta, sum;
  8. int factorial;
  9. int i, j;
  10. /* reset if there is no rainfall */
  11. if (R <= 0.0) {
  12. cumf = 0.0;
  13. f_ = 0.0;
  14. ponding = 0;
  15. return 0.0;
  16. }
  17. f1 = cnst = pt = 0.0;
  18. psi_dtheta = params.psi * params.dtheta;
  19. if (!ponding) {
  20. if (cumf) {
  21. f1 = cumf;
  22. R2 = -params.K0 / params.m *
  23. (psi_dtheta + f1) / (1 - exp(f1 / params.m));
  24. /* rainfall intensity is greater than infiltration
  25. * rate, so ponding starts */
  26. if (R2 < R) {
  27. f_ = cumf;
  28. pt = t - input.dt;
  29. ponding = 1;
  30. goto cont1;
  31. }
  32. }
  33. f2 = cumf + R * input.dt;
  34. R2 = -params.K0 / params.m *
  35. (psi_dtheta + f2) / (1 - exp(f2 / params.m));
  36. /* rainfall intensity is less than infiltration rate. all
  37. * rainfall will be infiltrated. */
  38. if (f2 == 0.0 || R2 > R) {
  39. f = R;
  40. cumf += f * input.dt;
  41. ponding = 0;
  42. return f;
  43. }
  44. /* rainfall intensity is greater than infiltration rate. */
  45. f_ = cumf + R2 * input.dt;
  46. for (i = 0; i < MAXITER; i++) {
  47. R2 = -params.K0 / params.m *
  48. (psi_dtheta + f_) / (1 - exp(f_ / params.m));
  49. if (R2 > R) {
  50. f1 = f_;
  51. f_ = (f_ + f2) / 2.0;
  52. f = f_ - f1;
  53. }
  54. else {
  55. f2 = f_;
  56. f_ = (f_ + f1) / 2.0;
  57. f = f_ - f2;
  58. }
  59. if (fabs(f) < TOLERANCE)
  60. break;
  61. }
  62. if (i == MAXITER) {
  63. Rast_set_d_null_value(&f, 1);
  64. return f;
  65. }
  66. pt = t - input.dt + (f_ - cumf) / R;
  67. if (pt > t) {
  68. f = R;
  69. cumf += f * input.dt;
  70. ponding = 0;
  71. return f;
  72. }
  73. cont1:
  74. cnst = 0.0;
  75. factorial = 1;
  76. fc = (f_ + psi_dtheta);
  77. for (j = 1; j <= NTERMS; j++) {
  78. factorial *= j;
  79. cnst += pow(fc / params.m, (double)j) / (double)(j * factorial);
  80. }
  81. cnst = log(fc) - (log(fc) + cnst) / exp(psi_dtheta / params.m);
  82. f_ += R * (t - pt) / 2.0;
  83. ponding = 1;
  84. }
  85. /* Newton-Raphson */
  86. for (i = 0; i < MAXITER; i++) {
  87. fc = f_ + psi_dtheta;
  88. sum = 0.0;
  89. factorial = 1;
  90. for (j = 1; j <= NTERMS; j++) {
  91. factorial *= j;
  92. sum += pow(fc / params.m, (double)j) / (double)(j * factorial);
  93. }
  94. f1 = -(log(fc) - (log(fc) + sum) /
  95. exp(psi_dtheta / params.m) - cnst) /
  96. (params.K0 / params.m) - (t - pt);
  97. f2 = (exp(f_ / params.m) - 1.0) / (fc * params.K0 / params.m);
  98. f = -f1 / f2;
  99. f_ += f;
  100. if (fabs(f) < TOLERANCE)
  101. break;
  102. }
  103. if (i == MAXITER) {
  104. Rast_set_d_null_value(&f, 1);
  105. return f;
  106. }
  107. if (f_ < cumf + R * input.dt) {
  108. f = (f_ - cumf) / input.dt;
  109. cumf = f_;
  110. /* initial guess for next time step */
  111. f_ += f * input.dt;
  112. }
  113. return f;
  114. }