basin.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include "basin.hpp"
  2. void
  3. Basin::compute_leak_direction(){
  4. switch(position){
  5. case Middle:
  6. if(abs(hleft-hright)<delta_both_leak) leak_direction=Both;
  7. else leak_direction=(hleft>hright)?Right:Left;
  8. break;
  9. case BorderLeft:
  10. leak_direction=Right;
  11. break;
  12. case BorderRight:
  13. leak_direction=Left;
  14. break;
  15. default:
  16. leak_direction=None;
  17. break;
  18. };
  19. }
  20. void Basin::compute_maxs(double* hsoil){
  21. switch(leak_direction){
  22. case Left:
  23. hmax=hleft;
  24. xmax_left=xleft;
  25. {
  26. int x;
  27. for(x=xleft+1;x<xright;++x){
  28. if(hsoil[x]+Physics::minimal_height_to_runoff>hmax){
  29. xmax_right=x;
  30. break;
  31. }
  32. }
  33. xmax_right=min(x,(int)xright);
  34. }
  35. break;
  36. case Right:
  37. hmax=hright;
  38. xmax_right=xright;
  39. {
  40. int x;
  41. for(x=xright-1;x>xleft;--x){
  42. if(hsoil[x]+Physics::minimal_height_to_runoff>hmax){
  43. xmax_left=x;
  44. break;
  45. }
  46. }
  47. xmax_left=max(x,(int)xleft);
  48. }
  49. break;
  50. case Both:
  51. hmax=min(hleft,hright);
  52. xmax_left=xleft;
  53. xmax_right=xright;
  54. break;
  55. case None:
  56. default:
  57. hmax=numeric_limits<double>::infinity();
  58. xmax_left=xleft;
  59. xmax_right=xright;
  60. break;
  61. };
  62. }
  63. Basin::Basin(Basin* left_,Basin* right_){
  64. left=left_;
  65. right=right_;
  66. xleft=left->xleft;
  67. xright=right->xright;
  68. hleft=left->hleft;
  69. hright=right->hright;
  70. hmin=left->hmax;
  71. xacc=left->xacc;
  72. if(left->position==BorderLeft){
  73. if(right->position==BorderRight) position=BorderBoth;
  74. else position=BorderLeft;
  75. }
  76. else if(right->position==BorderRight) position=BorderRight;
  77. else position=Middle;
  78. compute_leak_direction();
  79. }
  80. void
  81. Basin::display(string indent){
  82. cout<<indent<<'['<<xleft<<','<<xright<<"] : "<<hmax<<" : ["<<xmax_left<<","<<xmax_right<<"] and "<<hmin<<endl;
  83. if(left==nullptr) return;
  84. left->display(indent+' ');
  85. right->display(indent+' ');
  86. }
  87. void
  88. Basin::compute_vflow(double* hsoil,double* hov){
  89. if(is_primitive()){
  90. vflow=max(0.0,hov[xacc]-hsoil[xacc]-Physics::minimal_height_to_runoff);
  91. }
  92. else{
  93. left->compute_vflow(hsoil,hov);
  94. right->compute_vflow(hsoil,hov);
  95. vflow=left->vflow+right->vflow;
  96. }
  97. }
  98. void
  99. Basin::repartition(double* hsoil,double* hov,Direction* rundir){
  100. overflow=false;
  101. vmin=0;
  102. if(not is_primitive()){
  103. for(size_t ix=xleft;ix<=xright;++ix){
  104. vmin+=max(0.0,hmin-min(hov[ix],hsoil[ix]+Physics::minimal_height_to_runoff));
  105. }
  106. }
  107. if(vflow!=0 and vflow>=vmin){
  108. vmax=0;
  109. for(size_t ix=xmax_left;ix<=xmax_right;++ix){
  110. vmax+=max(0.0,hmax-min(hov[ix],hsoil[ix]+Physics::minimal_height_to_runoff));
  111. }
  112. if(vflow-vmax>1e-10){
  113. overflow=true;
  114. vleak=vflow-vmax;
  115. if(not is_primitive()){
  116. double delta=hov[right->xacc]-hsoil[right->xacc]-Physics::minimal_height_to_runoff;
  117. hov[left->xacc]+=delta;
  118. hov[right->xacc]-=delta;
  119. }
  120. hov[xacc]-=vleak;
  121. switch(leak_direction){
  122. case Left:
  123. hov[xleft-1]+=vleak;
  124. runoff(xleft-1,Left,rundir,hsoil,hov);
  125. break;
  126. case Right:
  127. hov[xright+1]+=vleak;
  128. runoff(xright+1,Right,rundir,hsoil,hov);
  129. break;
  130. case Both:
  131. hov[xleft-1]+=vleak/2;
  132. runoff(xleft-1,Left,rundir,hsoil,hov);
  133. hov[xright+1]+=vleak/2;
  134. runoff(xright+1,Right,rundir,hsoil,hov);
  135. break;
  136. default:
  137. cerr<<"[Bug] Impossible case ! ... in theory :)"<<endl;
  138. exit(-1);
  139. break;
  140. }
  141. }
  142. }
  143. else{
  144. if(not is_primitive()){
  145. left->repartition(hsoil,hov,rundir);
  146. right->repartition(hsoil,hov,rundir);
  147. overflow=left->overflow|right->overflow;
  148. }
  149. }
  150. }
  151. void
  152. Basin::runoff(size_t xstart,Direction dir,Direction* rundir,double* hsoil,double* hov){
  153. double r=max(0.0,hov[xstart]-hsoil[xstart]-Physics::minimal_height_to_runoff);
  154. int x=xstart;
  155. int xstep=(dir==Left)?-1:1;
  156. while(r>0 and rundir[x]!=None){
  157. hov[x]-=r;
  158. x+=xstep;
  159. hov[x]+=r;
  160. r=max(0.0,hov[x]-hsoil[x]-Physics::minimal_height_to_runoff);
  161. }
  162. }
  163. double
  164. Basin::f(double r,double* hsoil,double* hov,double vext){
  165. double res=-vext;
  166. for(size_t ix=xleft;ix<=xright;++ix){
  167. res+=max(r-min(hov[ix],hsoil[ix]+Physics::minimal_height_to_runoff),0.0);
  168. }
  169. return res;
  170. }
  171. double
  172. Basin::df(double r,double* hsoil,double* hov,double vext){
  173. double res=0;
  174. for(size_t ix=xleft;ix<=xright;++ix){
  175. if(r>min(hov[ix],hsoil[ix]+Physics::minimal_height_to_runoff)) ++res;
  176. }
  177. return res;
  178. }
  179. void
  180. Basin::flatten(double* hsoil,double* hov){
  181. double crit=1;
  182. size_t count=0;
  183. if(vflow>1e-9){
  184. double r=hsoil[xacc]+1;//Physics::minimal_height_to_runoff;
  185. while(crit>1e-10 and count<100){
  186. ++count;
  187. double rold=r;
  188. r-=f(r,hsoil,hov,vflow)/df(r,hsoil,hov,vflow);
  189. crit=abs(r-rold)+abs(f(r,hsoil,hov,vflow));
  190. }
  191. if(crit>1e-10){
  192. cerr<<" Overland coverge + [TODO] on fait quoi ?"<<endl;
  193. }
  194. if(r>=hmin or is_primitive()){
  195. for(size_t ix=xleft;ix<=xright;++ix){
  196. hov[ix]=max(r,min(hov[ix],hsoil[ix]+Physics::minimal_height_to_runoff));
  197. }
  198. }
  199. else{
  200. left->flatten(hsoil,hov);
  201. right->flatten(hsoil,hov);
  202. }
  203. }
  204. }