geometry.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #include "geometry.hpp"
  2. #include "physics.hpp"
  3. double inf = numeric_limits<double>::infinity();
  4. Geometry::Geometry(){
  5. lX=0;
  6. nX=0;
  7. dX=0;
  8. hsoil=nullptr;
  9. dhsoil=nullptr;
  10. hbot=nullptr;
  11. dhbot=nullptr;
  12. nZ=nullptr;
  13. dZ=nullptr;
  14. Z=nullptr;
  15. }
  16. Geometry::~Geometry(){
  17. if(hsoil!=nullptr){
  18. delete[] hsoil;
  19. delete[] dhsoil;
  20. delete[] hbot;
  21. delete[] dhbot;
  22. delete[] dZ;
  23. delete[] nZ;
  24. for(size_t i=0;i<nX;++i){
  25. delete[] Z[i];
  26. }
  27. delete[] Z;
  28. }
  29. }
  30. void
  31. Geometry::initZ(double dZ_avg,bool init){
  32. if(init){
  33. nZ=new size_t[nX];
  34. dZ=new double[nX];
  35. Z=new double*[nX];
  36. }
  37. for(size_t k=0;k<nX;++k){
  38. double d=hsoil[k]-hbot[k];
  39. size_t n=d/dZ_avg;
  40. double dz=d/n;
  41. dZ[k]=dz;
  42. nZ[k]=n+1;
  43. if(init) Z[k]=new double[n+1];
  44. for(size_t j=0;j<n+1;++j){
  45. Z[k][j]=hbot[k]+j*dz;
  46. }
  47. }
  48. }
  49. void
  50. Geometry::save(fstream& file) {
  51. file.write((char*)&lX,sizeof(double));
  52. file.write((char*)&nX,sizeof(size_t));
  53. file.write((char*)&dX,sizeof(double));
  54. file.write((char*)hsoil,nX*sizeof(double));
  55. file.write((char*)dhsoil,nX*sizeof(double));
  56. file.write((char*)hbot,nX*sizeof(double));
  57. file.write((char*)dhbot,nX*sizeof(double));
  58. file.write((char*)nZ,nX*sizeof(size_t));
  59. file.write((char*)dZ,nX*sizeof(double));
  60. for(size_t i=0;i<nX;++i){
  61. file.write((char*)Z[i],nZ[i]*sizeof(double));
  62. }
  63. }
  64. void
  65. Geometry::load(fstream& file,bool init) {
  66. file.read((char*)&lX,sizeof(double));
  67. file.read((char*)&nX,sizeof(size_t));
  68. file.read((char*)&dX,sizeof(double));
  69. if(init){
  70. hsoil=new double[nX];
  71. dhsoil=new double[nX];
  72. hbot=new double[nX];
  73. dhbot=new double[nX];
  74. nZ=new size_t[nX];
  75. dZ=new double[nX];
  76. Z=new double*[nX];
  77. }
  78. file.read((char*)hsoil,nX*sizeof(double));
  79. file.read((char*)dhsoil,nX*sizeof(double));
  80. file.read((char*)hbot,nX*sizeof(double));
  81. file.read((char*)dhbot,nX*sizeof(double));
  82. file.read((char*)nZ,nX*sizeof(size_t));
  83. file.read((char*)dZ,nX*sizeof(double));
  84. for(size_t i=0;i<nX;++i){
  85. if(init) Z[i]=new double[nZ[i]];
  86. file.read((char*)Z[i],nZ[i]*sizeof(double));
  87. }
  88. //Comoute dhsoil and dhbot
  89. dhsoil[0]=(hsoil[1]-hsoil[0])/dX;
  90. dhbot[0]=(hbot[1]-hbot[0])/dX;
  91. for(size_t i=1;i<nX-1;++i){
  92. dhsoil[i]=(hsoil[i+1]-hsoil[i-1])/(2*dX);
  93. dhbot[i]=(hbot[i+1]-hbot[i-1])/(2*dX);
  94. }
  95. dhsoil[nX-1]=(hsoil[nX-1]-hsoil[nX-2])/dX;
  96. dhbot[nX-1]=(hbot[nX-1]-hbot[nX-2])/dX;
  97. }
  98. pair<list<Basin*>::iterator,list<Basin*>::iterator>
  99. Geometry::find_basins(const Summit& s,list<Basin*>& basins){
  100. list<Basin*>::iterator it_left;
  101. list<Basin*>::iterator it_right;
  102. for(list<Basin*>::iterator it=basins.begin();it!=basins.end();++it){
  103. Basin* b=*it;
  104. if(b->xleft==s.ix){
  105. it_right=it;
  106. }
  107. if(b->xright==s.ix){
  108. it_left=it;
  109. }
  110. }
  111. return pair<list<Basin*>::iterator,list<Basin*>::iterator>(it_left,it_right);
  112. }
  113. void Geometry::compute_basins(){
  114. //Find local min point of hsoil
  115. vector<size_t> v_min;
  116. if(hsoil[0]<hsoil[1]) v_min.push_back(0);
  117. for(size_t ix=1;ix<nX-1;++ix){
  118. double h=hsoil[ix];
  119. if(hsoil[ix-1]>h and h<hsoil[ix+1]) v_min.push_back(ix);
  120. }
  121. if(hsoil[nX-2]>hsoil[nX-1]) v_min.push_back(nX-1);
  122. size_t nb=v_min.size();
  123. //Primitive Basins
  124. vector<Summit> summits;
  125. list<Basin*> basins_to_merge;
  126. for(size_t ib=0;ib<nb;++ib){
  127. Basin* b=new Basin;
  128. size_t xb=v_min[ib];
  129. //Find left bound
  130. b->xacc=xb;
  131. if(xb==0){
  132. b->xleft=xb;
  133. b->position=BorderLeft;
  134. }
  135. else{
  136. size_t ix=xb;
  137. while(ix>0 and hsoil[ix-1]>hsoil[ix]) --ix;
  138. b->xleft=ix;
  139. if(ix==0) b->position=BorderLeft;
  140. if(ix>0) summits.emplace_back(ix,hsoil[ix]);
  141. }
  142. //Find right bound
  143. if(xb==nX-1){
  144. b->xright=xb;
  145. b->position=BorderRight;
  146. }
  147. else{
  148. size_t ix=xb;
  149. while(ix<nX-1 and hsoil[ix+1]>hsoil[ix]) ++ix;
  150. if(ix==nX-1)b->position=BorderRight;
  151. b->xright=ix;
  152. }
  153. b->hleft=hsoil[b->xleft]+Physics::minimal_height_to_runoff;
  154. b->hright=hsoil[b->xright]+Physics::minimal_height_to_runoff;
  155. b->compute_leak_direction();
  156. b->compute_maxs(hsoil);
  157. // Set hmin
  158. b->hmin=hsoil[xb]+Physics::minimal_height_to_runoff;
  159. basins_to_merge.push_back(b);
  160. }
  161. //Determine meta basins
  162. if(summits.empty()){
  163. root_basin=new Basin;
  164. root_basin->position=BorderBoth;
  165. root_basin->left=nullptr;
  166. root_basin->right=nullptr;
  167. root_basin->xacc=0;
  168. root_basin->leak_direction=None;
  169. root_basin->xleft=0;
  170. root_basin->xright=nX-1;
  171. double h=hsoil[0];
  172. root_basin->hleft=h;
  173. root_basin->hright=h;
  174. root_basin->hmin=h;
  175. }
  176. else{
  177. sort(summits.begin(),summits.end());
  178. for(auto it=summits.begin();it!=summits.end();++it){
  179. Summit& s=*it;
  180. auto res=find_basins(s,basins_to_merge);
  181. list<Basin*>::iterator it_left=res.first;
  182. list<Basin*>::iterator it_right=res.second;
  183. Basin* b_left=*it_left;
  184. Basin* b_right=*it_right;
  185. basins_to_merge.erase(it_left);
  186. basins_to_merge.erase(it_right);
  187. Basin* b=new Basin(b_left,b_right);
  188. b->compute_maxs(hsoil);
  189. basins_to_merge.push_back(b);
  190. }
  191. root_basin=basins_to_merge.front();
  192. root_basin->display();
  193. }
  194. // Compute Runoff directions
  195. runoff_directions=new Direction[nX];
  196. for(size_t ix=1;ix<nX-1;++ix){
  197. double dh=(hsoil[ix+1]-hsoil[ix-1])/(2*dX);
  198. if(abs(dh)<max_slope_both_side_runoff) runoff_directions[ix]=Both;
  199. else runoff_directions[ix]=(dh>0)?Left:Right;
  200. }
  201. for(size_t ib=0;ib<nb;++ib){
  202. size_t xb=v_min[ib];
  203. runoff_directions[xb]=None;
  204. }
  205. runoff_directions[0]=Right;
  206. runoff_directions[nX-1]=Left;
  207. }