richards.cpp 6.3 KB

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