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