obs_prep.F90 80 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973
  1. MODULE obs_prep
  2. !!=====================================================================
  3. !! *** MODULE obs_prep ***
  4. !! Observation diagnostics: Prepare observation arrays: screening,
  5. !! sorting, coordinate search
  6. !!=====================================================================
  7. !!---------------------------------------------------------------------
  8. !! obs_pre_pro : First level check and screening of T/S profiles
  9. !! obs_pre_sla : First level check and screening of SLA observations
  10. !! obs_pre_sst : First level check and screening of SLA observations
  11. !! obs_pre_seaice : First level check and screening of sea ice observations
  12. !! obs_pre_vel : First level check and screening of velocity obs.
  13. !! obs_scr : Basic screening of the observations
  14. !! obs_coo_tim : Compute number of time steps to the observation time
  15. !! obs_sor : Sort the observation arrays
  16. !!---------------------------------------------------------------------
  17. !! * Modules used
  18. USE par_kind, ONLY : & ! Precision variables
  19. & wp
  20. USE in_out_manager ! I/O manager
  21. USE obs_profiles_def ! Definitions for storage arrays for profiles
  22. USE obs_surf_def ! Definitions for storage arrays for surface data
  23. USE obs_mpp, ONLY : & ! MPP support routines for observation diagnostics
  24. & obs_mpp_sum_integer, &
  25. & obs_mpp_sum_integers
  26. USE obs_inter_sup ! Interpolation support
  27. USE obs_oper ! Observation operators
  28. USE lib_mpp, ONLY : &
  29. & ctl_warn, ctl_stop
  30. IMPLICIT NONE
  31. !! * Routine accessibility
  32. PRIVATE
  33. PUBLIC &
  34. & obs_pre_pro, & ! First level check and screening of profiles
  35. & obs_pre_sla, & ! First level check and screening of SLA data
  36. & obs_pre_sst, & ! First level check and screening of SLA data
  37. & obs_pre_seaice, & ! First level check and screening of sea ice data
  38. & obs_pre_vel, & ! First level check and screening of velocity profiles
  39. & calc_month_len ! Calculate the number of days in the months of a year
  40. !!----------------------------------------------------------------------
  41. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  42. !! $Id: obs_prep.F90 4292 2013-11-20 16:28:04Z cetlod $
  43. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  44. !!----------------------------------------------------------------------
  45. CONTAINS
  46. SUBROUTINE obs_pre_pro( profdata, prodatqc, ld_t3d, ld_s3d, ld_nea, &
  47. & kdailyavtypes )
  48. !!----------------------------------------------------------------------
  49. !! *** ROUTINE obs_pre_pro ***
  50. !!
  51. !! ** Purpose : First level check and screening of T and S profiles
  52. !!
  53. !! ** Method : First level check and screening of T and S profiles
  54. !!
  55. !! ** Action :
  56. !!
  57. !! References :
  58. !!
  59. !! History :
  60. !! ! 2007-01 (K. Mogensen) Merge of obs_pre_t3d and obs_pre_s3d
  61. !! ! 2007-03 (K. Mogensen) General handling of profiles
  62. !! ! 2007-06 (K. Mogensen et al) Reject obs. near land.
  63. !!----------------------------------------------------------------------
  64. !! * Modules used
  65. USE domstp ! Domain: set the time-step
  66. USE par_oce ! Ocean parameters
  67. USE dom_oce, ONLY : & ! Geographical information
  68. & glamt, &
  69. & gphit, &
  70. & gdept_1d,&
  71. & tmask, &
  72. & nproc
  73. !! * Arguments
  74. TYPE(obs_prof), INTENT(INOUT) :: profdata ! Full set of profile data
  75. TYPE(obs_prof), INTENT(INOUT) :: prodatqc ! Subset of profile data not failing screening
  76. LOGICAL, INTENT(IN) :: ld_t3d ! Switch for temperature
  77. LOGICAL, INTENT(IN) :: ld_s3d ! Switch for salinity
  78. LOGICAL, INTENT(IN) :: ld_nea ! Switch for rejecting observation near land
  79. INTEGER, DIMENSION(imaxavtypes), OPTIONAL :: &
  80. & kdailyavtypes! Types for daily averages
  81. !! * Local declarations
  82. INTEGER :: iyea0 ! Initial date
  83. INTEGER :: imon0 ! - (year, month, day, hour, minute)
  84. INTEGER :: iday0
  85. INTEGER :: ihou0
  86. INTEGER :: imin0
  87. INTEGER :: icycle ! Current assimilation cycle
  88. ! Counters for observations that
  89. INTEGER :: iotdobs ! - outside time domain
  90. INTEGER :: iosdtobs ! - outside space domain (temperature)
  91. INTEGER :: iosdsobs ! - outside space domain (salinity)
  92. INTEGER :: ilantobs ! - within a model land cell (temperature)
  93. INTEGER :: ilansobs ! - within a model land cell (salinity)
  94. INTEGER :: inlatobs ! - close to land (temperature)
  95. INTEGER :: inlasobs ! - close to land (salinity)
  96. INTEGER :: igrdobs ! - fail the grid search
  97. ! Global counters for observations that
  98. INTEGER :: iotdobsmpp ! - outside time domain
  99. INTEGER :: iosdtobsmpp ! - outside space domain (temperature)
  100. INTEGER :: iosdsobsmpp ! - outside space domain (salinity)
  101. INTEGER :: ilantobsmpp ! - within a model land cell (temperature)
  102. INTEGER :: ilansobsmpp ! - within a model land cell (salinity)
  103. INTEGER :: inlatobsmpp ! - close to land (temperature)
  104. INTEGER :: inlasobsmpp ! - close to land (salinity)
  105. INTEGER :: igrdobsmpp ! - fail the grid search
  106. TYPE(obs_prof_valid) :: llvalid ! Profile selection
  107. TYPE(obs_prof_valid), DIMENSION(profdata%nvar) :: &
  108. & llvvalid ! T,S selection
  109. INTEGER :: jvar ! Variable loop variable
  110. INTEGER :: jobs ! Obs. loop variable
  111. INTEGER :: jstp ! Time loop variable
  112. INTEGER :: inrc ! Time index variable
  113. IF(lwp) WRITE(numout,*)'obs_pre_pro : Preparing the profile observations...'
  114. ! Initial date initialization (year, month, day, hour, minute)
  115. iyea0 = ndate0 / 10000
  116. imon0 = ( ndate0 - iyea0 * 10000 ) / 100
  117. iday0 = ndate0 - iyea0 * 10000 - imon0 * 100
  118. ihou0 = 0
  119. imin0 = 0
  120. icycle = no ! Assimilation cycle
  121. ! Diagnotics counters for various failures.
  122. iotdobs = 0
  123. igrdobs = 0
  124. iosdtobs = 0
  125. iosdsobs = 0
  126. ilantobs = 0
  127. ilansobs = 0
  128. inlatobs = 0
  129. inlasobs = 0
  130. ! -----------------------------------------------------------------------
  131. ! Find time coordinate for profiles
  132. ! -----------------------------------------------------------------------
  133. IF ( PRESENT(kdailyavtypes) ) THEN
  134. CALL obs_coo_tim_prof( icycle, &
  135. & iyea0, imon0, iday0, ihou0, imin0, &
  136. & profdata%nprof, profdata%nyea, profdata%nmon, &
  137. & profdata%nday, profdata%nhou, profdata%nmin, &
  138. & profdata%ntyp, profdata%nqc, profdata%mstp, &
  139. & iotdobs, kdailyavtypes = kdailyavtypes )
  140. ELSE
  141. CALL obs_coo_tim_prof( icycle, &
  142. & iyea0, imon0, iday0, ihou0, imin0, &
  143. & profdata%nprof, profdata%nyea, profdata%nmon, &
  144. & profdata%nday, profdata%nhou, profdata%nmin, &
  145. & profdata%ntyp, profdata%nqc, profdata%mstp, &
  146. & iotdobs )
  147. ENDIF
  148. CALL obs_mpp_sum_integer( iotdobs, iotdobsmpp )
  149. ! -----------------------------------------------------------------------
  150. ! Check for profiles failing the grid search
  151. ! -----------------------------------------------------------------------
  152. CALL obs_coo_grd( profdata%nprof, profdata%mi, profdata%mj, &
  153. & profdata%nqc, igrdobs )
  154. CALL obs_mpp_sum_integer( igrdobs, igrdobsmpp )
  155. ! -----------------------------------------------------------------------
  156. ! Reject all observations for profiles with nqc > 10
  157. ! -----------------------------------------------------------------------
  158. CALL obs_pro_rej( profdata )
  159. ! -----------------------------------------------------------------------
  160. ! Check for land points. This includes points below the model
  161. ! bathymetry so this is done for every point in the profile
  162. ! -----------------------------------------------------------------------
  163. ! Temperature
  164. CALL obs_coo_spc_3d( profdata%nprof, profdata%nvprot(1), &
  165. & profdata%npvsta(:,1), profdata%npvend(:,1), &
  166. & jpi, jpj, &
  167. & jpk, &
  168. & profdata%mi, profdata%mj, &
  169. & profdata%var(1)%mvk, &
  170. & profdata%rlam, profdata%rphi, &
  171. & profdata%var(1)%vdep, &
  172. & glamt, gphit, &
  173. & gdept_1d, tmask, &
  174. & profdata%nqc, profdata%var(1)%nvqc, &
  175. & iosdtobs, ilantobs, &
  176. & inlatobs, ld_nea )
  177. CALL obs_mpp_sum_integer( iosdtobs, iosdtobsmpp )
  178. CALL obs_mpp_sum_integer( ilantobs, ilantobsmpp )
  179. CALL obs_mpp_sum_integer( inlatobs, inlatobsmpp )
  180. ! Salinity
  181. CALL obs_coo_spc_3d( profdata%nprof, profdata%nvprot(2), &
  182. & profdata%npvsta(:,2), profdata%npvend(:,2), &
  183. & jpi, jpj, &
  184. & jpk, &
  185. & profdata%mi, profdata%mj, &
  186. & profdata%var(2)%mvk, &
  187. & profdata%rlam, profdata%rphi, &
  188. & profdata%var(2)%vdep, &
  189. & glamt, gphit, &
  190. & gdept_1d, tmask, &
  191. & profdata%nqc, profdata%var(2)%nvqc, &
  192. & iosdsobs, ilansobs, &
  193. & inlasobs, ld_nea )
  194. CALL obs_mpp_sum_integer( iosdsobs, iosdsobsmpp )
  195. CALL obs_mpp_sum_integer( ilansobs, ilansobsmpp )
  196. CALL obs_mpp_sum_integer( inlasobs, inlasobsmpp )
  197. ! -----------------------------------------------------------------------
  198. ! Copy useful data from the profdata data structure to
  199. ! the prodatqc data structure
  200. ! -----------------------------------------------------------------------
  201. ! Allocate the selection arrays
  202. ALLOCATE( llvalid%luse(profdata%nprof) )
  203. DO jvar = 1,profdata%nvar
  204. ALLOCATE( llvvalid(jvar)%luse(profdata%nvprot(jvar)) )
  205. END DO
  206. ! We want all data which has qc flags <= 10
  207. llvalid%luse(:) = ( profdata%nqc(:) <= 10 )
  208. DO jvar = 1,profdata%nvar
  209. llvvalid(jvar)%luse(:) = ( profdata%var(jvar)%nvqc(:) <= 10 )
  210. END DO
  211. ! The actual copying
  212. CALL obs_prof_compress( profdata, prodatqc, .TRUE., numout, &
  213. & lvalid=llvalid, lvvalid=llvvalid )
  214. ! Dellocate the selection arrays
  215. DEALLOCATE( llvalid%luse )
  216. DO jvar = 1,profdata%nvar
  217. DEALLOCATE( llvvalid(jvar)%luse )
  218. END DO
  219. ! -----------------------------------------------------------------------
  220. ! Print information about what observations are left after qc
  221. ! -----------------------------------------------------------------------
  222. ! Update the total observation counter array
  223. IF(lwp) THEN
  224. WRITE(numout,*)
  225. WRITE(numout,*) 'obs_pre_pro :'
  226. WRITE(numout,*) '~~~~~~~~~~~'
  227. WRITE(numout,*)
  228. WRITE(numout,*) ' Profiles outside time domain = ', &
  229. & iotdobsmpp
  230. WRITE(numout,*) ' Remaining profiles that failed grid search = ', &
  231. & igrdobsmpp
  232. WRITE(numout,*) ' Remaining T data outside space domain = ', &
  233. & iosdtobsmpp
  234. WRITE(numout,*) ' Remaining T data at land points = ', &
  235. & ilantobsmpp
  236. IF (ld_nea) THEN
  237. WRITE(numout,*) ' Remaining T data near land points (removed) = ',&
  238. & inlatobsmpp
  239. ELSE
  240. WRITE(numout,*) ' Remaining T data near land points (kept) = ',&
  241. & inlatobsmpp
  242. ENDIF
  243. WRITE(numout,*) ' T data accepted = ', &
  244. & prodatqc%nvprotmpp(1)
  245. WRITE(numout,*) ' Remaining S data outside space domain = ', &
  246. & iosdsobsmpp
  247. WRITE(numout,*) ' Remaining S data at land points = ', &
  248. & ilansobsmpp
  249. IF (ld_nea) THEN
  250. WRITE(numout,*) ' Remaining S data near land points (removed) = ',&
  251. & inlasobsmpp
  252. ELSE
  253. WRITE(numout,*) ' Remaining S data near land points (kept) = ',&
  254. & inlasobsmpp
  255. ENDIF
  256. WRITE(numout,*) ' S data accepted = ', &
  257. & prodatqc%nvprotmpp(2)
  258. WRITE(numout,*)
  259. WRITE(numout,*) ' Number of observations per time step :'
  260. WRITE(numout,*)
  261. WRITE(numout,997)
  262. WRITE(numout,998)
  263. ENDIF
  264. DO jobs = 1, prodatqc%nprof
  265. inrc = prodatqc%mstp(jobs) + 2 - nit000
  266. prodatqc%npstp(inrc) = prodatqc%npstp(inrc) + 1
  267. DO jvar = 1, prodatqc%nvar
  268. IF ( prodatqc%npvend(jobs,jvar) > 0 ) THEN
  269. prodatqc%nvstp(inrc,jvar) = prodatqc%nvstp(inrc,jvar) + &
  270. & ( prodatqc%npvend(jobs,jvar) - &
  271. & prodatqc%npvsta(jobs,jvar) + 1 )
  272. ENDIF
  273. END DO
  274. END DO
  275. CALL obs_mpp_sum_integers( prodatqc%npstp, prodatqc%npstpmpp, &
  276. & nitend - nit000 + 2 )
  277. DO jvar = 1, prodatqc%nvar
  278. CALL obs_mpp_sum_integers( prodatqc%nvstp(:,jvar), &
  279. & prodatqc%nvstpmpp(:,jvar), &
  280. & nitend - nit000 + 2 )
  281. END DO
  282. IF ( lwp ) THEN
  283. DO jstp = nit000 - 1, nitend
  284. inrc = jstp - nit000 + 2
  285. WRITE(numout,999) jstp, prodatqc%npstpmpp(inrc), &
  286. & prodatqc%nvstpmpp(inrc,1), &
  287. & prodatqc%nvstpmpp(inrc,2)
  288. END DO
  289. ENDIF
  290. 997 FORMAT(10X,'Time step',5X,'Profiles',5X,'Temperature',5X,'Salinity')
  291. 998 FORMAT(10X,'---------',5X,'--------',5X,'-----------',5X,'--------')
  292. 999 FORMAT(10X,I9,5X,I8,5X,I11,5X,I8)
  293. END SUBROUTINE obs_pre_pro
  294. SUBROUTINE obs_pre_sla( sladata, sladatqc, ld_sla, ld_nea )
  295. !!----------------------------------------------------------------------
  296. !! *** ROUTINE obs_pre_sla ***
  297. !!
  298. !! ** Purpose : First level check and screening of SLA observations
  299. !!
  300. !! ** Method : First level check and screening of SLA observations
  301. !!
  302. !! ** Action :
  303. !!
  304. !! References :
  305. !!
  306. !! History :
  307. !! ! 2007-03 (A. Weaver, K. Mogensen) Original
  308. !! ! 2007-06 (K. Mogensen et al) Reject obs. near land.
  309. !!----------------------------------------------------------------------
  310. !! * Modules used
  311. USE domstp ! Domain: set the time-step
  312. USE par_oce ! Ocean parameters
  313. USE dom_oce, ONLY : & ! Geographical information
  314. & glamt, &
  315. & gphit, &
  316. & tmask, &
  317. & nproc
  318. !! * Arguments
  319. TYPE(obs_surf), INTENT(INOUT) :: sladata ! Full set of SLA data
  320. TYPE(obs_surf), INTENT(INOUT) :: sladatqc ! Subset of SLA data not failing screening
  321. LOGICAL, INTENT(IN) :: ld_sla ! Switch for SLA data
  322. LOGICAL, INTENT(IN) :: ld_nea ! Switch for rejecting observation near land
  323. !! * Local declarations
  324. INTEGER :: iyea0 ! Initial date
  325. INTEGER :: imon0 ! - (year, month, day, hour, minute)
  326. INTEGER :: iday0
  327. INTEGER :: ihou0
  328. INTEGER :: imin0
  329. INTEGER :: icycle ! Current assimilation cycle
  330. ! Counters for observations that
  331. INTEGER :: iotdobs ! - outside time domain
  332. INTEGER :: iosdsobs ! - outside space domain
  333. INTEGER :: ilansobs ! - within a model land cell
  334. INTEGER :: inlasobs ! - close to land
  335. INTEGER :: igrdobs ! - fail the grid search
  336. ! Global counters for observations that
  337. INTEGER :: iotdobsmpp ! - outside time domain
  338. INTEGER :: iosdsobsmpp ! - outside space domain
  339. INTEGER :: ilansobsmpp ! - within a model land cell
  340. INTEGER :: inlasobsmpp ! - close to land
  341. INTEGER :: igrdobsmpp ! - fail the grid search
  342. LOGICAL, DIMENSION(:), ALLOCATABLE :: &
  343. & llvalid ! SLA data selection
  344. INTEGER :: jobs ! Obs. loop variable
  345. INTEGER :: jstp ! Time loop variable
  346. INTEGER :: inrc ! Time index variable
  347. IF(lwp) WRITE(numout,*)'obs_pre_sla : Preparing the SLA observations...'
  348. ! Initial date initialization (year, month, day, hour, minute)
  349. iyea0 = ndate0 / 10000
  350. imon0 = ( ndate0 - iyea0 * 10000 ) / 100
  351. iday0 = ndate0 - iyea0 * 10000 - imon0 * 100
  352. ihou0 = 0
  353. imin0 = 0
  354. icycle = no ! Assimilation cycle
  355. ! Diagnotics counters for various failures.
  356. iotdobs = 0
  357. igrdobs = 0
  358. iosdsobs = 0
  359. ilansobs = 0
  360. inlasobs = 0
  361. ! -----------------------------------------------------------------------
  362. ! Find time coordinate for SLA data
  363. ! -----------------------------------------------------------------------
  364. CALL obs_coo_tim( icycle, &
  365. & iyea0, imon0, iday0, ihou0, imin0, &
  366. & sladata%nsurf, sladata%nyea, sladata%nmon, &
  367. & sladata%nday, sladata%nhou, sladata%nmin, &
  368. & sladata%nqc, sladata%mstp, iotdobs )
  369. CALL obs_mpp_sum_integer( iotdobs, iotdobsmpp )
  370. ! -----------------------------------------------------------------------
  371. ! Check for SLA data failing the grid search
  372. ! -----------------------------------------------------------------------
  373. CALL obs_coo_grd( sladata%nsurf, sladata%mi, sladata%mj, &
  374. & sladata%nqc, igrdobs )
  375. CALL obs_mpp_sum_integer( igrdobs, igrdobsmpp )
  376. ! -----------------------------------------------------------------------
  377. ! Check for land points.
  378. ! -----------------------------------------------------------------------
  379. CALL obs_coo_spc_2d( sladata%nsurf, &
  380. & jpi, jpj, &
  381. & sladata%mi, sladata%mj, &
  382. & sladata%rlam, sladata%rphi, &
  383. & glamt, gphit, &
  384. & tmask(:,:,1), sladata%nqc, &
  385. & iosdsobs, ilansobs, &
  386. & inlasobs, ld_nea )
  387. CALL obs_mpp_sum_integer( iosdsobs, iosdsobsmpp )
  388. CALL obs_mpp_sum_integer( ilansobs, ilansobsmpp )
  389. CALL obs_mpp_sum_integer( inlasobs, inlasobsmpp )
  390. ! -----------------------------------------------------------------------
  391. ! Copy useful data from the sladata data structure to
  392. ! the sladatqc data structure
  393. ! -----------------------------------------------------------------------
  394. ! Allocate the selection arrays
  395. ALLOCATE( llvalid(sladata%nsurf) )
  396. ! We want all data which has qc flags <= 10
  397. llvalid(:) = ( sladata%nqc(:) <= 10 )
  398. ! The actual copying
  399. CALL obs_surf_compress( sladata, sladatqc, .TRUE., numout, &
  400. & lvalid=llvalid )
  401. ! Dellocate the selection arrays
  402. DEALLOCATE( llvalid )
  403. ! -----------------------------------------------------------------------
  404. ! Print information about what observations are left after qc
  405. ! -----------------------------------------------------------------------
  406. ! Update the total observation counter array
  407. IF(lwp) THEN
  408. WRITE(numout,*)
  409. WRITE(numout,*) 'obs_pre_sla :'
  410. WRITE(numout,*) '~~~~~~~~~~~'
  411. WRITE(numout,*)
  412. WRITE(numout,*) ' SLA data outside time domain = ', &
  413. & iotdobsmpp
  414. WRITE(numout,*) ' Remaining SLA data that failed grid search = ', &
  415. & igrdobsmpp
  416. WRITE(numout,*) ' Remaining SLA data outside space domain = ', &
  417. & iosdsobsmpp
  418. WRITE(numout,*) ' Remaining SLA data at land points = ', &
  419. & ilansobsmpp
  420. IF (ld_nea) THEN
  421. WRITE(numout,*) ' Remaining SLA data near land points (removed) = ', &
  422. & inlasobsmpp
  423. ELSE
  424. WRITE(numout,*) ' Remaining SLA data near land points (kept) = ', &
  425. & inlasobsmpp
  426. ENDIF
  427. WRITE(numout,*) ' SLA data accepted = ', &
  428. & sladatqc%nsurfmpp
  429. WRITE(numout,*)
  430. WRITE(numout,*) ' Number of observations per time step :'
  431. WRITE(numout,*)
  432. WRITE(numout,1997)
  433. WRITE(numout,1998)
  434. ENDIF
  435. DO jobs = 1, sladatqc%nsurf
  436. inrc = sladatqc%mstp(jobs) + 2 - nit000
  437. sladatqc%nsstp(inrc) = sladatqc%nsstp(inrc) + 1
  438. END DO
  439. CALL obs_mpp_sum_integers( sladatqc%nsstp, sladatqc%nsstpmpp, &
  440. & nitend - nit000 + 2 )
  441. IF ( lwp ) THEN
  442. DO jstp = nit000 - 1, nitend
  443. inrc = jstp - nit000 + 2
  444. WRITE(numout,1999) jstp, sladatqc%nsstpmpp(inrc)
  445. END DO
  446. ENDIF
  447. 1997 FORMAT(10X,'Time step',5X,'Sea level anomaly')
  448. 1998 FORMAT(10X,'---------',5X,'-----------------')
  449. 1999 FORMAT(10X,I9,5X,I17)
  450. END SUBROUTINE obs_pre_sla
  451. SUBROUTINE obs_pre_sst( sstdata, sstdatqc, ld_sst, ld_nea )
  452. !!----------------------------------------------------------------------
  453. !! *** ROUTINE obs_pre_sst ***
  454. !!
  455. !! ** Purpose : First level check and screening of SST observations
  456. !!
  457. !! ** Method : First level check and screening of SST observations
  458. !!
  459. !! ** Action :
  460. !!
  461. !! References :
  462. !!
  463. !! History :
  464. !! ! 2007-03 (S. Ricci) SST data preparation
  465. !!----------------------------------------------------------------------
  466. !! * Modules used
  467. USE domstp ! Domain: set the time-step
  468. USE par_oce ! Ocean parameters
  469. USE dom_oce, ONLY : & ! Geographical information
  470. & glamt, &
  471. & gphit, &
  472. & tmask, &
  473. & nproc
  474. !! * Arguments
  475. TYPE(obs_surf), INTENT(INOUT) :: sstdata ! Full set of SST data
  476. TYPE(obs_surf), INTENT(INOUT) :: sstdatqc ! Subset of SST data not failing screening
  477. LOGICAL :: ld_sst ! Switch for SST data
  478. LOGICAL :: ld_nea ! Switch for rejecting observation near land
  479. !! * Local declarations
  480. INTEGER :: iyea0 ! Initial date
  481. INTEGER :: imon0 ! - (year, month, day, hour, minute)
  482. INTEGER :: iday0
  483. INTEGER :: ihou0
  484. INTEGER :: imin0
  485. INTEGER :: icycle ! Current assimilation cycle
  486. ! Counters for observations that
  487. INTEGER :: iotdobs ! - outside time domain
  488. INTEGER :: iosdsobs ! - outside space domain
  489. INTEGER :: ilansobs ! - within a model land cell
  490. INTEGER :: inlasobs ! - close to land
  491. INTEGER :: igrdobs ! - fail the grid search
  492. ! Global counters for observations that
  493. INTEGER :: iotdobsmpp ! - outside time domain
  494. INTEGER :: iosdsobsmpp ! - outside space domain
  495. INTEGER :: ilansobsmpp ! - within a model land cell
  496. INTEGER :: inlasobsmpp ! - close to land
  497. INTEGER :: igrdobsmpp ! - fail the grid search
  498. LOGICAL, DIMENSION(:), ALLOCATABLE :: &
  499. & llvalid ! SST data selection
  500. INTEGER :: jobs ! Obs. loop variable
  501. INTEGER :: jstp ! Time loop variable
  502. INTEGER :: inrc ! Time index variable
  503. IF(lwp) WRITE(numout,*)'obs_pre_sst : Preparing the SST observations...'
  504. ! Initial date initialization (year, month, day, hour, minute)
  505. iyea0 = ndate0 / 10000
  506. imon0 = ( ndate0 - iyea0 * 10000 ) / 100
  507. iday0 = ndate0 - iyea0 * 10000 - imon0 * 100
  508. ihou0 = 0
  509. imin0 = 0
  510. icycle = no ! Assimilation cycle
  511. ! Diagnotics counters for various failures.
  512. iotdobs = 0
  513. igrdobs = 0
  514. iosdsobs = 0
  515. ilansobs = 0
  516. inlasobs = 0
  517. ! -----------------------------------------------------------------------
  518. ! Find time coordinate for SST data
  519. ! -----------------------------------------------------------------------
  520. CALL obs_coo_tim( icycle, &
  521. & iyea0, imon0, iday0, ihou0, imin0, &
  522. & sstdata%nsurf, sstdata%nyea, sstdata%nmon, &
  523. & sstdata%nday, sstdata%nhou, sstdata%nmin, &
  524. & sstdata%nqc, sstdata%mstp, iotdobs )
  525. CALL obs_mpp_sum_integer( iotdobs, iotdobsmpp )
  526. ! -----------------------------------------------------------------------
  527. ! Check for SST data failing the grid search
  528. ! -----------------------------------------------------------------------
  529. CALL obs_coo_grd( sstdata%nsurf, sstdata%mi, sstdata%mj, &
  530. & sstdata%nqc, igrdobs )
  531. CALL obs_mpp_sum_integer( igrdobs, igrdobsmpp )
  532. ! -----------------------------------------------------------------------
  533. ! Check for land points.
  534. ! -----------------------------------------------------------------------
  535. CALL obs_coo_spc_2d( sstdata%nsurf, &
  536. & jpi, jpj, &
  537. & sstdata%mi, sstdata%mj, &
  538. & sstdata%rlam, sstdata%rphi, &
  539. & glamt, gphit, &
  540. & tmask(:,:,1), sstdata%nqc, &
  541. & iosdsobs, ilansobs, &
  542. & inlasobs, ld_nea )
  543. CALL obs_mpp_sum_integer( iosdsobs, iosdsobsmpp )
  544. CALL obs_mpp_sum_integer( ilansobs, ilansobsmpp )
  545. CALL obs_mpp_sum_integer( inlasobs, inlasobsmpp )
  546. ! -----------------------------------------------------------------------
  547. ! Copy useful data from the sstdata data structure to
  548. ! the sstdatqc data structure
  549. ! -----------------------------------------------------------------------
  550. ! Allocate the selection arrays
  551. ALLOCATE( llvalid(sstdata%nsurf) )
  552. ! We want all data which has qc flags <= 0
  553. llvalid(:) = ( sstdata%nqc(:) <= 10 )
  554. ! The actual copying
  555. CALL obs_surf_compress( sstdata, sstdatqc, .TRUE., numout, &
  556. & lvalid=llvalid )
  557. ! Dellocate the selection arrays
  558. DEALLOCATE( llvalid )
  559. ! -----------------------------------------------------------------------
  560. ! Print information about what observations are left after qc
  561. ! -----------------------------------------------------------------------
  562. ! Update the total observation counter array
  563. IF(lwp) THEN
  564. WRITE(numout,*)
  565. WRITE(numout,*) 'obs_pre_sst :'
  566. WRITE(numout,*) '~~~~~~~~~~~'
  567. WRITE(numout,*)
  568. WRITE(numout,*) ' SST data outside time domain = ', &
  569. & iotdobsmpp
  570. WRITE(numout,*) ' Remaining SST data that failed grid search = ', &
  571. & igrdobsmpp
  572. WRITE(numout,*) ' Remaining SST data outside space domain = ', &
  573. & iosdsobsmpp
  574. WRITE(numout,*) ' Remaining SST data at land points = ', &
  575. & ilansobsmpp
  576. IF (ld_nea) THEN
  577. WRITE(numout,*) ' Remaining SST data near land points (removed) = ', &
  578. & inlasobsmpp
  579. ELSE
  580. WRITE(numout,*) ' Remaining SST data near land points (kept) = ', &
  581. & inlasobsmpp
  582. ENDIF
  583. WRITE(numout,*) ' SST data accepted = ', &
  584. & sstdatqc%nsurfmpp
  585. WRITE(numout,*)
  586. WRITE(numout,*) ' Number of observations per time step :'
  587. WRITE(numout,*)
  588. WRITE(numout,1997)
  589. WRITE(numout,1998)
  590. ENDIF
  591. DO jobs = 1, sstdatqc%nsurf
  592. inrc = sstdatqc%mstp(jobs) + 2 - nit000
  593. sstdatqc%nsstp(inrc) = sstdatqc%nsstp(inrc) + 1
  594. END DO
  595. CALL obs_mpp_sum_integers( sstdatqc%nsstp, sstdatqc%nsstpmpp, &
  596. & nitend - nit000 + 2 )
  597. IF ( lwp ) THEN
  598. DO jstp = nit000 - 1, nitend
  599. inrc = jstp - nit000 + 2
  600. WRITE(numout,1999) jstp, sstdatqc%nsstpmpp(inrc)
  601. END DO
  602. ENDIF
  603. 1997 FORMAT(10X,'Time step',5X,'Sea surface temperature')
  604. 1998 FORMAT(10X,'---------',5X,'-----------------')
  605. 1999 FORMAT(10X,I9,5X,I17)
  606. END SUBROUTINE obs_pre_sst
  607. SUBROUTINE obs_pre_seaice( seaicedata, seaicedatqc, ld_seaice, ld_nea )
  608. !!----------------------------------------------------------------------
  609. !! *** ROUTINE obs_pre_seaice ***
  610. !!
  611. !! ** Purpose : First level check and screening of Sea Ice observations
  612. !!
  613. !! ** Method : First level check and screening of Sea Ice observations
  614. !!
  615. !! ** Action :
  616. !!
  617. !! References :
  618. !!
  619. !! History :
  620. !! ! 2007-11 (D. Lea) based on obs_pre_sst
  621. !!----------------------------------------------------------------------
  622. !! * Modules used
  623. USE domstp ! Domain: set the time-step
  624. USE par_oce ! Ocean parameters
  625. USE dom_oce, ONLY : & ! Geographical information
  626. & glamt, &
  627. & gphit, &
  628. & tmask, &
  629. & nproc
  630. !! * Arguments
  631. TYPE(obs_surf), INTENT(INOUT) :: seaicedata ! Full set of Sea Ice data
  632. TYPE(obs_surf), INTENT(INOUT) :: seaicedatqc ! Subset of sea ice data not failing screening
  633. LOGICAL :: ld_seaice ! Switch for sea ice data
  634. LOGICAL :: ld_nea ! Switch for rejecting observation near land
  635. !! * Local declarations
  636. INTEGER :: iyea0 ! Initial date
  637. INTEGER :: imon0 ! - (year, month, day, hour, minute)
  638. INTEGER :: iday0
  639. INTEGER :: ihou0
  640. INTEGER :: imin0
  641. INTEGER :: icycle ! Current assimilation cycle
  642. ! Counters for observations that
  643. INTEGER :: iotdobs ! - outside time domain
  644. INTEGER :: iosdsobs ! - outside space domain
  645. INTEGER :: ilansobs ! - within a model land cell
  646. INTEGER :: inlasobs ! - close to land
  647. INTEGER :: igrdobs ! - fail the grid search
  648. ! Global counters for observations that
  649. INTEGER :: iotdobsmpp ! - outside time domain
  650. INTEGER :: iosdsobsmpp ! - outside space domain
  651. INTEGER :: ilansobsmpp ! - within a model land cell
  652. INTEGER :: inlasobsmpp ! - close to land
  653. INTEGER :: igrdobsmpp ! - fail the grid search
  654. LOGICAL, DIMENSION(:), ALLOCATABLE :: &
  655. & llvalid ! data selection
  656. INTEGER :: jobs ! Obs. loop variable
  657. INTEGER :: jstp ! Time loop variable
  658. INTEGER :: inrc ! Time index variable
  659. IF (lwp) WRITE(numout,*)'obs_pre_seaice : Preparing the sea ice observations...'
  660. ! Initial date initialization (year, month, day, hour, minute)
  661. iyea0 = ndate0 / 10000
  662. imon0 = ( ndate0 - iyea0 * 10000 ) / 100
  663. iday0 = ndate0 - iyea0 * 10000 - imon0 * 100
  664. ihou0 = 0
  665. imin0 = 0
  666. icycle = no ! Assimilation cycle
  667. ! Diagnotics counters for various failures.
  668. iotdobs = 0
  669. igrdobs = 0
  670. iosdsobs = 0
  671. ilansobs = 0
  672. inlasobs = 0
  673. ! -----------------------------------------------------------------------
  674. ! Find time coordinate for sea ice data
  675. ! -----------------------------------------------------------------------
  676. CALL obs_coo_tim( icycle, &
  677. & iyea0, imon0, iday0, ihou0, imin0, &
  678. & seaicedata%nsurf, seaicedata%nyea, seaicedata%nmon, &
  679. & seaicedata%nday, seaicedata%nhou, seaicedata%nmin, &
  680. & seaicedata%nqc, seaicedata%mstp, iotdobs )
  681. CALL obs_mpp_sum_integer( iotdobs, iotdobsmpp )
  682. ! -----------------------------------------------------------------------
  683. ! Check for sea ice data failing the grid search
  684. ! -----------------------------------------------------------------------
  685. CALL obs_coo_grd( seaicedata%nsurf, seaicedata%mi, seaicedata%mj, &
  686. & seaicedata%nqc, igrdobs )
  687. CALL obs_mpp_sum_integer( igrdobs, igrdobsmpp )
  688. ! -----------------------------------------------------------------------
  689. ! Check for land points.
  690. ! -----------------------------------------------------------------------
  691. CALL obs_coo_spc_2d( seaicedata%nsurf, &
  692. & jpi, jpj, &
  693. & seaicedata%mi, seaicedata%mj, &
  694. & seaicedata%rlam, seaicedata%rphi, &
  695. & glamt, gphit, &
  696. & tmask(:,:,1), seaicedata%nqc, &
  697. & iosdsobs, ilansobs, &
  698. & inlasobs, ld_nea )
  699. CALL obs_mpp_sum_integer( iosdsobs, iosdsobsmpp )
  700. CALL obs_mpp_sum_integer( ilansobs, ilansobsmpp )
  701. CALL obs_mpp_sum_integer( inlasobs, inlasobsmpp )
  702. ! -----------------------------------------------------------------------
  703. ! Copy useful data from the seaicedata data structure to
  704. ! the seaicedatqc data structure
  705. ! -----------------------------------------------------------------------
  706. ! Allocate the selection arrays
  707. ALLOCATE( llvalid(seaicedata%nsurf) )
  708. ! We want all data which has qc flags <= 0
  709. llvalid(:) = ( seaicedata%nqc(:) <= 10 )
  710. ! The actual copying
  711. CALL obs_surf_compress( seaicedata, seaicedatqc, .TRUE., numout, &
  712. & lvalid=llvalid )
  713. ! Dellocate the selection arrays
  714. DEALLOCATE( llvalid )
  715. ! -----------------------------------------------------------------------
  716. ! Print information about what observations are left after qc
  717. ! -----------------------------------------------------------------------
  718. ! Update the total observation counter array
  719. IF(lwp) THEN
  720. WRITE(numout,*)
  721. WRITE(numout,*) 'obs_pre_seaice :'
  722. WRITE(numout,*) '~~~~~~~~~~~'
  723. WRITE(numout,*)
  724. WRITE(numout,*) ' Sea ice data outside time domain = ', &
  725. & iotdobsmpp
  726. WRITE(numout,*) ' Remaining sea ice data that failed grid search = ', &
  727. & igrdobsmpp
  728. WRITE(numout,*) ' Remaining sea ice data outside space domain = ', &
  729. & iosdsobsmpp
  730. WRITE(numout,*) ' Remaining sea ice data at land points = ', &
  731. & ilansobsmpp
  732. IF (ld_nea) THEN
  733. WRITE(numout,*) ' Remaining sea ice data near land points (removed) = ', &
  734. & inlasobsmpp
  735. ELSE
  736. WRITE(numout,*) ' Remaining sea ice data near land points (kept) = ', &
  737. & inlasobsmpp
  738. ENDIF
  739. WRITE(numout,*) ' Sea ice data accepted = ', &
  740. & seaicedatqc%nsurfmpp
  741. WRITE(numout,*)
  742. WRITE(numout,*) ' Number of observations per time step :'
  743. WRITE(numout,*)
  744. WRITE(numout,1997)
  745. WRITE(numout,1998)
  746. ENDIF
  747. DO jobs = 1, seaicedatqc%nsurf
  748. inrc = seaicedatqc%mstp(jobs) + 2 - nit000
  749. seaicedatqc%nsstp(inrc) = seaicedatqc%nsstp(inrc) + 1
  750. END DO
  751. CALL obs_mpp_sum_integers( seaicedatqc%nsstp, seaicedatqc%nsstpmpp, &
  752. & nitend - nit000 + 2 )
  753. IF ( lwp ) THEN
  754. DO jstp = nit000 - 1, nitend
  755. inrc = jstp - nit000 + 2
  756. WRITE(numout,1999) jstp, seaicedatqc%nsstpmpp(inrc)
  757. END DO
  758. ENDIF
  759. 1997 FORMAT(10X,'Time step',5X,'Sea ice data ')
  760. 1998 FORMAT(10X,'---------',5X,'-----------------')
  761. 1999 FORMAT(10X,I9,5X,I17)
  762. END SUBROUTINE obs_pre_seaice
  763. SUBROUTINE obs_pre_vel( profdata, prodatqc, ld_vel3d, ld_nea, ld_dailyav )
  764. !!----------------------------------------------------------------------
  765. !! *** ROUTINE obs_pre_taovel ***
  766. !!
  767. !! ** Purpose : First level check and screening of U and V profiles
  768. !!
  769. !! ** Method : First level check and screening of U and V profiles
  770. !!
  771. !! History :
  772. !! ! 2007-06 (K. Mogensen) original : T and S profile data
  773. !! ! 2008-09 (M. Valdivieso) : TAO velocity data
  774. !! ! 2009-01 (K. Mogensen) : New feedback strictuer
  775. !!
  776. !!----------------------------------------------------------------------
  777. !! * Modules used
  778. USE domstp ! Domain: set the time-step
  779. USE par_oce ! Ocean parameters
  780. USE dom_oce, ONLY : & ! Geographical information
  781. & glamt, glamu, glamv, &
  782. & gphit, gphiu, gphiv, &
  783. & gdept_1d, &
  784. & tmask, umask, vmask, &
  785. & nproc
  786. !! * Arguments
  787. TYPE(obs_prof), INTENT(INOUT) :: profdata ! Full set of profile data
  788. TYPE(obs_prof), INTENT(INOUT) :: prodatqc ! Subset of profile data not failing screening
  789. LOGICAL, INTENT(IN) :: ld_vel3d ! Switch for zonal and meridional velocity components
  790. LOGICAL, INTENT(IN) :: ld_nea ! Switch for rejecting observation near land
  791. LOGICAL, INTENT(IN) :: ld_dailyav ! Switch for daily average data
  792. !! * Local declarations
  793. INTEGER :: iyea0 ! Initial date
  794. INTEGER :: imon0 ! - (year, month, day, hour, minute)
  795. INTEGER :: iday0
  796. INTEGER :: ihou0
  797. INTEGER :: imin0
  798. INTEGER :: icycle ! Current assimilation cycle
  799. ! Counters for observations that
  800. INTEGER :: iotdobs ! - outside time domain
  801. INTEGER :: iosduobs ! - outside space domain (zonal velocity component)
  802. INTEGER :: iosdvobs ! - outside space domain (meridional velocity component)
  803. INTEGER :: ilanuobs ! - within a model land cell (zonal velocity component)
  804. INTEGER :: ilanvobs ! - within a model land cell (meridional velocity component)
  805. INTEGER :: inlauobs ! - close to land (zonal velocity component)
  806. INTEGER :: inlavobs ! - close to land (meridional velocity component)
  807. INTEGER :: igrdobs ! - fail the grid search
  808. INTEGER :: iuvchku ! - reject u if v rejected and vice versa
  809. INTEGER :: iuvchkv !
  810. ! Global counters for observations that
  811. INTEGER :: iotdobsmpp ! - outside time domain
  812. INTEGER :: iosduobsmpp ! - outside space domain (zonal velocity component)
  813. INTEGER :: iosdvobsmpp ! - outside space domain (meridional velocity component)
  814. INTEGER :: ilanuobsmpp ! - within a model land cell (zonal velocity component)
  815. INTEGER :: ilanvobsmpp ! - within a model land cell (meridional velocity component)
  816. INTEGER :: inlauobsmpp ! - close to land (zonal velocity component)
  817. INTEGER :: inlavobsmpp ! - close to land (meridional velocity component)
  818. INTEGER :: igrdobsmpp ! - fail the grid search
  819. INTEGER :: iuvchkumpp ! - reject u if v rejected and vice versa
  820. INTEGER :: iuvchkvmpp !
  821. TYPE(obs_prof_valid) :: llvalid ! Profile selection
  822. TYPE(obs_prof_valid), DIMENSION(profdata%nvar) :: &
  823. & llvvalid ! U,V selection
  824. INTEGER :: jvar ! Variable loop variable
  825. INTEGER :: jobs ! Obs. loop variable
  826. INTEGER :: jstp ! Time loop variable
  827. INTEGER :: inrc ! Time index variable
  828. IF(lwp) WRITE(numout,*)'obs_pre_vel: Preparing the velocity profile data'
  829. ! Initial date initialization (year, month, day, hour, minute)
  830. iyea0 = ndate0 / 10000
  831. imon0 = ( ndate0 - iyea0 * 10000 ) / 100
  832. iday0 = ndate0 - iyea0 * 10000 - imon0 * 100
  833. ihou0 = 0
  834. imin0 = 0
  835. icycle = no ! Assimilation cycle
  836. ! Diagnotics counters for various failures.
  837. iotdobs = 0
  838. igrdobs = 0
  839. iosduobs = 0
  840. iosdvobs = 0
  841. ilanuobs = 0
  842. ilanvobs = 0
  843. inlauobs = 0
  844. inlavobs = 0
  845. iuvchku = 0
  846. iuvchkv = 0
  847. ! -----------------------------------------------------------------------
  848. ! Find time coordinate for profiles
  849. ! -----------------------------------------------------------------------
  850. CALL obs_coo_tim_prof( icycle, &
  851. & iyea0, imon0, iday0, ihou0, imin0, &
  852. & profdata%nprof, profdata%nyea, profdata%nmon, &
  853. & profdata%nday, profdata%nhou, profdata%nmin, &
  854. & profdata%ntyp, profdata%nqc, profdata%mstp, &
  855. & iotdobs, ld_dailyav = ld_dailyav )
  856. CALL obs_mpp_sum_integer( iotdobs, iotdobsmpp )
  857. ! -----------------------------------------------------------------------
  858. ! Check for profiles failing the grid search
  859. ! -----------------------------------------------------------------------
  860. CALL obs_coo_grd( profdata%nprof, profdata%mi(:,1), profdata%mj(:,1), &
  861. & profdata%nqc, igrdobs )
  862. CALL obs_coo_grd( profdata%nprof, profdata%mi(:,2), profdata%mj(:,2), &
  863. & profdata%nqc, igrdobs )
  864. CALL obs_mpp_sum_integer( igrdobs, igrdobsmpp )
  865. ! -----------------------------------------------------------------------
  866. ! Reject all observations for profiles with nqc > 10
  867. ! -----------------------------------------------------------------------
  868. CALL obs_pro_rej( profdata )
  869. ! -----------------------------------------------------------------------
  870. ! Check for land points. This includes points below the model
  871. ! bathymetry so this is done for every point in the profile
  872. ! -----------------------------------------------------------------------
  873. ! Zonal Velocity Component
  874. CALL obs_coo_spc_3d( profdata%nprof, profdata%nvprot(1), &
  875. & profdata%npvsta(:,1), profdata%npvend(:,1), &
  876. & jpi, jpj, &
  877. & jpk, &
  878. & profdata%mi, profdata%mj, &
  879. & profdata%var(1)%mvk, &
  880. & profdata%rlam, profdata%rphi, &
  881. & profdata%var(1)%vdep, &
  882. & glamu, gphiu, &
  883. & gdept_1d, umask, &
  884. & profdata%nqc, profdata%var(1)%nvqc, &
  885. & iosduobs, ilanuobs, &
  886. & inlauobs, ld_nea )
  887. CALL obs_mpp_sum_integer( iosduobs, iosduobsmpp )
  888. CALL obs_mpp_sum_integer( ilanuobs, ilanuobsmpp )
  889. CALL obs_mpp_sum_integer( inlauobs, inlauobsmpp )
  890. ! Meridional Velocity Component
  891. CALL obs_coo_spc_3d( profdata%nprof, profdata%nvprot(2), &
  892. & profdata%npvsta(:,2), profdata%npvend(:,2), &
  893. & jpi, jpj, &
  894. & jpk, &
  895. & profdata%mi, profdata%mj, &
  896. & profdata%var(2)%mvk, &
  897. & profdata%rlam, profdata%rphi, &
  898. & profdata%var(2)%vdep, &
  899. & glamv, gphiv, &
  900. & gdept_1d, vmask, &
  901. & profdata%nqc, profdata%var(2)%nvqc, &
  902. & iosdvobs, ilanvobs, &
  903. & inlavobs, ld_nea )
  904. CALL obs_mpp_sum_integer( iosdvobs, iosdvobsmpp )
  905. CALL obs_mpp_sum_integer( ilanvobs, ilanvobsmpp )
  906. CALL obs_mpp_sum_integer( inlavobs, inlavobsmpp )
  907. ! -----------------------------------------------------------------------
  908. ! Reject u if v is rejected and vice versa
  909. ! -----------------------------------------------------------------------
  910. CALL obs_uv_rej( profdata, iuvchku, iuvchkv )
  911. CALL obs_mpp_sum_integer( iuvchku, iuvchkumpp )
  912. CALL obs_mpp_sum_integer( iuvchkv, iuvchkvmpp )
  913. ! -----------------------------------------------------------------------
  914. ! Copy useful data from the profdata data structure to
  915. ! the prodatqc data structure
  916. ! -----------------------------------------------------------------------
  917. ! Allocate the selection arrays
  918. ALLOCATE( llvalid%luse(profdata%nprof) )
  919. DO jvar = 1,profdata%nvar
  920. ALLOCATE( llvvalid(jvar)%luse(profdata%nvprot(jvar)) )
  921. END DO
  922. ! We want all data which has qc flags = 0
  923. llvalid%luse(:) = ( profdata%nqc(:) <= 10 )
  924. DO jvar = 1,profdata%nvar
  925. llvvalid(jvar)%luse(:) = ( profdata%var(jvar)%nvqc(:) <= 10 )
  926. END DO
  927. ! The actual copying
  928. CALL obs_prof_compress( profdata, prodatqc, .TRUE., numout, &
  929. & lvalid=llvalid, lvvalid=llvvalid )
  930. ! Dellocate the selection arrays
  931. DEALLOCATE( llvalid%luse )
  932. DO jvar = 1,profdata%nvar
  933. DEALLOCATE( llvvalid(jvar)%luse )
  934. END DO
  935. ! -----------------------------------------------------------------------
  936. ! Print information about what observations are left after qc
  937. ! -----------------------------------------------------------------------
  938. ! Update the total observation counter array
  939. IF(lwp) THEN
  940. WRITE(numout,*)
  941. WRITE(numout,*) 'obs_pre_vel :'
  942. WRITE(numout,*) '~~~~~~~~~~~'
  943. WRITE(numout,*)
  944. WRITE(numout,*) ' Profiles outside time domain = ', &
  945. & iotdobsmpp
  946. WRITE(numout,*) ' Remaining profiles that failed grid search = ', &
  947. & igrdobsmpp
  948. WRITE(numout,*) ' Remaining U data outside space domain = ', &
  949. & iosduobsmpp
  950. WRITE(numout,*) ' Remaining U data at land points = ', &
  951. & ilanuobsmpp
  952. IF (ld_nea) THEN
  953. WRITE(numout,*) ' Remaining U data near land points (removed) = ',&
  954. & inlauobsmpp
  955. ELSE
  956. WRITE(numout,*) ' Remaining U data near land points (kept) = ',&
  957. & inlauobsmpp
  958. ENDIF
  959. WRITE(numout,*) ' U observation rejected since V rejected = ', &
  960. & iuvchku
  961. WRITE(numout,*) ' U data accepted = ', &
  962. & prodatqc%nvprotmpp(1)
  963. WRITE(numout,*) ' Remaining V data outside space domain = ', &
  964. & iosdvobsmpp
  965. WRITE(numout,*) ' Remaining V data at land points = ', &
  966. & ilanvobsmpp
  967. IF (ld_nea) THEN
  968. WRITE(numout,*) ' Remaining V data near land points (removed) = ',&
  969. & inlavobsmpp
  970. ELSE
  971. WRITE(numout,*) ' Remaining V data near land points (kept) = ',&
  972. & inlavobsmpp
  973. ENDIF
  974. WRITE(numout,*) ' V observation rejected since U rejected = ', &
  975. & iuvchkv
  976. WRITE(numout,*) ' V data accepted = ', &
  977. & prodatqc%nvprotmpp(2)
  978. WRITE(numout,*)
  979. WRITE(numout,*) ' Number of observations per time step :'
  980. WRITE(numout,*)
  981. WRITE(numout,997)
  982. WRITE(numout,998)
  983. ENDIF
  984. DO jobs = 1, prodatqc%nprof
  985. inrc = prodatqc%mstp(jobs) + 2 - nit000
  986. prodatqc%npstp(inrc) = prodatqc%npstp(inrc) + 1
  987. DO jvar = 1, prodatqc%nvar
  988. IF ( prodatqc%npvend(jobs,jvar) > 0 ) THEN
  989. prodatqc%nvstp(inrc,jvar) = prodatqc%nvstp(inrc,jvar) + &
  990. & ( prodatqc%npvend(jobs,jvar) - &
  991. & prodatqc%npvsta(jobs,jvar) + 1 )
  992. ENDIF
  993. END DO
  994. END DO
  995. CALL obs_mpp_sum_integers( prodatqc%npstp, prodatqc%npstpmpp, &
  996. & nitend - nit000 + 2 )
  997. DO jvar = 1, prodatqc%nvar
  998. CALL obs_mpp_sum_integers( prodatqc%nvstp(:,jvar), &
  999. & prodatqc%nvstpmpp(:,jvar), &
  1000. & nitend - nit000 + 2 )
  1001. END DO
  1002. IF ( lwp ) THEN
  1003. DO jstp = nit000 - 1, nitend
  1004. inrc = jstp - nit000 + 2
  1005. WRITE(numout,999) jstp, prodatqc%npstpmpp(inrc), &
  1006. & prodatqc%nvstpmpp(inrc,1), &
  1007. & prodatqc%nvstpmpp(inrc,2)
  1008. END DO
  1009. ENDIF
  1010. 997 FORMAT(10X,'Time step',5X,'Profiles',5X,'Zonal Comp.',5X,'Meridional Comp.')
  1011. 998 FORMAT(10X,'---------',5X,'--------',5X,'-----------',5X,'----------------')
  1012. 999 FORMAT(10X,I9,5X,I8,5X,I11,5X,I8)
  1013. END SUBROUTINE obs_pre_vel
  1014. SUBROUTINE obs_coo_tim( kcycle, &
  1015. & kyea0, kmon0, kday0, khou0, kmin0, &
  1016. & kobsno, &
  1017. & kobsyea, kobsmon, kobsday, kobshou, kobsmin, &
  1018. & kobsqc, kobsstp, kotdobs )
  1019. !!----------------------------------------------------------------------
  1020. !! *** ROUTINE obs_coo_tim ***
  1021. !!
  1022. !! ** Purpose : Compute the number of time steps to the observation time.
  1023. !!
  1024. !! ** Method : For time coordinates ( yea_obs, mon_obs, day_obs,
  1025. !! hou_obs, min_obs ), this routine locates the time step
  1026. !! that is closest to this time.
  1027. !!
  1028. !! ** Action :
  1029. !!
  1030. !! References :
  1031. !!
  1032. !! History :
  1033. !! ! 1997-07 (A. Weaver) Original
  1034. !! ! 2006-08 (A. Weaver) NEMOVAR migration
  1035. !! ! 2006-10 (A. Weaver) Cleanup
  1036. !! ! 2007-01 (K. Mogensen) Rewritten with loop
  1037. !! ! 2010-05 (D. Lea) Fix in leap year calculation for NEMO vn3.2
  1038. !!----------------------------------------------------------------------
  1039. !! * Modules used
  1040. USE dom_oce, ONLY : & ! Geographical information
  1041. & rdt
  1042. USE phycst, ONLY : & ! Physical constants
  1043. & rday, &
  1044. & rmmss, &
  1045. & rhhmm
  1046. !! * Arguments
  1047. INTEGER, INTENT(IN) :: kcycle ! Current cycle
  1048. INTEGER, INTENT(IN) :: kyea0 ! Initial date coordinates
  1049. INTEGER, INTENT(IN) :: kmon0
  1050. INTEGER, INTENT(IN) :: kday0
  1051. INTEGER, INTENT(IN) :: khou0
  1052. INTEGER, INTENT(IN) :: kmin0
  1053. INTEGER, INTENT(IN) :: kobsno ! Number of observations
  1054. INTEGER, INTENT(INOUT) :: kotdobs ! Number of observations failing time check
  1055. INTEGER, DIMENSION(kobsno), INTENT(IN ) :: &
  1056. & kobsyea, & ! Observation time coordinates
  1057. & kobsmon, &
  1058. & kobsday, &
  1059. & kobshou, &
  1060. & kobsmin
  1061. INTEGER, DIMENSION(kobsno), INTENT(INOUT) :: &
  1062. & kobsqc ! Quality control flag
  1063. INTEGER, DIMENSION(kobsno), INTENT(OUT) :: &
  1064. & kobsstp ! Number of time steps up to the
  1065. ! observation time
  1066. !! * Local declarations
  1067. INTEGER :: jyea
  1068. INTEGER :: jmon
  1069. INTEGER :: jday
  1070. INTEGER :: jobs
  1071. INTEGER :: iyeastr
  1072. INTEGER :: iyeaend
  1073. INTEGER :: imonstr
  1074. INTEGER :: imonend
  1075. INTEGER :: idaystr
  1076. INTEGER :: idayend
  1077. INTEGER :: iskip
  1078. INTEGER :: idaystp
  1079. REAL(KIND=wp) :: zminstp
  1080. REAL(KIND=wp) :: zhoustp
  1081. REAL(KIND=wp) :: zobsstp
  1082. INTEGER, DIMENSION(12) :: imonth_len !: length in days of the months of the current year
  1083. !-----------------------------------------------------------------------
  1084. ! Initialization
  1085. !-----------------------------------------------------------------------
  1086. ! Intialize the number of time steps per day
  1087. idaystp = NINT( rday / rdt )
  1088. !---------------------------------------------------------------------
  1089. ! Locate the model time coordinates for interpolation
  1090. !---------------------------------------------------------------------
  1091. DO jobs = 1, kobsno
  1092. ! Initialize the time step counter
  1093. kobsstp(jobs) = nit000 - 1
  1094. ! Flag if observation date is less than the initial date
  1095. IF ( ( kobsyea(jobs) < kyea0 ) &
  1096. & .OR. ( ( kobsyea(jobs) == kyea0 ) &
  1097. & .AND. ( kobsmon(jobs) < kmon0 ) ) &
  1098. & .OR. ( ( kobsyea(jobs) == kyea0 ) &
  1099. & .AND. ( kobsmon(jobs) == kmon0 ) &
  1100. & .AND. ( kobsday(jobs) < kday0 ) ) &
  1101. & .OR. ( ( kobsyea(jobs) == kyea0 ) &
  1102. & .AND. ( kobsmon(jobs) == kmon0 ) &
  1103. & .AND. ( kobsday(jobs) == kday0 ) &
  1104. & .AND. ( kobshou(jobs) < khou0 ) ) &
  1105. & .OR. ( ( kobsyea(jobs) == kyea0 ) &
  1106. & .AND. ( kobsmon(jobs) == kmon0 ) &
  1107. & .AND. ( kobsday(jobs) == kday0 ) &
  1108. & .AND. ( kobshou(jobs) == khou0 ) &
  1109. & .AND. ( kobsmin(jobs) <= kmin0 ) ) ) THEN
  1110. kobsstp(jobs) = -1
  1111. kobsqc(jobs) = kobsqc(jobs) + 11
  1112. kotdobs = kotdobs + 1
  1113. CYCLE
  1114. ENDIF
  1115. ! Compute the number of time steps to the observation day
  1116. iyeastr = kyea0
  1117. iyeaend = kobsyea(jobs)
  1118. !---------------------------------------------------------------------
  1119. ! Year loop
  1120. !---------------------------------------------------------------------
  1121. DO jyea = iyeastr, iyeaend
  1122. CALL calc_month_len( jyea, imonth_len )
  1123. imonstr = 1
  1124. IF ( jyea == kyea0 ) imonstr = kmon0
  1125. imonend = 12
  1126. IF ( jyea == kobsyea(jobs) ) imonend = kobsmon(jobs)
  1127. ! Month loop
  1128. DO jmon = imonstr, imonend
  1129. idaystr = 1
  1130. IF ( ( jmon == kmon0 ) &
  1131. & .AND. ( jyea == kyea0 ) ) idaystr = kday0
  1132. idayend = imonth_len(jmon)
  1133. IF ( ( jmon == kobsmon(jobs) ) &
  1134. & .AND. ( jyea == kobsyea(jobs) ) ) idayend = kobsday(jobs) - 1
  1135. ! Day loop
  1136. DO jday = idaystr, idayend
  1137. kobsstp(jobs) = kobsstp(jobs) + idaystp
  1138. END DO
  1139. END DO
  1140. END DO
  1141. ! Add in the number of time steps to the observation minute
  1142. zminstp = rmmss / rdt
  1143. zhoustp = rhhmm * zminstp
  1144. zobsstp = REAL( kobsmin(jobs) - kmin0, KIND=wp ) * zminstp &
  1145. & + REAL( kobshou(jobs) - khou0, KIND=wp ) * zhoustp
  1146. kobsstp(jobs) = kobsstp(jobs) + NINT( zobsstp )
  1147. ! Flag if observation step outside the time window
  1148. IF ( ( kobsstp(jobs) < ( nit000 - 1 ) ) &
  1149. & .OR.( kobsstp(jobs) > nitend ) ) THEN
  1150. kobsqc(jobs) = kobsqc(jobs) + 12
  1151. kotdobs = kotdobs + 1
  1152. CYCLE
  1153. ENDIF
  1154. END DO
  1155. END SUBROUTINE obs_coo_tim
  1156. SUBROUTINE calc_month_len( iyear, imonth_len )
  1157. !!----------------------------------------------------------------------
  1158. !! *** ROUTINE calc_month_len ***
  1159. !!
  1160. !! ** Purpose : Compute the number of days in a months given a year.
  1161. !!
  1162. !! ** Method :
  1163. !!
  1164. !! ** Action :
  1165. !!
  1166. !! History :
  1167. !! ! 10-05 (D. Lea) New routine based on day_init
  1168. !!----------------------------------------------------------------------
  1169. INTEGER, DIMENSION(12) :: imonth_len !: length in days of the months of the current year
  1170. INTEGER :: iyear !: year
  1171. ! length of the month of the current year (from nleapy, read in namelist)
  1172. IF ( nleapy < 2 ) THEN
  1173. imonth_len(:) = (/ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 /)
  1174. IF ( nleapy == 1 ) THEN ! we are using calendar with leap years
  1175. IF ( MOD(iyear, 4) == 0 .AND. ( MOD(iyear, 400) == 0 .OR. MOD(iyear, 100) /= 0 ) ) THEN
  1176. imonth_len(2) = 29
  1177. ENDIF
  1178. ENDIF
  1179. ELSE
  1180. imonth_len(:) = nleapy ! all months with nleapy days per year
  1181. ENDIF
  1182. END SUBROUTINE
  1183. SUBROUTINE obs_coo_tim_prof( kcycle, &
  1184. & kyea0, kmon0, kday0, khou0, kmin0, &
  1185. & kobsno, &
  1186. & kobsyea, kobsmon, kobsday, kobshou, kobsmin, &
  1187. & ktyp, kobsqc, kobsstp, kotdobs, kdailyavtypes, &
  1188. & ld_dailyav )
  1189. !!----------------------------------------------------------------------
  1190. !! *** ROUTINE obs_coo_tim ***
  1191. !!
  1192. !! ** Purpose : Compute the number of time steps to the observation time.
  1193. !!
  1194. !! ** Method : For time coordinates ( yea_obs, mon_obs, day_obs,
  1195. !! hou_obs, min_obs ), this routine locates the time step
  1196. !! that is closest to this time.
  1197. !!
  1198. !! ** Action :
  1199. !!
  1200. !! References :
  1201. !!
  1202. !! History :
  1203. !! ! 1997-07 (A. Weaver) Original
  1204. !! ! 2006-08 (A. Weaver) NEMOVAR migration
  1205. !! ! 2006-10 (A. Weaver) Cleanup
  1206. !! ! 2007-01 (K. Mogensen) Rewritten with loop
  1207. !!----------------------------------------------------------------------
  1208. !! * Modules used
  1209. !! * Arguments
  1210. INTEGER, INTENT(IN) :: kcycle ! Current cycle
  1211. INTEGER, INTENT(IN) :: kyea0 ! Initial date coordinates
  1212. INTEGER, INTENT(IN) :: kmon0
  1213. INTEGER, INTENT(IN) :: kday0
  1214. INTEGER, INTENT(IN) :: khou0
  1215. INTEGER, INTENT(IN) :: kmin0
  1216. INTEGER, INTENT(IN) :: kobsno ! Number of observations
  1217. INTEGER, INTENT(INOUT) :: kotdobs ! Number of observations failing time check
  1218. INTEGER, DIMENSION(kobsno), INTENT(IN ) :: &
  1219. & kobsyea, & ! Observation time coordinates
  1220. & kobsmon, &
  1221. & kobsday, &
  1222. & kobshou, &
  1223. & kobsmin, &
  1224. & ktyp ! Observation type.
  1225. INTEGER, DIMENSION(kobsno), INTENT(INOUT) :: &
  1226. & kobsqc ! Quality control flag
  1227. INTEGER, DIMENSION(kobsno), INTENT(OUT) :: &
  1228. & kobsstp ! Number of time steps up to the
  1229. ! observation time
  1230. INTEGER, DIMENSION(imaxavtypes), OPTIONAL :: &
  1231. & kdailyavtypes ! Types for daily averages
  1232. LOGICAL, OPTIONAL :: ld_dailyav ! All types are daily averages
  1233. !! * Local declarations
  1234. INTEGER :: jobs
  1235. !-----------------------------------------------------------------------
  1236. ! Call standard obs_coo_tim
  1237. !-----------------------------------------------------------------------
  1238. CALL obs_coo_tim( kcycle, &
  1239. & kyea0, kmon0, kday0, khou0, kmin0, &
  1240. & kobsno, &
  1241. & kobsyea, kobsmon, kobsday, kobshou, kobsmin, &
  1242. & kobsqc, kobsstp, kotdobs )
  1243. !------------------------------------------------------------------------
  1244. ! Always reject daily averaged data (e.g. MRB data (820)) at initial time
  1245. !------------------------------------------------------------------------
  1246. IF ( PRESENT(kdailyavtypes) ) THEN
  1247. DO jobs = 1, kobsno
  1248. IF ( kobsqc(jobs) <= 10 ) THEN
  1249. IF ( ( kobsstp(jobs) == (nit000 - 1) ).AND.&
  1250. & ( ANY (kdailyavtypes(:) == ktyp(jobs)) ) ) THEN
  1251. kobsqc(jobs) = kobsqc(jobs) + 14
  1252. kotdobs = kotdobs + 1
  1253. CYCLE
  1254. ENDIF
  1255. ENDIF
  1256. END DO
  1257. ENDIF
  1258. !------------------------------------------------------------------------
  1259. ! If ld_dailyav is set then all data assumed to be daily averaged
  1260. !------------------------------------------------------------------------
  1261. IF ( PRESENT( ld_dailyav) ) THEN
  1262. IF (ld_dailyav) THEN
  1263. DO jobs = 1, kobsno
  1264. IF ( kobsqc(jobs) <= 10 ) THEN
  1265. IF ( kobsstp(jobs) == (nit000 - 1) ) THEN
  1266. kobsqc(jobs) = kobsqc(jobs) + 14
  1267. kotdobs = kotdobs + 1
  1268. CYCLE
  1269. ENDIF
  1270. ENDIF
  1271. END DO
  1272. ENDIF
  1273. ENDIF
  1274. END SUBROUTINE obs_coo_tim_prof
  1275. SUBROUTINE obs_coo_grd( kobsno, kobsi, kobsj, kobsqc, kgrdobs )
  1276. !!----------------------------------------------------------------------
  1277. !! *** ROUTINE obs_coo_grd ***
  1278. !!
  1279. !! ** Purpose : Verify that the grid search has not failed
  1280. !!
  1281. !! ** Method : The previously computed i,j indeces are checked
  1282. !!
  1283. !! ** Action :
  1284. !!
  1285. !! References :
  1286. !!
  1287. !! History :
  1288. !! ! 2007-01 (K. Mogensen) Original
  1289. !!----------------------------------------------------------------------
  1290. !! * Arguments
  1291. INTEGER, INTENT(IN) :: kobsno ! Number of observations
  1292. INTEGER, DIMENSION(kobsno), INTENT(IN ) :: &
  1293. & kobsi, & ! i,j indeces previously computed
  1294. & kobsj
  1295. INTEGER, INTENT(INOUT) :: kgrdobs ! Number of observations failing the check
  1296. INTEGER, DIMENSION(kobsno), INTENT(INOUT) :: &
  1297. & kobsqc ! Quality control flag
  1298. !! * Local declarations
  1299. INTEGER :: jobs ! Loop variable
  1300. ! Flag if the grid search failed
  1301. DO jobs = 1, kobsno
  1302. IF ( ( kobsi(jobs) <= 0 ) .AND. ( kobsj(jobs) <= 0 ) ) THEN
  1303. kobsqc(jobs) = kobsqc(jobs) + 18
  1304. kgrdobs = kgrdobs + 1
  1305. ENDIF
  1306. END DO
  1307. END SUBROUTINE obs_coo_grd
  1308. SUBROUTINE obs_coo_spc_2d( kobsno, kpi, kpj, &
  1309. & kobsi, kobsj, pobslam, pobsphi, &
  1310. & plam, pphi, pmask, &
  1311. & kobsqc, kosdobs, klanobs, &
  1312. & knlaobs,ld_nea )
  1313. !!----------------------------------------------------------------------
  1314. !! *** ROUTINE obs_coo_spc_2d ***
  1315. !!
  1316. !! ** Purpose : Check for points outside the domain and land points
  1317. !!
  1318. !! ** Method : Remove the observations that are outside the model space
  1319. !! and time domain or located within model land cells.
  1320. !!
  1321. !! ** Action :
  1322. !!
  1323. !! History :
  1324. !! ! 2007-03 (A. Weaver, K. Mogensen) Original
  1325. !! ! 2007-06 (K. Mogensen et al) Reject obs. near land.
  1326. !!----------------------------------------------------------------------
  1327. !! * Modules used
  1328. !! * Arguments
  1329. INTEGER, INTENT(IN) :: kobsno ! Total number of observations
  1330. INTEGER, INTENT(IN) :: kpi ! Number of grid points in (i,j)
  1331. INTEGER, INTENT(IN) :: kpj
  1332. INTEGER, DIMENSION(kobsno), INTENT(IN) :: &
  1333. & kobsi, & ! Observation (i,j) coordinates
  1334. & kobsj
  1335. REAL(KIND=wp), DIMENSION(kobsno), INTENT(IN) :: &
  1336. & pobslam, & ! Observation (lon,lat) coordinates
  1337. & pobsphi
  1338. REAL(KIND=wp), DIMENSION(kpi,kpj), INTENT(IN) :: &
  1339. & plam, pphi ! Model (lon,lat) coordinates
  1340. REAL(KIND=wp), DIMENSION(kpi,kpj), INTENT(IN) :: &
  1341. & pmask ! Land mask array
  1342. INTEGER, DIMENSION(kobsno), INTENT(INOUT) :: &
  1343. & kobsqc ! Observation quality control
  1344. INTEGER, INTENT(INOUT) :: kosdobs ! Observations outside space domain
  1345. INTEGER, INTENT(INOUT) :: klanobs ! Observations within a model land cell
  1346. INTEGER, INTENT(INOUT) :: knlaobs ! Observations near land
  1347. LOGICAL, INTENT(IN) :: ld_nea ! Flag observations near land
  1348. !! * Local declarations
  1349. REAL(KIND=wp), DIMENSION(2,2,kobsno) :: &
  1350. & zgmsk ! Grid mask
  1351. REAL(KIND=wp), DIMENSION(2,2,kobsno) :: &
  1352. & zglam, & ! Model longitude at grid points
  1353. & zgphi ! Model latitude at grid points
  1354. INTEGER, DIMENSION(2,2,kobsno) :: &
  1355. & igrdi, & ! Grid i,j
  1356. & igrdj
  1357. LOGICAL :: lgridobs ! Is observation on a model grid point.
  1358. INTEGER :: iig, ijg ! i,j of observation on model grid point.
  1359. INTEGER :: jobs, ji, jj
  1360. ! Get grid point indices
  1361. DO jobs = 1, kobsno
  1362. ! For invalid points use 2,2
  1363. IF ( kobsqc(jobs) >= 10 ) THEN
  1364. igrdi(1,1,jobs) = 1
  1365. igrdj(1,1,jobs) = 1
  1366. igrdi(1,2,jobs) = 1
  1367. igrdj(1,2,jobs) = 2
  1368. igrdi(2,1,jobs) = 2
  1369. igrdj(2,1,jobs) = 1
  1370. igrdi(2,2,jobs) = 2
  1371. igrdj(2,2,jobs) = 2
  1372. ELSE
  1373. igrdi(1,1,jobs) = kobsi(jobs)-1
  1374. igrdj(1,1,jobs) = kobsj(jobs)-1
  1375. igrdi(1,2,jobs) = kobsi(jobs)-1
  1376. igrdj(1,2,jobs) = kobsj(jobs)
  1377. igrdi(2,1,jobs) = kobsi(jobs)
  1378. igrdj(2,1,jobs) = kobsj(jobs)-1
  1379. igrdi(2,2,jobs) = kobsi(jobs)
  1380. igrdj(2,2,jobs) = kobsj(jobs)
  1381. ENDIF
  1382. END DO
  1383. CALL obs_int_comm_2d( 2, 2, kobsno, igrdi, igrdj, pmask, zgmsk )
  1384. CALL obs_int_comm_2d( 2, 2, kobsno, igrdi, igrdj, plam, zglam )
  1385. CALL obs_int_comm_2d( 2, 2, kobsno, igrdi, igrdj, pphi, zgphi )
  1386. DO jobs = 1, kobsno
  1387. ! Skip bad observations
  1388. IF ( kobsqc(jobs) >= 10 ) CYCLE
  1389. ! Flag if the observation falls outside the model spatial domain
  1390. IF ( ( pobslam(jobs) < -180. ) &
  1391. & .OR. ( pobslam(jobs) > 180. ) &
  1392. & .OR. ( pobsphi(jobs) < -90. ) &
  1393. & .OR. ( pobsphi(jobs) > 90. ) ) THEN
  1394. kobsqc(jobs) = kobsqc(jobs) + 11
  1395. kosdobs = kosdobs + 1
  1396. CYCLE
  1397. ENDIF
  1398. ! Flag if the observation falls with a model land cell
  1399. IF ( SUM( zgmsk(1:2,1:2,jobs) ) == 0.0_wp ) THEN
  1400. kobsqc(jobs) = kobsqc(jobs) + 12
  1401. klanobs = klanobs + 1
  1402. CYCLE
  1403. ENDIF
  1404. ! Check if this observation is on a grid point
  1405. lgridobs = .FALSE.
  1406. iig = -1
  1407. ijg = -1
  1408. DO jj = 1, 2
  1409. DO ji = 1, 2
  1410. IF ( ( ABS( zgphi(ji,jj,jobs) - pobsphi(jobs) ) < 1.0e-6_wp ) &
  1411. & .AND. &
  1412. & ( ABS( zglam(ji,jj,jobs) - pobslam(jobs) ) < 1.0e-6_wp ) &
  1413. & ) THEN
  1414. lgridobs = .TRUE.
  1415. iig = ji
  1416. ijg = jj
  1417. ENDIF
  1418. END DO
  1419. END DO
  1420. ! For observations on the grid reject them if their are at
  1421. ! a masked point
  1422. IF (lgridobs) THEN
  1423. IF (zgmsk(iig,ijg,jobs) == 0.0_wp ) THEN
  1424. kobsqc(jobs) = kobsqc(jobs) + 12
  1425. klanobs = klanobs + 1
  1426. CYCLE
  1427. ENDIF
  1428. ENDIF
  1429. ! Flag if the observation falls is close to land
  1430. IF ( MINVAL( zgmsk(1:2,1:2,jobs) ) == 0.0_wp) THEN
  1431. IF (ld_nea) kobsqc(jobs) = kobsqc(jobs) + 14
  1432. knlaobs = knlaobs + 1
  1433. CYCLE
  1434. ENDIF
  1435. END DO
  1436. END SUBROUTINE obs_coo_spc_2d
  1437. SUBROUTINE obs_coo_spc_3d( kprofno, kobsno, kpstart, kpend, &
  1438. & kpi, kpj, kpk, &
  1439. & kobsi, kobsj, kobsk, &
  1440. & pobslam, pobsphi, pobsdep, &
  1441. & plam, pphi, pdep, pmask, &
  1442. & kpobsqc, kobsqc, kosdobs, &
  1443. & klanobs, knlaobs, ld_nea )
  1444. !!----------------------------------------------------------------------
  1445. !! *** ROUTINE obs_coo_spc_3d ***
  1446. !!
  1447. !! ** Purpose : Check for points outside the domain and land points
  1448. !! Reset depth of observation above highest model level
  1449. !! to the value of highest model level
  1450. !!
  1451. !! ** Method : Remove the observations that are outside the model space
  1452. !! and time domain or located within model land cells.
  1453. !!
  1454. !! NB. T and S profile observations lying between the ocean
  1455. !! surface and the depth of the first model T point are
  1456. !! assigned a depth equal to that of the first model T pt.
  1457. !!
  1458. !! ** Action :
  1459. !!
  1460. !! History :
  1461. !! ! 2007-01 (K. Mogensen) Rewrite of parts of obs_scr
  1462. !! ! 2007-06 (K. Mogensen et al) Reject obs. near land.
  1463. !!----------------------------------------------------------------------
  1464. !! * Modules used
  1465. USE dom_oce, ONLY : & ! Geographical information
  1466. & gdepw_1d
  1467. !! * Arguments
  1468. INTEGER, INTENT(IN) :: kprofno ! Number of profiles
  1469. INTEGER, INTENT(IN) :: kobsno ! Total number of observations
  1470. INTEGER, INTENT(IN) :: kpi ! Number of grid points in (i,j,k)
  1471. INTEGER, INTENT(IN) :: kpj
  1472. INTEGER, INTENT(IN) :: kpk
  1473. INTEGER, DIMENSION(kprofno), INTENT(IN) :: &
  1474. & kpstart, & ! Start of individual profiles
  1475. & kpend ! End of individual profiles
  1476. INTEGER, DIMENSION(kprofno), INTENT(IN) :: &
  1477. & kobsi, & ! Observation (i,j) coordinates
  1478. & kobsj
  1479. INTEGER, DIMENSION(kobsno), INTENT(IN) :: &
  1480. & kobsk ! Observation k coordinate
  1481. REAL(KIND=wp), DIMENSION(kprofno), INTENT(IN) :: &
  1482. & pobslam, & ! Observation (lon,lat) coordinates
  1483. & pobsphi
  1484. REAL(KIND=wp), DIMENSION(kobsno), INTENT(INOUT) :: &
  1485. & pobsdep ! Observation depths
  1486. REAL(KIND=wp), DIMENSION(kpi,kpj), INTENT(IN) :: &
  1487. & plam, pphi ! Model (lon,lat) coordinates
  1488. REAL(KIND=wp), DIMENSION(kpk), INTENT(IN) :: &
  1489. & pdep ! Model depth coordinates
  1490. REAL(KIND=wp), DIMENSION(kpi,kpj,kpk), INTENT(IN) :: &
  1491. & pmask ! Land mask array
  1492. INTEGER, DIMENSION(kprofno), INTENT(INOUT) :: &
  1493. & kpobsqc ! Profile quality control
  1494. INTEGER, DIMENSION(kobsno), INTENT(INOUT) :: &
  1495. & kobsqc ! Observation quality control
  1496. INTEGER, INTENT(INOUT) :: kosdobs ! Observations outside space domain
  1497. INTEGER, INTENT(INOUT) :: klanobs ! Observations within a model land cell
  1498. INTEGER, INTENT(INOUT) :: knlaobs ! Observations near land
  1499. LOGICAL, INTENT(IN) :: ld_nea ! Flag observations near land
  1500. !! * Local declarations
  1501. REAL(KIND=wp), DIMENSION(2,2,kpk,kprofno) :: &
  1502. & zgmsk ! Grid mask
  1503. REAL(KIND=wp), DIMENSION(2,2,kprofno) :: &
  1504. & zglam, & ! Model longitude at grid points
  1505. & zgphi ! Model latitude at grid points
  1506. INTEGER, DIMENSION(2,2,kprofno) :: &
  1507. & igrdi, & ! Grid i,j
  1508. & igrdj
  1509. LOGICAL :: lgridobs ! Is observation on a model grid point.
  1510. INTEGER :: iig, ijg ! i,j of observation on model grid point.
  1511. INTEGER :: jobs, jobsp, jk, ji, jj
  1512. ! Get grid point indices
  1513. DO jobs = 1, kprofno
  1514. ! For invalid points use 2,2
  1515. IF ( kpobsqc(jobs) >= 10 ) THEN
  1516. igrdi(1,1,jobs) = 1
  1517. igrdj(1,1,jobs) = 1
  1518. igrdi(1,2,jobs) = 1
  1519. igrdj(1,2,jobs) = 2
  1520. igrdi(2,1,jobs) = 2
  1521. igrdj(2,1,jobs) = 1
  1522. igrdi(2,2,jobs) = 2
  1523. igrdj(2,2,jobs) = 2
  1524. ELSE
  1525. igrdi(1,1,jobs) = kobsi(jobs)-1
  1526. igrdj(1,1,jobs) = kobsj(jobs)-1
  1527. igrdi(1,2,jobs) = kobsi(jobs)-1
  1528. igrdj(1,2,jobs) = kobsj(jobs)
  1529. igrdi(2,1,jobs) = kobsi(jobs)
  1530. igrdj(2,1,jobs) = kobsj(jobs)-1
  1531. igrdi(2,2,jobs) = kobsi(jobs)
  1532. igrdj(2,2,jobs) = kobsj(jobs)
  1533. ENDIF
  1534. END DO
  1535. CALL obs_int_comm_3d( 2, 2, kprofno, kpk, igrdi, igrdj, pmask, zgmsk )
  1536. CALL obs_int_comm_2d( 2, 2, kprofno, igrdi, igrdj, plam, zglam )
  1537. CALL obs_int_comm_2d( 2, 2, kprofno, igrdi, igrdj, pphi, zgphi )
  1538. DO jobs = 1, kprofno
  1539. ! Skip bad profiles
  1540. IF ( kpobsqc(jobs) >= 10 ) CYCLE
  1541. ! Check if this observation is on a grid point
  1542. lgridobs = .FALSE.
  1543. iig = -1
  1544. ijg = -1
  1545. DO jj = 1, 2
  1546. DO ji = 1, 2
  1547. IF ( ( ABS( zgphi(ji,jj,jobs) - pobsphi(jobs) ) < 1.0e-6_wp ) &
  1548. & .AND. &
  1549. & ( ABS( zglam(ji,jj,jobs) - pobslam(jobs) ) < 1.0e-6_wp ) &
  1550. & ) THEN
  1551. lgridobs = .TRUE.
  1552. iig = ji
  1553. ijg = jj
  1554. ENDIF
  1555. END DO
  1556. END DO
  1557. ! Reject observations
  1558. DO jobsp = kpstart(jobs), kpend(jobs)
  1559. ! Flag if the observation falls outside the model spatial domain
  1560. IF ( ( pobslam(jobs) < -180. ) &
  1561. & .OR. ( pobslam(jobs) > 180. ) &
  1562. & .OR. ( pobsphi(jobs) < -90. ) &
  1563. & .OR. ( pobsphi(jobs) > 90. ) &
  1564. & .OR. ( pobsdep(jobsp) < 0.0 ) &
  1565. & .OR. ( pobsdep(jobsp) > gdepw_1d(kpk)) ) THEN
  1566. kobsqc(jobsp) = kobsqc(jobsp) + 11
  1567. kosdobs = kosdobs + 1
  1568. CYCLE
  1569. ENDIF
  1570. ! Flag if the observation falls with a model land cell
  1571. IF ( SUM( zgmsk(1:2,1:2,kobsk(jobsp)-1:kobsk(jobsp),jobs) ) &
  1572. & == 0.0_wp ) THEN
  1573. kobsqc(jobsp) = kobsqc(jobsp) + 12
  1574. klanobs = klanobs + 1
  1575. CYCLE
  1576. ENDIF
  1577. ! For observations on the grid reject them if their are at
  1578. ! a masked point
  1579. IF (lgridobs) THEN
  1580. IF (zgmsk(iig,ijg,kobsk(jobsp)-1,jobs) == 0.0_wp ) THEN
  1581. kobsqc(jobsp) = kobsqc(jobsp) + 12
  1582. klanobs = klanobs + 1
  1583. CYCLE
  1584. ENDIF
  1585. ENDIF
  1586. ! Flag if the observation falls is close to land
  1587. IF ( MINVAL( zgmsk(1:2,1:2,kobsk(jobsp)-1:kobsk(jobsp),jobs) ) == &
  1588. & 0.0_wp) THEN
  1589. IF (ld_nea) kobsqc(jobsp) = kobsqc(jobsp) + 14
  1590. knlaobs = knlaobs + 1
  1591. ENDIF
  1592. ! Set observation depth equal to that of the first model depth
  1593. IF ( pobsdep(jobsp) <= pdep(1) ) THEN
  1594. pobsdep(jobsp) = pdep(1)
  1595. ENDIF
  1596. END DO
  1597. END DO
  1598. END SUBROUTINE obs_coo_spc_3d
  1599. SUBROUTINE obs_pro_rej( profdata )
  1600. !!----------------------------------------------------------------------
  1601. !! *** ROUTINE obs_pro_rej ***
  1602. !!
  1603. !! ** Purpose : Reject all data within a rejected profile
  1604. !!
  1605. !! ** Method :
  1606. !!
  1607. !! ** Action :
  1608. !!
  1609. !! References :
  1610. !!
  1611. !! History :
  1612. !! ! 2007-10 (K. Mogensen) Original code
  1613. !!----------------------------------------------------------------------
  1614. !! * Modules used
  1615. !! * Arguments
  1616. TYPE(obs_prof), INTENT(INOUT) :: profdata ! Profile data
  1617. !! * Local declarations
  1618. INTEGER :: jprof
  1619. INTEGER :: jvar
  1620. INTEGER :: jobs
  1621. ! Loop over profiles
  1622. DO jprof = 1, profdata%nprof
  1623. IF ( profdata%nqc(jprof) > 10 ) THEN
  1624. DO jvar = 1, profdata%nvar
  1625. DO jobs = profdata%npvsta(jprof,jvar), &
  1626. & profdata%npvend(jprof,jvar)
  1627. profdata%var(jvar)%nvqc(jobs) = &
  1628. & profdata%var(jvar)%nvqc(jobs) + 26
  1629. END DO
  1630. END DO
  1631. ENDIF
  1632. END DO
  1633. END SUBROUTINE obs_pro_rej
  1634. SUBROUTINE obs_uv_rej( profdata, knumu, knumv )
  1635. !!----------------------------------------------------------------------
  1636. !! *** ROUTINE obs_uv_rej ***
  1637. !!
  1638. !! ** Purpose : Reject u if v is rejected and vice versa
  1639. !!
  1640. !! ** Method :
  1641. !!
  1642. !! ** Action :
  1643. !!
  1644. !! References :
  1645. !!
  1646. !! History :
  1647. !! ! 2009-2 (K. Mogensen) Original code
  1648. !!----------------------------------------------------------------------
  1649. !! * Modules used
  1650. !! * Arguments
  1651. TYPE(obs_prof), INTENT(INOUT) :: profdata ! Profile data
  1652. INTEGER, INTENT(INOUT) :: knumu ! Number of u rejected
  1653. INTEGER, INTENT(INOUT) :: knumv ! Number of v rejected
  1654. !! * Local declarations
  1655. INTEGER :: jprof
  1656. INTEGER :: jvar
  1657. INTEGER :: jobs
  1658. ! Loop over profiles
  1659. DO jprof = 1, profdata%nprof
  1660. IF ( ( profdata%npvsta(jprof,1) /= profdata%npvsta(jprof,2) ) .OR. &
  1661. & ( profdata%npvend(jprof,1) /= profdata%npvend(jprof,2) ) ) THEN
  1662. CALL ctl_stop('U,V profiles inconsistent in obs_uv_rej')
  1663. RETURN
  1664. ENDIF
  1665. DO jobs = profdata%npvsta(jprof,1), profdata%npvend(jprof,1)
  1666. IF ( ( profdata%var(1)%nvqc(jobs) > 10 ) .AND. &
  1667. & ( profdata%var(2)%nvqc(jobs) <= 10) ) THEN
  1668. profdata%var(2)%nvqc(jobs) = profdata%var(2)%nvqc(jobs) + 42
  1669. knumv = knumv + 1
  1670. ENDIF
  1671. IF ( ( profdata%var(2)%nvqc(jobs) > 10 ) .AND. &
  1672. & ( profdata%var(1)%nvqc(jobs) <= 10) ) THEN
  1673. profdata%var(1)%nvqc(jobs) = profdata%var(1)%nvqc(jobs) + 42
  1674. knumu = knumu + 1
  1675. ENDIF
  1676. END DO
  1677. END DO
  1678. END SUBROUTINE obs_uv_rej
  1679. END MODULE obs_prep