richards.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #include "richards.hpp"
  2. namespace Kernel{
  3. Richards::Richards(){
  4. sup_A=nullptr;
  5. diag_A=nullptr;
  6. sub_A=nullptr;
  7. sup_B=nullptr;
  8. diag_B=nullptr;
  9. sub_B=nullptr;
  10. sup_C=nullptr;
  11. diag_C=nullptr;
  12. sub_C=nullptr;
  13. F=nullptr;
  14. G=nullptr;
  15. S=nullptr;
  16. H=nullptr;
  17. R=nullptr;
  18. I=nullptr;
  19. BB=nullptr;
  20. }
  21. void
  22. Richards::init(size_t ix_,size_t nZ_,double dZ_,double* pumps_){
  23. pumps=pumps_;
  24. ix=ix_;
  25. nZ=nZ_;
  26. dZ=dZ_;
  27. temp_P[0]=new double[nZ];
  28. temp_P[1]=new double[nZ];
  29. sub_A=new double[nZ-2];
  30. sub_B=new double[nZ-2];
  31. sub_C=new double[nZ-2];
  32. diag_A=new double[nZ-1];
  33. diag_B=new double[nZ-1];
  34. diag_C=new double[nZ-1];
  35. sup_A=new double[nZ-2];
  36. sup_B=new double[nZ-2];
  37. sup_C=new double[nZ-2];
  38. F=new double[nZ-1];
  39. G=new double[nZ-1];
  40. S=new double[nZ-1];
  41. H=new double[nZ-1];
  42. R=new double[nZ-1];
  43. I=new double[nZ-1];
  44. BB=new double[nZ-1];
  45. }
  46. void
  47. Richards::run(){
  48. #ifdef MYDEBUG
  49. if(Debug::ix==ix) cout<<" [Richards::run] start"<<endl;
  50. #endif
  51. norm_previous_P=norm2(previous_P,nZ);
  52. has_converged=weighted_run(1);
  53. if(!has_converged) has_converged=weighted_run(0.5);
  54. #ifdef MYDEBUG
  55. if(Debug::ix==ix) cout<<" [Richards::run] stop"<<endl;
  56. #endif
  57. }
  58. bool
  59. Richards::weighted_run(double w){
  60. Debug::debug_Thomas=(Debug::ix==ix);
  61. #ifdef MYDEBUG
  62. if(Debug::ix==ix){
  63. cout<<" [Richards::weighted_run] start"<<endl;
  64. cout<<" [Richards::weighted_run] w = "<<w<<endl;
  65. }
  66. #endif
  67. double error=numeric_limits<double>::infinity();
  68. size_t count=0;
  69. in_P=near_P;
  70. out_P=temp_P[1];
  71. while(error>=tolerence_Richards and count<max_iterations_Richards){
  72. ++count;
  73. #ifdef MYDEBUG
  74. if(Debug::level>1 and Debug::ix==ix) cout<<" [Richards::weighted_run] count = "<<count<<endl;
  75. #endif
  76. solve_system();
  77. if(w<1){
  78. for(size_t i=0;i<nZ;++i){
  79. out_P[i]=w*out_P[i]+(1-w)*in_P[i];
  80. }
  81. }
  82. //Computed P is in out_P=temp_P[count%2]
  83. /*if(Debug::ix==ix) Debug::display("in_P",in_P,0,nZ);
  84. if(Debug::ix==ix) Debug::display("out_P",out_P,0,nZ);*/
  85. error=error2(in_P,out_P,nZ)/norm_previous_P;
  86. if(count==1){
  87. in_P=temp_P[1];
  88. out_P=temp_P[0];
  89. }
  90. else{
  91. swap(in_P,out_P);
  92. }
  93. #ifdef MYDEBUG
  94. if(Debug::ix==ix){
  95. cout<<" [Richards::weighted_run] error = "<<error<<endl;;
  96. }
  97. #endif
  98. }
  99. if(error<tolerence_Richards){
  100. //Last computed P is in temp_P[count%2] which is now also in_P
  101. assert(in_P==temp_P[count%2]);
  102. swap(P,temp_P[count%2]);
  103. #ifdef MYDEBUG
  104. if(Debug::ix==ix){
  105. if(Debug::level>1) cout<<" [Richards::weighted_run] converge"<<endl;
  106. cout<<" [Richards::weighted_run] stop"<<endl;
  107. }
  108. #endif
  109. return true;
  110. }
  111. #ifdef MYDEBUG
  112. if(Debug::ix==ix){
  113. cout<<" [Richards::weighted_run] not converge"<<endl;
  114. cout<<" [Richards::weighted_run] stop"<<endl;
  115. }
  116. #endif
  117. return false;
  118. }
  119. void
  120. Richards::solve_system(){
  121. #ifdef MYDEBUG
  122. if(Debug::ix==ix) cout<<" [Richards::solve_system] start"<<endl;
  123. assert(nZ>=3);
  124. #endif
  125. //Compute A
  126. diag_A[0]=(Physics::phi*dZ*Physics::ds(in_P[0]))/(2*dt);
  127. for(size_t i=1;i<nZ-1;++i){
  128. diag_A[i]=(Physics::phi*dZ*Physics::ds(in_P[i]))/dt;
  129. }
  130. //Compute B
  131. //TODO : A optimiser boucle par rapport aux appels de Kr
  132. double alpha=Physics::k0/(2*Physics::rho*Physics::g*dZ);
  133. diag_B[0]=alpha*(Physics::kr(in_P[0])+Physics::kr(in_P[1]));
  134. sup_B[0]=-diag_B[0];
  135. diag_B[nZ-2]=alpha*(Physics::kr(in_P[nZ-3])+2*Physics::kr(in_P[nZ-2])+Physics::kr(in_P[nZ-1]));
  136. sub_B[nZ-3]=-alpha*(Physics::kr(in_P[nZ-3])+Physics::kr(in_P[nZ-2]));
  137. for(size_t i=1;i<nZ-2;++i){
  138. diag_B[i]=alpha*(Physics::kr(in_P[i-1])+2*Physics::kr(in_P[i])+Physics::kr(in_P[i+1]));
  139. sub_B[i-1]=-alpha*(Physics::kr(in_P[i-1])+Physics::kr(in_P[i]));
  140. sup_B[i]=-alpha*(Physics::kr(in_P[i])+Physics::kr(in_P[i+1]));
  141. }
  142. //Compute C
  143. double hk=Physics::k0/2;
  144. double temp=1/(dZ*Physics::rho*Physics::g);
  145. diag_C[0]=-hk*Physics::dkr(in_P[0])*(temp*(in_P[1]-in_P[0])+1);
  146. sup_C[0]=-hk*Physics::dkr(in_P[1])*(temp*(in_P[1]-in_P[0])+1);
  147. diag_C[nZ-2]=hk*Physics::dkr(in_P[nZ-3])*temp*(-in_P[nZ-3]+2*in_P[nZ-2]-in_P[nZ-1]);
  148. sub_C[nZ-3]=hk*Physics::dkr(in_P[nZ-3])*(temp*(in_P[nZ-2]-in_P[nZ-3])+1);
  149. for(size_t i=1;i<nZ-2;++i){
  150. diag_C[i]=hk*Physics::dkr(in_P[i])*temp*(-in_P[i-1]+2*in_P[i]-in_P[i+1]);
  151. sub_C[i-1]=hk*Physics::dkr(in_P[i-1])*(temp*(in_P[i]-in_P[i-1])+1);
  152. sup_C[i]=-hk*Physics::dkr(in_P[i+1])*(temp*(in_P[i+1]-in_P[i])+1);
  153. }
  154. //Compute G
  155. clear(G,nZ-1);
  156. G[nZ-2]=-alpha*(Physics::kr(in_P[nZ-2])+Physics::kr(in_P[nZ-1]))*in_P[nZ-1];
  157. //Compute S
  158. S[0]=-hk*(Physics::kr(in_P[0])+Physics::kr(in_P[1]));
  159. for(size_t i=1;i<nZ-1;++i){
  160. S[i]=hk*(Physics::kr(in_P[i-1])-Physics::kr(in_P[i+1]));
  161. }
  162. //Compute H
  163. clear(H,nZ-1);
  164. H[nZ-2]=-hk*Physics::dkr(in_P[nZ-1])*(temp*(in_P[nZ-1]-in_P[nZ-2])+1);
  165. //Compute R
  166. clear(R,nZ-1);
  167. R[0]=-flux_bot;
  168. //Compute I
  169. I[0]=(Physics::phi*dZ*(Physics::s(in_P[0])-Physics::s(previous_P[0])))/(2*dt);
  170. for(size_t i=1;i<nZ-1;++i){
  171. I[i]=(Physics::phi*dZ*(Physics::s(in_P[i])-Physics::s(previous_P[i])))/dt;
  172. }
  173. //Compute BB
  174. for(size_t i=1;i<nZ-2;++i){
  175. BB[i]=dZ*(pumps[i-1]/6+(2*pumps[i])/3+pumps[i+1]/6);
  176. }
  177. BB[0]=dZ*(pumps[0]/3+pumps[1]/6);
  178. BB[nZ-2]=dZ*(pumps[nZ-3]/6+(2*pumps[nZ-2])/3);
  179. //Compute F
  180. F[0]=R[0]-G[0]-I[0]-S[0]-H[0]+BB[0]+(diag_A[0]+diag_C[0])*in_P[0]+sup_C[0]*in_P[1];
  181. for(size_t i=1;i<nZ-2;++i){
  182. F[i]=div_w[i]*dZ+R[i]-G[i]-I[i]-S[i]-H[i]+BB[i]+(diag_A[i]+diag_C[i])*in_P[i]+sub_C[i-1]*in_P[i-1]+sup_C[i]*in_P[i+1];
  183. }
  184. F[nZ-2]=div_w[nZ-2]*dZ+R[nZ-2]-G[nZ-2]-I[nZ-2]-S[nZ-2]-H[nZ-2]+BB[nZ-2]+(diag_A[nZ-2]+diag_C[nZ-2])*in_P[nZ-2]+sub_C[nZ-3]*in_P[nZ-3];
  185. // / if(ix==39) display("F",F,nZ-1);
  186. //TODO Add contribution of BB in F
  187. for(size_t i=0;i<nZ-2;++i){
  188. sub_A[i]=(sub_B[i]+sub_C[i]);
  189. diag_A[i]+=(diag_B[i]+diag_C[i]);
  190. sup_A[i]=(sup_B[i]+sup_C[i]);
  191. }
  192. diag_A[nZ-2]+=(diag_B[nZ-2]+diag_C[nZ-2]);
  193. //Debug::display("sup_A",sup_A,0,nZ-2);
  194. Thomas(nZ-1,sub_A,diag_A,sup_A,F,out_P);
  195. out_P[nZ-1]=in_P[nZ-1];
  196. #ifdef MYDEBUG
  197. if(Debug::ix==ix){
  198. cout<<" [Richards::solve_system] out = "<<out_P<<endl;
  199. cout<<" [Richards::solve_system] stop"<<endl;
  200. }
  201. #endif
  202. }
  203. }