obsinter_z1d.h90 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. !!----------------------------------------------------------------------
  2. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  3. !! $Id: obsinter_z1d.h90 2287 2010-10-18 07:53:52Z smasson $
  4. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  5. !!----------------------------------------------------------------------
  6. SUBROUTINE obs_int_z1d( kpk, kkco, k1dint, kdep, &
  7. & pobsdep, pobsk, pobs2k, &
  8. & pobs, pdep, pobsmask )
  9. !!---------------------------------------------------------------------
  10. !!
  11. !! *** ROUTINE obs_int_z1d ***
  12. !!
  13. !! ** Purpose : Vertical interpolation to the observation point.
  14. !!
  15. !! ** Method : If k1dint = 0 then use linear interpolation.
  16. !! If k1dint = 1 then use cubic spline interpolation.
  17. !!
  18. !! ** Action :
  19. !!
  20. !! References :
  21. !!
  22. !! History
  23. !! ! 97-11 (A. Weaver, S. Ricci, N. Daget)
  24. !! ! 06-03 (G. Smith) Conversion to F90 for use with NEMOVAR
  25. !! ! 06-10 (A. Weaver) Cleanup
  26. !! ! 07-01 (K. Mogensen) Use profile rather than single level
  27. !!---------------------------------------------------------------------
  28. !! * Arguments
  29. INTEGER, INTENT(IN) :: kpk ! Number of vertical levels
  30. INTEGER, INTENT(IN) :: k1dint ! 0 = linear; 1 = cubic spline interpolation
  31. INTEGER, INTENT(IN) :: kdep ! Number of levels in profile
  32. INTEGER, INTENT(IN), DIMENSION(kdep) :: &
  33. & kkco ! Array indicies for interpolation
  34. REAL(KIND=wp), INTENT(IN), DIMENSION(kdep) :: &
  35. & pobsdep ! Depth of the observation
  36. REAL(KIND=wp), INTENT(IN), DIMENSION(kpk) :: &
  37. & pobsk, & ! Model profile at a given (lon,lat)
  38. & pobs2k, & ! 2nd derivative of the interpolating function
  39. & pdep, & ! Model depth array
  40. & pobsmask ! Vertical mask
  41. REAL(KIND=wp), INTENT(OUT), DIMENSION(kdep) :: &
  42. & pobs ! Model equivalent at observation point
  43. !! * Local declarations
  44. REAL(KIND=wp) :: z1dm ! Distance above and below obs to model grid points
  45. REAL(KIND=wp) :: z1dp
  46. REAL(KIND=wp) :: zsum ! Dummy variables for computation
  47. REAL(KIND=wp) :: zsum2
  48. INTEGER :: jdep ! Observation depths loop variable
  49. !------------------------------------------------------------------------
  50. ! Loop over all observation depths
  51. !------------------------------------------------------------------------
  52. DO jdep = 1, kdep
  53. !---------------------------------------------------------------------
  54. ! Initialization
  55. !---------------------------------------------------------------------
  56. z1dm = ( pdep(kkco(jdep)) - pobsdep(jdep) )
  57. z1dp = ( pobsdep(jdep) - pdep(kkco(jdep)-1) )
  58. IF ( pobsmask(kkco(jdep)) == 0.0_wp ) z1dp = 0.0_wp
  59. zsum = z1dm + z1dp
  60. IF ( k1dint == 0 ) THEN
  61. !-----------------------------------------------------------------
  62. ! Linear interpolation
  63. !-----------------------------------------------------------------
  64. pobs(jdep) = ( z1dm * pobsk(kkco(jdep)-1) &
  65. & + z1dp * pobsk(kkco(jdep) ) ) / zsum
  66. ELSEIF ( k1dint == 1 ) THEN
  67. !-----------------------------------------------------------------
  68. ! Cubic spline interpolation
  69. !-----------------------------------------------------------------
  70. zsum2 = zsum * zsum
  71. pobs(jdep) = ( z1dm * pobsk (kkco(jdep)-1) &
  72. & + z1dp * pobsk (kkco(jdep) ) &
  73. & + ( z1dm * ( z1dm * z1dm - zsum2 ) * pobs2k(kkco(jdep)-1) &
  74. & + z1dp * ( z1dp * z1dp - zsum2 ) * pobs2k(kkco(jdep) ) &
  75. & ) / 6.0_wp &
  76. & ) / zsum
  77. ENDIF
  78. END DO
  79. END SUBROUTINE obs_int_z1d
  80. SUBROUTINE obs_int_z1d_spl( kpk, pobsk, pobs2k, &
  81. & pdep, pobsmask )
  82. !!--------------------------------------------------------------------
  83. !!
  84. !! *** ROUTINE obs_int_z1d_spl ***
  85. !!
  86. !! ** Purpose : Compute the local vector of vertical second-derivatives
  87. !! of the interpolating function used with a cubic spline.
  88. !!
  89. !! ** Method :
  90. !!
  91. !! Top and bottom boundary conditions on the 2nd derivative are
  92. !! set to zero.
  93. !!
  94. !! ** Action :
  95. !!
  96. !! References :
  97. !!
  98. !! History
  99. !! ! 01-11 (A. Weaver, S. Ricci, N. Daget)
  100. !! ! 06-03 (G. Smith) Conversion to F90 for use with NEMOVAR
  101. !! ! 06-10 (A. Weaver) Cleanup
  102. !!----------------------------------------------------------------------
  103. !! * Arguments
  104. INTEGER, INTENT(IN) :: kpk ! Number of vertical levels
  105. REAL(KIND=wp), INTENT(IN), DIMENSION(kpk) :: &
  106. & pobsk, & ! Model profile at a given (lon,lat)
  107. & pdep, & ! Model depth array
  108. & pobsmask ! Vertical mask
  109. REAL(KIND=wp), INTENT(OUT), DIMENSION(kpk) :: &
  110. & pobs2k ! 2nd derivative of the interpolating function
  111. !! * Local declarations
  112. INTEGER :: jk
  113. REAL(KIND=wp) :: za
  114. REAL(KIND=wp) :: zb
  115. REAL(KIND=wp) :: zc
  116. REAL(KIND=wp) :: zpa
  117. REAL(KIND=wp) :: zkm
  118. REAL(KIND=wp) :: zkp
  119. REAL(KIND=wp) :: zk
  120. REAL(KIND=wp), DIMENSION(kpk-1) :: &
  121. & zs, &
  122. & zp, &
  123. & zu, &
  124. & zv
  125. !-----------------------------------------------------------------------
  126. ! Matrix initialisation
  127. !-----------------------------------------------------------------------
  128. zs(1) = 0.0_wp
  129. zp(1) = 0.0_wp
  130. zv(1) = -0.5_wp
  131. DO jk = 2, kpk-1
  132. zs(jk) = ( pdep(jk ) - pdep(jk-1) ) &
  133. & / ( pdep(jk+1) - pdep(jk-1) )
  134. zp(jk) = zs(jk) * zv(jk-1) + 2.0_wp
  135. zv(jk) = ( zs(jk) - 1.0_wp ) / zp(jk)
  136. END DO
  137. !-----------------------------------------------------------------------
  138. ! Solution of the tridiagonal system
  139. !-----------------------------------------------------------------------
  140. ! Top boundary condition
  141. zu(1) = 0.0_wp
  142. DO jk = 2, kpk-1
  143. za = pdep(jk+1) - pdep(jk-1)
  144. zb = pdep(jk+1) - pdep(jk )
  145. zc = pdep(jk ) - pdep(jk-1)
  146. zpa = 6.0_wp / ( zp(jk) * za )
  147. zkm = zpa / zc
  148. zkp = zpa / zb
  149. zk = - ( zkm + zkp )
  150. zu(jk) = pobsk(jk+1) * zkp &
  151. & + pobsk(jk ) * zk &
  152. & + pobsk(jk-1) * zkm &
  153. & + zu(jk-1) * ( -zs(jk) / zp(jk) )
  154. END DO
  155. !-----------------------------------------------------------------------
  156. ! Second derivative
  157. !-----------------------------------------------------------------------
  158. pobs2k(kpk) = 0.0_wp
  159. ! Bottom boundary condition
  160. DO jk = kpk-1, 1, -1
  161. pobs2k(jk) = zv(jk) * pobs2k(jk+1) + zu(jk)
  162. IF ( pobsmask(jk+1) == 0.0_wp ) pobs2k(jk) = 0.0_wp
  163. END DO
  164. END SUBROUTINE obs_int_z1d_spl