richards.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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. if(Debug::level>0 and Debug::ix==ix) cout<<" [Richards::run] start"<<endl;
  48. norm_previous_P=norm2(previous_P,nZ);
  49. has_converged=weighted_run(1);
  50. if(!has_converged) has_converged=weighted_run(0.5);
  51. if(Debug::level>0 and Debug::ix==ix) cout<<" [Richards::run] stop"<<endl;
  52. }
  53. bool
  54. Richards::weighted_run(double w){
  55. if(Debug::level>0 and Debug::ix==ix) cout<<" [Richards::weighted_run] start"<<endl;
  56. if(Debug::level>0 and Debug::ix==ix) cout<<" [Richards::weighted_run] w = "<<w<<endl;
  57. double error=numeric_limits<double>::infinity();
  58. size_t count=0;
  59. in_P=near_P;
  60. out_P=temp_P[1];
  61. while(error>=tolerence_Richards and count<max_iterations_Richards){
  62. ++count;
  63. if(Debug::level>1 and Debug::ix==ix) cout<<" [Richards::weighted_run] count = "<<count<<endl;
  64. solve_system();
  65. //Computed P is in out_P=temp_P[count%2]
  66. error=error2(in_P,out_P,nZ)/norm_previous_P;
  67. if(count==1){
  68. in_P=temp_P[1];
  69. out_P=temp_P[0];
  70. }
  71. else{
  72. swap(in_P,out_P);
  73. }
  74. }
  75. if(error<tolerence_Richards){
  76. //Last computed P is in temp_P[count%2] which is now also in_P
  77. assert(in_P==temp_P[count%2]);
  78. swap(P,temp_P[count%2]);
  79. if(Debug::ix==ix){
  80. if(Debug::level>1) cout<<" [Richards::weighted_run] converge"<<endl;
  81. if(Debug::level>0) cout<<" [Richards::weighted_run] stop"<<endl;
  82. }
  83. return true;
  84. }
  85. if(Debug::level>0 and Debug::ix==ix){
  86. cout<<" [Richards::weighted_run] not converge"<<endl;
  87. cout<<" [Richards::weighted_run] stop"<<endl;
  88. }
  89. return false;
  90. }
  91. void
  92. Richards::solve_system(){
  93. if(Debug::level>0 and Debug::ix==ix) cout<<" [Richards::solve_system] start"<<endl;
  94. assert(nZ>=3);
  95. //Compute A
  96. diag_A[0]=(Physics::phi*dZ*Physics::ds(in_P[0]))/(2*dt);
  97. for(size_t i=1;i<nZ-1;++i){
  98. diag_A[i]=(Physics::phi*dZ*Physics::ds(in_P[i]))/dt;
  99. }
  100. //Compute B
  101. //TODO : A optimiser boucle par rapport aux appels de Kr
  102. double alpha=Physics::k0/(2*Physics::rho*Physics::g*dZ);
  103. diag_B[0]=alpha*(Physics::kr(in_P[0])+Physics::kr(in_P[1]));
  104. sup_B[0]=-diag_B[0];
  105. diag_B[nZ-2]=alpha*(Physics::kr(in_P[nZ-3])+2*Physics::kr(in_P[nZ-2])+Physics::kr(in_P[nZ-1]));
  106. sub_B[nZ-3]=-alpha*(Physics::kr(in_P[nZ-3])+Physics::kr(in_P[nZ-2]));
  107. for(size_t i=1;i<nZ-2;++i){
  108. diag_B[i]=alpha*(Physics::kr(in_P[i-1])+2*Physics::kr(in_P[i])+Physics::kr(in_P[i+1]));
  109. sub_B[i-1]=-alpha*(Physics::kr(in_P[i-1])+Physics::kr(in_P[i]));
  110. sup_B[i]=-alpha*(Physics::kr(in_P[i])+Physics::kr(in_P[i+1]));
  111. }
  112. //Compute C
  113. double hk=Physics::k0/2;
  114. double temp=1/(dZ*Physics::rho*Physics::g);
  115. diag_C[0]=-hk*Physics::dkr(in_P[0])*(temp*(in_P[1]-in_P[0])+1);
  116. sup_C[0]=-hk*Physics::dkr(in_P[1])*(temp*(in_P[1]-in_P[0])+1);
  117. 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]);
  118. sub_C[nZ-3]=hk*Physics::dkr(in_P[nZ-3])*(temp*(in_P[nZ-2]-in_P[nZ-3])+1);
  119. for(size_t i=1;i<nZ-2;++i){
  120. diag_C[i]=hk*Physics::dkr(in_P[i])*temp*(-in_P[i-1]+2*in_P[i]-in_P[i+1]);
  121. sub_C[i-1]=hk*Physics::dkr(in_P[i-1])*(temp*(in_P[i]-in_P[i-1])+1);
  122. sup_C[i]=-hk*Physics::dkr(in_P[i+1])*(temp*(in_P[i+1]-in_P[i])+1);
  123. }
  124. //Compute G
  125. clear(G,nZ-1);
  126. G[nZ-2]=-alpha*(Physics::kr(in_P[nZ-2])+Physics::kr(in_P[nZ-1]))*in_P[nZ-1];
  127. //Compute S
  128. S[0]=-hk*(Physics::kr(in_P[0])+Physics::kr(in_P[1]));
  129. for(size_t i=1;i<nZ-1;++i){
  130. S[i]=hk*(Physics::kr(in_P[i-1])-Physics::kr(in_P[i+1]));
  131. }
  132. //Compute H
  133. clear(H,nZ-1);
  134. H[nZ-2]=-hk*Physics::dkr(in_P[nZ-1])*(temp*(in_P[nZ-1]-in_P[nZ-2])+1);
  135. //Compute R
  136. clear(R,nZ-1);
  137. R[0]=-flux_bot;
  138. //Compute I
  139. I[0]=(Physics::phi*dZ*(Physics::s(in_P[0])-Physics::s(previous_P[0])))/(2*dt);
  140. for(size_t i=1;i<nZ-1;++i){
  141. I[i]=(Physics::phi*dZ*(Physics::s(in_P[i])-Physics::s(previous_P[i])))/dt;
  142. }
  143. //Compute BB
  144. clear(BB,nZ-1);
  145. //TODO : Add BB computation from fpump
  146. //Compute F
  147. F[0]=div_w[0]*dZ+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];
  148. for(size_t i=1;i<nZ-2;++i){
  149. 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];
  150. }
  151. 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];
  152. // / if(ix==39) display("F",F,nZ-1);
  153. //TODO Add contribution of BB in F
  154. for(size_t i=0;i<nZ-2;++i){
  155. sub_A[i]=(sub_B[i]+sub_C[i]);
  156. diag_A[i]+=(diag_B[i]+diag_C[i]);
  157. sup_A[i]=(sup_B[i]+sup_C[i]);
  158. }
  159. diag_A[nZ-2]+=(diag_B[nZ-2]+diag_C[nZ-2]);
  160. Thomas(nZ-1,sub_A,diag_A,sup_A,F,out_P);
  161. out_P[nZ-1]=in_P[nZ-1];
  162. if(Debug::level>0 and Debug::ix==ix){
  163. cout<<" [Richards::solve_system] out = "<<out_P<<endl;
  164. cout<<" [Richards::solve_system] stop"<<endl;
  165. }
  166. }
  167. }