hydro.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. /****************************************************************************
  2. *
  3. * MODULE: simwe library
  4. * AUTHOR(S): Helena Mitasova, Jaro Hofierka, Lubos Mitas:
  5. * PURPOSE: Hydrologic and sediment transport simulation (SIMWE)
  6. *
  7. * COPYRIGHT: (C) 2002 by the GRASS Development Team
  8. *
  9. * This program is free software under the GNU General Public
  10. * License (>=v2). Read the file COPYING that comes with GRASS
  11. * for details.
  12. *
  13. *****************************************************************************/
  14. /* hydro.c (simlib), 20.nov.2002, JH */
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <math.h>
  18. #include <grass/gis.h>
  19. #include <grass/bitmap.h>
  20. #include <grass/linkm.h>
  21. #include <grass/glocale.h>
  22. #include <grass/waterglobs.h>
  23. /*
  24. * Soeren 8. Mar 2011 TODO:
  25. * Put all these global variables into several meaningful structures and
  26. * document use and purpose.
  27. *
  28. */
  29. struct options parm;
  30. struct flags flag;
  31. struct _points points;
  32. char *elevin;
  33. char *dxin;
  34. char *dyin;
  35. char *rain;
  36. char *infil;
  37. char *traps;
  38. char *manin;
  39. /* char *observation; */
  40. char *depth;
  41. char *disch;
  42. char *err;
  43. char *outwalk;
  44. char *mapset;
  45. char *mscale;
  46. char *tserie;
  47. char *wdepth;
  48. char *detin;
  49. char *tranin;
  50. char *tauin;
  51. char *tc;
  52. char *et;
  53. char *conc;
  54. char *flux;
  55. char *erdep;
  56. char *rainval;
  57. char *maninval;
  58. char *infilval;
  59. struct seed seed;
  60. struct Cell_head cellhd;
  61. double xmin, ymin, xmax, ymax;
  62. double mayy, miyy, maxx, mixx;
  63. int mx, my;
  64. int mx2, my2;
  65. double bxmi, bymi, bxma, byma, bresx, bresy;
  66. int maxwab;
  67. double step, conv;
  68. double frac;
  69. double bxmi, bymi;
  70. float **zz, **cchez;
  71. double **v1, **v2, **slope;
  72. double **gama, **gammas, **si, **inf, **sigma;
  73. float **dc, **tau, **er, **ct, **trap;
  74. float **dif;
  75. /* suspected BUG below: fist array subscripts go from 1 to MAXW
  76. * correct: from 0 to MAXW - 1, e.g for (lw = 0; lw < MAXW; lw++) */
  77. double vavg[MAXW][2], stack[MAXW][3], w[MAXW][3];
  78. int iflag[MAXW];
  79. double hbeta;
  80. double hhmax, sisum, vmean;
  81. double infsum, infmean;
  82. int maxw, maxwa, nwalk;
  83. double rwalk, bresx, bresy, xrand, yrand;
  84. double stepx, stepy, xp0, yp0;
  85. double chmean, si0, deltap, deldif, cch, hhc, halpha;
  86. double eps;
  87. int maxwab, nstack;
  88. int iterout, mx2o, my2o;
  89. int miter, nwalka;
  90. double timec;
  91. int ts, timesec;
  92. double rain_val;
  93. double manin_val;
  94. double infil_val;
  95. struct History history; /* holds meta-data (title, comments,..) */
  96. /* **************************************************** */
  97. /* create walker representation of si */
  98. /* ******************************************************** */
  99. /* .......... iblock loop */
  100. void main_loop(void)
  101. {
  102. int i, ii, l, k;
  103. int icoub, nmult;
  104. int iw, iblock, lw;
  105. int itime, iter1;
  106. int nfiterh, nfiterw;
  107. int mgen, mgen2, mgen3;
  108. int nblock;
  109. int icfl;
  110. int mitfac;
  111. /* int mitfac, p; */
  112. double x, y;
  113. double velx, vely, stxm, stym;
  114. double factor, conn, gaux, gauy;
  115. double d1, addac, decr;
  116. double barea, sarea, walkwe;
  117. double gen, gen2, wei2, wei3, wei, weifac;
  118. float eff;
  119. nblock = 1;
  120. icoub = 0;
  121. icfl = 0;
  122. nstack = 0;
  123. if (maxwa > (MAXW - mx * my)) {
  124. mitfac = maxwa / (MAXW - mx * my);
  125. nblock = mitfac + 1;
  126. maxwa = maxwa / nblock;
  127. }
  128. /* Create the observation points */
  129. create_observation_points();
  130. G_debug(2, " maxwa, nblock %d %d", maxwa, nblock);
  131. for (iblock = 1; iblock <= nblock; iblock++) {
  132. ++icoub;
  133. lw = 0;
  134. walkwe = 0.;
  135. barea = stepx * stepy;
  136. sarea = bresx * bresy;
  137. G_debug(2, " barea,sarea,rwalk,sisum: %f %f %f %f", barea, sarea,
  138. rwalk, sisum);
  139. /* write hh.walkers0 */
  140. for (k = 0; k < my; k++) {
  141. for (l = 0; l < mx; l++) { /* run thru the whole area */
  142. if (zz[k][l] != UNDEF) {
  143. x = xp0 + stepx * (double)(l);
  144. y = yp0 + stepy * (double)(k);
  145. gen = rwalk * si[k][l] / sisum;
  146. mgen = (int)gen;
  147. wei = gen / (double)(mgen + 1);
  148. /*if (si[k][l] != 0.) { */
  149. /* this stuff later for multiscale */
  150. gen2 =
  151. (double)maxwab *si[k][l] / (si0 *
  152. (double)(mx2o * my2o));
  153. gen2 = gen2 * (barea / sarea);
  154. mgen2 = (int)gen2;
  155. wei2 = gen2 / (double)(mgen2 + 1);
  156. mgen3 =
  157. (int)((double)mgen2 * wei2 / ((double)mgen * wei));
  158. nmult = mgen3 + 1;
  159. wei3 = gen2 / (double)((mgen + 1) * (mgen2 + 1));
  160. weifac = wei3 / wei;
  161. /* } else {
  162. nmult = 1;
  163. weifac = 1.;
  164. fprintf(stderr, "\n zero rainfall excess in cell");
  165. } */
  166. /*G_debug(2, " gen,gen2,wei,wei2,mgen3,nmult: %f %f %f %f %d %d",gen,gen2,wei,wei2,mgen3,nmult);
  167. */
  168. for (iw = 1; iw <= mgen + 1; iw++) { /* assign walkers */
  169. if (lw >= MAXW) /* max valid value is MAXW - 1, not MAXW */
  170. G_fatal_error(_("nwalk (%d) > maxw (%d)!"), lw, MAXW);
  171. w[lw][0] = x + stepx * (ulec() - 0.5);
  172. w[lw][1] = y + stepy * (ulec() - 0.5);
  173. w[lw][2] = wei;
  174. walkwe += w[lw][2];
  175. vavg[lw][0] = v1[k][l];
  176. vavg[lw][1] = v2[k][l];
  177. if (w[lw][0] >= xmin && w[lw][1] >= ymin &&
  178. w[lw][0] <= xmax && w[lw][1] <= ymax) {
  179. iflag[lw] = 0;
  180. }
  181. else {
  182. iflag[lw] = 1;
  183. }
  184. lw++;
  185. }
  186. } /*DEFined area */
  187. }
  188. }
  189. nwalk = lw;
  190. G_debug(2, " nwalk, maxw %d %d", nwalk, MAXW);
  191. G_debug(2, " walkwe (walk weight),frac %f %f", walkwe, frac);
  192. stxm = stepx * (double)(mx + 1) - xmin;
  193. stym = stepy * (double)(my + 1) - ymin;
  194. nwalka = 0;
  195. deldif = sqrt(deltap) * frac; /* diffuse factor */
  196. factor = deltap * sisum / (rwalk * (double)nblock);
  197. G_debug(2, " deldif,factor %f %e", deldif, factor);
  198. /* ********************************************************** */
  199. /* main loop over the projection time */
  200. /* *********************************************************** */
  201. G_debug(2, "main loop over the projection time... ");
  202. for (i = 1; i <= miter; i++) { /* iteration loop depending on simulation time and deltap */
  203. G_percent(i, miter, 1);
  204. iter1 = i / iterout;
  205. iter1 *= iterout;
  206. if (iter1 == i) {
  207. nfiterw = i / iterout + 10;
  208. nfiterh = i / iterout + 40;
  209. G_debug(2, "iblock=%d i=%d miter=%d nwalk=%d nwalka=%d",
  210. iblock, i, miter, nwalk, nwalka);
  211. }
  212. if (nwalka == 0 && i > 1)
  213. goto L_800;
  214. /* ************************************************************ */
  215. /* .... propagate one step */
  216. /* ************************************************************ */
  217. addac = factor;
  218. conn = (double)nblock / (double)iblock;
  219. if (i == 1) {
  220. addac = factor * .5;
  221. }
  222. nwalka = 0;
  223. nstack = 0;
  224. for (lw = 0; lw < nwalk; lw++) {
  225. if (w[lw][2] > EPS) { /* check the walker weight */
  226. ++nwalka;
  227. l = (int)((w[lw][0] + stxm) / stepx) - mx - 1;
  228. k = (int)((w[lw][1] + stym) / stepy) - my - 1;
  229. if (l > mx - 1 || k > my - 1 || k < 0 || l < 0) {
  230. G_debug(2, " k,l=%d,%d", k, l);
  231. printf(" lw,w=%d %f %f", lw, w[lw][1], w[lw][2]);
  232. G_debug(2, " stxym=%f %f", stxm, stym);
  233. printf(" step=%f %f", stepx, stepy);
  234. G_debug(2, " m=%d %d", my, mx);
  235. printf(" nwalka,nwalk=%d %d", nwalka, nwalk);
  236. G_debug(2, " ");
  237. }
  238. if (zz[k][l] != UNDEF) {
  239. if (infil != NULL) { /* infiltration part */
  240. if (inf[k][l] - si[k][l] > 0.) {
  241. decr = pow(addac * w[lw][2], 3. / 5.); /* decreasing factor in m */
  242. if (inf[k][l] > decr) {
  243. inf[k][l] -= decr; /* decrease infilt. in cell and eliminate the walker */
  244. w[lw][2] = 0.;
  245. }
  246. else {
  247. w[lw][2] -= pow(inf[k][l], 5. / 3.) / addac; /* use just proportional part of the walker weight */
  248. inf[k][l] = 0.;
  249. }
  250. }
  251. }
  252. gama[k][l] += (addac * w[lw][2]); /* add walker weigh to water depth or conc. */
  253. d1 = gama[k][l] * conn;
  254. hhc = pow(d1, 3. / 5.);
  255. if (hhc > hhmax && wdepth == NULL) { /* increased diffusion if w.depth > hhmax */
  256. dif[k][l] = (halpha + 1) * deldif;
  257. velx = vavg[lw][0];
  258. vely = vavg[lw][1];
  259. }
  260. else {
  261. dif[k][l] = deldif;
  262. velx = v1[k][l];
  263. vely = v2[k][l];
  264. }
  265. if (traps != NULL && trap[k][l] != 0.) { /* traps */
  266. eff = ulec(); /* random generator */
  267. if (eff <= trap[k][l]) {
  268. velx = -0.1 * v1[k][l]; /* move it slightly back */
  269. vely = -0.1 * v2[k][l];
  270. }
  271. }
  272. gaux = gasdev();
  273. gauy = gasdev();
  274. w[lw][0] += (velx + dif[k][l] * gaux); /* move the walker */
  275. w[lw][1] += (vely + dif[k][l] * gauy);
  276. if (hhc > hhmax && wdepth == NULL) {
  277. vavg[lw][0] = hbeta * (vavg[lw][0] + v1[k][l]);
  278. vavg[lw][1] = hbeta * (vavg[lw][1] + v2[k][l]);
  279. }
  280. if (w[lw][0] <= xmin || w[lw][1] <= ymin || w[lw][0]
  281. >= xmax || w[lw][1] >= ymax) {
  282. w[lw][2] = 1e-10; /* eliminate walker if it is out of area */
  283. }
  284. else {
  285. if (wdepth != NULL) {
  286. l = (int)((w[lw][0] + stxm) / stepx) - mx - 1;
  287. k = (int)((w[lw][1] + stym) / stepy) - my - 1;
  288. w[lw][2] *= sigma[k][l];
  289. }
  290. } /* else */
  291. } /*DEFined area */
  292. else {
  293. w[lw][2] = 1e-10; /* eliminate walker if it is out of area */
  294. }
  295. }
  296. } /* lw loop */
  297. /* Changes made by Soeren 8. Mar 2011 to replace the site walker output implementation */
  298. /* Save all walkers located within the computational region and with valid
  299. z coordinates */
  300. if ((i == miter || i == iter1)) {
  301. nstack = 0;
  302. for (lw = 0; lw < nwalk; lw++) {
  303. /* Compute the elevation raster map index */
  304. l = (int)((w[lw][0] + stxm) / stepx) - mx - 1;
  305. k = (int)((w[lw][1] + stym) / stepy) - my - 1;
  306. /* Check for correct elevation raster map index */
  307. if(l < 0 || l >= mx || k < 0 || k >= my)
  308. continue;
  309. if (w[lw][2] > EPS && zz[k][l] != UNDEF) {
  310. /* Save the 3d position of the walker */
  311. stack[nstack][0] = mixx / conv + w[lw][0] / conv;
  312. stack[nstack][1] = miyy / conv + w[lw][1] / conv;
  313. stack[nstack][2] = zz[k][l];
  314. nstack++;
  315. }
  316. } /* lw loop */
  317. }
  318. if (i == iter1 && ts == 1) {
  319. /* call output for iteration output */
  320. if (erdep != NULL)
  321. erod(gama); /* divergence of gama field */
  322. conn = (double)nblock / (double)iblock;
  323. itime = (int)(i * deltap * timec);
  324. ii = output_data(itime, conn);
  325. if (ii != 1)
  326. G_fatal_error(_("Unable to write raster maps"));
  327. }
  328. /* Write the water depth each time step at an observation point */
  329. if(points.is_open)
  330. {
  331. double value = 0.0;
  332. int p;
  333. fprintf(points.output, "%.6d ", i);
  334. /* Write for each point */
  335. for(p = 0; p < points.npoints; p++)
  336. {
  337. l = (int)((points.x[p] - mixx + stxm) / stepx) - mx - 1;
  338. k = (int)((points.y[p] - miyy + stym) / stepy) - my - 1;
  339. if (zz[k][l] != UNDEF) {
  340. if (wdepth == NULL)
  341. value = step * gama[k][l] * cchez[k][l];
  342. else
  343. value = gama[k][l] * slope[k][l];
  344. fprintf(points.output, "%2.4f ", value);
  345. } else {
  346. /* Point is invalid, so a negative value is written */
  347. fprintf(points.output, "%2.4f ", -1.0);
  348. }
  349. }
  350. fprintf(points.output, "\n");
  351. }
  352. } /* miter */
  353. L_800:
  354. /* Soeren 8. Mar 2011: Why is this commented out?*/
  355. /* if (iwrib != nblock) {
  356. icount = icoub / iwrib;
  357. if (icoub == (icount * iwrib)) {
  358. ++icfl;
  359. nflw = icfl + 50;
  360. conn = (double) nblock / (double) iblock;
  361. }
  362. } */
  363. if (err != NULL) {
  364. for (k = 0; k < my; k++) {
  365. for (l = 0; l < mx; l++) {
  366. if (zz[k][l] != UNDEF) {
  367. d1 = gama[k][l] * (double)conn;
  368. gammas[k][l] += pow(d1, 3. / 5.);
  369. } /* DEFined area */
  370. }
  371. }
  372. }
  373. if (erdep != NULL)
  374. erod(gama);
  375. }
  376. /* ........ end of iblock loop */
  377. /* Close the observation logfile */
  378. if(points.is_open)
  379. fclose(points.output);
  380. points.is_open = 0;
  381. }