obs_grid.F90 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182
  1. MODULE obs_grid
  2. !!======================================================================
  3. !! *** MODULE obs_grid ***
  4. !! Observation diagnostics: Various tools for grid searching etc.
  5. !!======================================================================
  6. !!----------------------------------------------------------------------
  7. !! obs_grid_search : Find i,j on the ORCA grid from lat,lon
  8. !! obs_level_search : Find level from depth
  9. !! obs_zlevel_search : Find depth level from observed depth
  10. !! obs_tlevel_search : Find temperature level from observed temp
  11. !! obs_rlevel_search : Find density level from observed density
  12. !!----------------------------------------------------------------------
  13. !! * Modules used
  14. USE par_kind, ONLY : & ! Precision variables
  15. & wp
  16. USE par_oce, ONLY : & ! Ocean parameters
  17. & jpk, &
  18. & jpni, &
  19. & jpnj, &
  20. & jpnij
  21. USE dom_oce ! Ocean space and time domain variables
  22. USE obs_mpp, ONLY : & ! MPP support routines for observation diagnostics
  23. & obs_mpp_find_obs_proc, &
  24. & mpp_global_max, &
  25. & obs_mpp_max_integer
  26. USE phycst, ONLY : & ! Physical constants
  27. & rad
  28. USE obs_utils, ONLY : & ! Observation operator utility functions
  29. & grt_cir_dis, &
  30. & chkerr
  31. USE in_out_manager ! Printing support
  32. USE netcdf
  33. USE obs_const, ONLY : &
  34. & obfillflt ! Fillvalue
  35. USE lib_mpp, ONLY : &
  36. & ctl_warn, ctl_stop
  37. IMPLICIT NONE
  38. !! * Routine accessibility
  39. PUBLIC obs_grid_setup, & ! Setup grid searching
  40. & obs_grid_search, & ! Find i, j on the ORCA grid from lat, lon
  41. & obs_grid_deallocate, & ! Deallocate the look up table
  42. & obs_level_search ! Find level from depth
  43. PRIVATE linquad, & ! Determine whether a point lies within a cell
  44. & maxdist, & ! Find the maximum distance between 2 pts in a cell
  45. & obs_grd_bruteforce, & ! Find i, j on the ORCA grid from lat, lon
  46. & obs_grd_lookup ! Find i, j on the ORCA grid from lat, lon quicker
  47. !!* Module variables
  48. !! Default values
  49. REAL, PUBLIC :: grid_search_res = 0.5 ! Resolution of grid
  50. INTEGER, PRIVATE :: gsearch_nlons_def ! Num of longitudes
  51. INTEGER, PRIVATE :: gsearch_nlats_def ! Num of latitudes
  52. REAL(wp), PRIVATE :: gsearch_lonmin_def ! Min longitude
  53. REAL(wp), PRIVATE :: gsearch_latmin_def ! Min latitude
  54. REAL(wp), PRIVATE :: gsearch_dlon_def ! Lon spacing
  55. REAL(wp), PRIVATE :: gsearch_dlat_def ! Lat spacing
  56. !! Variable versions
  57. INTEGER, PRIVATE :: nlons ! Num of longitudes
  58. INTEGER, PRIVATE :: nlats ! Num of latitudes
  59. REAL(wp), PRIVATE :: lonmin ! Min longitude
  60. REAL(wp), PRIVATE :: latmin ! Min latitude
  61. REAL(wp), PRIVATE :: dlon ! Lon spacing
  62. REAL(wp), PRIVATE :: dlat ! Lat spacing
  63. INTEGER, PRIVATE :: maxxdiff, maxydiff ! Max diffs between model points
  64. INTEGER, PRIVATE :: limxdiff, limydiff
  65. ! Data storage
  66. REAL(wp), PRIVATE, DIMENSION(:,:), ALLOCATABLE :: &
  67. & lons, &
  68. & lats
  69. INTEGER, PRIVATE, DIMENSION(:,:), ALLOCATABLE :: &
  70. & ixpos, &
  71. & iypos, &
  72. & iprocn
  73. ! Switches
  74. LOGICAL, PUBLIC :: ln_grid_search_lookup ! Use lookup table to speed up grid search
  75. LOGICAL, PUBLIC :: ln_grid_global ! Use global distribution of observations
  76. CHARACTER(LEN=44), PUBLIC :: &
  77. & grid_search_file ! file name head for grid search lookup
  78. !!----------------------------------------------------------------------
  79. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  80. !! $Id: obs_grid.F90 4990 2014-12-15 16:42:49Z timgraham $
  81. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  82. !!----------------------------------------------------------------------
  83. CONTAINS
  84. SUBROUTINE obs_grid_search( kobsin, plam, pphi, kobsi, kobsj, kproc, &
  85. & cdgrid )
  86. !!----------------------------------------------------------------------
  87. !! *** ROUTINE obs_grid_search ***
  88. !!
  89. !! ** Purpose : Search local gridpoints to find the grid box containing
  90. !! the observations calls either
  91. !! obs_grd_bruteforce - the original brute force search
  92. !! or
  93. !! obs_grd_lookup - uses a lookup table to do a fast
  94. !!search
  95. !!History :
  96. !! ! 2007-12 (D. Lea)
  97. !!------------------------------------------------------------------------
  98. !! * Arguments
  99. INTEGER :: &
  100. & kobsin ! Size of the observation arrays
  101. REAL(KIND=wp), DIMENSION(kobsin), INTENT(IN) :: &
  102. & plam, & ! Longitude of obsrvations
  103. & pphi ! Latitude of observations
  104. INTEGER, DIMENSION(kobsin), INTENT(OUT) :: &
  105. & kobsi, & ! I-index of observations
  106. & kobsj, & ! J-index of observations
  107. & kproc ! Processor number of observations
  108. CHARACTER(LEN=1) :: &
  109. & cdgrid ! Grid to search
  110. IF(kobsin > 0) THEN
  111. IF ( ln_grid_search_lookup .AND. ( cdgrid == 'T' ) ) THEN
  112. CALL obs_grd_lookup( kobsin, plam, pphi, &
  113. & kobsi, kobsj, kproc )
  114. ELSE
  115. IF ( cdgrid == 'T' ) THEN
  116. CALL obs_grd_bruteforce( jpi, jpj, jpiglo, jpjglo, &
  117. & nldi, nlei,nldj, nlej, &
  118. & nproc, jpnij, &
  119. & glamt, gphit, tmask, &
  120. & kobsin, plam, pphi, &
  121. & kobsi, kobsj, kproc )
  122. ELSEIF ( cdgrid == 'U' ) THEN
  123. CALL obs_grd_bruteforce( jpi, jpj, jpiglo, jpjglo, &
  124. & nldi, nlei,nldj, nlej, &
  125. & nproc, jpnij, &
  126. & glamu, gphiu, umask, &
  127. & kobsin, plam, pphi, &
  128. & kobsi, kobsj, kproc )
  129. ELSEIF ( cdgrid == 'V' ) THEN
  130. CALL obs_grd_bruteforce( jpi, jpj, jpiglo, jpjglo, &
  131. & nldi, nlei,nldj, nlej, &
  132. & nproc, jpnij, &
  133. & glamv, gphiv, vmask, &
  134. & kobsin, plam, pphi, &
  135. & kobsi, kobsj, kproc )
  136. ELSEIF ( cdgrid == 'F' ) THEN
  137. CALL obs_grd_bruteforce( jpi, jpj, jpiglo, jpjglo, &
  138. & nldi, nlei,nldj, nlej, &
  139. & nproc, jpnij, &
  140. & glamf, gphif, fmask, &
  141. & kobsin, plam, pphi, &
  142. & kobsi, kobsj, kproc )
  143. ELSE
  144. CALL ctl_stop( 'Grid not supported' )
  145. ENDIF
  146. ENDIF
  147. ENDIF
  148. END SUBROUTINE obs_grid_search
  149. #include "obs_grd_bruteforce.h90"
  150. SUBROUTINE obs_grd_lookup( kobs, plam, pphi, kobsi, kobsj, kproc )
  151. !!----------------------------------------------------------------------
  152. !! *** ROUTINE obs_grid_lookup ***
  153. !!
  154. !! ** Purpose : Search local gridpoints to find the grid box containing
  155. !! the observations (much faster then obs_grd_bruteforce)
  156. !!
  157. !! ** Method : Call to linquad
  158. !!
  159. !! ** Action : Return kproc holding the observation and kiobsi,kobsj
  160. !! valid on kproc=nproc processor only.
  161. !!
  162. !! History :
  163. !! ! 2007-12 (D. Lea) new routine based on obs_grid_search
  164. !!! updated with fixes from new version of obs_grid_search_bruteforce
  165. !!! speeded up where points are not near a "difficult" region like an edge
  166. !!----------------------------------------------------------------------
  167. !! * Arguments
  168. INTEGER :: kobs ! Size of the observation arrays
  169. REAL(KIND=wp), DIMENSION(kobs), INTENT(IN) :: &
  170. & plam, & ! Longitude of obsrvations
  171. & pphi ! Latitude of observations
  172. INTEGER, DIMENSION(kobs), INTENT(OUT) :: &
  173. & kobsi, & ! I-index of observations
  174. & kobsj, & ! J-index of observations
  175. & kproc ! Processor number of observations
  176. !! * Local declarations
  177. REAL(KIND=wp), DIMENSION(:), ALLOCATABLE :: &
  178. & zplam
  179. REAL(wp) :: zlammax
  180. REAL(wp) :: zlam
  181. INTEGER :: ji
  182. INTEGER :: jj
  183. INTEGER :: jk
  184. INTEGER :: jo
  185. INTEGER :: isx
  186. INTEGER :: isy
  187. INTEGER :: jimin
  188. INTEGER :: jimax
  189. INTEGER :: jjmin
  190. INTEGER :: jjmax
  191. INTEGER :: jojimin
  192. INTEGER :: jojimax
  193. INTEGER :: jojjmin
  194. INTEGER :: jojjmax
  195. INTEGER :: ipx1
  196. INTEGER :: ipy1
  197. INTEGER :: ip
  198. INTEGER :: jp
  199. INTEGER :: ipx
  200. INTEGER :: ipy
  201. INTEGER :: ipmx
  202. INTEGER :: jlon
  203. INTEGER :: jlat
  204. INTEGER :: joffset
  205. INTEGER :: jostride
  206. REAL(KIND=wp), DIMENSION(:,:), ALLOCATABLE :: &
  207. & zlamg, &
  208. & zphig, &
  209. & zmskg, &
  210. & zphitmax,&
  211. & zphitmin,&
  212. & zlamtmax,&
  213. & zlamtmin
  214. LOGICAL, DIMENSION(:,:), ALLOCATABLE :: &
  215. & llinvalidcell
  216. REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: &
  217. & zlamtm, &
  218. & zphitm
  219. LOGICAL :: llfourflag
  220. INTEGER :: ifourflagcountt
  221. INTEGER :: ifourflagcountf
  222. INTEGER, DIMENSION(5) :: ifourflagcountr
  223. !-----------------------------------------------------------------------
  224. ! Define grid for grid search
  225. !-----------------------------------------------------------------------
  226. IF (ln_grid_global) THEN
  227. jlon = jpiglo
  228. jlat = jpjglo
  229. joffset = nproc
  230. jostride = jpnij
  231. ELSE
  232. jlon = jpi
  233. jlat = jpj
  234. joffset = 0
  235. jostride = 1
  236. ENDIF
  237. !-----------------------------------------------------------------------
  238. ! Set up data for grid search
  239. !-----------------------------------------------------------------------
  240. ALLOCATE( &
  241. & zlamg(jlon,jlat), &
  242. & zphig(jlon,jlat), &
  243. & zmskg(jlon,jlat), &
  244. & zphitmax(jlon-1,jlat-1), &
  245. & zphitmin(jlon-1,jlat-1), &
  246. & zlamtmax(jlon-1,jlat-1), &
  247. & zlamtmin(jlon-1,jlat-1), &
  248. & llinvalidcell(jlon-1,jlat-1), &
  249. & zlamtm(4,jlon-1,jlat-1), &
  250. & zphitm(4,jlon-1,jlat-1) &
  251. & )
  252. !-----------------------------------------------------------------------
  253. ! Copy data to local arrays
  254. !-----------------------------------------------------------------------
  255. IF (ln_grid_global) THEN
  256. zlamg(:,:) = -1.e+10
  257. zphig(:,:) = -1.e+10
  258. zmskg(:,:) = -1.e+10
  259. ! Add various grids here.
  260. DO jj = nldj, nlej
  261. DO ji = nldi, nlei
  262. zlamg(mig(ji),mjg(jj)) = glamt(ji,jj)
  263. zphig(mig(ji),mjg(jj)) = gphit(ji,jj)
  264. zmskg(mig(ji),mjg(jj)) = tmask(ji,jj,1)
  265. END DO
  266. END DO
  267. CALL mpp_global_max( zlamg )
  268. CALL mpp_global_max( zphig )
  269. CALL mpp_global_max( zmskg )
  270. ELSE
  271. ! Add various grids here.
  272. DO jj = 1, jlat
  273. DO ji = 1, jlon
  274. zlamg(ji,jj) = glamt(ji,jj)
  275. zphig(ji,jj) = gphit(ji,jj)
  276. zmskg(ji,jj) = tmask(ji,jj,1)
  277. END DO
  278. END DO
  279. ENDIF
  280. !-----------------------------------------------------------------------
  281. ! Copy longitudes
  282. !-----------------------------------------------------------------------
  283. ALLOCATE( &
  284. & zplam(kobs) &
  285. & )
  286. DO jo = 1, kobs
  287. zplam(jo) = plam(jo)
  288. END DO
  289. !-----------------------------------------------------------------------
  290. ! Set default values for output
  291. !-----------------------------------------------------------------------
  292. kproc(:) = -1
  293. kobsi(:) = -1
  294. kobsj(:) = -1
  295. !-----------------------------------------------------------------------
  296. ! Copy grid positions to temporary arrays and renormalize to 0 to 360.
  297. !-----------------------------------------------------------------------
  298. DO jj = 1, jlat-1
  299. DO ji = 1, jlon-1
  300. zlamtm(1,ji,jj) = zlamg(ji ,jj )
  301. zphitm(1,ji,jj) = zphig(ji ,jj )
  302. zlamtm(2,ji,jj) = zlamg(ji+1,jj )
  303. zphitm(2,ji,jj) = zphig(ji+1,jj )
  304. zlamtm(3,ji,jj) = zlamg(ji+1,jj+1)
  305. zphitm(3,ji,jj) = zphig(ji+1,jj+1)
  306. zlamtm(4,ji,jj) = zlamg(ji ,jj+1)
  307. zphitm(4,ji,jj) = zphig(ji ,jj+1)
  308. END DO
  309. END DO
  310. WHERE ( zlamtm(:,:,:) < 0.0_wp )
  311. zlamtm(:,:,:) = zlamtm(:,:,:) + 360.0_wp
  312. END WHERE
  313. WHERE ( zlamtm(:,:,:) > 360.0_wp )
  314. zlamtm(:,:,:) = zlamtm(:,:,:) - 360.0_wp
  315. END WHERE
  316. !-----------------------------------------------------------------------
  317. ! Handle case of the wraparound; beware, not working with orca180
  318. !-----------------------------------------------------------------------
  319. DO jj = 1, jlat-1
  320. DO ji = 1, jlon-1
  321. zlammax = MAXVAL( zlamtm(:,ji,jj) )
  322. WHERE (zlammax - zlamtm(:, ji, jj) > 180 ) &
  323. & zlamtm(:,ji,jj) = zlamtm(:,ji,jj) + 360._wp
  324. zphitmax(ji,jj) = MAXVAL(zphitm(:,ji,jj))
  325. zphitmin(ji,jj) = MINVAL(zphitm(:,ji,jj))
  326. zlamtmax(ji,jj) = MAXVAL(zlamtm(:,ji,jj))
  327. zlamtmin(ji,jj) = MINVAL(zlamtm(:,ji,jj))
  328. END DO
  329. END DO
  330. !-----------------------------------------------------------------------
  331. ! Search for boxes with only land points mark them invalid
  332. !-----------------------------------------------------------------------
  333. llinvalidcell(:,:) = .FALSE.
  334. DO jj = 1, jlat-1
  335. DO ji = 1, jlon-1
  336. llinvalidcell(ji,jj) = &
  337. & zmskg(ji ,jj ) == 0.0_wp .AND. &
  338. & zmskg(ji+1,jj ) == 0.0_wp .AND. &
  339. & zmskg(ji+1,jj+1) == 0.0_wp .AND. &
  340. & zmskg(ji ,jj+1) == 0.0_wp
  341. END DO
  342. END DO
  343. if(lwp) WRITE(numout,*) 'obs_grid_lookup do coordinate search using lookup table'
  344. !-----------------------------------------------------------------------
  345. ! Do coordinate search using lookup table with local searches.
  346. ! - For land points kproc is set to number of the processor + 1000000
  347. ! and we continue the search.
  348. ! - For ocean points kproc is set to the number of the processor
  349. ! and we stop the search.
  350. !-----------------------------------------------------------------------
  351. ifourflagcountt = 0
  352. ifourflagcountf = 0
  353. ifourflagcountr(:) = 0
  354. !------------------------------------------------------------------------
  355. ! Master loop for grid search
  356. !------------------------------------------------------------------------
  357. gpkobs: DO jo = 1+joffset, kobs, jostride
  358. ! Normal case
  359. ! specify 4 points which surround the lat lon of interest
  360. ! x i,j+1 x i+1, j+1
  361. !
  362. !
  363. ! * lon,lat
  364. ! x i,j x i+1,j
  365. ! bottom corner point
  366. ipx1 = INT( ( zplam(jo) - lonmin ) / dlon + 1.0 )
  367. ipy1 = INT( ( pphi (jo) - latmin ) / dlat + 1.0 )
  368. ipx = ipx1 + 1
  369. ipy = ipy1 + 1
  370. ! flag for searching around four points separately
  371. ! default to false
  372. llfourflag = .FALSE.
  373. ! check for point fully outside of region
  374. IF ( (ipx1 > nlons) .OR. (ipy1 > nlats) .OR. &
  375. & (ipx < 1) .OR. (ipy < 1) ) THEN
  376. CYCLE
  377. ENDIF
  378. ! check wrap around
  379. IF ( (ipx > nlons) .OR. (ipy > nlats) .OR. &
  380. & (ipx1 < 1) .OR. (ipy1 < 1) ) THEN
  381. llfourflag=.TRUE.
  382. ifourflagcountr(1) = ifourflagcountr(1) + 1
  383. ENDIF
  384. IF (.NOT. llfourflag) THEN
  385. IF (MAXVAL(ixpos(ipx1:ipx,ipy1:ipy)) == -1) CYCLE! cycle if no lookup points found
  386. ENDIF
  387. jimin = 0
  388. jimax = 0
  389. jjmin = 0
  390. jjmax = 0
  391. IF (.NOT. llfourflag) THEN
  392. ! calculate points range
  393. ! define a square region encompassing the four corner points
  394. ! do I need the -1 points?
  395. jojimin = MINVAL(ixpos(ipx1:ipx,ipy1:ipy)) - 1
  396. jojimax = MAXVAL(ixpos(ipx1:ipx,ipy1:ipy)) + 1
  397. jojjmin = MINVAL(iypos(ipx1:ipx,ipy1:ipy)) - 1
  398. jojjmax = MAXVAL(iypos(ipx1:ipx,ipy1:ipy)) + 1
  399. jimin = jojimin - 1
  400. jimax = jojimax + 1
  401. jjmin = jojjmin - 1
  402. jjmax = jojjmax + 1
  403. IF ( jojimin < 0 .OR. jojjmin < 0) THEN
  404. llfourflag = .TRUE.
  405. ifourflagcountr(2) = ifourflagcountr(2) + 1
  406. ENDIF
  407. IF ( jojimax - jojimin > maxxdiff) THEN
  408. llfourflag = .TRUE.
  409. ifourflagcountr(3) = ifourflagcountr(3) + 1
  410. ENDIF
  411. IF ( jojjmax - jojjmin > maxydiff) THEN
  412. llfourflag = .TRUE.
  413. ifourflagcountr(4) = ifourflagcountr(4) + 1
  414. ENDIF
  415. ENDIF
  416. ipmx = 0
  417. IF (llfourflag) ipmx = 1
  418. IF (llfourflag) THEN
  419. ifourflagcountt = ifourflagcountt + 1
  420. ELSE
  421. ifourflagcountf = ifourflagcountf + 1
  422. ENDIF
  423. gridpointsn : DO ip = 0, ipmx
  424. DO jp = 0, ipmx
  425. IF ( kproc(jo) /= -1 ) EXIT gridpointsn
  426. ipx = ipx1 + ip
  427. ipy = ipy1 + jp
  428. IF (llfourflag) THEN
  429. ! deal with wrap around
  430. IF ( ipx > nlons ) ipx = 1
  431. IF ( ipy > nlats ) ipy = 1
  432. IF ( ipx < 1 ) ipx = nlons
  433. IF ( ipy < 1 ) ipy = nlats
  434. ! get i,j
  435. isx = ixpos(ipx,ipy)
  436. isy = iypos(ipx,ipy)
  437. ! estimate appropriate search region (use max/min values)
  438. jimin = isx - maxxdiff - 1
  439. jimax = isx + maxxdiff + 1
  440. jjmin = isy - maxydiff - 1
  441. jjmax = isy + maxydiff + 1
  442. ENDIF
  443. IF ( jimin < 1 ) jimin = 1
  444. IF ( jimax > jlon-1 ) jimax = jlon-1
  445. IF ( jjmin < 1 ) jjmin = 1
  446. IF ( jjmax > jlat-1 ) jjmax = jlat-1
  447. !---------------------------------------------------------------
  448. ! Ensure that all observation longtiudes are between 0 and 360
  449. !---------------------------------------------------------------
  450. IF ( zplam(jo) < 0.0_wp ) zplam(jo) = zplam(jo) + 360.0_wp
  451. IF ( zplam(jo) > 360.0_wp ) zplam(jo) = zplam(jo) - 360.0_wp
  452. !---------------------------------------------------------------
  453. ! Find observations which are on within 1e-6 of a grid point
  454. !---------------------------------------------------------------
  455. gridloop: DO jj = jjmin, jjmax
  456. DO ji = jimin, jimax
  457. IF ( ABS( zphig(ji,jj) - pphi(jo) ) < 1e-6 ) THEN
  458. zlam = zlamg(ji,jj)
  459. IF ( zlam < 0.0_wp ) zlam = zlam + 360.0_wp
  460. IF ( zlam > 360.0_wp ) zlam = zlam - 360.0_wp
  461. IF ( ABS( zlam - zplam(jo) ) < 1e-6 ) THEN
  462. IF ( llinvalidcell(ji,jj) ) THEN
  463. kproc(jo) = nproc + 1000000
  464. kobsi(jo) = ji + 1
  465. kobsj(jo) = jj + 1
  466. CYCLE
  467. ELSE
  468. kproc(jo) = nproc
  469. kobsi(jo) = ji + 1
  470. kobsj(jo) = jj + 1
  471. EXIT gridloop
  472. ENDIF
  473. ENDIF
  474. ENDIF
  475. END DO
  476. END DO gridloop
  477. !---------------------------------------------------------------
  478. ! Ensure that all observation longtiudes are between -180/180
  479. !---------------------------------------------------------------
  480. IF ( zplam(jo) > 180 ) zplam(jo) = zplam(jo) - 360.0_wp
  481. IF ( kproc(jo) == -1 ) THEN
  482. ! Normal case
  483. gridpoints : DO jj = jjmin, jjmax
  484. DO ji = jimin, jimax
  485. IF ( ( zplam(jo) > zlamtmax(ji,jj) ) .OR. &
  486. & ( zplam(jo) < zlamtmin(ji,jj) ) ) CYCLE
  487. IF ( ABS( pphi(jo) ) < 85 ) THEN
  488. IF ( ( pphi(jo) > zphitmax(ji,jj) ) .OR. &
  489. & ( pphi(jo) < zphitmin(ji,jj) ) ) CYCLE
  490. ENDIF
  491. IF ( linquad( zplam(jo), pphi(jo), &
  492. & zlamtm(:,ji,jj), zphitm(:,ji,jj) ) ) THEN
  493. IF ( llinvalidcell(ji,jj) ) THEN
  494. kproc(jo) = nproc + 1000000
  495. kobsi(jo) = ji + 1
  496. kobsj(jo) = jj + 1
  497. CYCLE
  498. ELSE
  499. kproc(jo) = nproc
  500. kobsi(jo) = ji + 1
  501. kobsj(jo) = jj + 1
  502. EXIT gridpoints
  503. ENDIF
  504. ENDIF
  505. END DO
  506. END DO gridpoints
  507. ENDIF
  508. ! In case of failure retry for obs. longtiude + 360.
  509. IF ( kproc(jo) == -1 ) THEN
  510. gridpoints_greenwich : DO jj = jjmin, jjmax
  511. DO ji = jimin, jimax
  512. IF ( ( zplam(jo)+360.0_wp > zlamtmax(ji,jj) ) .OR. &
  513. & ( zplam(jo)+360.0_wp < zlamtmin(ji,jj) ) ) CYCLE
  514. IF ( ABS( pphi(jo) ) < 85 ) THEN
  515. IF ( ( pphi(jo) > zphitmax(ji,jj) ) .OR. &
  516. & ( pphi(jo) < zphitmin(ji,jj) ) ) CYCLE
  517. ENDIF
  518. IF ( linquad( zplam(jo)+360.0_wp, pphi(jo), &
  519. & zlamtm(:,ji,jj), zphitm(:,ji,jj) ) ) THEN
  520. IF ( llinvalidcell(ji,jj) ) THEN
  521. kproc(jo) = nproc + 1000000
  522. kobsi(jo) = ji + 1
  523. kobsj(jo) = jj + 1
  524. CYCLE
  525. ELSE
  526. kproc(jo) = nproc
  527. kobsi(jo) = ji + 1
  528. kobsj(jo) = jj + 1
  529. EXIT gridpoints_greenwich
  530. ENDIF
  531. ENDIF
  532. END DO
  533. END DO gridpoints_greenwich
  534. ENDIF ! kproc
  535. END DO
  536. END DO gridpointsn
  537. END DO gpkobs ! kobs
  538. !----------------------------------------------------------------------
  539. ! Synchronize kproc on all processors
  540. !----------------------------------------------------------------------
  541. IF ( ln_grid_global ) THEN
  542. CALL obs_mpp_max_integer( kproc, kobs )
  543. CALL obs_mpp_max_integer( kobsi, kobs )
  544. CALL obs_mpp_max_integer( kobsj, kobs )
  545. ELSE
  546. CALL obs_mpp_find_obs_proc( kproc, kobsi, kobsj, kobs )
  547. ENDIF
  548. WHERE( kproc(:) >= 1000000 )
  549. kproc(:) = kproc(:) - 1000000
  550. END WHERE
  551. DEALLOCATE( &
  552. & zlamg, &
  553. & zphig, &
  554. & zmskg, &
  555. & zphitmax, &
  556. & zphitmin, &
  557. & zlamtmax, &
  558. & zlamtmin, &
  559. & llinvalidcell, &
  560. & zlamtm, &
  561. & zphitm, &
  562. & zplam &
  563. & )
  564. END SUBROUTINE obs_grd_lookup
  565. SUBROUTINE obs_grid_setup
  566. !!----------------------------------------------------------------------
  567. !! *** ROUTINE obs_grid_setup ***
  568. !!
  569. !! ** Purpose : Setup a lookup table to reduce the searching required
  570. !! for converting lat lons to grid point location
  571. !! produces or reads in a preexisting file for use in
  572. !! obs_grid_search_lookup_local
  573. !!
  574. !! ** Method : calls obs_grid_search_bruteforce_local with a array
  575. !! of lats and lons
  576. !!
  577. !! History :
  578. !! ! 2007-12 (D. Lea) new routine
  579. !!----------------------------------------------------------------------
  580. !! * Local declarations
  581. CHARACTER(LEN=15), PARAMETER :: &
  582. & cpname = 'obs_grid_setup'
  583. CHARACTER(LEN=40) :: cfname
  584. INTEGER :: ji
  585. INTEGER :: jj
  586. INTEGER :: jk
  587. INTEGER :: jo
  588. INTEGER :: idfile, idny, idnx, idxpos, idypos
  589. INTEGER :: idlat, idlon, fileexist
  590. INTEGER, DIMENSION(2) :: incdim
  591. CHARACTER(LEN=20) :: datestr=" ",timestr=" "
  592. REAL(wp) :: tmpx1, tmpx2, tmpy1, tmpy2
  593. REAL(wp) :: meanxdiff, meanydiff
  594. REAL(wp) :: meanxdiff1, meanydiff1
  595. REAL(wp) :: meanxdiff2, meanydiff2
  596. INTEGER :: numx1, numx2, numy1, numy2, df
  597. INTEGER :: jimin, jimax, jjmin, jjmax
  598. REAL(wp), DIMENSION(:,:), ALLOCATABLE :: &
  599. & lonsi, &
  600. & latsi
  601. INTEGER, DIMENSION(:,:), ALLOCATABLE :: &
  602. & ixposi, &
  603. & iyposi, &
  604. & iproci
  605. INTEGER, PARAMETER :: histsize=90
  606. INTEGER, DIMENSION(histsize) :: &
  607. & histx1, histx2, histy1, histy2
  608. REAL, DIMENSION(histsize) :: &
  609. & fhistx1, fhistx2, fhisty1, fhisty2
  610. REAL(wp) :: histtol
  611. IF (ln_grid_search_lookup) THEN
  612. WRITE(numout,*) 'Calling obs_grid_setup'
  613. IF(lwp) WRITE(numout,*)
  614. IF(lwp) WRITE(numout,*)'Grid search resolution : ', grid_search_res
  615. gsearch_nlons_def = NINT( 360.0_wp / grid_search_res )
  616. gsearch_nlats_def = NINT( 180.0_wp / grid_search_res )
  617. gsearch_lonmin_def = -180.0_wp + 0.5_wp * grid_search_res
  618. gsearch_latmin_def = -90.0_wp + 0.5_wp * grid_search_res
  619. gsearch_dlon_def = grid_search_res
  620. gsearch_dlat_def = grid_search_res
  621. IF (lwp) THEN
  622. WRITE(numout,*)'Grid search gsearch_nlons_def = ',gsearch_nlons_def
  623. WRITE(numout,*)'Grid search gsearch_nlats_def = ',gsearch_nlats_def
  624. WRITE(numout,*)'Grid search gsearch_lonmin_def = ',gsearch_lonmin_def
  625. WRITE(numout,*)'Grid search gsearch_latmin_def = ',gsearch_latmin_def
  626. WRITE(numout,*)'Grid search gsearch_dlon_def = ',gsearch_dlon_def
  627. WRITE(numout,*)'Grid search gsearch_dlat_def = ',gsearch_dlat_def
  628. ENDIF
  629. IF ( ln_grid_global ) THEN
  630. WRITE(cfname, FMT="(A,'_',A)") &
  631. & TRIM(grid_search_file), 'global.nc'
  632. ELSE
  633. WRITE(cfname, FMT="(A,'_',I4.4,'of',I4.4,'by',I4.4,'.nc')") &
  634. & TRIM(grid_search_file), nproc, jpni, jpnj
  635. ENDIF
  636. fileexist=nf90_open( TRIM( cfname ), nf90_nowrite, &
  637. & idfile )
  638. IF ( fileexist == nf90_noerr ) THEN
  639. ! read data
  640. ! initially assume size is as defined (to be fixed)
  641. WRITE(numout,*) 'Reading: ',cfname
  642. CALL chkerr( nf90_open( TRIM( cfname ), nf90_nowrite, idfile ), &
  643. & cpname, __LINE__ )
  644. CALL chkerr( nf90_get_att( idfile, nf90_global, 'maxxdiff', maxxdiff ), &
  645. & cpname, __LINE__ )
  646. CALL chkerr( nf90_get_att( idfile, nf90_global, 'maxydiff', maxydiff ), &
  647. & cpname, __LINE__ )
  648. CALL chkerr( nf90_get_att( idfile, nf90_global, 'dlon', dlon ), &
  649. & cpname, __LINE__ )
  650. CALL chkerr( nf90_get_att( idfile, nf90_global, 'dlat', dlat ), &
  651. & cpname, __LINE__ )
  652. CALL chkerr( nf90_get_att( idfile, nf90_global, 'lonmin', lonmin ), &
  653. & cpname, __LINE__ )
  654. CALL chkerr( nf90_get_att( idfile, nf90_global, 'latmin', latmin ), &
  655. & cpname, __LINE__ )
  656. CALL chkerr( nf90_inq_dimid(idfile, 'nx' , idnx), &
  657. & cpname, __LINE__ )
  658. CALL chkerr( nf90_inquire_dimension( idfile, idnx, len = nlons ), &
  659. & cpname, __LINE__ )
  660. CALL chkerr( nf90_inq_dimid(idfile, 'ny' , idny), &
  661. & cpname, __LINE__ )
  662. CALL chkerr( nf90_inquire_dimension( idfile, idny, len = nlats ), &
  663. & cpname, __LINE__ )
  664. ALLOCATE( &
  665. & lons(nlons,nlats), &
  666. & lats(nlons,nlats), &
  667. & ixpos(nlons,nlats), &
  668. & iypos(nlons,nlats), &
  669. & iprocn(nlons,nlats) &
  670. & )
  671. CALL chkerr( nf90_inq_varid( idfile, 'XPOS', idxpos ), &
  672. & cpname, __LINE__ )
  673. CALL chkerr( nf90_get_var ( idfile, idxpos, ixpos), &
  674. & cpname, __LINE__ )
  675. CALL chkerr( nf90_inq_varid( idfile, 'YPOS', idypos ), &
  676. & cpname, __LINE__ )
  677. CALL chkerr( nf90_get_var ( idfile, idypos, iypos), &
  678. & cpname, __LINE__ )
  679. CALL chkerr( nf90_close( idfile ), cpname, __LINE__ )
  680. ! setup arrays
  681. DO ji = 1, nlons
  682. DO jj = 1, nlats
  683. lons(ji,jj) = lonmin + (ji-1) * dlon
  684. lats(ji,jj) = latmin + (jj-1) * dlat
  685. END DO
  686. END DO
  687. ! if we are not reading the file we need to create it
  688. ! create new obs grid search lookup file
  689. ELSE
  690. ! call obs_grid_search
  691. IF (lwp) THEN
  692. WRITE(numout,*) 'creating: ',cfname
  693. WRITE(numout,*) 'calling obs_grid_search: ',nlons*nlats
  694. ENDIF
  695. ! set parameters from default values
  696. nlons = gsearch_nlons_def
  697. nlats = gsearch_nlats_def
  698. lonmin = gsearch_lonmin_def
  699. latmin = gsearch_latmin_def
  700. dlon = gsearch_dlon_def
  701. dlat = gsearch_dlat_def
  702. ! setup arrays
  703. ALLOCATE( &
  704. & lonsi(nlons,nlats), &
  705. & latsi(nlons,nlats), &
  706. & ixposi(nlons,nlats), &
  707. & iyposi(nlons,nlats), &
  708. & iproci(nlons,nlats) &
  709. & )
  710. DO ji = 1, nlons
  711. DO jj = 1, nlats
  712. lonsi(ji,jj) = lonmin + (ji-1) * dlon
  713. latsi(ji,jj) = latmin + (jj-1) * dlat
  714. END DO
  715. END DO
  716. CALL obs_grd_bruteforce( jpi, jpj, jpiglo, jpjglo, &
  717. & nldi, nlei,nldj, nlej, &
  718. & nproc, jpnij, &
  719. & glamt, gphit, tmask, &
  720. & nlons*nlats, lonsi, latsi, &
  721. & ixposi, iyposi, iproci )
  722. ! minimise file size by removing regions with no data from xypos file
  723. ! should be able to just use xpos (ypos will have the same areas of missing data)
  724. jimin=1
  725. jimax=nlons
  726. jjmin=1
  727. jjmax=nlats
  728. minlon_xpos: DO ji= 1, nlons
  729. IF (COUNT(ixposi(ji,:) >= 0) > 0) THEN
  730. jimin=ji
  731. EXIT minlon_xpos
  732. ENDIF
  733. END DO minlon_xpos
  734. maxlon_xpos: DO ji= nlons, 1, -1
  735. IF (COUNT(ixposi(ji,:) >= 0) > 0) THEN
  736. jimax=ji
  737. EXIT maxlon_xpos
  738. ENDIF
  739. END DO maxlon_xpos
  740. minlat_xpos: DO jj= 1, nlats
  741. IF (COUNT(ixposi(:,jj) >= 0) > 0) THEN
  742. jjmin=jj
  743. EXIT minlat_xpos
  744. ENDIF
  745. END DO minlat_xpos
  746. maxlat_xpos: DO jj= nlats, 1, -1
  747. IF (COUNT(ixposi(:,jj) >= 0) > 0) THEN
  748. jjmax=jj
  749. EXIT maxlat_xpos
  750. ENDIF
  751. END DO maxlat_xpos
  752. lonmin = lonsi(jimin,jjmin)
  753. latmin = latsi(jimin,jjmin)
  754. nlons = jimax-jimin+1
  755. nlats = jjmax-jjmin+1
  756. ! construct new arrays
  757. ALLOCATE( &
  758. & lons(nlons,nlats), &
  759. & lats(nlons,nlats), &
  760. & ixpos(nlons,nlats), &
  761. & iypos(nlons,nlats), &
  762. & iprocn(nlons,nlats) &
  763. & )
  764. lons(:,:) = lonsi(jimin:jimax,jjmin:jjmax)
  765. lats(:,:) = latsi(jimin:jimax,jjmin:jjmax)
  766. ixpos(:,:) = ixposi(jimin:jimax,jjmin:jjmax)
  767. iypos(:,:) = iyposi(jimin:jimax,jjmin:jjmax)
  768. iprocn(:,:) = iproci(jimin:jimax,jjmin:jjmax)
  769. DEALLOCATE(lonsi,latsi,ixposi,iyposi,iproci)
  770. ! calculate (estimate) maxxdiff, maxydiff
  771. ! this is to help define the search area for obs_grid_search_lookup
  772. maxxdiff = 1
  773. maxydiff = 1
  774. tmpx1 = 0
  775. tmpx2 = 0
  776. tmpy1 = 0
  777. tmpy2 = 0
  778. numx1 = 0
  779. numx2 = 0
  780. numy1 = 0
  781. numy2 = 0
  782. ! calculate the mean absolute xdiff and ydiff
  783. ! also calculate a histogram
  784. ! note the reason why looking for xdiff and ydiff in both directions
  785. ! is to allow for rotated grids
  786. DO ji = 1, nlons-1
  787. DO jj = 1, nlats-1
  788. IF ( ixpos(ji,jj) > 0 .AND. iypos(ji,jj) > 0 ) THEN
  789. IF ( ixpos(ji+1,jj) > 0 ) THEN
  790. df = ABS( ixpos(ji+1,jj) - ixpos(ji,jj) )
  791. tmpx1 = tmpx1+df
  792. numx1 = numx1+1
  793. IF ( df < histsize ) histx1(df+1) = histx1(df+1) + 1
  794. ENDIF
  795. IF ( ixpos(ji,jj+1) > 0 ) THEN
  796. df = ABS( ixpos(ji,jj+1) - ixpos(ji,jj) )
  797. tmpx2 = tmpx2 + df
  798. numx2 = numx2 + 1
  799. IF ( df < histsize ) histx2(df+1) = histx2(df+1) + 1
  800. ENDIF
  801. IF (iypos(ji+1,jj) > 0) THEN
  802. df = ABS( iypos(ji+1,jj) - iypos(ji,jj) )
  803. tmpy1 = tmpy1 + df
  804. numy1 = numy1 + 1
  805. IF ( df < histsize ) histy1(df+1) = histy1(df+1) + 1
  806. ENDIF
  807. IF ( iypos(ji,jj+1) > 0 ) THEN
  808. df = ABS( iypos(ji,jj+1) - iypos(ji,jj) )
  809. tmpy2 = tmpy2 + df
  810. numy2 = numy2 + 1
  811. IF ( df < histsize ) histy2(df+1) = histy2(df+1) + 1
  812. ENDIF
  813. ENDIF
  814. END DO
  815. END DO
  816. IF (lwp) THEN
  817. WRITE(numout,*) 'histograms'
  818. WRITE(numout,*) '0 1 2 3 4 5 6 7 8 9 10 ...'
  819. WRITE(numout,*) 'histx1'
  820. WRITE(numout,*) histx1
  821. WRITE(numout,*) 'histx2'
  822. WRITE(numout,*) histx2
  823. WRITE(numout,*) 'histy1'
  824. WRITE(numout,*) histy1
  825. WRITE(numout,*) 'histy2'
  826. WRITE(numout,*) histy2
  827. ENDIF
  828. meanxdiff1 = tmpx1 / numx1
  829. meanydiff1 = tmpy1 / numy1
  830. meanxdiff2 = tmpx2 / numx2
  831. meanydiff2 = tmpy2 / numy2
  832. meanxdiff = MAXVAL((/ meanxdiff1, meanxdiff2 /))
  833. meanydiff = MAXVAL((/ meanydiff1, meanydiff2 /))
  834. IF (lwp) THEN
  835. WRITE(numout,*) tmpx1, tmpx2, tmpy1, tmpy2
  836. WRITE(numout,*) numx1, numx2, numy1, numy2
  837. WRITE(numout,*) 'meanxdiff: ',meanxdiff, meanxdiff1, meanxdiff2
  838. WRITE(numout,*) 'meanydiff: ',meanydiff, meanydiff1, meanydiff2
  839. ENDIF
  840. tmpx1 = 0
  841. tmpx2 = 0
  842. tmpy1 = 0
  843. tmpy2 = 0
  844. numx1 = 0
  845. numx2 = 0
  846. numy1 = 0
  847. numy2 = 0
  848. histx1(:) = 0
  849. histx2(:) = 0
  850. histy1(:) = 0
  851. histy2(:) = 0
  852. limxdiff = meanxdiff * 4! limit the difference to avoid picking up wraparound
  853. limydiff = meanydiff * 4
  854. DO ji = 1, nlons-1
  855. DO jj = 1, nlats-1
  856. IF ( ixpos(ji,jj) > 0 .AND. iypos(ji,jj) > 0 ) THEN
  857. IF ( ixpos(ji+1,jj) > 0 ) THEN
  858. df = ABS( ixpos(ji+1,jj)-ixpos(ji,jj) )
  859. tmpx1 = df
  860. IF ( df < limxdiff ) numx1 = numx1+1
  861. IF ( df < histsize ) histx1(df+1) = histx1(df+1) + 1
  862. ENDIF
  863. IF ( ixpos(ji,jj+1) > 0 ) THEN
  864. df = ABS( ixpos(ji,jj+1) - ixpos(ji,jj) )
  865. tmpx2 = df
  866. IF ( df < limxdiff ) numx2 = numx2 + 1
  867. IF ( df < histsize ) histx2(df+1) = histx2(df+1) + 1
  868. ENDIF
  869. IF (iypos(ji+1,jj) > 0) THEN
  870. df = ABS( iypos(ji+1,jj) - iypos(ji,jj) )
  871. tmpy1 = df
  872. IF ( df < limydiff ) numy1 = numy1 + 1
  873. IF ( df < histsize ) histy1(df+1) = histy1(df+1) + 1
  874. ENDIF
  875. IF (iypos(ji,jj+1) > 0) THEN
  876. df = ABS( iypos(ji,jj+1) - iypos(ji,jj) )
  877. tmpy2 = df
  878. IF ( df < limydiff ) numy2 = numy2+1
  879. IF ( df < histsize ) histy2(df+1) = histy2(df+1)+1
  880. ENDIF
  881. IF ( maxxdiff < tmpx1 .AND. tmpx1 < limxdiff ) &
  882. & maxxdiff = tmpx1
  883. IF ( maxxdiff < tmpx2 .AND. tmpx2 < limxdiff ) &
  884. & maxxdiff = tmpx2
  885. IF ( maxydiff < tmpy1 .AND. tmpy1 < limydiff ) &
  886. & maxydiff = tmpy1
  887. IF ( maxydiff < tmpy2 .AND. tmpy2 < limydiff ) &
  888. & maxydiff = tmpy2
  889. ENDIF
  890. END DO
  891. END DO
  892. ! cumulative histograms
  893. DO ji = 1, histsize - 1
  894. histx1(ji+1) = histx1(ji+1) + histx1(ji)
  895. histx2(ji+1) = histx2(ji+1) + histx2(ji)
  896. histy1(ji+1) = histy1(ji+1) + histy1(ji)
  897. histy2(ji+1) = histy2(ji+1) + histy2(ji)
  898. END DO
  899. fhistx1(:) = histx1(:) * 1.0 / numx1
  900. fhistx2(:) = histx2(:) * 1.0 / numx2
  901. fhisty1(:) = histy1(:) * 1.0 / numy1
  902. fhisty2(:) = histy2(:) * 1.0 / numy2
  903. ! output new histograms
  904. IF (lwp) THEN
  905. WRITE(numout,*) 'cumulative histograms'
  906. WRITE(numout,*) '0 1 2 3 4 5 6 7 8 9 10 ...'
  907. WRITE(numout,*) 'fhistx1'
  908. WRITE(numout,*) fhistx1
  909. WRITE(numout,*) 'fhistx2'
  910. WRITE(numout,*) fhistx2
  911. WRITE(numout,*) 'fhisty1'
  912. WRITE(numout,*) fhisty1
  913. WRITE(numout,*) 'fhisty2'
  914. WRITE(numout,*) fhisty2
  915. ENDIF
  916. ! calculate maxxdiff and maxydiff based on cumulative histograms
  917. ! where > 0.999 of points are
  918. ! maxval just converts 1x1 vector return from maxloc to a scalar
  919. histtol = 0.999
  920. tmpx1 = MAXVAL( MAXLOC( fhistx1(:), mask = ( fhistx1(:) <= histtol ) ) )
  921. tmpx2 = MAXVAL( MAXLOC( fhistx2(:), mask = ( fhistx2(:) <= histtol ) ) )
  922. tmpy1 = MAXVAL( MAXLOC( fhisty1(:), mask = ( fhisty1(:) <= histtol ) ) )
  923. tmpy2 = MAXVAL( MAXLOC( fhisty2(:), mask = ( fhisty2(:) <= histtol ) ) )
  924. maxxdiff = MAXVAL( (/ tmpx1, tmpx2 /) ) + 1
  925. maxydiff = MAXVAL( (/ tmpy1, tmpy2 /) ) + 1
  926. ! Write out data
  927. IF ( ( .NOT. ln_grid_global ) .OR. &
  928. & ( ( ln_grid_global ) .AND. ( nproc==0 ) ) ) THEN
  929. CALL chkerr( nf90_create (TRIM(cfname), nf90_clobber, idfile), &
  930. & cpname, __LINE__ )
  931. CALL chkerr( nf90_put_att( idfile, nf90_global, 'title', &
  932. & 'Mapping file from lon/lat to model grid point' ),&
  933. & cpname,__LINE__ )
  934. CALL chkerr( nf90_put_att( idfile, nf90_global, 'maxxdiff', &
  935. & maxxdiff ), &
  936. & cpname,__LINE__ )
  937. CALL chkerr( nf90_put_att( idfile, nf90_global, 'maxydiff', &
  938. & maxydiff ), &
  939. & cpname,__LINE__ )
  940. CALL chkerr( nf90_put_att( idfile, nf90_global, 'dlon', dlon ),&
  941. & cpname,__LINE__ )
  942. CALL chkerr( nf90_put_att( idfile, nf90_global, 'dlat', dlat ),&
  943. & cpname,__LINE__ )
  944. CALL chkerr( nf90_put_att( idfile, nf90_global, 'lonmin', &
  945. & lonmin ), &
  946. & cpname,__LINE__ )
  947. CALL chkerr( nf90_put_att( idfile, nf90_global, 'latmin', &
  948. & latmin ), &
  949. & cpname,__LINE__ )
  950. CALL chkerr( nf90_def_dim(idfile, 'nx' , nlons, idnx), &
  951. & cpname,__LINE__ )
  952. CALL chkerr( nf90_def_dim(idfile, 'ny' , nlats, idny), &
  953. & cpname,__LINE__ )
  954. incdim(1) = idnx
  955. incdim(2) = idny
  956. CALL chkerr( nf90_def_var( idfile, 'LON', nf90_float, incdim, &
  957. & idlon ), &
  958. & cpname, __LINE__ )
  959. CALL chkerr( nf90_put_att( idfile, idlon, 'long_name', &
  960. & 'longitude' ), &
  961. & cpname, __LINE__ )
  962. CALL chkerr( nf90_def_var( idfile, 'LAT', nf90_float, incdim, &
  963. & idlat ), &
  964. & cpname, __LINE__ )
  965. CALL chkerr( nf90_put_att( idfile, idlat, 'long_name', &
  966. & 'latitude' ), &
  967. & cpname, __LINE__ )
  968. CALL chkerr( nf90_def_var( idfile, 'XPOS', nf90_int, incdim, &
  969. & idxpos ), &
  970. & cpname, __LINE__ )
  971. CALL chkerr( nf90_put_att( idfile, idxpos, 'long_name', &
  972. & 'x position' ), &
  973. & cpname, __LINE__ )
  974. CALL chkerr( nf90_put_att( idfile, idxpos, '_FillValue', -1 ), &
  975. & cpname, __LINE__ )
  976. CALL chkerr( nf90_def_var( idfile, 'YPOS', nf90_int, incdim, &
  977. & idypos ), &
  978. & cpname, __LINE__ )
  979. CALL chkerr( nf90_put_att( idfile, idypos, 'long_name', &
  980. & 'y position' ), &
  981. & cpname, __LINE__ )
  982. CALL chkerr( nf90_put_att( idfile, idypos, '_FillValue', -1 ), &
  983. & cpname, __LINE__ )
  984. CALL chkerr( nf90_enddef( idfile ), cpname, __LINE__ )
  985. CALL chkerr( nf90_put_var( idfile, idlon, lons), &
  986. & cpname, __LINE__ )
  987. CALL chkerr( nf90_put_var( idfile, idlat, lats), &
  988. & cpname, __LINE__ )
  989. CALL chkerr( nf90_put_var( idfile, idxpos, ixpos), &
  990. & cpname, __LINE__ )
  991. CALL chkerr( nf90_put_var( idfile, idypos, iypos), &
  992. & cpname, __LINE__ )
  993. CALL chkerr( nf90_close( idfile ), cpname, __LINE__ )
  994. ! should also output max i, max j spacing for use in
  995. ! obs_grid_search_lookup
  996. ENDIF
  997. ENDIF
  998. ENDIF
  999. END SUBROUTINE obs_grid_setup
  1000. SUBROUTINE obs_grid_deallocate( )
  1001. !!----------------------------------------------------------------------
  1002. !! *** ROUTINE obs_grid_setup ***
  1003. !!
  1004. !! ** Purpose : Deallocate arrays setup by obs_grid_setup
  1005. !!
  1006. !! History :
  1007. !! ! 2007-12 (D. Lea) new routine
  1008. !!-----------------------------------------------------------------------
  1009. IF (ln_grid_search_lookup) THEN
  1010. DEALLOCATE( lons, lats, ixpos, iypos, iprocn )
  1011. ENDIF
  1012. END SUBROUTINE obs_grid_deallocate
  1013. #include "obs_level_search.h90"
  1014. #include "linquad.h90"
  1015. #include "maxdist.h90"
  1016. #include "find_obs_proc.h90"
  1017. END MODULE obs_grid