domc1d.F90 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. MODULE domc1d
  2. !!======================================================================
  3. !! *** MODULE domc1d ***
  4. !! Ocean Domain : 1D column position from lat/lon namelist specification
  5. !!======================================================================
  6. !! History : 3.5 ! 2013-04 (D. Calvert) Original code
  7. !!----------------------------------------------------------------------
  8. #if defined key_c1d
  9. !!----------------------------------------------------------------------
  10. !! 'key_c1d' : 1D Configuration
  11. !!----------------------------------------------------------------------
  12. !! dom_c1d : Determine jpizoom/jpjzoom from a given lat/lon
  13. !!----------------------------------------------------------------------
  14. USE phycst ! Physical constants (and par_oce)
  15. USE iom ! I/O library (iom_get)
  16. USE in_out_manager ! I/O manager (ctmp1)
  17. USE dom_oce , ONLY : nimpp, njmpp ! Shared/distributed memory setting (mpp_init routine)
  18. USE wrk_nemo ! Memory allocation
  19. USE timing ! Timing
  20. IMPLICIT NONE
  21. PRIVATE
  22. PUBLIC dom_c1d ! Routine called in domcfg.F90
  23. !!----------------------------------------------------------------------
  24. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  25. !! $Id: domc1d.F90 2355 2015-05-20 07:11:50Z ufla $
  26. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  27. !!----------------------------------------------------------------------
  28. CONTAINS
  29. SUBROUTINE dom_c1d( plat, plon )
  30. !!----------------------------------------------------------------------
  31. !! *** ROUTINE dom_c1d ***
  32. !!
  33. !! ** Purpose : Recalculate jpizoom/jpjzoom indices from lat/lon point
  34. !!
  35. !! ** Method : Calculate global gphit and glamt as for dom_hgr.
  36. !! After, find closest grid point to lat/lon point as for
  37. !! dom_ngb on T grid. From this infer jpizoom and jpjzoom.
  38. !!
  39. !! ** Action : Recalculate jpizoom, jpjzoom (indices of C1D zoom)
  40. !!----------------------------------------------------------------------
  41. NAMELIST/namdom/ nn_bathy, rn_bathy , rn_e3zps_min, rn_e3zps_rat, nn_msh, rn_hmin, &
  42. & nn_acc , rn_atfp , rn_rdt , rn_rdtmin , &
  43. & rn_rdtmax, rn_rdth , nn_closea , ln_crs, &
  44. & jphgr_msh, &
  45. & ppglam0, ppgphi0, ppe1_deg, ppe2_deg, ppe1_m, ppe2_m, &
  46. & ppsur, ppa0, ppa1, ppkth, ppacr, ppdzmin, pphmax, ldbletanh, &
  47. & ppa2, ppkth2, ppacr2
  48. INTEGER :: ji, jj ! Dummy loop indices
  49. INTEGER :: inum ! Coordinate file handle (case 0)
  50. INTEGER :: ijeq ! Index of equator T point (case 4)
  51. INTEGER :: ios ! Local integer output status for namelist read
  52. INTEGER , DIMENSION(2) :: iloc ! Minloc returned indices
  53. REAL(wp), INTENT(in) :: plat ! Column latitude
  54. REAL(wp), INTENT(in) :: plon ! Column longitude
  55. REAL(wp) :: zlon ! Wraparound longitude
  56. REAL(wp) :: zti, ztj, zarg ! Local scalars
  57. REAL(wp) :: glam0, gphi0 ! Variables corresponding to parameters ppglam0 ppgphi0 set in par_oce
  58. REAL(wp) :: zlam1, zcos_alpha, ze1, ze1deg ! Case 5 local scalars
  59. REAL(wp) :: zphi1, zsin_alpha, zim05, zjm05 ! "
  60. REAL(wp) , POINTER, DIMENSION(:,:) :: gphidta, glamdta, zdist ! Global lat/lon
  61. !!----------------------------------------------------------------------
  62. IF( nn_timing == 1 ) CALL timing_start('dom_c1d')
  63. REWIND( numnam_ref ) ! Namelist namdom in reference namelist : space & time domain (bathymetry, mesh, timestep)
  64. READ ( numnam_ref, namdom, IOSTAT = ios, ERR = 901 )
  65. 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namdom in reference namelist', lwp )
  66. !
  67. REWIND( numnam_cfg ) ! Namelist namdom in configuration namelist : space & time domain (bathymetry, mesh, timestep)
  68. READ ( numnam_cfg, namdom, IOSTAT = ios, ERR = 902 )
  69. 902 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namdom in configuration namelist', lwp )
  70. CALL wrk_alloc( jpidta, jpjdta, gphidta, glamdta, zdist )
  71. ! ============================= !
  72. ! Code from dom_hgr: !
  73. ! Calculate global horizontal !
  74. ! mesh, only glamt and gphit !
  75. ! ============================= !
  76. SELECT CASE( jphgr_msh ) ! type of horizontal mesh
  77. CASE ( 0 ) ! curvilinear coordinate on the sphere read in coordinate.nc file
  78. CALL iom_open( 'coordinates', inum )
  79. CALL iom_get( inum, jpdom_unknown, 'glamt', glamdta ) ! mig, mjg undefined at this point
  80. CALL iom_get( inum, jpdom_unknown, 'gphit', gphidta ) ! so use jpdom_unknown not jpdom_data
  81. CALL iom_close ( inum )
  82. CASE ( 1 ) ! geographical mesh on the sphere with regular grid-spacing
  83. DO jj = 1, jpjdta
  84. DO ji = 1, jpidta
  85. zti = FLOAT( ji - 1 + nimpp - 1 )
  86. ztj = FLOAT( jj - 1 + njmpp - 1 )
  87. glamdta(ji,jj) = ppglam0 + ppe1_deg * zti
  88. gphidta(ji,jj) = ppgphi0 + ppe2_deg * ztj
  89. END DO
  90. END DO
  91. CASE ( 2:3 ) ! f- or beta-plane with regular grid-spacing
  92. glam0 = 0.e0
  93. gphi0 = - ppe2_m * 1.e-3
  94. DO jj = 1, jpjdta
  95. DO ji = 1, jpidta
  96. glamdta(ji,jj) = glam0 + ppe1_m * 1.e-3 * FLOAT( ji - 1 + nimpp - 1 )
  97. gphidta(ji,jj) = gphi0 + ppe2_m * 1.e-3 * FLOAT( jj - 1 + njmpp - 1 )
  98. END DO
  99. END DO
  100. CASE ( 4 ) ! geographical mesh on the sphere, isotropic MERCATOR type
  101. IF( ppgphi0 == -90 ) CALL ctl_stop( ' Mercator grid cannot start at south pole !!!! ' )
  102. zarg = rpi / 4. - rpi / 180. * ppgphi0 / 2.
  103. ijeq = ABS( 180. / rpi * LOG( COS( zarg ) / SIN( zarg ) ) / ppe1_deg )
  104. IF( ppgphi0 > 0 ) ijeq = -ijeq
  105. DO jj = 1, jpjdta
  106. DO ji = 1, jpidta
  107. zti = FLOAT( ji - 1 + nimpp - 1 )
  108. ztj = FLOAT( jj - ijeq + njmpp - 1 )
  109. glamdta(ji,jj) = ppglam0 + ppe1_deg * zti
  110. gphidta(ji,jj) = 1. / rad * ASIN ( TANH( ppe1_deg * rad * ztj ) )
  111. END DO
  112. END DO
  113. CASE ( 5 ) ! beta-plane with regular grid-spacing and rotated domain (GYRE configuration)
  114. zlam1 = -85
  115. zphi1 = 29
  116. ze1 = 106000. / FLOAT(jp_cfg)
  117. zsin_alpha = - SQRT( 2. ) / 2.
  118. zcos_alpha = SQRT( 2. ) / 2.
  119. ze1deg = ze1 / (ra * rad)
  120. glam0 = zlam1 + zcos_alpha * ze1deg * FLOAT( jpjdta-2 ) ! Force global
  121. gphi0 = zphi1 + zsin_alpha * ze1deg * FLOAT( jpjdta-2 )
  122. DO jj = 1, jpjdta
  123. DO ji = 1, jpidta
  124. zim05 = FLOAT( ji + nimpp - 1 ) - 1.5
  125. zjm05 = FLOAT( jj + njmpp - 1 ) - 1.5
  126. glamdta(ji,jj) = glam0 + zim05 * ze1deg * zcos_alpha + zjm05 * ze1deg * zsin_alpha
  127. gphidta(ji,jj) = gphi0 - zim05 * ze1deg * zsin_alpha + zjm05 * ze1deg * zcos_alpha
  128. END DO
  129. END DO
  130. CASE DEFAULT
  131. WRITE(ctmp1,*) ' bad flag value for jphgr_msh = ', jphgr_msh
  132. CALL ctl_stop( ctmp1 )
  133. END SELECT
  134. ! ============================== !
  135. ! Code from dom_ngb: !
  136. ! Calculate the nearest grid !
  137. ! point to the given lat/lon & !
  138. ! update jpizoom and jpjzoom !
  139. ! ============================== !
  140. zlon = MOD( plon + 720., 360. ) ! plon between 0 and 360
  141. glamdta(:,:) = MOD( glamdta(:,:) + 720., 360. ) ! glamdta between 0 and 360
  142. IF( zlon > 270. ) zlon = zlon - 360. ! zlon between -90 and 270
  143. IF( zlon < 90. ) WHERE( glamdta(:,:) > 180. ) glamdta(:,:) = glamdta(:,:) - 360. ! glamdta between -180 and 180
  144. glamdta(:,:) = glamdta(:,:) - zlon
  145. gphidta(:,:) = gphidta(:,:) - plat
  146. zdist(:,:) = glamdta(:,:) * glamdta(:,:) + gphidta(:,:) * gphidta(:,:)
  147. iloc(:) = MINLOC( zdist(:,:) ) ! No mask; zoom indices freely defined
  148. jpizoom = iloc(1) + nimpp - 2 ! Minloc index - 1; want the bottom-left
  149. jpjzoom = iloc(2) + njmpp - 2 ! corner index of the zoom domain.
  150. CALL wrk_dealloc( jpidta, jpjdta, gphidta, glamdta, zdist )
  151. IF (lwp) THEN
  152. WRITE(numout,*)
  153. WRITE(numout,*) 'dom_c1d : compute jpizoom & jpjzoom from global mesh and given coordinates'
  154. WRITE(numout,*) '~~~~~~~'
  155. WRITE(numout,*) ' column i zoom index jpizoom = ', jpizoom
  156. WRITE(numout,*) ' column j zoom index jpjzoom = ', jpjzoom
  157. WRITE(numout,*)
  158. ENDIF
  159. IF( nn_timing == 1 ) CALL timing_stop('dom_c1d')
  160. END SUBROUTINE dom_c1d
  161. #else
  162. !!----------------------------------------------------------------------
  163. !! Default option NO 1D Configuration
  164. !!----------------------------------------------------------------------
  165. CONTAINS
  166. SUBROUTINE dom_c1d( plat, plon ) ! Empty routine
  167. REAL :: plat, plon
  168. WRITE(*,*) 'dom_c1d: You should not have seen this print! error?',plat,plon
  169. END SUBROUTINE dom_c1d
  170. #endif
  171. !!======================================================================
  172. END MODULE domc1d