sedco3.F90 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. MODULE sedco3
  2. #if defined key_sed
  3. !!======================================================================
  4. !! *** MODULE sedco3 ***
  5. !! Sediment : carbonate in sediment pore water
  6. !!=====================================================================
  7. !! * Modules used
  8. USE sed ! sediment global variable
  9. IMPLICIT NONE
  10. PRIVATE
  11. !! * Routine accessibility
  12. PUBLIC sed_co3
  13. !! * Module variables
  14. REAL(wp) :: epsmax = 1.e-12 ! convergence limite value
  15. !!----------------------------------------------------------------------
  16. !! OPA 9.0 ! LODYC-IPSL (2003)
  17. !!----------------------------------------------------------------------
  18. !! $Id: sedco3.F90 2355 2015-05-20 07:11:50Z ufla $
  19. CONTAINS
  20. SUBROUTINE sed_co3( kt )
  21. !!----------------------------------------------------------------------
  22. !! *** ROUTINE sed_co3 ***
  23. !!
  24. !! ** Purpose : carbonate ion and proton concentration
  25. !! in sediment pore water
  26. !!
  27. !! ** Methode : - solving nonlinear equation for [H+] with given alkalinity
  28. !! and total co2
  29. !! - one dimensional newton-raphson algorithm for [H+])
  30. !!
  31. !! History :
  32. !! ! 98-08 (E. Maier-Reimer, Christoph Heinze ) Original code
  33. !! ! 04-10 (N. Emprin, M. Gehlen ) coupled with PISCES
  34. !! ! 06-04 (C. Ethe) Re-organization
  35. !!----------------------------------------------------------------------
  36. !! * Arguments
  37. INTEGER, INTENT(in) :: kt ! time step
  38. !
  39. !---Local variables
  40. INTEGER :: jiter, ji, jk, ipt ! dummy loop indices
  41. INTEGER :: itermax ! maximum number of Newton-Raphson iterations
  42. INTEGER :: itime ! number of time to perform Newton-Raphson algorithm
  43. LOGICAL :: lconv = .FALSE. ! flag for convergence
  44. REAL(wp) :: brems ! relaxation. parameter
  45. REAL(wp) :: zresm, zresm1, zhipor_min
  46. REAL(wp) :: zalk, zbor, zsil, zpo4, zdic
  47. REAL(wp) :: zh_old, zh_old2, zh_old3, zh_old4
  48. REAL(wp) :: zuu, zvv, zduu, zdvv
  49. REAL(wp) :: zup, zvp, zdup, zdvp
  50. REAL(wp) :: zah_old, zah_olds
  51. REAL(wp) :: zh_new, zh_new2, zco3
  52. !!----------------------------------------------------------------------
  53. IF( kt == nitsed000 ) THEN
  54. WRITE(numsed,*) ' sed_co3 : carbonate ion and proton concentration calculation '
  55. WRITE(numsed,*) ' '
  56. ENDIF
  57. itermax = 30
  58. brems = 1.
  59. itime = 0
  60. DO jk = 1, jpksed
  61. 10001 CONTINUE
  62. IF( itime <= 2 ) THEN
  63. lconv = .FALSE.
  64. IF( itime > 0 ) THEN
  65. ! increase max number of iterations and relaxation parameter
  66. itermax = 200
  67. !! brems = 0.3
  68. IF( itime == 2 ) hipor(1:jpoce,jk) = 3.e-9 ! re-initilazation of [H] values
  69. ENDIF
  70. iflag: DO jiter = 1, itermax
  71. ! Store previous hi field.
  72. zresm = -1.e10
  73. ipt = 1
  74. DO ji = 1, jpoce
  75. ! dissociation constant are in mol/kg of solution
  76. ! convert pwcp concentration [mol/l] in mol/kg for solution
  77. zalk = pwcp(ji,jk,jwalk) / densSW(ji)
  78. zh_old = hipor(ji,jk) / densSW(ji)
  79. zh_old2 = zh_old * zh_old
  80. zh_old3 = zh_old2 * zh_old
  81. zh_old4 = zh_old3 * zh_old
  82. zbor = borats(ji) / densSW(ji)
  83. zsil = pwcp(ji,jk,jwsil) / densSW(ji)
  84. zpo4 = pwcp(ji,jk,jwpo4) / densSW(ji)
  85. zdic = pwcp(ji,jk,jwdic) / densSW(ji)
  86. ! intermediate calculation
  87. zuu = zdic * ( ak1s(ji) / zh_old + 2.* ak12s(ji) / zh_old2 )
  88. zvv = 1. + ak1s(ji) / zh_old + ak12s(ji) / zh_old2
  89. zduu = zdic * ( -ak1s(ji) / zh_old2 - 4. * ak12s(ji) / zh_old3 )
  90. zdvv = -ak1s(ji) / zh_old2 - 2. * ak12s(ji) / zh_old3
  91. zup = zpo4 * ( ak12ps(ji) / zh_old2 + 2. * ak123ps(ji) / zh_old3 - 1.)
  92. zvp = 1. + ak1ps(ji) / zh_old + ak12ps(ji) / zh_old2 + ak123ps(ji) / zh_old3
  93. zdup = zpo4 * ( -2. * ak12ps(ji) / zh_old3 - 6. * ak123ps(ji) / zh_old4 )
  94. zdvp = -ak1ps(ji) / zh_old2 - 2.* ak12ps(ji) / zh_old3 - 3. * ak123ps(ji) / zh_old4
  95. zah_old = zuu / zvv + zbor / ( 1. + zh_old / akbs(ji) ) + &
  96. & akws(ji) / zh_old - zh_old + zsil / ( 1. + zh_old / aksis(ji) ) + &
  97. & zup / zvp
  98. zah_olds = ( ( zduu * zvv - zdvv * zuu ) / ( zvv * zvv ) ) - &
  99. & zbor / akbs(ji) * ( 1. + zh_old / akbs(ji) )**(-2) - &
  100. & akws(ji) / zh_old2 - 1. - &
  101. & zsil / aksis(ji) * ( 1. + zh_old / aksis(ji) )**(-2) + &
  102. & ( ( zdup * zvp - zdvp * zup ) / ( zvp * zvp ) )
  103. !
  104. zh_new = zh_old - brems * ( zah_old - zalk ) / zah_olds
  105. !
  106. zresm1 = ABS( zh_new - zh_old )
  107. IF( zresm1 > zresm ) THEN
  108. zresm = zresm1
  109. ENDIF
  110. !
  111. zh_new2 = zh_new * zh_new
  112. zco3 = ( ak12s(ji) * zdic ) / ( ak12s(ji) + ak1s(ji) * zh_new + zh_new2)
  113. ! again in mol/l
  114. hipor (ji,jk) = zh_new * densSW(ji)
  115. co3por(ji,jk) = zco3 * densSW(ji)
  116. ENDDO ! end loop ji
  117. ! convergence test
  118. IF( zresm <= epsmax ) THEN
  119. lconv = .TRUE.
  120. !minimum value of hipor
  121. zhipor_min = MINVAL( hipor(1:jpoce,jk ) )
  122. EXIT iflag
  123. ENDIF
  124. ENDDO iflag
  125. IF( lconv ) THEN
  126. ! WRITE(numsed,*) ' convergence after iter =', jiter, ' iterations ; res =',zresm
  127. IF( zhipor_min < 0. ) THEN
  128. IF ( itime == 0 ) THEN
  129. ! WRITE(numsed,*) ' but hipor < 0 ; try one more time for jk = ', jk
  130. ! WRITE(numsed,*) ' with re-initialization of initial PH field '
  131. itime = 2
  132. GOTO 10001
  133. ELSE
  134. ! WRITE(numsed,*) ' convergence after iter =', jiter, ' iterations ; res =',zresm
  135. ! WRITE(numsed,*) ' but hipor < 0, again for second time for jk = ', jk
  136. ! WRITE(numsed,*) ' We stop : STOP '
  137. STOP
  138. ENDIF
  139. ELSE
  140. ! WRITE(numsed,*) ' successfull convergence for level jk = ',jk,&
  141. ! & ' after iter =', jiter, ' iterations ; res =',zresm
  142. ! WRITE(numsed,*) ' '
  143. itime = 0
  144. ENDIF
  145. ELSE
  146. itime = itime + 1
  147. WRITE(numsed,*) ' No convergence for jk = ', jk, ' after ', itime, ' try'
  148. IF ( itime == 1 ) THEN
  149. WRITE(numsed,*) ' try one more time with more iterations and higher relax. value'
  150. GOTO 10001
  151. ELSE IF ( itime == 2 ) THEN
  152. WRITE(numsed,*) ' try one more time for with more iterations, higher relax. value'
  153. WRITE(numsed,*) ' and with re-initialization of initial PH field '
  154. ELSE
  155. WRITE(numsed,*) ' No more... we stop '
  156. STOP
  157. ENDIF
  158. ENDIF
  159. ENDIF
  160. ENDDO
  161. END SUBROUTINE sed_co3
  162. #else
  163. !!======================================================================
  164. !! MODULE sedco3 : Dummy module
  165. !!======================================================================
  166. !! $Id: sedco3.F90 2355 2015-05-20 07:11:50Z ufla $
  167. CONTAINS
  168. SUBROUTINE sed_co3( kt ) ! Empty routine
  169. INTEGER, INTENT(in) :: kt
  170. WRITE(*,*) 'sed_co3: You should not have seen this print! error?', kt
  171. END SUBROUTINE sed_co3
  172. !!======================================================================
  173. #endif
  174. END MODULE sedco3