Simulation Core
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

493 строки
27 KiB

  1. # 1 "/home/admin/SimulationCore2/FluidFlow/kick/Gas_Kick_Calculator.f90"
  2. SUBROUTINE GasKickCalculator
  3. use SimulationVariables
  4. use KickVARIABLESModule
  5. use SimulationVariables !@
  6. Use CReservoirVariables
  7. Use CFormationVariables
  8. USE Fluid_Flow_Startup_Vars
  9. use PressureDisplayVARIABLESModule
  10. USE FricPressDropVarsModule
  11. USE MudSystemVARIABLES
  12. use SimulationVariables !@@@
  13. USE CMudPropertiesVariables
  14. USE CError
  15. USE , INTRINSIC :: IEEE_ARITHMETIC
  16. !! Note: a subject that may be confusing is that when we use gauge pressure and when're using absolute pressure?!
  17. !! all stated pressure are gauge pressure, so I do like this.
  18. !! only when we want to use a state equation (like ideal gas equation), we should use absolute equation and so I do this.
  19. !! Thus gas pocket pressure are all absolute pressure.
  20. IMPLICIT NONE
  21. INTEGER :: i , j , k , l
  22. SolvingEquationError = .FALSE.
  23. KickVandPFunction(:) = 0.d0
  24. KickJacobian(: , :) = 0.d0
  25. !====================================================
  26. ! Gas Properties (Methane Gas)
  27. !====================================================
  28. !GasPocketNewTemp%Array(1) = 600
  29. BottomHoleTemperature = 600
  30. KickFluxAvgPressure = (BottomHolePress + FormPressure) / 2 + StandardPress
  31. KickFluxAvgTemperature = (FormTemperature + BottomHoleTemperature) / 2
  32. KickFluxAvgCompressibility = 0.98d0
  33. K_Aa = (5.8742362 * 10.**(-3) * KickFluxAvgTemperature**1.2288) / (511.1728532 + KickFluxAvgTemperature)
  34. K_Bb = 5.5565586 + (1000.01 / KickFluxAvgTemperature)
  35. K_Cc = 2.47862 - 0.12294 * K_Bb
  36. GasKickSIDensity = KickFluxAvgPressure / (KickFluxAvgCompressibility * &
  37. KickFluxAvgTemperature * data%State%GasType(KickGasType)%GasConstant) * Convpcftogpcm3
  38. GasKickViscosity = K_Aa * EXP(K_Bb * GasKickSIDensity**K_Cc)
  39. !!!!!!!!!!!!!!!!!!!!!!!!!
  40. !!!!!!!!!!!!!! Calculating compressibility for bottom hole condition
  41. BottomHoleCompressibility = 0.98d0
  42. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  43. GasKickBg = 0.00504 * KickFluxAvgCompressibility * KickFluxAvgTemperature / KickFluxAvgPressure ![bbl/SCF]
  44. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  45. !WRITE (*,*) 'Gas Kick Top'
  46. !===> Kick Flow Rate Calculation
  47. IF (FormPressure > BottomHolePress) THEN
  48. KickmdotACoef = 10.0**(-8) * 1.15741d0 * 7.080 * FormPermeability * REAL(KickFormLength) * data%State%GasType(KickGasType)%StDensity / &
  49. (GasKickViscosity * GasKickBg * LOG(10000.0))
  50. !IF (WellHeadOpen .AND. NoGasPocket == 1) KickmdotACoef = (1.d0 + 2.d0) * KickmdotACoef
  51. ELSE
  52. KickmdotACoef = 0.0
  53. END IF
  54. i = data%State%FricPressDrop%StringLastEl
  55. j = data%State%FricPressDrop%OpenholeFirstEl - 1
  56. k = GasPocketFlowEl(1 , 1)
  57. KickmdotBCoef = FormPressure + StandardPress !! - Sum(static and friction pressure loss) of flow elements below gas pocket, see below
  58. IF (FormPressure > BottomHolePress) THEN
  59. !WRITE (*,*) 'k , i, j' , k , i, j
  60. IF (k >= data%State%FricPressDrop%OpenholeFirstEl) THEN ! Bottom of active kick is in openhole
  61. KickmdotBCoef = KickmdotBCoef - (SUM(FlowEl(data%State%FricPressDrop%OpenholeFirstEl : k)%StaticPressDiff)) !+ SUM(FlowEl(j + 1 : GasPocketFlowEl(1 , 1) - 1)%FricPressLoss
  62. !WRITE (*,*) '1 SUM(FlowEl(j + 1 : k)%FricPressLoss', k, SUM(FlowEl(j + 1 : k)%FricPressLoss)
  63. ELSE IF (k < data%State%FricPressDrop%OpenholeFirstEl) THEN ! bottom of 1st gas pocket (active kick) is in annulus ond/or choke line only
  64. KickmdotBCoef = KickmdotBCoef - SUM(FlowEl(data%State%FricPressDrop%OpenholeFirstEl : data%State%FricPressDrop%NumbEl)%StaticPressDiff) &
  65. - (SUM(FlowEl(data%State%FricPressDrop%AnnulusFirstEl : k)%StaticPressDiff) + SUM(FlowEl(data%State%FricPressDrop%AnnulusFirstEl : k)%FricPressLoss))
  66. END IF
  67. END IF
  68. DO l = 1 , NoGasPocket
  69. KickUnknownVector(2 * l - 1) = GasPocketNewVol%Array(l)
  70. KickUnknownVector(2 * l) = GasPocketNewPress%Array(l)
  71. END DO
  72. IF (WellHeadOpen) THEN
  73. !!!!!!!!!! Calculation of functions of pocket Pressure and gas Volumes
  74. !IF (GasPocketElementNo(1) > 0) WRITE (*,*) ' GasPocketElementNo(1) ' , GasPocketElementNo(1)
  75. !WRITE (*,*) ' Kick Unknown Vector' , KickUnknownVector!(1) , KickUnknownVector(2)
  76. IF (KickIteration == 1) THEN ! updating initial guess based on previous time step data
  77. DO l = 1 , NoGasPocket
  78. KickUnknownVector(2 * l - 1) = KickUnknownVector(2 * l - 1) + GasPocketDeltaVol%Array(l)
  79. END DO
  80. END IF
  81. KickVandPFunction(1) = KickUnknownVector(1) - GasPocketCompressibility%Array(1) * data%State%GasType(KickGasType)%GasConstant * & ! VandP(1) = V(1)
  82. GasPocketNewTemp%Array(1) * (GasPocketWeight%Array(1) + KickmdotACoef * MAX(((KickmdotBCoef - KickUnknownVector(2)) * dt) , 0.0)) / KickUnknownVector(2)
  83. !WRITE (*,*) 'KickVandPFunction(1)',KickVandPFunction(1)
  84. l = 2 * NoGasPocket
  85. CALL KickFunctionsCalculator(KickVandPFunction(l) , NoGasPocket , 2) ! VandP(last) = P(last)
  86. !WRITE (*,*) 'KickVandPFunction(l)', l, KickVandPFunction(l)
  87. DO l = 2 , NoGasPocket ! VandP(Odd) = V(l, l > 1)
  88. KickVandPFunction(2 * l - 1) = KickUnknownVector(2 * l - 1) - GasPocketCompressibility%Array(l) * data%State%GasType(KickGasType)%GasConstant * &
  89. GasPocketNewTemp%Array(l) * GasPocketWeight%Array(l) / KickUnknownVector(2 * l)
  90. !WRITE(*,*) 'KickVandPFunction(V)', l, KickVandPFunction(2 * l - 1)
  91. END DO
  92. DO l = NoGasPocket - 1 , 1 , -1
  93. CALL KickFunctionsCalculator(KickVandPFunction(2 * l) , l , 1) ! VandP(Even) = P(l, l < NoGasPocket)
  94. !WRITE(*,*) 'KickVandPFunction(P)', l , KickVandPFunction(2 * l)
  95. END DO
  96. !!!!!!!!!! END - Calculation of functions of pocket Pressure and gas Volumes
  97. !!!!!!!!!! Calculation of Jacobian
  98. DO k = 1 , 2 * NoGasPocket ! Main Diagonal
  99. KickJacobian(k , k) = 1.d0
  100. END DO
  101. KickJacobian(1,2) = (GasPocketCompressibility%Array(1) * data%State%GasType(KickGasType)%GasConstant * GasPocketNewTemp%Array(1) &
  102. * (GasPocketWeight%Array(1) + KickmdotACoef * KickmdotBCoef * dt) / KickUnknownVector(2)**2) ! Row 1 Finished
  103. IF (KickJacobian(1,2) == 0.d0) THEN
  104. CALL Error('KickJacobian(1,2) = 0.0')
  105. KickJacobian(1,2) = OldKickJacobian(1,2)
  106. END IF
  107. !WRITE(*,*) 'KickJacobian(1,2)', KickJacobian(1,2)
  108. l = NoGasPocket
  109. CALL KickFunctionsCalculator(KickJacobian(2 * l , 2 * l - 1) , NoGasPocket , 4) ! for last Row
  110. IF (KickJacobian(2 * l , 2 * l - 1) == 0.d0) THEN
  111. CALL Error ('KickJacobian(Last,Odd) = 0.0')
  112. KickJacobian(2 * l , 2 * l - 1) = OldKickJacobian(2 * l , 2 * l - 1)
  113. END IF
  114. DO k = NoGasPocket - 1 , 1 , -1
  115. KickJacobian(2 * l , 2 * k - 1) = KickJacobian(2 * l , 2 * l - 1)
  116. END DO ! Last Row Finished
  117. !WRITE(*,*) 'KickJacobian(2,1)', KickJacobian(2,1)
  118. DO k = 2 , NoGasPocket
  119. KickJacobian(2 * k - 1 , 2 * k) = GasPocketCompressibility%Array(k) * data%State%GasType(KickGasType)%GasConstant * GasPocketNewTemp%Array(k) &
  120. * GasPocketWeight%Array(k) / KickUnknownVector(2 * k)**2
  121. END DO ! Odd Rows (V equations) Finished
  122. DO k = 1 , NoGasPocket - 1
  123. KickJacobian(2 * k , 2 * k + 2) = -1.d0
  124. END DO ! Even Rows (P equations) effect of upper pocket
  125. DO k = 2 , 2 * (NoGasPocket - 1) , 2
  126. DO l = 1 , k - 1 , 2
  127. CALL KickFunctionsCalculator(KickJacobian(k , l) , k / 2 , 3)
  128. IF (KickJacobian(k , l) == 0.d0) THEN
  129. WRITE (*,*) 'Jacobian Array = 0.0', k , l
  130. CALL Error ('KickJacobian(k , l) = 0.0')
  131. KickJacobian(k , l) = OldKickJacobian(k , l)
  132. END IF
  133. END DO
  134. END DO
  135. IF (ANY(IEEE_IS_NaN(KickJacobian))) CALL ErrorStop ('NaN in calculating Kick Jacobian, Call your Service Provider')
  136. !!!!!!!!!! Solving linear equation in order to finding correction vector for correcting pocket pressure and gas induced flowrates
  137. KickVandPFunction = -1.d0 * KickVandPFunction
  138. CALL SOLVE_LINEAR_EQUATIONS(KickJacobian , KickCorrectionVector , KickVandPFunction , SolvingEquationError, SIZE(KickCorrectionVector))
  139. IF (SolvingEquationError) CALL ErrorStop( ' Error in solving kick equation ' )
  140. KickUnknownVector = KickUnknownVector + KickCorrectionUnderRelaxation * KickCorrectionVector
  141. DO l = 1 , NoGasPocket
  142. GasPocketNewVol%Array(l) = KickUnknownVector(2 * l - 1)
  143. IF (IEEE_IS_NaN(GasPocketNewVol%Array(l))) CALL ErrorStop('Volume of this pocket is Not a Number:', l)
  144. IF (GasPocketNewVol%Array(l) <= 0.d0) CALL Error('Volume of this pocket is Negative or Zero:', l)
  145. GasPocketNewPress%Array(l) = KickUnknownVector(2 * l)
  146. IF (IEEE_IS_NaN(GasPocketNewPress%Array(l))) CALL ErrorStop('Pressure of this Pocket is Not a Number:', l)
  147. IF (GasPocketNewPress%Array(l) <= 0.d0) CALL ErrorStop('Pressure of this Pocket is Negative or Zero:', l)
  148. END DO
  149. ELSE ! well haed is closed, so build up process or migration occurs
  150. !WRITE (*,*) 'GasPocketOldPress (before)' , GasPocketOldPress(1)
  151. GasPocketNewPress%Array(1) = GasPocketOldPress%Array(1) * &
  152. (REAL((GasPocketWeight%Array(1) + KickmdotACoef * KickmdotBCoef * dt) / (GasPocketWeight%Array(1) + KickmdotACoef * GasPocketOldPress%Array(1) * dt)))
  153. END IF
  154. !DO l = 1 , NoGasPocket
  155. GasPocketDeltaVol%Array(:) = GasPocketNewVol%Array(:) - GasPocketOldVol%Array(:)
  156. GasPocketFlowInduced%Array(:) = (GasPocketDeltaVol%Array(:)) / dt * 448.8 ! gpm
  157. !END DO
  158. GasKickPumpFlowRate = 0.0
  159. IF (NOT(KickOffBottom) .AND. WellHeadOpen) GasKickPumpFlowRate = GasPocketFlowInduced%Array(1)
  160. END SUBROUTINE
  161. SUBROUTINE KickFunctionsCalculator(ExitValue , GasPocketNo , CalcMode)
  162. use SimulationVariables
  163. use KickVARIABLESModule
  164. USE FricPressDropVarsModule
  165. USE Fluid_Flow_Startup_Vars
  166. USE CError
  167. USE , INTRINSIC :: IEEE_Arithmetic
  168. IMPLICIT NONE
  169. REAL(8) :: ExitValue
  170. INTEGER :: GasPocketNo , CalcMode
  171. INTEGER :: x
  172. INTEGER :: y
  173. INTEGER :: z , i , j
  174. x = GasPocketFlowEl(GasPocketNo , 1)
  175. IF (GasPocketNo < NoGasPocket) y = GasPocketFlowEl(GasPocketNo + 1 , 1)
  176. i = data%State%FricPressDrop%StringLastEl
  177. j = data%State%FricPressDrop%OpenholeFirstEl - 1
  178. ! Case 1: gas pocket is completely in OP and STARTX of upper gas pocket is also
  179. ! Case 2: gas pocket is completely in OP and STARTX of upper gas pocket is above Bit
  180. ! Case 3: gas pocket is AROUNDBIT and so upper gas pocket is in ANN (or Choke line)
  181. ! Case 4: gas pocket is completely in ANN and upper gas pocket is also
  182. ! CalcMode 1: KickVandPFunction between 2 pocket
  183. ! CalcMode 2: KickVandPFunction for top gas pocket
  184. ! CalcMode 3: KickJacobian between 2 Pocket
  185. ! CalcMode 4: KickJacobian for top (last) gas pocket
  186. ! CalcMode 5: Calculating pressure of bottom pocket based on upper pocket
  187. IF (CalcMode == 1) THEN ! calculating pressure difference between two pocket, include static pressure difference and frictional
  188. ! pressure difference, use in calculating 'KickVandPFunction'
  189. ExitValue = KickUnknownVector(2 * GasPocketNo) - KickUnknownVector(2 * GasPocketNo + 2)
  190. IF (x >= data%State%FricPressDrop%OpenholeFirstEl .AND. y < data%State%FricPressDrop%OpenholeFirstEl) THEN ! Case 2 , Case 3
  191. ExitValue = ExitValue - SUM(FlowEl(x : data%State%FricPressDrop%NumbEl)%StaticPressDiff) - SUM(FlowEl(x : data%State%FricPressDrop%NumbEl)%FricPressLoss) &
  192. - SUM(FlowEl(data%State%FricPressDrop%AnnulusFirstEl : y)%StaticPressDiff) - SUM(FlowEl(data%State%FricPressDrop%AnnulusFirstEl : y)%FricPressLoss)
  193. ELSE ! Case 1 , Case 4
  194. ExitValue = ExitValue - SUM(FlowEl(x : y)%StaticPressDiff) - SUM(FlowEl(x : y)%FricPressLoss)
  195. END IF
  196. ELSE IF (CalcMode == 2) THEN
  197. ExitValue = KickUnknownVector(2 * GasPocketNo) - StandardPress - data%State%FricPressDrop%Kchoke * FlowEl(data%State%FricPressDrop%OpenholeFirstEl - 1)%Flowrate**2
  198. IF (x >= data%State%FricPressDrop%OpenholeFirstEl) THEN ! Gas Pocket is in Openhole
  199. ExitValue = ExitValue - SUM(FlowEl(x : data%State%FricPressDrop%NumbEl)%StaticPressDiff) - SUM(FlowEl(x : data%State%FricPressDrop%NumbEl)%FricPressLoss) &
  200. - SUM(FlowEl(data%State%FricPressDrop%AnnulusFirstEl : data%State%FricPressDrop%OpenholeFirstEl - 1)%StaticPressDiff) - SUM(FlowEl(data%State%FricPressDrop%AnnulusFirstEl : data%State%FricPressDrop%OpenholeFirstEl - 1)%FricPressLoss)
  201. ELSE ! Gas Pocket is in Annulus
  202. ExitValue = ExitValue - SUM(FlowEl(x : data%State%FricPressDrop%OpenholeFirstEl - 1)%StaticPressDiff) - SUM(FlowEl(x : data%State%FricPressDrop%OpenholeFirstEl - 1)%FricPressLoss)
  203. END IF
  204. ELSE IF (CalcMode == 3) THEN ! calculating derivative of pressure difference between two pocket, relative to change in flowrate
  205. ! use in calculating 'KickJacobian'
  206. IF (x >= data%State%FricPressDrop%OpenholeFirstEl .AND. y < data%State%FricPressDrop%OpenholeFirstEl) THEN ! Top kick STARTX is in Annulus
  207. DO z = x , data%State%FricPressDrop%NumbEl ! open hole elements
  208. CALL PartialDerivativeFricToFlowRate(z)
  209. IF (IEEE_IS_NaN(FlowEl(z)%FricToQPartialDiff)) THEN
  210. WRITE (*,*) ' FricToQPartialDiff , GenRe ' , x , FlowEl(z)%FricToQPartialDiff , FlowEl(z)%GenRe
  211. WRITE (*,*) ' Op start, end, density, Q, mu' , FlowEl(z)%StartX, FlowEl(z)%EndX, FlowEl(z)%Density, FlowEl(z)%FlowRate, FlowEl(z)%mueff
  212. CALL ErrorStop('NaN in calculating partial derivative')
  213. END IF
  214. END DO
  215. DO z = data%State%FricPressDrop%AnnulusFirstEl , y ! Annulus elements
  216. CALL PartialDerivativeFricToFlowRate(z)
  217. IF (IEEE_IS_NaN(FlowEl(z)%FricToQPartialDiff)) THEN
  218. WRITE (*,*) ' FricToQPartialDiff , GenRe ' , x , FlowEl(z)%FricToQPartialDiff , FlowEl(z)%GenRe
  219. WRITE (*,*) ' Op start, end, density, Q, mu' , FlowEl(z)%StartX, FlowEl(z)%EndX, FlowEl(z)%Density, FlowEl(z)%FlowRate, FlowEl(z)%mueff
  220. CALL ErrorStop('NaN in calculating partial derivative')
  221. END IF
  222. END DO
  223. ExitValue = ExitValue - (SUM(FlowEl(x : data%State%FricPressDrop%NumbEl)%FricToQPartialDiff) + SUM(FlowEl(data%State%FricPressDrop%AnnulusFirstEl : y)%FricToQPartialDiff)) * 448.8 / dt
  224. ELSE ! both pockets are one side of bit
  225. DO z = x , y
  226. CALL PartialDerivativeFricToFlowRate(z)
  227. IF (IEEE_IS_NaN(FlowEl(z)%FricToQPartialDiff)) THEN
  228. WRITE (*,*) ' FricToQPartialDiff , GenRe ' , x , FlowEl(z)%FricToQPartialDiff , FlowEl(z)%GenRe
  229. WRITE (*,*) ' Op start, end, density, Q, mu' , FlowEl(z)%StartX, FlowEl(z)%EndX, FlowEl(z)%Density, FlowEl(z)%FlowRate, FlowEl(z)%mueff
  230. CALL ErrorStop('NaN in calculating partial derivative')
  231. END IF
  232. END DO
  233. ExitValue = ExitValue - SUM(FlowEl(x : y)%FricToQPartialDiff) * 448.8 / dt
  234. END IF
  235. ELSE IF (CalcMode == 4) THEN ! partial derivative of frictional pressure drop relative to flowrate for top gas pocket
  236. ExitValue = - 2.d0 * data%State%FricPressDrop%Kchoke * FlowEl(data%State%FricPressDrop%OpenholeFirstEl - 1)%Flowrate * 448.8 / dt
  237. IF (x >= data%State%FricPressDrop%OpenholeFirstEl) THEN ! kick STARTX is in openhole
  238. DO z = x , data%State%FricPressDrop%NumbEl ! open hole elements
  239. CALL PartialDerivativeFricToFlowRate(z)
  240. IF (IEEE_IS_NaN(FlowEl(z)%FricToQPartialDiff)) THEN
  241. WRITE (*,*) ' FricToQPartialDiff , GenRe ' , x , FlowEl(z)%FricToQPartialDiff , FlowEl(z)%GenRe
  242. WRITE (*,*) ' Op start, end, density, Q, mu' , FlowEl(z)%StartX, FlowEl(z)%EndX, FlowEl(z)%Density, FlowEl(z)%FlowRate, FlowEl(z)%mueff
  243. CALL ErrorStop('NaN in calculating partial derivative')
  244. END IF
  245. END DO
  246. DO z = data%State%FricPressDrop%AnnulusFirstEl , data%State%FricPressDrop%OpenholeFirstEl - 1 ! Annulus elements
  247. CALL PartialDerivativeFricToFlowRate(z)
  248. IF (IEEE_IS_NaN(FlowEl(z)%FricToQPartialDiff)) THEN
  249. WRITE (*,*) ' FricToQPartialDiff , GenRe ' , x , FlowEl(z)%FricToQPartialDiff , FlowEl(z)%GenRe
  250. WRITE (*,*) ' Op start, end, density, Q, mu' , FlowEl(z)%StartX, FlowEl(z)%EndX, FlowEl(z)%Density, FlowEl(z)%FlowRate, FlowEl(z)%mueff
  251. CALL ErrorStop('NaN in calculating partial derivative')
  252. END IF
  253. END DO
  254. ExitValue = ExitValue - (SUM(FlowEl(x : data%State%FricPressDrop%NumbEl)%FricToQPartialDiff) + SUM(FlowEl(data%State%FricPressDrop%AnnulusFirstEl : data%State%FricPressDrop%OpenholeFirstEl - 1)%FricToQPartialDiff)) * 448.8 / dt
  255. ELSE
  256. DO z = x , data%State%FricPressDrop%OpenholeFirstEl - 1 ! Annulus elements
  257. CALL PartialDerivativeFricToFlowRate(z)
  258. IF (IEEE_IS_NaN(FlowEl(z)%FricToQPartialDiff)) THEN
  259. WRITE (*,*) ' FricToQPartialDiff , GenRe ' , x , FlowEl(z)%FricToQPartialDiff , FlowEl(z)%GenRe
  260. WRITE (*,*) ' Op start, end, density, Q, mu' , FlowEl(z)%StartX, FlowEl(z)%EndX, FlowEl(z)%Density, FlowEl(z)%FlowRate, FlowEl(z)%mueff
  261. CALL ErrorStop('NaN in calculating partial derivative')
  262. END IF
  263. END DO
  264. ExitValue = ExitValue - SUM(FlowEl(x : data%State%FricPressDrop%OpenholeFirstEl - 1)%FricToQPartialDiff) * 448.8 / dt
  265. END IF
  266. ELSE IF (CalcMode == 5) THEN
  267. IF (x >= data%State%FricPressDrop%OpenholeFirstEl .AND. y < data%State%FricPressDrop%OpenholeFirstEl) THEN ! Gas Pocket is in Openhole and upper pocket is in annulus
  268. !WRITE (*,*) 'x , y 1' , x, y
  269. ExitValue = GasPocketNewPress%Array(GasPocketNo + 1) + SUM(FlowEl(x : data%State%FricPressDrop%NumbEl)%StaticPressDiff) + SUM(FlowEl(data%State%FricPressDrop%AnnulusFirstEl : y)%StaticPressDiff)
  270. ELSE ! Both gas pockets are in Annulus or openhole
  271. !WRITE (*,*) 'x , y 2' , x, y
  272. ExitValue = GasPocketNewPress%Array(GasPocketNo + 1) + SUM(FlowEl(x : y)%StaticPressDiff)
  273. END IF
  274. END IF
  275. END SUBROUTINE
  276. SUBROUTINE NewGasKick
  277. use SimulationVariables
  278. use KickVARIABLESModule
  279. use SimulationVariables !@
  280. Use CReservoirVariables
  281. Use CFormationVariables
  282. USE Fluid_Flow_Startup_Vars
  283. use PressureDisplayVARIABLESModule
  284. USE FricPressDropVarsModule
  285. USE MudSystemVARIABLES
  286. use SimulationVariables !@@@
  287. USE CMudPropertiesVariables
  288. USE CError
  289. USE , INTRINSIC :: IEEE_ARITHMETIC
  290. !! Note: a subject that may be confusing is that when we use gauge pressure and when using absolute pressure?!
  291. !! all stated pressure are gauge pressure, so I do like this.
  292. !! only when we want to use a state equation (like ideal gas equation), we should use absolute equation and so I do this.
  293. !! Thus gas pocket pressure are all absolute pressure.
  294. IMPLICIT NONE
  295. INTEGER :: i , j , k , l
  296. IF (NOT(ALLOCATED(GasPocketWeight%Array))) THEN ! 1st kick
  297. WRITE (*,*) ' New Influx 1'
  298. NoGasPocket = 1
  299. data%State%MudSystem%NewInfluxNumber = data%State%MudSystem%NewInfluxNumber + 1
  300. data%State%MudSystem%NewInfluxElementCreated = 0
  301. KickOffBottom = .FALSE.
  302. CALL GasPocketOldPress%AddToFirst((BottomHolePress + StandardPress) * 1.d0)
  303. CALL GasPocketNewPress%AddToFirst((BottomHolePress + StandardPress) * 1.d0)
  304. CALL GasPocketOldTemp%AddToFirst(600.0)
  305. CALL GasPocketNewTemp%AddToFirst(600.0)
  306. CALL GasPocketOldVol%AddToFirst(0.d0)
  307. CALL GasPocketNewVol%AddToFirst(0.d0)
  308. CALL GasPocketdeltaVol%AddToFirst(0.0)
  309. CALL GasPocketFlowInduced%AddToFirst(0.0)
  310. CALL GasPocketModifiedVol%AddToFirst(0.0)
  311. CALL GasPocketWeight%AddToFirst(0.0)
  312. CALL GasPocketDensity%AddToFirst(2.0)
  313. CALL GasPocketCompressibility%AddToFirst(0.98)
  314. ALLOCATE(KickJacobian(2 , 2) , OldKickJacobian(2 , 2) , KickVandPFunction(2) , KickUnknownVector(2) , KickCorrectionVector(2))
  315. BottomHoleTemperature = 600
  316. KickFluxAvgPressure = (BottomHolePress + FormPressure) / 2 + StandardPress
  317. KickFluxAvgTemperature = (FormTemperature + BottomHoleTemperature) / 2
  318. KickFluxAvgCompressibility = 0.98
  319. GasKickSIDensity = KickFluxAvgPressure / (KickFluxAvgCompressibility * &
  320. KickFluxAvgTemperature * data%State%GasType(KickGasType)%GasConstant) * Convpcftogpcm3
  321. GasKickDensity = GasKickSIDensity * 8.3523
  322. GasPocketWeight%Array(1) = GasKickDensity * MinKickVol !1.0:seyyed gofte !KickmdotACoef * (KickmdotBCoef - GasPocketNewPress%Array(1)) * dt
  323. GasPocketNewVol%Array(1) = GasPocketCompressibility%Array(1) * data%State%GasType(KickGasType)%GasConstant * &
  324. GasPocketNewTemp%Array(1) * GasPocketWeight%Array(1) / GasPocketNewPress%Array(1)
  325. GasPocketDeltaVol%Array(1) = 0.05 !GasPocketNewVol%Array(1)
  326. GasPocketFlowInduced%Array(1) = (GasPocketDeltaVol%Array(1)) / dt * 448.8 ! gpm
  327. GasKickPumpFlowRate = GasPocketFlowInduced%Array(1)
  328. WRITE (*,*) ' FormPressure , BottomHolePress' , FormPressure , BottomHolePress, GasKickDensity
  329. WRITE (*,*) ' No Press(psia) Vol(gal) Weight(lbm) Flow Induced(gpm)'
  330. DO i = 1 , NoGasPocket
  331. WRITE (*,102) i , GasPocketNewPress%Array(i), GasPocketNewVol%Array(i) * Convft3toUSgal, GasPocketWeight%Array(i), GasPocketFlowInduced%Array(i)
  332. END DO
  333. !ELSE IF (NoGasPocket < MaxGasPocket .AND. KickOffBottom .AND. (GasPocketNewVol%Array(1) > MinAllowableKickVol .OR. KickWasExitingThroughChoke)) THEN
  334. ELSE IF (NoGasPocket < MaxGasPocket .AND. KickOffBottom .AND. (GasPocketNewVol%Array(1) > MinAllowableKickVol .OR. ANY(GasPocketFlowEl(1 , :) == data%State%FricPressDrop%OpenholeFirstEl - 1))) THEN
  335. WRITE (*,*) ' New Influx', NoGasPocket + 1
  336. 102 FORMAT (I2, 4X, (F8.1), 3X, (F8.3), 2X, (F8.3), 8X, (F8.3))
  337. NoGasPocket = NoGasPocket + 1
  338. data%State%MudSystem%NewInfluxNumber = data%State%MudSystem%NewInfluxNumber + 1
  339. data%State%MudSystem%NewInfluxElementCreated = 0
  340. KickOffBottom = .FALSE.
  341. CALL GasPocketOldPress%AddToFirst((BottomHolePress + StandardPress) * 1.d0)
  342. CALL GasPocketNewPress%AddToFirst((BottomHolePress + StandardPress) * 1.d0)
  343. CALL GasPocketOldTemp%AddToFirst(600.0)
  344. CALL GasPocketNewTemp%AddToFirst(600.0)
  345. CALL GasPocketOldVol%AddToFirst(0.d0)
  346. CALL GasPocketNewVol%AddToFirst(0.d0)
  347. CALL GasPocketdeltaVol%AddToFirst(0.0)
  348. CALL GasPocketFlowInduced%AddToFirst(0.0)
  349. CALL GasPocketModifiedVol%AddToFirst(0.0)
  350. CALL GasPocketWeight%AddToFirst(0.0)
  351. CALL GasPocketDensity%AddToFirst(2.0)
  352. CALL GasPocketCompressibility%AddToFirst(0.98)
  353. DEALLOCATE(KickJacobian , OldKickJacobian , KickVandPFunction , KickUnknownVector , KickCorrectionVector)
  354. ALLOCATE(KickJacobian(2 * NoGasPocket , 2 * NoGasPocket) , OldKickJacobian(2 * NoGasPocket , 2 * NoGasPocket))
  355. ALLOCATE(KickUnknownVector(2 * NoGasPocket) , KickCorrectionVector(2 * NoGasPocket) , KickVandPFunction(2 * NoGasPocket))
  356. BottomHoleTemperature = 600
  357. KickFluxAvgPressure = (BottomHolePress + FormPressure) / 2 + StandardPress
  358. KickFluxAvgTemperature = (FormTemperature + BottomHoleTemperature) / 2
  359. KickFluxAvgCompressibility = 0.98
  360. GasKickSIDensity = KickFluxAvgPressure / (KickFluxAvgCompressibility * &
  361. KickFluxAvgTemperature * data%State%GasType(KickGasType)%GasConstant) * Convpcftogpcm3
  362. GasKickDensity = GasKickSIDensity * 8.3523
  363. !GasPocketWeight%Array(1) = GasKickDensity * 0.05 !KickmdotACoef * (KickmdotBCoef - GasPocketNewPress%Array(1)) * dt
  364. GasPocketWeight%Array(1) = GasKickDensity * MinKickVol !1.0:seyyed gofte !KickmdotACoef * (KickmdotBCoef - GasPocketNewPress%Array(1)) * dt
  365. GasPocketNewVol%Array(1) = GasPocketCompressibility%Array(1) * data%State%GasType(KickGasType)%GasConstant * &
  366. GasPocketNewTemp%Array(1) * GasPocketWeight%Array(1) / GasPocketNewPress%Array(1)
  367. GasPocketDeltaVol%Array(1) = 0.05 !GasPocketNewVol%Array(1)
  368. GasPocketFlowInduced%Array(1) = (GasPocketDeltaVol%Array(1)) / dt * 448.8 ! gpm
  369. GasKickPumpFlowRate = GasPocketFlowInduced%Array(1)
  370. WRITE (*,*) ' FormPressure , BottomHolePress' , FormPressure , BottomHolePress, GasKickDensity
  371. WRITE (*,*) ' No Press(psia) Vol(gal) Weight(lbm) Flow Induced(gpm)'
  372. DO i = 1 , NoGasPocket
  373. WRITE (*,102) i , GasPocketNewPress%Array(i), GasPocketNewVol%Array(i) * Convft3toUSgal, GasPocketWeight%Array(i), GasPocketFlowInduced%Array(i)
  374. END DO
  375. ELSE ! no new kick, so mass of 1st kick should increase
  376. GasPocketWeight%Array(1) = GasPocketweight%Array(1) + KickmdotACoef * (KickmdotBCoef - GasPocketNewPress%Array(1)) * dt
  377. GasKickPumpFlowRate = GasPocketFlowInduced%Array(1)
  378. IF (NoGasPocket > 1 .OR. SecondaryKickWeight > 0.0) THEN
  379. SecondaryKickWeight = SecondaryKickWeight + KickmdotACoef * (KickmdotBCoef - GasPocketNewPress%Array(1)) * dt
  380. SecondaryKickVol = SecondaryKickWeight / GasReservoirDensity / 42.0 ! 42 USGal = 1bbl
  381. END IF
  382. END IF
  383. END SUBROUTINE