obsinter_h2d.h90 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359
  1. !!----------------------------------------------------------------------
  2. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  3. !! $Id: obsinter_h2d.h90 2474 2010-12-16 15:32:33Z djlea $
  4. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  5. !!----------------------------------------------------------------------
  6. SUBROUTINE obs_int_h2d_init( kpk, kpk2, k2dint, plam, pphi, &
  7. & pglam, pgphi, pmask, pweig, pobsmask, &
  8. & iminpoints )
  9. !!-----------------------------------------------------------------------
  10. !!
  11. !! *** ROUTINE obs_int_h2d ***
  12. !!
  13. !! ** Purpose : Computes weights for horizontal interpolation to the
  14. !! observation point.
  15. !!
  16. !! ** Method : Horizontal interpolation to the observation point using
  17. !! model values at the corners of the surrounding grid
  18. !! points.
  19. !!
  20. !! Interpolation Schemes :
  21. !!
  22. !! 1) k2dint = 0: Distance-weighted interpolation scheme 1
  23. !!
  24. !! The interpolation weights are computed as a weighted
  25. !! sum of the distance between the model grid points (A)
  26. !! and the observation point (B). Distance (s) is computed
  27. !! using the great-circle distance formula:
  28. !!
  29. !! s(AB) = arcos( sin( phiA ) x sin( phiB )
  30. !! + cos( phiA ) x cos( phiB )
  31. !! x cos( lamB - lamA ) )
  32. !!
  33. !! 2) k2dint = 1: Distance-weighted interpolation scheme 2
  34. !!
  35. !! As k2dint = 0 but with distance (ds) computed using
  36. !! a small-angle approximation to the great-circle formula:
  37. !!
  38. !! ds(AB) = sqrt( ( phiB - phiA )^{2}
  39. !! + ( ( lamB - lamA ) * cos( phiB ) )^{2} )
  40. !!
  41. !! 3) k2dint = 2: Bilinear interpolation on a geographical grid
  42. !!
  43. !! The interpolation is split into two 1D interpolations in
  44. !! the longitude and latitude directions, respectively.
  45. !!
  46. !! 4) k2dint = 3: General bilinear remapping interpolation
  47. !!
  48. !! An iterative scheme that involves first mapping a
  49. !! quadrilateral cell into a cell with coordinates
  50. !! (0,0), (1,0), (0,1) and (1,1).
  51. !!
  52. !! 5) k2dint = 4: Polynomial interpolation
  53. !!
  54. !! The interpolation weights are computed by fitting a
  55. !! polynomial function of the form
  56. !!
  57. !! P(i) = a1(i) + a2(i) * phi + a3(i) * plam
  58. !! + a4(i) * phi * plam
  59. !!
  60. !! through the model values at the four surrounding grid points.
  61. !!
  62. !! ** Action :
  63. !!
  64. !! References : Jones, P.: A users guide for SCRIP: A Spherical
  65. !! Coordinate Remapping and Interpolation Package.
  66. !! Version 1.4. Los Alomos.
  67. !!
  68. !! http://www.acl.lanl.gov/climate/software/SCRIP/SCRIPmain.html
  69. !!
  70. !! History :
  71. !! ! 97-11 (A. Weaver, N. Daget)
  72. !! ! 06-03 (A. Vidard) NEMOVAR migration
  73. !! ! 06-10 (A. Weaver) Cleanup
  74. !! ! 07-08 (K. Mogensen) Split in two routines for easier adj.
  75. !!-----------------------------------------------------------------------
  76. !! * Modules used
  77. !! * Arguments
  78. INTEGER, INTENT(IN) :: &
  79. & kpk, & ! Parameter values for automatic arrays
  80. & kpk2, &
  81. & k2dint ! Interpolation scheme options
  82. ! = 0 distance-weighted (great circle)
  83. ! = 1 distance-weighted (small angle)
  84. ! = 2 bilinear (geographical grid)
  85. ! = 3 bilinear (quadrilateral grid)
  86. ! = 4 polynomial (quadrilateral grid)
  87. REAL(KIND=wp), INTENT(INOUT) :: &
  88. & plam, &
  89. & pphi ! Geographical (lat,lon) coordinates of
  90. ! observation
  91. REAL(KIND=wp), DIMENSION(2,2), INTENT(IN) :: &
  92. & pglam, & ! Model variable lat
  93. & pgphi ! Model variable lon
  94. REAL(KIND=wp), DIMENSION(2,2,kpk2), INTENT(IN) :: &
  95. & pmask ! Model variable mask
  96. REAL(KIND=wp), DIMENSION(2,2,kpk2), INTENT(OUT) :: &
  97. & pweig ! Weights for interpolation
  98. REAL(KIND=wp), DIMENSION(kpk2), INTENT(OUT) :: &
  99. & pobsmask ! Vertical mask for observations
  100. INTEGER, INTENT(IN), OPTIONAL :: &
  101. & iminpoints ! Reject point which is not surrounded
  102. ! by at least iminpoints sea points
  103. !! * Local declarations
  104. INTEGER :: &
  105. & jk
  106. INTEGER :: &
  107. & ikmax, &
  108. & iamb1, &
  109. & iamb2
  110. REAL(KIND=wp) :: &
  111. & zphimm, &
  112. & zphimp, &
  113. & zphipm, &
  114. & zphipp, &
  115. & zlammm, &
  116. & zlammp, &
  117. & zlampm, &
  118. & zlampp, &
  119. & zphimin, &
  120. & zphimax, &
  121. & zlammin, &
  122. & zlammax
  123. REAL(KIND=wp), DIMENSION(kpk2) :: &
  124. & z2dmm, &
  125. & z2dmp, &
  126. & z2dpm, &
  127. & z2dpp, &
  128. & z2dmmt, &
  129. & z2dmpt, &
  130. & z2dpmt, &
  131. & z2dppt, &
  132. & zsum
  133. LOGICAL :: &
  134. & ll_ds1, &
  135. & ll_skip, &
  136. & ll_fail
  137. !------------------------------------------------------------------------
  138. ! Constants for the 360 degrees ambiguity
  139. !------------------------------------------------------------------------
  140. iamb1 = 10 ! dlam < iamb1 * dphi
  141. iamb2 = 3 ! Special treatment if iamb2 * lam < max(lam)
  142. !------------------------------------------------------------------------
  143. ! Initialize number of levels
  144. !------------------------------------------------------------------------
  145. IF ( kpk2 == 1 ) THEN
  146. ikmax = 1
  147. ELSEIF ( kpk2 == kpk) THEN
  148. ikmax = kpk-1
  149. ENDIF
  150. !------------------------------------------------------------------------
  151. ! Initialize the cell corners
  152. !------------------------------------------------------------------------
  153. zphimm = pgphi(1,1)
  154. zphimp = pgphi(1,2)
  155. zphipm = pgphi(2,1)
  156. zphipp = pgphi(2,2)
  157. zlammm = pglam(1,1)
  158. zlammp = pglam(1,2)
  159. zlampm = pglam(2,1)
  160. zlampp = pglam(2,2)
  161. !------------------------------------------------------------------------
  162. ! Treat the 360 degrees ambiguity
  163. !------------------------------------------------------------------------
  164. DO WHILE ( ( zlammm < 0.0_wp ).OR.( zlammm > 360.0_wp ) &
  165. & .OR.( zlampm < 0.0_wp ).OR.( zlampm > 360.0_wp ) &
  166. & .OR.( zlampp < 0.0_wp ).OR.( zlampp > 360.0_wp ) &
  167. & .OR.( zlammp < 0.0_wp ).OR.( zlammp > 360.0_wp ) )
  168. IF ( zlammm < 0.0_wp ) zlammm = zlammm + 360.0_wp
  169. IF ( zlammm > 360.0_wp ) zlammm = zlammm - 360.0_wp
  170. IF ( zlammp < 0.0_wp ) zlammp = zlammp + 360.0_wp
  171. IF ( zlammp > 360.0_wp ) zlammp = zlammp - 360.0_wp
  172. IF ( zlampm < 0.0_wp ) zlampm = zlampm + 360.0_wp
  173. IF ( zlampm > 360.0_wp ) zlampm = zlampm - 360.0_wp
  174. IF ( zlampp < 0.0_wp ) zlampp = zlampp + 360.0_wp
  175. IF ( zlampp > 360.0_wp ) zlampp = zlampp - 360.0_wp
  176. END DO
  177. DO WHILE ( ( plam < 0.0_wp ) .OR. ( plam > 360.0_wp ) )
  178. IF ( plam < 0.0_wp ) plam = plam + 360.0_wp
  179. IF ( plam > 360.0_wp ) plam = plam - 360.0_wp
  180. END DO
  181. !------------------------------------------------------------------------
  182. ! Special case for observation on grid points
  183. !------------------------------------------------------------------------
  184. ll_skip = .FALSE.
  185. IF ( ( ABS( zphimm - pphi ) < 1.0e-6_wp ) .AND. &
  186. & ( ABS( zlammm - plam ) < 1.0e-6_wp ) ) THEN
  187. z2dmm(:) = 1.0_wp
  188. z2dpm(:) = 0.0_wp
  189. z2dmp(:) = 0.0_wp
  190. z2dpp(:) = 0.0_wp
  191. ll_skip = .TRUE.
  192. ENDIF
  193. IF ( ( ABS( zphipm - pphi ) < 1.0e-6_wp ) .AND. &
  194. & ( ABS( zlampm - plam ) < 1.0e-6_wp ) ) THEN
  195. z2dmm(:) = 0.0_wp
  196. z2dpm(:) = 1.0_wp
  197. z2dmp(:) = 0.0_wp
  198. z2dpp(:) = 0.0_wp
  199. ll_skip = .TRUE.
  200. ENDIF
  201. IF ( ( ABS( zphimp - pphi ) < 1.0e-6_wp ) .AND. &
  202. & ( ABS( zlammp - plam ) < 1.0e-6_wp ) ) THEN
  203. z2dmm(:) = 0.0_wp
  204. z2dpm(:) = 0.0_wp
  205. z2dmp(:) = 1.0_wp
  206. z2dpp(:) = 0.0_wp
  207. ll_skip = .TRUE.
  208. ENDIF
  209. IF ( ( ABS( zphipp - pphi ) < 1.0e-6_wp ) .AND. &
  210. & ( ABS( zlampp - plam ) < 1.0e-6_wp ) ) THEN
  211. z2dmm(:) = 0.0_wp
  212. z2dpm(:) = 0.0_wp
  213. z2dmp(:) = 0.0_wp
  214. z2dpp(:) = 1.0_wp
  215. ll_skip = .TRUE.
  216. ENDIF
  217. IF ( .NOT.ll_skip ) THEN
  218. zphimin = MIN( zphimm, zphipm, zphipp, zphimp )
  219. zphimax = MAX( zphimm, zphipm, zphipp, zphimp )
  220. zlammin = MIN( zlammm, zlampm, zlampp, zlammp )
  221. zlammax = MAX( zlammm, zlampm, zlampp, zlammp )
  222. IF ( ( ( zlammax - zlammin ) / ( zphimax - zphimin ) ) > iamb1 ) THEN
  223. IF ( iamb2 * zlammm < zlammax ) zlammm = zlammm + 360.0_wp
  224. IF ( iamb2 * zlammp < zlammax ) zlammp = zlammp + 360.0_wp
  225. IF ( iamb2 * zlampm < zlammax ) zlampm = zlampm + 360.0_wp
  226. IF ( iamb2 * zlampp < zlammax ) zlampp = zlampp + 360.0_wp
  227. ENDIF
  228. zlammin = MIN( zlammm, zlampm, zlampp, zlammp )
  229. IF ( zlammm > ( zlammin + 180.0_wp ) ) zlammm = zlammm - 360.0_wp
  230. IF ( zlammp > ( zlammin + 180.0_wp ) ) zlammp = zlammp - 360.0_wp
  231. IF ( zlampm > ( zlammin + 180.0_wp ) ) zlampm = zlampm - 360.0_wp
  232. IF ( zlampp > ( zlammin + 180.0_wp ) ) zlampp = zlampp - 360.0_wp
  233. IF ( plam < zlammin ) plam = plam + 360.0_wp
  234. z2dmm = 0.0_wp
  235. z2dmp = 0.0_wp
  236. z2dpm = 0.0_wp
  237. z2dpp = 0.0_wp
  238. SELECT CASE (k2dint)
  239. CASE(0)
  240. CALL obs_int_h2d_ds1( kpk2, ikmax, &
  241. & pphi, plam, pmask, &
  242. & zphimm, zlammm, zphimp, zlammp, &
  243. & zphipm, zlampm, zphipp, zlampp, &
  244. & z2dmm, z2dmp, z2dpm, z2dpp )
  245. CASE(1)
  246. CALL obs_int_h2d_ds2( kpk2, ikmax, &
  247. & pphi, plam, pmask, &
  248. & zphimm, zlammm, zphimp, zlammp, &
  249. & zphipm, zlampm, zphipp, zlampp, &
  250. & z2dmm, z2dmp, z2dpm, z2dpp )
  251. CASE(2)
  252. CALL obs_int_h2d_bil( kpk2, ikmax, &
  253. & pphi, plam, pmask, &
  254. & zlammp, &
  255. & zphipm, zphipp, zlampp, &
  256. & z2dmm, z2dmp, z2dpm, z2dpp )
  257. CASE(3)
  258. CALL obs_int_h2d_bir( kpk2, ikmax, &
  259. & pphi, plam, pmask, &
  260. & zphimm, zlammm, zphimp, zlammp, &
  261. & zphipm, zlampm, zphipp, zlampp, &
  262. & z2dmm, z2dmp, z2dpm, z2dpp, ll_fail )
  263. IF (ll_fail) THEN
  264. IF(lwp) THEN
  265. WRITE(numout,*)'Bilinear weight computation failed'
  266. WRITE(numout,*)'Switching to great circle distance'
  267. WRITE(numout,*)
  268. ENDIF
  269. CALL obs_int_h2d_ds1( kpk2, ikmax, &
  270. & pphi, plam, pmask, &
  271. & zphimm, zlammm, zphimp, zlammp, &
  272. & zphipm, zlampm, zphipp, zlampp, &
  273. & z2dmm, z2dmp, z2dpm, z2dpp )
  274. ENDIF
  275. CASE(4)
  276. CALL obs_int_h2d_pol( kpk2, ikmax, &
  277. & pphi, plam, pmask, &
  278. & zphimm, zlammm, zphimp, zlammp, &
  279. & zphipm, zlampm, zphipp, zlampp, &
  280. & z2dmm, z2dmp, z2dpm, z2dpp )
  281. END SELECT
  282. ENDIF
  283. !------------------------------------------------------------------------
  284. ! Compute weights for interpolation to the observation point
  285. !------------------------------------------------------------------------
  286. pobsmask(:) = 0.0_wp
  287. pweig(:,:,:) = 0.0_wp
  288. ! ll_ds1 is used for failed interpolations
  289. ll_ds1 = .FALSE.
  290. DO jk = 1, ikmax
  291. IF (PRESENT(iminpoints)) THEN
  292. IF (NINT(SUM(pmask(:,:,jk)))<iminpoints) CYCLE
  293. ENDIF
  294. zsum(jk) = z2dmm(jk) + z2dmp(jk) + z2dpm(jk) + z2dpp(jk)
  295. IF ( zsum(jk) /= 0.0_wp ) THEN
  296. pweig(1,1,jk) = z2dmm(jk)
  297. pweig(1,2,jk) = z2dmp(jk)
  298. pweig(2,1,jk) = z2dpm(jk)
  299. pweig(2,2,jk) = z2dpp(jk)
  300. ! Set the vertical mask
  301. IF ( ( ( z2dmm(jk) > 0.0_wp ) .AND. &
  302. & ( pmask(1,1,jk) == 1.0_wp ) ) .OR. &
  303. & ( ( z2dmp(jk) > 0.0_wp ) .AND. &
  304. & ( pmask(1,2,jk) == 1.0_wp ) ) .OR. &
  305. & ( ( z2dpm(jk) > 0.0_wp ) .AND. &
  306. & ( pmask(2,1,jk) == 1.0_wp ) ) .OR. &
  307. & ( ( z2dpp(jk) > 0.0_wp ) .AND. &
  308. & ( pmask(2,2,jk) == 1.0_wp ) ) ) pobsmask(jk)=1.0_wp
  309. ELSE
  310. ! If the interpolation has failed due to the point
  311. ! being on the intersect of two land points retry with
  312. ! k2dint = 0
  313. IF ( ( pmask(1,1,jk) /= 0.0_wp ).OR. &
  314. & ( pmask(1,2,jk) /= 0.0_wp ).OR. &
  315. & ( pmask(2,1,jk) /= 0.0_wp ).OR. &
  316. & ( pmask(2,2,jk) /= 0.0_wp ) ) THEN
  317. ! If ll_ds1 is false compute k2dint = 0 weights
  318. IF ( .NOT.ll_ds1 ) THEN
  319. CALL obs_int_h2d_ds1( kpk2, ikmax, &
  320. & pphi, plam, pmask, &
  321. & zphimm, zlammm, zphimp, zlammp, &
  322. & zphipm, zlampm, zphipp, zlampp, &
  323. & z2dmmt, z2dmpt, z2dpmt, z2dppt )
  324. ll_ds1 = .TRUE.
  325. ENDIF
  326. zsum(jk) = z2dmmt(jk) + z2dmpt(jk) + z2dpmt(jk) + z2dppt(jk)
  327. IF ( zsum(jk) /= 0.0_wp ) THEN
  328. pweig(1,1,jk) = z2dmmt(jk)
  329. pweig(1,2,jk) = z2dmpt(jk)
  330. pweig(2,1,jk) = z2dpmt(jk)
  331. pweig(2,2,jk) = z2dppt(jk)
  332. ! Set the vertical mask
  333. IF ( ( ( z2dmmt(jk) > 0.0_wp ) .AND. &
  334. & ( pmask(1,1,jk) == 1.0_wp ) ) .OR. &
  335. & ( ( z2dmpt(jk) > 0.0_wp ) .AND. &
  336. & ( pmask(1,2,jk) == 1.0_wp ) ) .OR. &
  337. & ( ( z2dpmt(jk) > 0.0_wp) .AND. &
  338. & ( pmask(2,1,jk) == 1.0_wp ) ) .OR. &
  339. & ( ( z2dppt(jk) > 0.0_wp ) .AND. &
  340. & ( pmask(2,2,jk) == 1.0_wp ) ) ) &
  341. & pobsmask(jk)=1.0_wp
  342. ENDIF
  343. ENDIF
  344. ENDIF
  345. END DO
  346. END SUBROUTINE obs_int_h2d_init
  347. SUBROUTINE obs_int_h2d( kpk, kpk2, &
  348. & pweig, pmod, pobsk )
  349. !!-----------------------------------------------------------------------
  350. !!
  351. !! *** ROUTINE obs_int_h2d ***
  352. !!
  353. !! ** Purpose : Horizontal interpolation to the observation point.
  354. !!
  355. !! ** Method : Horizontal interpolation to the observation point using
  356. !! model values at the corners of the surrounding grid
  357. !! points.
  358. !!
  359. !! ** Action :
  360. !!
  361. !! References :
  362. !!
  363. !! History :
  364. !! ! 97-11 (A. Weaver, N. Daget)
  365. !! ! 06-03 (A. Vidard) NEMOVAR migration
  366. !! ! 06-10 (A. Weaver) Cleanup
  367. !! ! 07-08 (K. Mogensen) Split in two routines for easier adj.
  368. !!-----------------------------------------------------------------------
  369. !! * Modules used
  370. !! * Arguments
  371. INTEGER, INTENT(IN) :: &
  372. & kpk, & ! Parameter values for automatic arrays
  373. & kpk2
  374. REAL(KIND=wp), DIMENSION(2,2,kpk2), INTENT(IN) :: &
  375. & pweig ! Interpolation weights
  376. REAL(KIND=wp), DIMENSION(2,2,kpk2), INTENT(IN) :: &
  377. & pmod ! Model variable to interpolate
  378. REAL(KIND=wp), DIMENSION(kpk2), INTENT(OUT) :: &
  379. & pobsk ! Model profile interpolated to obs (i,j) pt
  380. !! * Local declarations
  381. INTEGER :: &
  382. & jk
  383. INTEGER :: &
  384. & ikmax
  385. REAL(KIND=wp) :: &
  386. & zsum
  387. !------------------------------------------------------------------------
  388. ! Initialize number of levels
  389. !------------------------------------------------------------------------
  390. IF ( kpk2 == 1 ) THEN
  391. ikmax = 1
  392. ELSEIF ( kpk2 == kpk) THEN
  393. ikmax = kpk-1
  394. ENDIF
  395. !------------------------------------------------------------------------
  396. ! Interpolate to the observation point
  397. !------------------------------------------------------------------------
  398. pobsk(:) = obfillflt
  399. DO jk = 1, ikmax
  400. zsum = pweig(1,1,jk) + pweig(1,2,jk) + pweig(2,1,jk) + pweig(2,2,jk)
  401. IF ( zsum /= 0.0_wp ) THEN
  402. pobsk(jk) = ( pweig(1,1,jk) * pmod(1,1,jk) &
  403. & + pweig(1,2,jk) * pmod(1,2,jk) &
  404. & + pweig(2,1,jk) * pmod(2,1,jk) &
  405. & + pweig(2,2,jk) * pmod(2,2,jk) &
  406. & ) / zsum
  407. ENDIF
  408. END DO
  409. END SUBROUTINE obs_int_h2d
  410. SUBROUTINE obs_int_h2d_ds1( kpk2, kmax, &
  411. & pphi, plam, pmask, &
  412. & pphimm, plammm, pphimp, plammp, &
  413. & pphipm, plampm, pphipp, plampp, &
  414. & p2dmm, p2dmp, p2dpm, p2dpp )
  415. !!-----------------------------------------------------------------------
  416. !!
  417. !! *** ROUTINE obs_int_h2d_ds1 ***
  418. !!
  419. !! ** Purpose : Distance-weighted interpolation scheme (k2dint = 0)
  420. !!
  421. !! ** Method : The interpolation weights are computed as a weighted
  422. !! sum of the distance between the model grid points (A)
  423. !! and the observation point (B).
  424. !!
  425. !! Distance (s) is computed using the great-circle distance formula:
  426. !!
  427. !! s(AB) = arcos( sin( phiA ) x sin( phiB )
  428. !! + cos( phiA ) x cos( phiB ) x cos( lamB - lamA )
  429. !!
  430. !! ** Action :
  431. !!
  432. !! History :
  433. !! ! 97-11 (A. Weaver, N. Daget)
  434. !! ! 06-10 (A. Weaver) Cleanup
  435. !!-----------------------------------------------------------------------
  436. !! * Modules used
  437. !! * Arguments
  438. INTEGER, INTENT(IN) :: &
  439. & kpk2, & ! Parameter values for automatic arrays
  440. & kmax
  441. REAL(KIND=wp), INTENT(IN) :: &
  442. & pphi, & ! Geographical location of observation
  443. & plam, &
  444. & pphimm, & ! Geographical location of surrounding
  445. & pphimp, & ! model grid points
  446. & pphipm, &
  447. & pphipp, &
  448. & plammm, &
  449. & plammp, &
  450. & plampm, &
  451. & plampp
  452. REAL(KIND=wp), DIMENSION(2,2,kpk2), INTENT(IN) :: &
  453. & pmask ! Model variable mask
  454. REAL(KIND=wp), DIMENSION(kpk2), INTENT(OUT) :: &
  455. & p2dmm, & ! Interpolation weights
  456. & p2dmp, &
  457. & p2dpm, &
  458. & p2dpp
  459. !! * Local declarations
  460. INTEGER :: &
  461. & jk
  462. REAL(KIND=wp) :: &
  463. & zphi2, &
  464. & zlam2, &
  465. & zcola, &
  466. & za2, &
  467. & zb2, &
  468. & zc2, &
  469. & zphimm2, &
  470. & zphimp2, &
  471. & zphipm2, &
  472. & zphipp2, &
  473. & zlammm2, &
  474. & zlammp2, &
  475. & zlampm2, &
  476. & zlampp2, &
  477. & za1mm, &
  478. & za1mp, &
  479. & za1pm, &
  480. & za1pp, &
  481. & zcomm, &
  482. & zcomp, &
  483. & zcopm, &
  484. & zcopp, &
  485. & zb1mm, &
  486. & zb1mp, &
  487. & zb1pm, &
  488. & zb1pp, &
  489. & zc1mm, &
  490. & zc1mp, &
  491. & zc1pm, &
  492. & zc1pp, &
  493. & zsopmpp, &
  494. & zsommmp, &
  495. & zsomm, &
  496. & zsomp, &
  497. & zsopm, &
  498. & zsopp
  499. !------------------------------------------------------------------------
  500. ! Distance-weighted interpolation using the great circle formula
  501. !------------------------------------------------------------------------
  502. zphi2 = pphi * rad
  503. zlam2 = plam * rad
  504. zcola = COS( zphi2 )
  505. za2 = SIN( zphi2 )
  506. zb2 = zcola * COS( zlam2 )
  507. zc2 = zcola * SIN( zlam2 )
  508. zphimm2 = pphimm * rad
  509. zphimp2 = pphimp * rad
  510. zphipm2 = pphipm * rad
  511. zphipp2 = pphipp * rad
  512. zlammm2 = plammm * rad
  513. zlammp2 = plammp * rad
  514. zlampm2 = plampm * rad
  515. zlampp2 = plampp * rad
  516. za1mm = SIN( zphimm2 )
  517. za1mp = SIN( zphimp2 )
  518. za1pm = SIN( zphipm2 )
  519. za1pp = SIN( zphipp2 )
  520. zcomm = COS( zphimm2 )
  521. zcomp = COS( zphimp2 )
  522. zcopm = COS( zphipm2 )
  523. zcopp = COS( zphipp2 )
  524. zb1mm = zcomm * COS( zlammm2 )
  525. zb1mp = zcomp * COS( zlammp2 )
  526. zb1pm = zcopm * COS( zlampm2 )
  527. zb1pp = zcopp * COS( zlampp2 )
  528. zc1mm = zcomm * SIN( zlammm2 )
  529. zc1mp = zcomp * SIN( zlammp2 )
  530. zc1pm = zcopm * SIN( zlampm2 )
  531. zc1pp = zcopp * SIN( zlampp2 )
  532. ! Function for arcsin(sqrt(1-x^2) version of great-circle formula
  533. zsomm = grt_cir_dis( za1mm, za2, zb1mm, zb2, zc1mm, zc2 )
  534. zsomp = grt_cir_dis( za1mp, za2, zb1mp, zb2, zc1mp, zc2 )
  535. zsopm = grt_cir_dis( za1pm, za2, zb1pm, zb2, zc1pm, zc2 )
  536. zsopp = grt_cir_dis( za1pp, za2, zb1pp, zb2, zc1pp, zc2 )
  537. zsopmpp = zsopm * zsopp
  538. zsommmp = zsomm * zsomp
  539. DO jk = 1, kmax
  540. p2dmm(jk) = zsomp * zsopmpp * pmask(1,1,jk)
  541. p2dmp(jk) = zsomm * zsopmpp * pmask(1,2,jk)
  542. p2dpm(jk) = zsopp * zsommmp * pmask(2,1,jk)
  543. p2dpp(jk) = zsopm * zsommmp * pmask(2,2,jk)
  544. END DO
  545. END SUBROUTINE obs_int_h2d_ds1
  546. SUBROUTINE obs_int_h2d_ds2( kpk2, kmax, &
  547. & pphi, plam, pmask, &
  548. & pphimm, plammm, pphimp, plammp, &
  549. & pphipm, plampm, pphipp, plampp, &
  550. & p2dmm, p2dmp, p2dpm, p2dpp )
  551. !!-----------------------------------------------------------------------
  552. !!
  553. !! *** ROUTINE obs_int_h2d_ds2 ***
  554. !!
  555. !! ** Purpose : Distance-weighted interpolation scheme (k2dint = 1)
  556. !!
  557. !! ** Method : As k2dint = 0 but with distance (ds) computed using a
  558. !! small-angle approximation to the great-circle distance
  559. !! formula:
  560. !!
  561. !! ds(AB) = sqrt( ( phiB - phiA )^{2}
  562. !! + ( ( lamB - lamA ) * cos( phiB ) )^{2} )
  563. !!
  564. !! ** Action :
  565. !!
  566. !! History :
  567. !! ! 97-11 (A. Weaver, N. Daget)
  568. !! ! 06-10 (A. Weaver) Cleanup
  569. !!-----------------------------------------------------------------------
  570. !!-----------------------------------------------------------------------
  571. !! * Modules used
  572. !!-----------------------------------------------------------------------
  573. !! * Arguments
  574. INTEGER, INTENT(IN) :: &
  575. & kpk2, & ! Parameter values for automatic arrays
  576. & kmax
  577. REAL(KIND=wp), INTENT(IN) :: &
  578. & pphi, & ! Geographical location of observation
  579. & plam, &
  580. & pphimm, & ! Geographical location of surrounding
  581. & pphimp, & ! model grid points
  582. & pphipm, &
  583. & pphipp, &
  584. & plammm, &
  585. & plammp, &
  586. & plampm, &
  587. & plampp
  588. REAL(KIND=wp), DIMENSION(2,2,kpk2), INTENT(IN) :: &
  589. & pmask ! Model variable mask
  590. REAL(KIND=wp), DIMENSION(kpk2), INTENT(OUT) :: &
  591. & p2dmm, & ! Interpolation weights
  592. & p2dmp, &
  593. & p2dpm, &
  594. & p2dpp
  595. !! * Local declarations
  596. INTEGER :: &
  597. & jk
  598. REAL(KIND=wp) :: &
  599. & zcosp, &
  600. & zdlmm, &
  601. & zdlmp, &
  602. & zdlpm, &
  603. & zdlpp, &
  604. & zdpmm, &
  605. & zdpmp, &
  606. & zdppm, &
  607. & zdppp, &
  608. & zsomm, &
  609. & zsomp, &
  610. & zsopm, &
  611. & zsopp, &
  612. & zsopmpp, &
  613. & zsommmp
  614. !------------------------------------------------------------------------
  615. ! Distance-weighted interpolation with a small angle approximation
  616. !------------------------------------------------------------------------
  617. zcosp = COS( pphi * rad )
  618. zdlmm = plammm - plam
  619. zdlmp = plammp - plam
  620. zdlpm = plampm - plam
  621. zdlpp = plampp - plam
  622. zdpmm = pphimm - pphi
  623. zdpmp = pphimp - pphi
  624. zdppm = pphipm - pphi
  625. zdppp = pphipp - pphi
  626. zsomm = grt_cir_dis_saa( zdlmm, zdpmm, zcosp )
  627. zsomp = grt_cir_dis_saa( zdlmp, zdpmp, zcosp )
  628. zsopm = grt_cir_dis_saa( zdlpm, zdppm, zcosp )
  629. zsopp = grt_cir_dis_saa( zdlpp, zdppp, zcosp )
  630. zsopmpp = zsopm * zsopp
  631. zsommmp = zsomm * zsomp
  632. DO jk = 1, kmax
  633. p2dmm(jk) = zsomp * zsopmpp * pmask(1,1,jk)
  634. p2dmp(jk) = zsomm * zsopmpp * pmask(1,2,jk)
  635. p2dpm(jk) = zsopp * zsommmp * pmask(2,1,jk)
  636. p2dpp(jk) = zsopm * zsommmp * pmask(2,2,jk)
  637. END DO
  638. END SUBROUTINE obs_int_h2d_ds2
  639. SUBROUTINE obs_int_h2d_bil( kpk2, kmax, &
  640. & pphi, plam, pmask, &
  641. & plammp, pphipm, pphipp, plampp, &
  642. & p2dmm, p2dmp, p2dpm, p2dpp)
  643. !!-----------------------------------------------------------------------
  644. !!
  645. !! *** ROUTINE obs_int_h2d_bil ***
  646. !!
  647. !! ** Purpose : Bilinear interpolation on a geographical grid (k2dint = 2)
  648. !!
  649. !! ** Method : The interpolation is split into two 1D interpolations in
  650. !! the longitude and latitude directions, respectively.
  651. !!
  652. !! An iterative scheme that involves first mapping a quadrilateral
  653. !! cell into a cell with coordinates (0,0), (1,0), (0,1) and (1,1).
  654. !!
  655. !! ** Action :
  656. !!
  657. !! History :
  658. !! ! 97-11 (A. Weaver, N. Daget)
  659. !! ! 06-10 (A. Weaver) Cleanup
  660. !!-----------------------------------------------------------------------
  661. !! * Arguments
  662. INTEGER, INTENT(IN) :: &
  663. & kpk2, & ! Parameter values for automatic arrays
  664. & kmax
  665. REAL(KIND=wp), INTENT(IN) :: &
  666. & pphi, & ! Geographical location of observation
  667. & plam, &
  668. & pphipm, & ! Geographical location of surrounding
  669. & pphipp, & ! model grid points
  670. & plammp, &
  671. & plampp
  672. REAL(KIND=wp), DIMENSION(2,2,kpk2), INTENT(IN) :: &
  673. & pmask ! Model variable mask
  674. REAL(KIND=wp), DIMENSION(kpk2), INTENT(OUT) :: &
  675. & p2dmm, & ! Interpolation weights
  676. & p2dmp, &
  677. & p2dpm, &
  678. & p2dpp
  679. !! * Local declarations
  680. INTEGER :: &
  681. & jk
  682. REAL(KIND=wp) :: &
  683. & zdlmp, &
  684. & zdppm, &
  685. & zdlpp, &
  686. & zdppp
  687. !----------------------------------------------------------------------
  688. ! Bilinear interpolation for geographical grid
  689. !----------------------------------------------------------------------
  690. zdlmp = ABS(plam - plammp)
  691. zdppm = ABS(pphi - pphipm)
  692. zdlpp = ABS(plampp - plam)
  693. zdppp = ABS(pphipp - pphi)
  694. DO jk = 1, kmax
  695. p2dmm(jk) = zdlpp * zdppp * pmask(1,1,jk)
  696. p2dmp(jk) = zdlpp * zdppm * pmask(1,2,jk)
  697. p2dpm(jk) = zdlmp * zdppp * pmask(2,1,jk)
  698. p2dpp(jk) = zdlmp * zdppm * pmask(2,2,jk)
  699. END DO
  700. END SUBROUTINE obs_int_h2d_bil
  701. SUBROUTINE obs_int_h2d_bir( kpk2, kmax, &
  702. & pphi, plam, pmask, &
  703. & pphimm, plammm, pphimp, plammp, &
  704. & pphipm, plampm, pphipp, plampp, &
  705. & p2dmm, p2dmp, p2dpm, p2dpp, ldfail )
  706. !!-----------------------------------------------------------------------
  707. !!
  708. !! *** ROUTINE obs_int_h2d_bir ***
  709. !!
  710. !! ** Purpose : General bilinear remapping interpolation (k2dint = 3)
  711. !!
  712. !! ** Method : An iterative scheme that involves first mapping a
  713. !! quadrilateral cell into a cell with coordinates
  714. !! (0,0), (1,0), (0,1) and (1,1).
  715. !!
  716. !! ** Action :
  717. !!
  718. !! History :
  719. !! ! 97-11 (A. Weaver, N. Daget)
  720. !! ! 06-10 (A. Weaver) Cleanup
  721. !!-----------------------------------------------------------------------
  722. !! * Arguments
  723. INTEGER, INTENT(IN) :: &
  724. & kpk2, & ! Parameter values for automatic arrays
  725. & kmax
  726. REAL(KIND=wp), INTENT(IN) :: &
  727. & pphi, & ! Geographical location of observation
  728. & plam, &
  729. & pphimm, & ! Geographical location of surrounding
  730. & pphimp, & ! model grid points
  731. & pphipm, &
  732. & pphipp, &
  733. & plammm, &
  734. & plammp, &
  735. & plampm, &
  736. & plampp
  737. REAL(KIND=wp), DIMENSION(2,2,kpk2), INTENT(IN) :: &
  738. & pmask ! Model variable mask
  739. REAL(KIND=wp), DIMENSION(kpk2), INTENT(OUT) :: &
  740. & p2dmm, & ! Interpolation weights
  741. & p2dmp, &
  742. & p2dpm, &
  743. & p2dpp
  744. LOGICAL, INTENT(OUT) :: &
  745. & ldfail
  746. !! * Local declarations
  747. INTEGER :: &
  748. & jk
  749. REAL(KIND=wp) :: &
  750. & zbiwmm, &
  751. & zbiwmp, &
  752. & zbiwpm, &
  753. & zbiwpp
  754. !----------------------------------------------------------------------
  755. ! Bilinear remapping interpolation for general quadrilateral grid
  756. !----------------------------------------------------------------------
  757. CALL bil_wgt( pphimm, pphimp, pphipm, pphipp, &
  758. & plammm, plammp, plampm, plampp, &
  759. & zbiwmm, zbiwmp, zbiwpm, zbiwpp, &
  760. & pphi , plam, ldfail )
  761. IF ( .NOT.ldfail ) THEN
  762. DO jk = 1, kmax
  763. p2dmm(jk) = zbiwmm * pmask(1,1,jk)
  764. p2dmp(jk) = zbiwmp * pmask(1,2,jk)
  765. p2dpm(jk) = zbiwpm * pmask(2,1,jk)
  766. p2dpp(jk) = zbiwpp * pmask(2,2,jk)
  767. END DO
  768. ENDIF
  769. END SUBROUTINE obs_int_h2d_bir
  770. SUBROUTINE obs_int_h2d_pol( kpk2, kmax, &
  771. & pphi, plam, pmask, &
  772. & pphimm, plammm, pphimp, plammp, &
  773. & pphipm, plampm, pphipp, plampp, &
  774. & p2dmm, p2dmp, p2dpm, p2dpp )
  775. !!-----------------------------------------------------------------------
  776. !!
  777. !! *** ROUTINE obs_int_h2d_pol ***
  778. !!
  779. !! ** Purpose : Polynomial interpolation (k2dint = 4)
  780. !!
  781. !! ** Method : The interpolation weights are computed by fitting a
  782. !! polynomial function of the form
  783. !!
  784. !! P(i) = a1(i) + a2(i) * phi + a3(i) * plam + a4(i) * phi * plam
  785. !!
  786. !! through the model values at four surrounding grid pts (i=1,4).
  787. !! As k2dint = 0 but with distance (ds) computed using a small-
  788. !! angle approximation to the great-circle distance formula:
  789. !!
  790. !! ds(AB) = sqrt( ( phiB - phiA )^{2}
  791. !! + ( ( lamB - lamA ) * cos( phiB ) )^{2} )
  792. !!
  793. !! ** Action :
  794. !!
  795. !! History :
  796. !! ! 97-11 (A. Weaver, N. Daget)
  797. !! ! 06-10 (A. Weaver) Cleanup
  798. !!-----------------------------------------------------------------------
  799. !! * Arguments
  800. INTEGER, INTENT(IN) :: &
  801. & kpk2, & ! Parameter values for automatic arrays
  802. & kmax
  803. REAL(KIND=wp), INTENT(IN) :: &
  804. & pphi, & ! Geographical location of observation
  805. & plam, &
  806. & pphimm, & ! Geographical location of surrounding
  807. & pphimp, & ! model grid points
  808. & pphipm, &
  809. & pphipp, &
  810. & plammm, &
  811. & plammp, &
  812. & plampm, &
  813. & plampp
  814. REAL(KIND=wp), DIMENSION(2,2,kpk2), INTENT(IN) :: &
  815. & pmask ! Model variable mask
  816. REAL(KIND=wp), DIMENSION(kpk2), INTENT(OUT) :: &
  817. & p2dmm, & ! Interpolation weights
  818. & p2dmp, &
  819. & p2dpm, &
  820. & p2dpp
  821. !! * Local declarations
  822. INTEGER :: &
  823. & jk
  824. REAL(KIND=wp) :: &
  825. & zplp
  826. REAL(KIND=wp), DIMENSION(4,4) :: &
  827. & zmat, &
  828. & zmati
  829. !------------------------------------------------------------------------
  830. ! Polynomial interpolation
  831. !------------------------------------------------------------------------
  832. zmat(1,1) = 1.0_wp
  833. zmat(1,2) = 1.0_wp
  834. zmat(1,3) = 1.0_wp
  835. zmat(1,4) = 1.0_wp
  836. zmat(2,1) = plammm
  837. zmat(2,2) = plammp
  838. zmat(2,3) = plampm
  839. zmat(2,4) = plampp
  840. zmat(3,1) = pphimm
  841. zmat(3,2) = pphimp
  842. zmat(3,3) = pphipm
  843. zmat(3,4) = pphipp
  844. zmat(4,1) = plammm * pphimm
  845. zmat(4,2) = plammp * pphimp
  846. zmat(4,3) = plampm * pphipm
  847. zmat(4,4) = plampp * pphipp
  848. CALL lu_invmat( zmat, 4, zmati )
  849. zplp = plam * pphi
  850. DO jk = 1, kmax
  851. p2dmm(jk) = ABS( zmati(1,1) + zmati(1,2) * plam &
  852. & + zmati(1,3) * pphi + zmati(1,4) * zplp ) &
  853. & * pmask(1,1,jk)
  854. p2dmp(jk) = ABS( zmati(2,1) + zmati(2,2) * plam &
  855. & + zmati(2,3) * pphi + zmati(2,4) * zplp ) &
  856. & * pmask(1,2,jk)
  857. p2dpm(jk) = ABS( zmati(3,1) + zmati(3,2) * plam &
  858. & + zmati(3,3) * pphi + zmati(3,4) * zplp ) &
  859. & * pmask(2,1,jk)
  860. p2dpp(jk) = ABS( zmati(4,1) + zmati(4,2) * plam &
  861. & + zmati(4,3) * pphi + zmati(4,4) * zplp ) &
  862. & * pmask(2,2,jk)
  863. END DO
  864. END SUBROUTINE obs_int_h2d_pol
  865. SUBROUTINE bil_wgt( pphimm, pphimp, pphipm, pphipp, &
  866. & plammm, plammp, plampm, plampp, &
  867. & pbiwmm, pbiwmp, pbiwpm, pbiwpp, &
  868. & pphi , plam, ldfail )
  869. !!-------------------------------------------------------------------
  870. !!
  871. !! *** ROUTINE bil_wgt ***
  872. !!
  873. !! ** Purpose : Compute the weights for a bilinear remapping
  874. !! interpolation scheme.
  875. !!
  876. !! ** Method : This scheme is appropriate for bilinear interpolation
  877. !! on a general quadrilateral grid.
  878. !! This scheme is also used in OASIS.
  879. !!
  880. !! This routine is a derivative of the SCRIP software.
  881. !! Copyright 1997, 1998 the Regents of the University
  882. !! of California. See SCRIP_Copyright.txt.
  883. !!
  884. !! ** Action :
  885. !!
  886. !! References : Jones, P.: A user's guide for SCRIP: A Spherical
  887. !! Coordinate Remapping and Interpolation Package.
  888. !! Version 1.4. Los Alamos.
  889. !!
  890. !! http://www.acl.lanl.gov/climate/software/SCRIP/SCRIPmain.html
  891. !!
  892. !! History
  893. !! ! 97-11 (A. Weaver, N. Daget)
  894. !! ! 06-03 (A. Vidard)
  895. !! ! 06-10 (A. Weaver) Cleanup
  896. !!-----------------------------------------------------------------------
  897. !! * Arguments
  898. REAL(KIND=wp), INTENT(IN) :: &
  899. & pphi, & ! Geographical location of observation
  900. & plam, &
  901. & pphimm, & ! Geographical location of surrounding
  902. & pphimp, & ! model grid points
  903. & pphipm, &
  904. & pphipp, &
  905. & plammm, &
  906. & plammp, &
  907. & plampm, &
  908. & plampp
  909. REAL(KIND=wp), INTENT(OUT) :: &
  910. & pbiwmm, & ! Interpolation weights
  911. & pbiwmp, &
  912. & pbiwpm, &
  913. & pbiwpp
  914. LOGICAL, INTENT(out) :: &
  915. & ldfail
  916. !! * Local declarations
  917. INTEGER :: &
  918. & jiter
  919. INTEGER :: &
  920. & itermax
  921. REAL(KIND=wp) :: &
  922. & zphi, & ! Geographical location of observation
  923. & zlam, &
  924. & zphimm, & ! Geographical location of surrounding
  925. & zphimp, & ! model grid points
  926. & zphipm, &
  927. & zphipp, &
  928. & zlammm, &
  929. & zlammp, &
  930. & zlampm, &
  931. & zlampp, &
  932. & zdth1, &
  933. & zdth2, &
  934. & zdth3, &
  935. & zdthp, &
  936. & zdph1, &
  937. & zdph2, &
  938. & zdph3, &
  939. & zdphp, &
  940. & zmat1, &
  941. & zmat2, &
  942. & zmat3, &
  943. & zmat4, &
  944. & zdeli, &
  945. & zdelj, &
  946. & ziguess, &
  947. & zjguess, &
  948. & zeps, &
  949. & zdeterm, &
  950. & z2pi, &
  951. & zhpi
  952. ! Initialization
  953. ! Conversion to radians
  954. zphi = pphi * rad
  955. zlam = plam * rad
  956. zphimm = pphimm * rad
  957. zphimp = pphimp * rad
  958. zphipm = pphipm * rad
  959. zphipp = pphipp * rad
  960. zlammm = plammm * rad
  961. zlammp = plammp * rad
  962. zlampm = plampm * rad
  963. zlampp = plampp * rad
  964. ldfail = .FALSE.
  965. zdth1 = zphipm - zphimm
  966. zdth2 = zphimp - zphimm
  967. zdth3 = zphipp - zphipm - zdth2
  968. zdph1 = zlampm - zlammm
  969. zdph2 = zlammp - zlammm
  970. zdph3 = zlampp - zlampm
  971. z2pi = 2.0_wp * rpi
  972. IF ( zdph1 > 3.0_wp * rpi ) zdph1 = zdph1 - z2pi
  973. IF ( zdph2 > 3.0_wp * rpi ) zdph2 = zdph2 - z2pi
  974. IF ( zdph3 > 3.0_wp * rpi ) zdph3 = zdph3 - z2pi
  975. IF ( zdph1 < -3.0_wp * rpi ) zdph1 = zdph1 + z2pi
  976. IF ( zdph2 < -3.0_wp * rpi ) zdph2 = zdph2 + z2pi
  977. IF ( zdph3 < -3.0_wp * rpi ) zdph3 = zdph3 + z2pi
  978. zdph3 = zdph3 - zdph2
  979. ziguess = 0.5_wp
  980. zjguess = 0.5_wp
  981. itermax = 100
  982. IF ( wp == sp ) THEN
  983. zeps = 1.0e-6_wp ! Single precision
  984. ELSE
  985. zeps = 1.0e-10_wp ! Double precision
  986. ENDIF
  987. !------------------------------------------------------------------------
  988. ! Iterate to determine (i,j) in new coordinate system
  989. !------------------------------------------------------------------------
  990. jiter_loop: DO jiter = 1, itermax
  991. zdthp = zphi - zphimm - zdth1 * ziguess - zdth2 * zjguess &
  992. & - zdth3 * ziguess * zjguess
  993. zdphp = zlam - zlammm
  994. zhpi = 0.5_wp * rpi
  995. IF ( zdphp > 3.0_wp * zhpi ) zdphp = zdphp - z2pi
  996. IF ( zdphp < -3.0_wp * zhpi ) zdphp = zdphp + z2pi
  997. zdphp = zdphp - zdph1 * ziguess - zdph2 * zjguess &
  998. & - zdph3 * ziguess * zjguess
  999. zmat1 = zdth1 + zdth3 * zjguess
  1000. zmat2 = zdth2 + zdth3 * ziguess
  1001. zmat3 = zdph1 + zdph3 * zjguess
  1002. zmat4 = zdph2 + zdph3 * ziguess
  1003. ! Matrix determinant
  1004. zdeterm = zmat1 * zmat4 - zmat2 * zmat3
  1005. zdeli = ( zdthp * zmat4 - zmat2 * zdphp) / zdeterm
  1006. zdelj = ( zmat1 * zdphp - zdthp * zmat3) / zdeterm
  1007. IF ( ABS( zdeli ) < zeps .AND. ABS( zdelj ) < zeps ) EXIT jiter_loop
  1008. ziguess = ziguess + zdeli
  1009. zjguess = zjguess + zdelj
  1010. ! DJL prevent ziguess and zjguess from going outside the range
  1011. ! 0 to 1
  1012. ! prevents interpolated value going wrong
  1013. ! for example sea ice concentration gt 1
  1014. IF ( ziguess < 0 ) ziguess = 0.0_wp
  1015. IF ( zjguess < 0 ) zjguess = 0.0_wp
  1016. IF ( ziguess > 1 ) ziguess = 1.0_wp
  1017. IF ( zjguess > 1 ) zjguess = 1.0_wp
  1018. END DO jiter_loop
  1019. IF ( jiter <= itermax ) THEN
  1020. ! Successfully found i,j, now compute the weights
  1021. pbiwmm = ( 1.0_wp - ziguess ) * ( 1.0_wp - zjguess )
  1022. pbiwmp = ( 1.0_wp - ziguess ) * zjguess
  1023. pbiwpm = ziguess * ( 1.0_wp - zjguess )
  1024. pbiwpp = ziguess * zjguess
  1025. ELSEIF ( jiter > itermax ) THEN
  1026. IF(lwp) THEN
  1027. WRITE(numout,*)'Obs lat/lon : ',pphi, plam
  1028. WRITE(numout,*)'Grid lats : ',pphimm, pphimp, pphipm, pphipp
  1029. WRITE(numout,*)'Grid lons : ',plammm, plammp, plampm, plampp
  1030. WRITE(numout,*)'Current i,j : ',ziguess, zjguess
  1031. WRITE(numout,*)'Weights : ',pbiwmm, pbiwmp, pbiwpm, pbiwpp
  1032. WRITE(numout,*)'jiter = ',jiter
  1033. WRITE(numout,*)'zeps = ',zeps
  1034. WRITE(numout,*)'zdeli, zdelj = ',zdeli, zdelj
  1035. WRITE(numout,*)' Iterations for i,j exceed max iteration count!'
  1036. WRITE(numout,*)
  1037. ldfail = .TRUE.
  1038. ENDIF
  1039. ENDIF
  1040. END SUBROUTINE bil_wgt
  1041. SUBROUTINE lu_invmat( pmatin, kdim, pmatou )
  1042. !!-----------------------------------------------------------------------
  1043. !!
  1044. !! *** ROUTINE lu_invmat ***
  1045. !!
  1046. !! ** Purpose : Invert a matrix using LU decomposition.
  1047. !!
  1048. !! ** Method :
  1049. !!
  1050. !! ** Action :
  1051. !!
  1052. !! References :
  1053. !!
  1054. !! History
  1055. !! ! 02-11 (A. Weaver, N. Daget)
  1056. !! ! 06-03 (A. Vidard)
  1057. !! ! 06-10 (A. Weaver) Cleanup
  1058. !! ! 06-11 (NEMOVAR task force) Fix declaration of zd.
  1059. !!-----------------------------------------------------------------------
  1060. !! * Arguments
  1061. INTEGER, INTENT(IN) :: &
  1062. & kdim ! Array dimension
  1063. REAL(KIND=wp), DIMENSION(kdim,kdim), INTENT(IN) :: &
  1064. & pmatin
  1065. REAL(KIND=wp), DIMENSION(kdim,kdim), INTENT(OUT) :: &
  1066. & pmatou
  1067. !! * Local declarations
  1068. INTEGER :: &
  1069. & ji, &
  1070. & jj
  1071. INTEGER, DIMENSION(kdim) :: &
  1072. & indx
  1073. REAL(KIND=wp), DIMENSION(kdim,kdim) :: &
  1074. & zmat
  1075. REAL(KIND=wp) :: &
  1076. & zd
  1077. ! Invert the matrix
  1078. DO jj = 1, kdim
  1079. DO ji = 1, kdim
  1080. pmatou(ji,jj) = 0.0_wp
  1081. zmat(ji,jj) = pmatin(ji,jj)
  1082. END DO
  1083. pmatou(jj,jj) = 1.0_wp
  1084. END DO
  1085. CALL lu_decomp( zmat, kdim, kdim, indx, zd )
  1086. DO jj = 1, kdim
  1087. CALL lu_backsb( zmat, kdim, kdim, indx, pmatou(1,jj) )
  1088. END DO
  1089. END SUBROUTINE lu_invmat
  1090. SUBROUTINE lu_decomp( pmatin, kdim1, kdim2, kindex, pflt )
  1091. !!-----------------------------------------------------------------------
  1092. !!
  1093. !! *** ROUTINE lu_decomp ***
  1094. !!
  1095. !! ** Purpose : Compute the LU decomposition of a matrix
  1096. !!
  1097. !! ** Method :
  1098. !!
  1099. !! ** Action :
  1100. !!
  1101. !! References :
  1102. !!
  1103. !! History
  1104. !! ! 02-11 (A. Weaver, N. Daget)
  1105. !! ! 06-03 (A. Vidard)
  1106. !! ! 06-10 (A. Weaver) Cleanup
  1107. !!-----------------------------------------------------------------------
  1108. !! * Arguments
  1109. INTEGER, INTENT(IN) :: &
  1110. & kdim1, & ! Array dimensions
  1111. & kdim2
  1112. INTEGER, DIMENSION(kdim1), INTENT(OUT) :: &
  1113. & kindex
  1114. REAL(KIND=wp), INTENT(OUT) :: &
  1115. & pflt
  1116. REAL(KIND=wp), DIMENSION(kdim2,kdim2), INTENT(INOUT) :: &
  1117. & pmatin
  1118. !! * Local declarations
  1119. INTEGER, PARAMETER :: &
  1120. & jpmax = 100
  1121. REAL(KIND=wp), PARAMETER :: &
  1122. & pptiny = 1.0e-20_wp
  1123. REAL(KIND=wp), DIMENSION(jpmax) :: &
  1124. & zvv
  1125. INTEGER :: &
  1126. & ji, &
  1127. & jj, &
  1128. & jk
  1129. INTEGER :: &
  1130. & imax
  1131. REAL(KIND=wp) :: &
  1132. & zsum, &
  1133. & zdum, &
  1134. & zaamax
  1135. ! Main computation
  1136. pflt = 1.0_wp
  1137. DO ji = 1, kdim1
  1138. zaamax = 0.0_wp
  1139. DO jj = 1, kdim1
  1140. IF ( ABS( pmatin(ji,jj) ) > zaamax ) zaamax = ABS( pmatin(ji,jj) )
  1141. END DO
  1142. IF ( zaamax == 0.0_wp ) THEN
  1143. CALL ctl_stop( 'singular matrix' )
  1144. ENDIF
  1145. zvv(ji) = 1.0_wp / zaamax
  1146. END DO
  1147. DO jj = 1, kdim1
  1148. DO ji = 1, jj-1
  1149. zsum = pmatin(ji,jj)
  1150. DO jk = 1, ji-1
  1151. zsum = zsum - pmatin(ji,jk) * pmatin(jk,jj)
  1152. END DO
  1153. pmatin(ji,jj) = zsum
  1154. END DO
  1155. zaamax = 0.0_wp
  1156. DO ji = jj, kdim1
  1157. zsum = pmatin(ji,jj)
  1158. DO jk = 1, jj-1
  1159. zsum = zsum - pmatin(ji,jk) * pmatin(jk,jj)
  1160. END DO
  1161. pmatin(ji,jj) = zsum
  1162. zdum = zvv(ji) * ABS( zsum )
  1163. IF ( zdum >= zaamax ) THEN
  1164. imax = ji
  1165. zaamax = zdum
  1166. ENDIF
  1167. END DO
  1168. IF ( jj /= imax ) THEN
  1169. DO jk = 1, kdim1
  1170. zdum = pmatin(imax,jk)
  1171. pmatin(imax,jk) = pmatin(jj,jk)
  1172. pmatin(jj,jk) = zdum
  1173. END DO
  1174. pflt = -pflt
  1175. zvv(imax) = zvv(jj)
  1176. ENDIF
  1177. kindex(jj) = imax
  1178. IF ( pmatin(jj,jj) == 0.0_wp ) pmatin(jj,jj) = pptiny
  1179. IF ( jj /= kdim1 ) THEN
  1180. zdum = 1.0_wp / pmatin(jj,jj)
  1181. DO ji = jj+1, kdim1
  1182. pmatin(ji,jj) = pmatin(ji,jj) * zdum
  1183. END DO
  1184. ENDIF
  1185. END DO
  1186. END SUBROUTINE lu_decomp
  1187. SUBROUTINE lu_backsb( pmat, kdim1, kdim2, kindex, pvect )
  1188. !!-----------------------------------------------------------------------
  1189. !!
  1190. !! *** ROUTINE lu_backsb ***
  1191. !!
  1192. !! ** Purpose : Back substitution
  1193. !!
  1194. !! ** Method :
  1195. !!
  1196. !! ** Action :
  1197. !!
  1198. !! References :
  1199. !!
  1200. !! History
  1201. !! ! 02-11 (A. Weaver, N. Daget)
  1202. !! ! 06-03 (A. Vidard)
  1203. !! ! 06-10 (A. Weaver) Cleanup
  1204. !!-----------------------------------------------------------------------
  1205. !! * Arguments
  1206. INTEGER, INTENT(IN) :: &
  1207. & kdim1, & ! Array dimensions
  1208. & kdim2
  1209. INTEGER, DIMENSION(kdim1), INTENT(IN) :: &
  1210. & kindex
  1211. REAL(KIND=wp), DIMENSION(kdim1), INTENT(INOUT) :: &
  1212. & pvect
  1213. REAL(KIND=wp), DIMENSION(kdim2,kdim2), INTENT(IN) :: &
  1214. & pmat
  1215. !! * Local declarations
  1216. INTEGER :: &
  1217. & ji, &
  1218. & jii, &
  1219. & jj, &
  1220. & jll
  1221. REAL(KIND=wp) :: &
  1222. & zsum
  1223. ! Main computation
  1224. jii = 0
  1225. DO ji = 1, kdim1
  1226. jll = kindex(ji)
  1227. zsum = pvect(jll)
  1228. pvect(jll) = pvect(ji)
  1229. IF ( jii /= 0 ) THEN
  1230. DO jj = jii, ji-1
  1231. zsum = zsum - pmat(ji,jj) * pvect(jj)
  1232. END DO
  1233. ELSEIF ( zsum /= 0.0_wp ) THEN
  1234. jii = ji
  1235. ENDIF
  1236. pvect(ji) = zsum
  1237. END DO
  1238. DO ji = kdim1, 1, -1
  1239. zsum = pvect(ji)
  1240. DO jj = ji+1, kdim1
  1241. zsum = zsum - pmat(ji,jj) * pvect(jj)
  1242. END DO
  1243. pvect(ji) = zsum / pmat(ji,ji)
  1244. END DO
  1245. END SUBROUTINE lu_backsb