user_output_station_F90.chem 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588
  1. !
  2. #define IF_NOTOK_RETURN(action) if (status/=0) then; write (gol,'("in ",a)') rname; call goErr; action; return; end if
  3. #define IF_ERROR_RETURN(action) if (status> 0) then; write (gol,'("in ",a)') rname; call goErr; action; return; end if
  4. !
  5. #include "tm5.inc"
  6. !
  7. !-----------------------------------------------------------------------------
  8. ! TM5 !
  9. !-----------------------------------------------------------------------------
  10. !BOP
  11. !
  12. ! !MODULE: USER_OUTPUT_STATION
  13. !
  14. ! !DESCRIPTION: Routines to deal with output for specific stations.
  15. !
  16. ! This version adds code to the original version in order to
  17. ! write AOD and alpha to the station files (cf #ifdef with_optics)
  18. !\\
  19. !\\
  20. ! !INTERFACE:
  21. !
  22. MODULE USER_OUTPUT_STATION
  23. !
  24. ! !USES:
  25. !
  26. use GO, only : gol, goErr, goPr
  27. use binas, only : ae, twopi, grav
  28. use dims, only : im, jm, lm, dx, dy, xref, yref, xbeg, ybeg, xend, yend
  29. use dims, only : nregions, region_name, itaur, xcyc
  30. use chem_param, only : ntrace, ntracet, names, fscale
  31. use file_hdf, only : THdfFile, Init, Done, TSds, SetDim
  32. use ParTools, only : isRoot, myid
  33. IMPLICIT NONE
  34. PRIVATE
  35. !
  36. ! !PUBLIC MEMBER FUNCTIONS:
  37. !
  38. public :: read_stationlist ! read files with station definitions
  39. public :: init_station_output ! init output files
  40. public :: reset_stationconc_accumulator ! set to 0 acummulation arrays
  41. public :: output_stationconc ! accumulate arrays
  42. public :: evaluate_stationconc ! compute mean and std dev
  43. public :: write_stationconc ! write mean conc to file
  44. public :: free_stationfields ! close output files, free arrays
  45. #if defined(with_pm) || defined(with_optics)
  46. public :: n_stat2
  47. public :: io_hdf
  48. ! Optics wants to write wavelength information here.
  49. ! Optics can do it more easily than user_output.
  50. ! Optics uses user_output_station. This means that user_output_station
  51. ! cannot use optics.
  52. ! PM also uses this.
  53. #endif
  54. !
  55. ! !PRIVATE DATA MEMBERS:
  56. !
  57. character(len=100) :: StationlistFFilename2 ! list of 'validation' stations
  58. character(len=100) :: InputDir = './'
  59. logical :: output_stations_meteo = .true.
  60. character(len=300) :: StationSpeclist
  61. integer :: StationlistFileFormat ! 1: old format, 2: new format, 3: newer format
  62. integer :: n_stat2 ! number of 'validation' stations (not used for 4DVAR)
  63. integer, dimension(ntrace) :: station_speclist ! list of species for output (may differ per PE)
  64. integer :: station_nspec ! number of species for output (may differ per PE)
  65. integer, parameter :: n_metdat = 7 ! max number of meteo data (for output in station output file)
  66. integer, parameter :: n_interpol = 3 ! number of station interpolation methods
  67. integer, parameter :: n_neighbors = 6 ! number of neighboring grid cells used for estimate of represent. error
  68. character(len=4), dimension(n_interpol), parameter :: c_interpol = (/'_grd','_slp','_int'/)
  69. character(len=12),dimension(n_metdat ), parameter :: C_metdat = &
  70. (/'Temperature', &
  71. 'Pressure ',&
  72. 'uwind ',&
  73. 'vwind ',&
  74. 'windspeed ',&
  75. 'winddir ',&
  76. 'blh '/)
  77. character(len=12),dimension(n_metdat ), parameter :: U_metdat = &
  78. (/'K ', &
  79. 'hPa ', &
  80. 'm/s ', &
  81. 'm/s ', &
  82. 'm/s ', &
  83. 'degrees wrtN', &
  84. 'm '/)
  85. type(THdfFile) :: io_hdf ! contains HDF output file
  86. integer :: io_record = 0
  87. ! 'open' datasets of the io_hdf output file:
  88. type(TSds), dimension(:,:), allocatable :: Sds
  89. type(TSds), dimension(n_metdat) :: Sds_meteo
  90. type(TSds) :: Sds_idate
  91. #ifdef with_optics
  92. Type(TSds), public :: sds_station_aod
  93. Type(TSds), public :: sds_station_alpha
  94. #endif
  95. #ifdef with_pm
  96. Type(TSds), public :: sds_station_pm
  97. #endif
  98. ! --- const -------------------------
  99. character(len=*), parameter :: mname = 'user_output_station'
  100. !
  101. ! !PUBLIC TYPES:
  102. !
  103. type, public :: stations
  104. character(len=13) :: ident ! station identifier
  105. character(len=50) :: name ! station name
  106. real :: lat ! latitude of station
  107. real :: lon ! longitude of station
  108. real :: height ! height of station
  109. real :: height_sample ! sampling height
  110. real :: height_surface ! height of model surface
  111. real :: height_sample_above_surf ! height_sample-height_surface
  112. integer :: index ! index of station
  113. integer :: region
  114. integer :: is
  115. integer :: js
  116. integer :: ls
  117. character(len=2) :: type ! sampling type (FM = flask; CM = continuous)
  118. integer :: land ! land or ocean site
  119. integer :: nonsurf ! 1: nonsurface sites (e.g. towers); 0: 'regular' sites
  120. real,dimension(n_metdat) :: metdat ! meteodata (interpolated) at stations
  121. real,dimension(:,:),pointer :: c_mean ! c_mean(species, interpolation)
  122. real,dimension(:,:),pointer :: c_std ! c_std(species, interpolation)
  123. integer :: ncount ! counter
  124. logical :: ontile ! is located on current tile of domain decomposition
  125. ! No one is estimating representativeness errors. You can compare the different interpolations to acquire something similar.
  126. ! grid neighbors (for estimate of representativeness error)
  127. ! real,dimension(:,:),pointer :: c_mean_nb ! mean concentrations of neighbors (species, neighb. index)
  128. ! real,dimension(:,:),pointer :: c_std_nb ! standard deviation (species, neighb. index)
  129. ! integer,dimension(:,:),pointer :: ncount_nb ! counter (species, neighb. index)
  130. ! real,dimension(:),pointer :: dc_mod ! estimate of representativeness error (species)
  131. !(based on 3D gradient to grid cell neighbors)
  132. end type stations
  133. !
  134. ! !PUBLIC DATA MEMBERS:
  135. !
  136. type(stations), dimension(:), public, allocatable :: stat ! collection of stations
  137. character(len=100), public :: StationlistFFilename ! list of 'regular' stations
  138. logical, public :: write_Stationfiles = .true. ! do station
  139. integer, save, public :: n_stat ! number of 'regular' stations (used for 4DVAR)
  140. integer, save, public :: io_nrecords ! # record = # timesteps
  141. !
  142. ! !REVISION HISTORY:
  143. !
  144. ! Modified by Peter Beramaschi.
  145. ! Parallel version Maarten Krol Jul 2003
  146. ! jun 2005: switch to HDF output file
  147. ! jul 2007: paralel writing to increase performance..
  148. ! 16 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  149. !
  150. ! !REMARKS:
  151. !
  152. !EOP
  153. !------------------------------------------------------------------------
  154. CONTAINS
  155. !--------------------------------------------------------------------------
  156. ! TM5 !
  157. !--------------------------------------------------------------------------
  158. !BOP
  159. !
  160. ! !IROUTINE: FREE_STATIONFIELDS
  161. !
  162. ! !DESCRIPTION: close output files and deallocate arrays
  163. !\\
  164. !\\
  165. ! !INTERFACE:
  166. !
  167. SUBROUTINE FREE_STATIONFIELDS( status )
  168. !
  169. ! !INPUT/OUTPUT PARAMETERS:
  170. !
  171. integer, intent(inout) :: status
  172. !
  173. ! !REVISION HISTORY:
  174. !
  175. !EOP
  176. !------------------------------------------------------------------------
  177. !BOC
  178. integer :: i_stat
  179. character(len=*), parameter :: rname = mname//'/free_stationfields'
  180. !__START_SUBROUTINE______________________________________________________
  181. if(write_Stationfiles) then
  182. call close_stationfiles( status )
  183. IF_NOTOK_RETURN(status=1)
  184. endif
  185. write(gol,*) '************************************', station_nspec ; call goPr
  186. !cmk : the following lines do not work on huygens????
  187. if (station_nspec > 0 ) then
  188. do i_stat = 1, n_stat+n_stat2
  189. deallocate(stat(i_stat)%c_mean)
  190. deallocate(stat(i_stat)%c_std )
  191. enddo
  192. End If
  193. ! do i_stat = 1, n_stat
  194. ! deallocate(stat(i_stat)%c_mean_nb)
  195. ! deallocate(stat(i_stat)%c_std_nb)
  196. ! deallocate(stat(i_stat)%ncount_nb)
  197. ! deallocate(stat(i_stat)%dc_mod)
  198. ! enddo
  199. deallocate( stat )
  200. status = 0
  201. END SUBROUTINE FREE_STATIONFIELDS
  202. !EOC
  203. !--------------------------------------------------------------------------
  204. ! TM5 !
  205. !--------------------------------------------------------------------------
  206. !BOP
  207. !
  208. ! !IROUTINE: READ_STATIONLIST
  209. !
  210. ! !DESCRIPTION: Reads input files with stations definition. Allocate and
  211. ! fill station objects.
  212. !\\
  213. !\\
  214. ! !INTERFACE:
  215. !
  216. SUBROUTINE READ_STATIONLIST( status )
  217. !
  218. ! !USES:
  219. !
  220. use GO, only : TrcFile, Init, Done, ReadRc
  221. use global_data, only : rcfile
  222. use chem_param, only : ntracet, names
  223. use tm5_distgrid, only : dgrid, get_distgrid
  224. use ParTools, only : isRoot
  225. !
  226. ! !INPUT/OUTPUT PARAMETERS:
  227. !
  228. integer, intent(inout) :: status
  229. !
  230. ! !REVISION HISTORY:
  231. ! 16 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  232. !
  233. !EOP
  234. !------------------------------------------------------------------------
  235. !BOC
  236. integer :: slen1, slen2 !string length
  237. character(len=200) :: dummy
  238. integer :: fstatus
  239. integer :: i_stat
  240. integer :: region
  241. integer, dimension(6) :: idate_sim
  242. integer :: itau_sim, isim, ispec
  243. integer :: ipos, i, n
  244. integer :: i1, j1, i2, j2, is, js ! tile bounds and station indices
  245. real :: dxr, dyr ! x,y resolution (in degrees) for current region
  246. character(len=8) :: name_spec
  247. integer :: sunit1=110
  248. integer :: sunit2=111
  249. type(TrcFile) :: rcF
  250. character(len=*), parameter :: rname = mname//'/read_stationlist'
  251. !__START_SUBROUTINE______________________________________________________
  252. call Init( rcF, rcfile, status)
  253. IF_NOTOK_RETURN(status=1)
  254. call ReadRc( rcF, 'inputdir.station', InputDir,status)
  255. IF_NOTOK_RETURN(status=1)
  256. call ReadRc( rcF, 'input.station.filename', StationlistFFilename,status)
  257. IF_NOTOK_RETURN(status=1)
  258. call ReadRc( rcF, 'input.station.filename2', StationlistFFilename2,status)
  259. IF_NOTOK_RETURN(status=1)
  260. call ReadRc( rcF, 'input.station.fileformat', StationlistFileFormat,status)
  261. IF_NOTOK_RETURN(status=1)
  262. call ReadRc( rcF, 'station.speclist', StationSpeclist,status)
  263. IF_NOTOK_RETURN(status=1)
  264. call Done( rcF ,status)
  265. IF_NOTOK_RETURN(status=1)
  266. ! -------- count # of regular and validation stations
  267. n_stat=0
  268. n_stat2=0
  269. slen1=len_trim(StationlistFFilename)
  270. if ( slen1 > 0 ) then
  271. !=========================================
  272. ! open StationFile (with list of stations)
  273. !=========================================
  274. open(UNIT=sunit1, FORM='FORMATTED', &
  275. FILE=trim(InputDir)//trim(StationlistFFilename), &
  276. STATUS='OLD', ERR=1000)
  277. read(sunit1, '(a)') dummy
  278. ! count number of stations
  279. do
  280. read(sunit1, '(a)', end=100) dummy
  281. !if((dummy(1:1) /= ' ') .and. (dummy(1:7) /= 'species')) then
  282. n_stat = n_stat+1
  283. enddo
  284. 100 continue
  285. end if
  286. slen2=len_trim(StationlistFFilename2)
  287. if ( slen2 > 0 ) then
  288. !=========================================
  289. ! open StationFile (with list of stations)
  290. !=========================================
  291. open(UNIT=sunit2, FORM='FORMATTED', &
  292. FILE=trim(InputDir)//trim(StationlistFFilename2), &
  293. STATUS='OLD', ERR=1001)
  294. read(sunit2, '(a)') dummy
  295. ! count number of stations
  296. do
  297. read(sunit2, '(a)', END=200) dummy
  298. if((dummy(1:1) /= ' ') .and. (dummy(1:7) /= 'species')) then
  299. n_stat2 = n_stat2+1
  300. else
  301. goto 200
  302. endif
  303. enddo
  304. 200 continue
  305. end if
  306. ! ---- determine index of species in good order
  307. station_nspec = 0
  308. ipos = 1
  309. do
  310. i = index(StationSpeclist(ipos:),' ')
  311. if (i == 0) then
  312. name_spec = trim(StationSpeclist(ipos:))
  313. else
  314. name_spec = trim(StationSpeclist(ipos:ipos+i-1))
  315. ipos = ipos + i
  316. endif
  317. do n=1,ntracet
  318. if (trim(name_spec).eq.trim(names(n))) then
  319. station_nspec = station_nspec + 1
  320. station_speclist(station_nspec) = n
  321. endif
  322. enddo
  323. if(trim(name_spec).eq.'') exit
  324. enddo
  325. write(gol,*) trim(mname),':station_nspec; station_speclist', &
  326. station_nspec, station_speclist(1:station_nspec)
  327. call goPr
  328. ! ---- allocate station objects
  329. allocate(stat(n_stat+n_stat2)) ! all PE have all station, but only some will fill data
  330. if (station_nspec > 0) then
  331. do i_stat = 1, n_stat+n_stat2
  332. allocate(stat(i_stat)%c_mean(station_nspec,n_interpol))
  333. allocate(stat(i_stat)%c_std(station_nspec,n_interpol))
  334. enddo
  335. end if
  336. ! do i_stat = 1, n_stat
  337. ! allocate(stat(i_stat)%c_mean_nb(station_nspec,n_neighbors))
  338. ! allocate(stat(i_stat)%c_std_nb(station_nspec,n_neighbors))
  339. ! allocate(stat(i_stat)%ncount_nb(station_nspec,n_neighbors))
  340. ! allocate(stat(i_stat)%dc_mod(station_nspec))
  341. ! enddo
  342. ! ---- Read/fill stations definition, assuming first they are in region #1
  343. dyr = dy/yref(1)
  344. dxr = dx/xref(1)
  345. call get_distgrid( dgrid(1), i_strt=i1, i_stop=i2, j_strt=j1, j_stop=j2)
  346. if ( slen1 > 0 ) then
  347. !=========================
  348. ! read 'regular' stations
  349. !=========================
  350. rewind(sunit1)
  351. read(sunit1, '(a)') dummy
  352. do i_stat=1, n_stat
  353. select case(StationlistFileFormat)
  354. case(1)
  355. read(sunit1, '(a7,1x,f8.2,f8.2,f8.1,1x,a50)') &
  356. stat(i_stat)%ident, &
  357. stat(i_stat)%lat, &
  358. stat(i_stat)%lon, &
  359. stat(i_stat)%height, &
  360. stat(i_stat)%name
  361. stat(i_stat)%nonsurf = 0
  362. case(2)
  363. read(sunit1, '(a11,f8.2,4x,f8.2,4x,f8.1,1x,a2,1x,i2,1x,a50)') &
  364. stat(i_stat)%ident, &
  365. stat(i_stat)%lat, &
  366. stat(i_stat)%lon, &
  367. stat(i_stat)%height, &
  368. stat(i_stat)%type, &
  369. stat(i_stat)%nonsurf, &
  370. stat(i_stat)%name
  371. case(3)
  372. read(sunit1, '(a13,f6.2,4x,f8.2,4x,f8.0,4x,i1,5x,i1,a50)') &
  373. stat(i_stat)%ident, &
  374. stat(i_stat)%lat, &
  375. stat(i_stat)%lon, &
  376. stat(i_stat)%height, &
  377. stat(i_stat)%land, &
  378. stat(i_stat)%nonsurf, &
  379. stat(i_stat)%name
  380. stat(i_stat)%ident = adjustl(stat(i_stat)%ident)
  381. endselect
  382. stat(i_stat)%index = i_stat
  383. ! assume global region as default for average mixing ratios
  384. stat(i_stat)%region = 1
  385. is = int((stat(i_stat)%lon-float(xbeg(1)))/dxr + 0.99999)
  386. js = int((stat(i_stat)%lat-float(ybeg(1)))/dyr + 0.99999)
  387. stat(i_stat)%is = is
  388. stat(i_stat)%js = js
  389. ! is it on current PE?
  390. if (is>=i1.and.is<=i2.and.js>=j1.and.js<=j2) then
  391. stat(i_stat)%ontile=.true.
  392. else
  393. stat(i_stat)%ontile=.false.
  394. end if
  395. end do
  396. ! close stationfile
  397. close(sunit1)
  398. endif
  399. if ( slen2 > 0 ) then
  400. !=========================
  401. ! read 'validation' stations
  402. !=========================
  403. rewind(sunit2)
  404. read(sunit2, '(a)') dummy
  405. do i_stat=n_stat+1, n_stat+n_stat2
  406. select case(StationlistFileFormat)
  407. case(1)
  408. read(sunit2, '(a7,1x,f8.2,f8.2,f8.1,1x,a50)') &
  409. stat(i_stat)%ident, &
  410. stat(i_stat)%lat, &
  411. stat(i_stat)%lon, &
  412. stat(i_stat)%height, &
  413. stat(i_stat)%name
  414. stat(i_stat)%nonsurf = 0
  415. case(2)
  416. read(sunit2, '(a11,f8.2,f8.2,f8.1,1x,a2,1x,i2,1x,a50)') &
  417. stat(i_stat)%ident, &
  418. stat(i_stat)%lat, &
  419. stat(i_stat)%lon, &
  420. stat(i_stat)%height, &
  421. stat(i_stat)%type, &
  422. stat(i_stat)%nonsurf, &
  423. stat(i_stat)%name
  424. case(3)
  425. read(sunit1, '(a13,f6.2,4x,f8.2,4x,f8.0,4x,i1,5x,i1,a50)') &
  426. stat(i_stat)%ident, &
  427. stat(i_stat)%lat, &
  428. stat(i_stat)%lon, &
  429. stat(i_stat)%height, &
  430. stat(i_stat)%land, &
  431. stat(i_stat)%nonsurf, &
  432. stat(i_stat)%name
  433. stat(i_stat)%ident = adjustl(stat(i_stat)%ident)
  434. endselect
  435. stat(i_stat)%index = i_stat
  436. ! assume global region as default for average mixing ratios
  437. stat(i_stat)%region = 1
  438. is = int((stat(i_stat)%lon-float(xbeg(1)))/dxr + 0.99999)
  439. js = int((stat(i_stat)%lat-float(ybeg(1)))/dyr + 0.99999)
  440. stat(i_stat)%is = is
  441. stat(i_stat)%js = js
  442. if (is>=i1.and.is<=i2.and.js>=j1.and.js<=j2) then
  443. stat(i_stat)%ontile=.true.
  444. else
  445. stat(i_stat)%ontile=.false.
  446. end if
  447. end do
  448. ! close stationfile
  449. close(sunit2)
  450. end if
  451. !=================================================
  452. ! determine region with highest refinement factor
  453. !=================================================
  454. do i_stat=1, n_stat+n_stat2
  455. do region=1, nregions
  456. dyr = dy/yref(region)
  457. dxr = dx/xref(region)
  458. if ( (stat(i_stat)%lon .ge. xbeg(region) .and. &
  459. stat(i_stat)%lon .le. xend(region)) .and. &
  460. (stat(i_stat)%lat .ge. ybeg(region) .and. &
  461. stat(i_stat)%lat .le. yend(region) ) ) then
  462. !=====================
  463. ! station is in region
  464. !=====================
  465. ! determine region with hightes refinement factor
  466. if (xref(region) > xref(stat(i_stat)%region)) then
  467. stat(i_stat)%region = region
  468. is = int((stat(i_stat)%lon-float(xbeg(region)))/dxr + 0.99999)
  469. js = int((stat(i_stat)%lat-float(ybeg(region)))/dyr + 0.99999)
  470. stat(i_stat)%is = is
  471. stat(i_stat)%js = js
  472. call get_distgrid( dgrid(region), i_strt=i1, i_stop=i2, j_strt=j1, j_stop=j2)
  473. if (is>=i1.and.is<=i2.and.js>=j1.and.js<=j2) then
  474. stat(i_stat)%ontile=.true.
  475. else
  476. stat(i_stat)%ontile=.false.
  477. end if
  478. end if
  479. end if
  480. end do
  481. end do
  482. if ( isRoot ) then
  483. write(gol,*) '==========================' ; call goPr
  484. write(gol,*) ' regular stations ' ; call goPr
  485. write(gol,*) '==========================' ; call goPr
  486. do i_stat=1, n_stat
  487. write(gol, '(a13,1x,f8.2,f8.2,f8.1,1x,i4,1x,i2,1x,a50)') &
  488. stat(i_stat)%ident, &
  489. stat(i_stat)%lat, &
  490. stat(i_stat)%lon, &
  491. stat(i_stat)%height, &
  492. stat(i_stat)%region, &
  493. stat(i_stat)%nonsurf, &
  494. stat(i_stat)%name ; call goPr
  495. end do
  496. write(gol,*) '==========================' ; call goPr
  497. write(gol,*) ' validation stations ' ; call goPr
  498. write(gol,*) '==========================' ; call goPr
  499. do i_stat=n_stat+1, n_stat+n_stat2
  500. write(gol, '(a11,1x,f8.2,f8.2,f8.1,1x,i4,1x,i2,1x,a50)') &
  501. stat(i_stat)%ident, &
  502. stat(i_stat)%lat, &
  503. stat(i_stat)%lon, &
  504. stat(i_stat)%height, &
  505. stat(i_stat)%region, &
  506. stat(i_stat)%nonsurf, &
  507. stat(i_stat)%name ; call goPr
  508. end do
  509. endif
  510. call reset_stationconc_accumulator
  511. ! ok
  512. status = 0
  513. return
  514. ! error handling
  515. 1000 write(gol,*) 'read_stationlist: could not open ' // trim(InputDir)//trim(StationlistFFilename) ; call goErr
  516. 1001 write(gol,*) 'read_stationlist: could not open ' // trim(InputDir)//trim(StationlistFFilename2) ; call goErr
  517. status = 1
  518. END SUBROUTINE READ_STATIONLIST
  519. !EOC
  520. !--------------------------------------------------------------------------
  521. ! TM5 !
  522. !--------------------------------------------------------------------------
  523. !BOP
  524. !
  525. ! !IROUTINE: INIT_STATION_OUTPUT
  526. !
  527. ! !DESCRIPTION: initialize hdf files for station output.
  528. !\\
  529. !\\
  530. ! !INTERFACE:
  531. !
  532. SUBROUTINE INIT_STATION_OUTPUT( status )
  533. !
  534. ! !USES:
  535. !
  536. use Dims, only : itaui, itaue, ndyn_max, idatei, idatee
  537. use file_hdf, only : Init, WriteAttribute, WriteData, TSds, Done
  538. use GO, only : TrcFile, Init, Done, ReadRc
  539. use global_data, only : rcfile, outdir
  540. !
  541. ! !OUTPUT PARAMETERS:
  542. !
  543. integer, intent(out) :: status
  544. !
  545. ! !REVISION HISTORY:
  546. ! 16 Mar 2012 - P. Le Sager -
  547. !
  548. ! !REMARKS:
  549. !
  550. !EOP
  551. !------------------------------------------------------------------------
  552. !BOC
  553. integer :: i_stat
  554. integer :: io_status
  555. type(TrcFile) :: rcF
  556. character(len=12) :: xname
  557. integer :: i, ii, j
  558. type(TSds) :: sds_temp
  559. character(len=200) :: station_filename
  560. character(len=3) :: smyid
  561. character(len=10) :: sidatei, sidatee
  562. character(len=*), parameter :: rname = mname//'/init_station_output'
  563. !__START_SUBROUTINE______________________________________________________
  564. if (write_Stationfiles )then
  565. call Init( rcF, rcfile ,status)
  566. IF_NOTOK_RETURN(status=1)
  567. call ReadRc( rcF, 'output.station.filename', station_filename,status)
  568. IF_NOTOK_RETURN(status=1)
  569. call Done( rcF ,status)
  570. IF_NOTOK_RETURN(status=1)
  571. #ifdef MPI
  572. i = index(station_filename,'.hdf')
  573. write(smyid,'(a1,i2.2)') '_',myid
  574. write(sidatei,'(i4.4,3i2.2)') idatei(1:4)
  575. write(sidatee,'(i4.4,3i2.2)') idatee(1:4)
  576. if(i /= 0) then
  577. station_filename = station_filename(1:i-1)//smyid//'_'//sidatei//'_'//sidatee//'.hdf'
  578. else
  579. station_filename = trim(station_filename)//smyid//'_'//sidatei//'_'//sidatee//'.hdf'
  580. endif
  581. #else
  582. i = index(station_filename,'.hdf')
  583. write(sidatei,'(i4.4,3i2.2)') idatei(1:4)
  584. write(sidatee,'(i4.4,3i2.2)') idatee(1:4)
  585. if(i /= 0) then
  586. station_filename = station_filename(1:i-1)//'_'//sidatei//'_'//sidatee//'.hdf'
  587. else
  588. station_filename = trim(station_filename)//'_'//sidatei//'_'//sidatee//'.hdf'
  589. endif
  590. #endif
  591. call Init( io_hdf, trim(outdir)//'/'//trim(station_filename),'create', status )
  592. IF_NOTOK_RETURN(status=1)
  593. io_record = 0
  594. Write(*,*) "Using itaui in stations"
  595. io_nrecords =abs(itaue-itaui)/ndyn_max
  596. call WriteAttribute( io_hdf, 'io_nrecords', io_nrecords,status)
  597. IF_NOTOK_RETURN(status=1)
  598. call WriteAttribute( io_hdf, 'n_stat', n_stat,status)
  599. IF_NOTOK_RETURN(status=1)
  600. call WriteAttribute( io_hdf, 'n_stat2', n_stat2,status) ! validation stations
  601. IF_NOTOK_RETURN(status=1)
  602. call WriteAttribute( io_hdf, 'n_spec', station_nspec,status)
  603. IF_NOTOK_RETURN(status=1)
  604. If (station_nspec > 0) Then
  605. call WriteAttribute( io_hdf, 'station_speclist', station_speclist(1:station_nspec), status)
  606. IF_NOTOK_RETURN(status=1)
  607. call WriteAttribute( io_hdf, 'station_specnames', names(station_speclist(1:station_nspec)), status)
  608. IF_NOTOK_RETURN(status=1)
  609. End If
  610. call WriteAttribute( io_hdf, 'station_lat', stat(:)%lat, status)
  611. IF_NOTOK_RETURN(status=1)
  612. call WriteAttribute( io_hdf, 'station_lon', stat(:)%lon, status)
  613. IF_NOTOK_RETURN(status=1)
  614. call WriteAttribute( io_hdf, 'station_height', stat(:)%height, status)
  615. IF_NOTOK_RETURN(status=1)
  616. call WriteAttribute( io_hdf, 'station_index', stat(:)%index, status)
  617. IF_NOTOK_RETURN(status=1)
  618. call WriteAttribute( io_hdf, 'station_nonsurf', stat(:)%nonsurf, status)
  619. IF_NOTOK_RETURN(status=1)
  620. call WriteAttribute( io_hdf, 'station_region', stat(:)%region, status)
  621. IF_NOTOK_RETURN(status=1)
  622. call WriteAttribute( io_hdf, 'station_is', stat(:)%is, status)
  623. IF_NOTOK_RETURN(status=1)
  624. call WriteAttribute( io_hdf, 'station_js', stat(:)%js, status)
  625. IF_NOTOK_RETURN(status=1)
  626. call WriteAttribute( io_hdf, 'station_names', stat(:)%name, status)
  627. IF_NOTOK_RETURN(status=1)
  628. call WriteAttribute( io_hdf, 'station_ident', stat(:)%ident, status)
  629. IF_NOTOK_RETURN(status=1)
  630. If (station_nspec > 0) Then
  631. allocate(Sds(station_nspec, n_interpol))
  632. do i=1, station_nspec
  633. do ii= 1,n_interpol
  634. xname = trim(names(station_speclist(i)))//c_interpol(ii)
  635. call init(Sds(i,ii), io_hdf, xname, (/n_stat+n_stat2, io_nrecords/), 'real(4)', status)
  636. IF_NOTOK_RETURN(status=1)
  637. call SetDim( sds(i,ii), 0, 'n_stations', 'station number', (/ (j, j=1,n_stat+n_stat2) /) , status)
  638. IF_NOTOK_RETURN(status=1)
  639. call SetDim( sds(i,ii), 1, 'n_records ', 'time slot #', (/ (j, j=1,io_nrecords) /) , status)
  640. IF_NOTOK_RETURN(status=1)
  641. call WriteAttribute(Sds(i,ii), 'Unit', 'Volume mixing ration (ppb)', status)
  642. IF_NOTOK_RETURN(status=1)
  643. enddo
  644. enddo
  645. End If
  646. if (myid /= 0) output_stations_meteo = .false.
  647. if (output_stations_meteo) then
  648. do i=1,n_metdat
  649. call init(sds_meteo(i), io_hdf, c_metdat(i), (/n_stat+n_stat2, io_nrecords/), 'real(4)', status)
  650. IF_NOTOK_RETURN(status=1)
  651. call SetDim( sds_meteo(i), 0, 'n_stations', 'station number', (/ (j, j=1,n_stat+n_stat2) /) , status)
  652. IF_NOTOK_RETURN(status=1)
  653. call SetDim( sds_meteo(i), 1, 'n_records ', 'time slot #', (/ (j, j=1,io_nrecords) /) , status)
  654. IF_NOTOK_RETURN(status=1)
  655. call WriteAttribute(Sds_meteo(i), 'Unit', u_metdat(i), status)
  656. IF_NOTOK_RETURN(status=1)
  657. enddo
  658. endif
  659. call init(sds_idate, io_hdf, 'idate', (/6, io_nrecords/), 'integer(2)', status)
  660. IF_NOTOK_RETURN(status=1)
  661. call SetDim( sds_idate, 1, 'n_records ', 'time slot #', (/ (j, j=1,io_nrecords) /), status )
  662. IF_NOTOK_RETURN(status=1)
  663. call WriteAttribute(Sds_idate, 'Unit', 'year month day hour minutes seconds', status)
  664. IF_NOTOK_RETURN(status=1)
  665. end if ! write stationfiles = T
  666. ! ok
  667. status = 0
  668. END SUBROUTINE INIT_STATION_OUTPUT
  669. !EOC
  670. !--------------------------------------------------------------------------
  671. ! TM5 !
  672. !--------------------------------------------------------------------------
  673. !BOP
  674. !
  675. ! !IROUTINE: CLOSE_STATIONFILES
  676. !
  677. ! !DESCRIPTION: close ouput files.
  678. !\\
  679. !\\
  680. ! !INTERFACE:
  681. !
  682. SUBROUTINE CLOSE_STATIONFILES( status )
  683. !
  684. ! !USES:
  685. !
  686. use file_hdf, only: Done
  687. !
  688. ! !INPUT/OUTPUT PARAMETERS:
  689. !
  690. integer, intent(inout) :: status
  691. !
  692. ! !REVISION HISTORY:
  693. !
  694. !EOP
  695. !------------------------------------------------------------------------
  696. !BOC
  697. integer :: i, ii
  698. character(len=*), parameter :: rname = mname//'/close_station_files'
  699. !__START_SUBROUTINE______________________________________________________
  700. if (write_Stationfiles )then
  701. If (station_nspec > 0) Then
  702. do i=1, station_nspec
  703. do ii= 1,n_interpol
  704. call Done(sds(i,ii), status)
  705. IF_NOTOK_RETURN(status=1)
  706. enddo
  707. enddo
  708. deallocate(Sds)
  709. End If
  710. if (myid /= 0) output_stations_meteo = .false.
  711. if (output_stations_meteo) then
  712. do i=1,n_metdat
  713. call Done(sds_meteo(i),status)
  714. IF_NOTOK_RETURN(status=1)
  715. enddo
  716. endif
  717. call Done(sds_idate, status)
  718. IF_NOTOK_RETURN(status=1)
  719. call Done(io_hdf, status)
  720. IF_NOTOK_RETURN(status=1)
  721. write(gol,*) 'Station file closed ' ; call goPr
  722. endif
  723. ! ok
  724. status = 0
  725. END SUBROUTINE CLOSE_STATIONFILES
  726. !EOC
  727. !--------------------------------------------------------------------------
  728. ! TM5 !
  729. !--------------------------------------------------------------------------
  730. !BOP
  731. !
  732. ! !IROUTINE: OUTPUT_STATIONCONC
  733. !
  734. ! !DESCRIPTION: accumulate mean and std dev arrays
  735. !\\
  736. !\\
  737. ! !INTERFACE:
  738. !
  739. SUBROUTINE OUTPUT_STATIONCONC(region, status)
  740. !
  741. ! !USES:
  742. !
  743. use global_data, only : mass_dat, conv_dat
  744. use MeteoData, only : m_dat, gph_dat, temper_dat, pu_dat, pv_dat, phlb_dat
  745. use datetime, only : tau2date
  746. !
  747. ! !INPUT PARAMETERS:
  748. !
  749. integer,intent(in) :: region
  750. !
  751. ! !INPUT/OUTPUT PARAMETERS:
  752. !
  753. integer,intent(inout):: status
  754. !
  755. ! !REVISION HISTORY:
  756. ! 16 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  757. !
  758. ! !REMARKS:
  759. !
  760. !EOP
  761. !------------------------------------------------------------------------
  762. !BOC
  763. real,dimension(:,:,:,:),pointer :: rm ! tracer mass
  764. real,dimension(:,:,:,:),pointer :: rxm,rym,rzm ! slopes of tracer mass
  765. real,dimension(:,:,:) ,pointer :: m ! air mass
  766. real,dimension(:,:,:) ,pointer :: gph ! geopotential height
  767. ! real, dimension(:,:,:,:), allocatable, target :: rmg ! MPI arrays to gather fields.
  768. ! real, dimension(:,:,:,:), allocatable, target :: rxmg, rymg, rzmg
  769. ! real, dimension(:,:,: ), allocatable, target :: mg
  770. integer :: i_interpol ! interpolation procedures:
  771. real :: sampleheight
  772. ! 1: no interpolation
  773. ! 2: interpolation based on slopes
  774. ! 3: 3D linear interpolations
  775. integer :: i,j,l ! grid cell indices
  776. integer :: is,js,ls ! i,j,l index of grid cell in which station lis located
  777. integer :: isn,jsn,lsn ! i,j,l index of grid cell which is taken as neighbour for linear interpolation
  778. integer :: lst, lstn ! MPI implementation
  779. integer :: js_north, js_south ! j index of grid cell for neighbours for windspeed_v interpolation
  780. integer :: is_west ! i index of grid cell for neighbour for windspeed_u interpolation
  781. integer :: n ! index of tracer
  782. integer :: i_stat ! index of station
  783. real :: ris,rjs,rls ! deviation of station from center of the grid cell (-0.5 ... +0.5)
  784. real :: wcx,wcy,wcz ! x,y,z-weight of grid cell (1.0 ... 0.5)
  785. real :: dxr, dyr ! x,y resolution (in degrees) for current region
  786. real,dimension(0:lm(region)) :: height ! height of vertical grid boundaries
  787. integer, dimension(6) :: idate_f ! current idate for region
  788. integer :: sunit ! unit number for station output file
  789. real :: rm_interpol ! tracer mass, interpolated to station location
  790. integer :: ispec ! index over activated tracers
  791. !=============
  792. ! meteo output
  793. !=============
  794. real,dimension(n_stat,n_metdat) :: metdat ! meteodata (interpolated) at stations
  795. real,dimension(:,:,:), pointer :: T ! temperature
  796. real,dimension(:,:,:), pointer :: phlb ! pressure grid boundaries
  797. real,dimension(:,:,:), pointer :: pu ! mass flux x-direction [kg/s]
  798. real,dimension(:,:,:), pointer :: pv ! mass flux y-direction [kg/s]
  799. real,dimension(:,:), pointer :: blh ! boundary layer height [m]
  800. real :: T_interpol ! temperature, interpolated to station location
  801. real :: p_interpol ! pressure, interpolated to station location
  802. real :: windspeed_u_interpol ! wind speed [m/s] x-direction , interpolated to station location
  803. real :: windspeed_v_interpol ! wind speed [m/s] y-direction , interpolated to station location
  804. real :: windspeed_interpol ! wind speed [m/s] , interpolated to station location
  805. real :: winddir_interpol ! wind direction , interpolated to station location
  806. real :: blh_interpol ! boundary layer height , interpolated to station location
  807. real :: lat_j ! latitude of grid cell center js [degrees]
  808. real :: lat_jn ! latitude of grid cell center jsn [degrees]
  809. real :: ddx_j ! x-extension of grid cell js [m]
  810. real :: ddx_jn ! x-extension of grid cell jsn [m]
  811. real :: ddy ! y-extension of grid cell js [m]
  812. real :: vmr ! volume mi
  813. integer :: communicator,root_id,lmr,imr,jmr
  814. character(len=*), parameter :: rname = mname//'/output_station_conc'
  815. !__START_SUBROUTINE______________________________________________________
  816. imr = im(region) ; jmr = jm(region) ; lmr = lm(region)
  817. m => m_dat(region)%data
  818. rm => mass_dat(region)%rm
  819. rxm => mass_dat(region)%rxm
  820. rym => mass_dat(region)%rym
  821. rzm => mass_dat(region)%rzm
  822. ! assign pointers (METEO)
  823. gph => gph_dat(region)%data
  824. t => temper_dat(region)%data
  825. pu => pu_dat(region)%data
  826. pv => pv_dat(region)%data
  827. blh => conv_dat(region)%blh
  828. phlb => phlb_dat(region)%data
  829. ! perform now on all PEs
  830. ! x and y resolution [degrees] for current region
  831. dyr = dy/yref(region)
  832. dxr = dx/xref(region)
  833. ! idate for current region
  834. call tau2date(itaur(region),idate_f)
  835. !====================
  836. ! loop over stations
  837. !====================
  838. do i_stat=1, n_stat+n_stat2
  839. if (stat(i_stat)%region == region) then
  840. if(stat(i_stat)%ontile) then
  841. !avoid edges!
  842. ris = (stat(i_stat)%lon-float(xbeg(region)))/dxr + 0.99999
  843. rjs = (stat(i_stat)%lat-float(ybeg(region)))/dyr + 0.99999
  844. is = int(ris) ! i-index of grid cell in which station is located
  845. js = int(rjs) ! j-index of grid cell in which station is located
  846. ! x-deviation from the center of the grid cell (-0.5...+0.5)
  847. ris = ris-is-0.5
  848. ! y-deviation from the center of the grid cell (-0.5...+0.5)
  849. rjs = rjs-js-0.5
  850. !=================================
  851. !the neighbour for x interpolation
  852. !=================================
  853. if ( ris .gt. 0 ) then
  854. isn = is+1
  855. else
  856. isn = is-1
  857. endif
  858. !=================================
  859. !the neighbour for y interpolation
  860. !=================================
  861. if ( rjs .gt. 0 ) then
  862. jsn = js+1
  863. else
  864. jsn = js-1
  865. endif
  866. ! x- / y-weighting of grid cell in which station is located
  867. wcx = (1.0-abs(ris)) ! 1.0 ... 0.5
  868. wcy = (1.0-abs(rjs)) ! 1.0 ... 0.5
  869. !=================================================================
  870. ! if index of neighbour is exceeding range of region set
  871. ! neighbour = current cell (i.e. no interpolation)
  872. ! in case of cyclic x-boundaries take corresponding cyclic i index
  873. !=================================================================
  874. if ( jsn == 0) jsn=1
  875. if ( jsn == jm(region)+1 ) jsn=jm(region) ! isn-->jsn (wouter Peters)
  876. ! if ( xcyc(region) == 0 ) then
  877. ! ! non-cyclic boundaries
  878. ! if ( isn == 0) isn=1
  879. ! if ( isn == im(region)+1 ) isn=im(region)
  880. ! else
  881. ! ! cyclic x-boundaries
  882. ! if ( isn == 0 ) isn=im(region)
  883. ! if ( isn == im(region)+1 ) isn=1
  884. ! end if
  885. !============================================
  886. ! interpolate the gph to xy position of station
  887. !============================================
  888. !ls = 1 !layer
  889. do l=0,lm(region)
  890. !CMK note: gph now from 1-->lm+1 (dec 2002)
  891. height(l) = wcx * wcy* gph(is,js,l+1) + &
  892. (1.0-wcx)* wcy* gph(isn,js,l+1) + &
  893. wcx *(1.0-wcy)* gph(is,jsn,l+1) + &
  894. (1.0-wcx)*(1.0-wcy)* gph(isn,jsn,l+1)
  895. end do
  896. !===========================
  897. ! determine layer of station
  898. !===========================
  899. if(stat(i_stat)%nonsurf == 1) then
  900. sampleheight=height(0)+stat(i_stat)%height
  901. else
  902. sampleheight=stat(i_stat)%height
  903. endif
  904. ! do not allow sampleheight below model surface
  905. sampleheight = max(sampleheight, height(0))
  906. do l=0,lm(region)
  907. if(height(l) > sampleheight) exit
  908. end do
  909. select case(l)
  910. case(0)
  911. !PB this should no longer occur !!
  912. ! force station to model surface
  913. ls = 1
  914. rls = -0.5
  915. case default
  916. ls = l ! station's layer
  917. ! the off-set from the center of the layer (-0.5--->+0.5)
  918. ! (interpolation is in (m))
  919. rls = (sampleheight - height(l-1)) / &
  920. (height(l)-height(l-1)) - 0.5
  921. end select
  922. stat(i_stat)%ls = ls ! store for output to file
  923. stat(i_stat)%height_sample = sampleheight ! store for output to file
  924. stat(i_stat)%height_surface = height(0) ! store for output to file
  925. stat(i_stat)%height_sample_above_surf = sampleheight-height(0) ! store for output to file
  926. !=================================
  927. !the neighbour for z interpolation
  928. !=================================
  929. if ( rls > 0 ) then
  930. lsn = ls+1
  931. else
  932. lsn = ls-1
  933. end if
  934. ! z-weighting of grid cell in which station is located
  935. wcz = (1.0-abs(rls)) !.0 ... 0.5
  936. !=========================================================
  937. ! if vertical neighbor is 0 (which does not exist)
  938. ! take vertical layer with l=2 for EXTRApolation to ground
  939. !=========================================================
  940. if(lsn == 0) then
  941. lsn=2
  942. wcz=1.0-rls ! 1.0 ... 1.5
  943. endif
  944. if(lsn == lmr+1) then
  945. !=========================================================
  946. ! if vertical neighbor is lmr+1 (which does not exist)
  947. ! -> no interpolation
  948. !=========================================================
  949. lsn=lmr ! no interpolation
  950. wcz=1.0
  951. endif
  952. if (station_nspec > 0) Then
  953. do ispec=1,station_nspec
  954. n = station_speclist(ispec)
  955. lst = ls
  956. lstn = lsn
  957. !========================================
  958. ! value of grid box without interpolation
  959. !========================================
  960. vmr = rm(is,js,lst,n) / m(is,js,lst) * fscale(n)
  961. stat(i_stat)%c_mean(ispec,1) = &
  962. stat(i_stat)%c_mean(ispec,1) + vmr
  963. stat(i_stat)%c_std(ispec,1) = &
  964. stat(i_stat)%c_std(ispec,1) + vmr*vmr
  965. !========================================
  966. ! interpolation using slopes
  967. !========================================
  968. !rm-value is obtained from rm + slopes.
  969. !slope = rxm = (rm*dX/dx *deltaX/2)
  970. rm_interpol = rm(is,js,lst,n) + 2.0*(ris*rxm(is,js,lst,n) + &
  971. rjs*rym(is,js,lst,n) + &
  972. rls*rzm(is,js,lst,n) )
  973. rm_interpol = max(0.0,rm_interpol)
  974. vmr = rm_interpol/m(is,js,lst) *fscale(n)
  975. stat(i_stat)%c_mean(ispec,2) = &
  976. stat(i_stat)%c_mean(ispec,2) + vmr
  977. stat(i_stat)%c_std(ispec,2) = &
  978. stat(i_stat)%c_std(ispec,2) + vmr*vmr
  979. !========================================
  980. ! 3D linear interpolation
  981. !========================================
  982. ! this PE handles also the neighbour layer
  983. if (lstn <= lmr) then ! lstn = 0 is already excluded (apply vertical EXTRApolation with upper neighbor; see above)
  984. rm_interpol = wcx *wcy *wcz *rm(is,js,lst,n) /m(is,js,lst) + &
  985. (1.0-wcx)*wcy *wcz *rm(isn,js,lst,n) /m(isn,js,lst) + &
  986. wcx *(1.0-wcy)*wcz *rm(is,jsn,lst,n) /m(is,jsn,lst) + &
  987. (1.0-wcx)*(1.0-wcy)*wcz *rm(isn,jsn,lst,n) /m(isn,jsn,lst) + &
  988. wcx *wcy *(1.0-wcz) *rm(is,js,lstn,n) /m(is,js,lstn) + &
  989. (1.0-wcx)*wcy *(1.0-wcz) *rm(isn,js,lstn,n) /m(isn,js,lstn) + &
  990. wcx *(1.0-wcy)*(1.0-wcz) *rm(is,jsn,lstn,n) /m(is,jsn,lstn) + &
  991. (1.0-wcx)*(1.0-wcy)*(1.0-wcz) *rm(isn,jsn,lstn,n)/m(isn,jsn,lstn)
  992. else !other PE calculates neighbouring contribution
  993. !PB do NOT apply factor wcz here (no interpolation in z direction in this case) !!!!!
  994. rm_interpol = wcx *wcy *rm(is,js,lst,n) /m(is,js,lst) + &
  995. (1.0-wcx)*wcy *rm(isn,js,lst,n) /m(isn,js,lst) + &
  996. wcx *(1.0-wcy) *rm(is,jsn,lst,n) /m(is,jsn,lst) + &
  997. (1.0-wcx)*(1.0-wcy) *rm(isn,jsn,lst,n) /m(isn,jsn,lst)
  998. endif
  999. vmr = rm_interpol*fscale(n)
  1000. stat(i_stat)%c_mean(ispec,3) = stat(i_stat)%c_mean(ispec,3) + vmr
  1001. stat(i_stat)%c_std(ispec,3) = stat(i_stat)%c_std(ispec,3) + vmr*vmr
  1002. end do !ispec
  1003. End If
  1004. !======================
  1005. !meteo data at stations
  1006. !======================
  1007. if (output_stations_meteo) then
  1008. !====================================
  1009. ! 3D linear interpolation Temperature
  1010. !====================================
  1011. T_interpol = &
  1012. wcx *wcy *wcz *T(is,js,ls) + &
  1013. (1.0-wcx)*wcy *wcz *T(isn,js,ls) + &
  1014. wcx *(1.0-wcy)*wcz *T(is,jsn,ls) + &
  1015. (1.0-wcx)*(1.0-wcy)*wcz *T(isn,jsn,ls) + &
  1016. wcx *wcy *(1.0-wcz) *T(is,js,lsn) + &
  1017. (1.0-wcx)*wcy *(1.0-wcz) *T(isn,js,lsn) + &
  1018. wcx *(1.0-wcy)*(1.0-wcz) *T(is,jsn,lsn) + &
  1019. (1.0-wcx)*(1.0-wcy)*(1.0-wcz) *T(isn,jsn,lsn)
  1020. stat(i_stat)%metdat(1) = stat(i_stat)%metdat(1) + T_interpol
  1021. !====================================
  1022. ! 3D linear interpolation pressure
  1023. !====================================
  1024. p_interpol =(((0.5-rls) * phlb(is,js,ls) + (0.5+rls) * phlb(is,js,ls+1)) * wcx * wcy + &
  1025. ((0.5-rls) * phlb(isn,js,ls) + (0.5+rls) * phlb(isn,js,ls+1)) * (1.0-wcx) * wcy + &
  1026. ((0.5-rls) * phlb(is,jsn,ls) + (0.5+rls) * phlb(is,jsn,ls+1)) * wcx * (1.0-wcy) + &
  1027. ((0.5-rls) * phlb(isn,jsn,ls)+ (0.5+rls) * phlb(isn,jsn,ls+1))* (1.0-wcx) * (1.0-wcy) ) *0.01 ![Pa] -> [hPa]
  1028. stat(i_stat)%metdat(2) = stat(i_stat)%metdat(2) + p_interpol
  1029. !====================================
  1030. ! 3D windspeed_u_interpol (x-direction)
  1031. !====================================
  1032. ! pu is eastward flux through east grid box boundary
  1033. ! windspeed_u_interpol wind component from east
  1034. ! latitude of grid cell center js [degrees]
  1035. lat_j =ybeg(region)+(js -0.5)*dyr
  1036. ! latitude of grid cell center jsn [degrees]
  1037. lat_jn=ybeg(region)+(jsn-0.5)*dyr
  1038. ! x-extension of grid cell js [m]
  1039. ddx_j =ae * twopi * dxr / 360.0 * cos(lat_j*twopi/360.0)
  1040. ! x-extension of grid cell jsn [m]
  1041. ddx_jn=ae * twopi * dxr / 360.0 * cos(lat_jn*twopi/360.0)
  1042. is_west=is-1
  1043. ! if ( xcyc(region) == 0 ) then
  1044. ! ! non-cyclic boundaries
  1045. ! if ( is_west == 0 ) is_west=1
  1046. ! else
  1047. ! ! cyclic x-boundaries
  1048. ! if ( is_west == 0 ) is_west=im(region)
  1049. ! end if
  1050. !west border !east border
  1051. windspeed_u_interpol=((0.5-ris) * pu(is_west,js,ls)/m(is_west,js,ls) + &
  1052. (0.5+ris) * pu(is,js,ls)/ m(is,js,ls) ) * &
  1053. ddx_j * wcy * wcz + &
  1054. ((0.5-ris) * pu(is_west,jsn,ls)/m(is_west,jsn,ls) + &
  1055. (0.5+ris) * pu(is,jsn,ls)/m(is,jsn,ls) ) * &
  1056. ddx_jn * (1.0-wcy)* wcz + &
  1057. ((0.5-ris) * pu(is_west,js,lsn)/m(is_west,js,lsn) + &
  1058. (0.5+ris) * pu(is,js,lsn)/ m(is,js,lsn)) * &
  1059. ddx_j * wcy * (1.0-wcz) + &
  1060. ((0.5-ris) * pu(is_west,jsn,lsn)/m(is_west,js,lsn) + &
  1061. (0.5+ris) * pu(is,jsn,lsn)/ m(is,jsn,lsn) ) * &
  1062. ddx_jn * (1.0-wcy)* (1.0-wcz)
  1063. !====================================
  1064. ! 3D windspeed_v_interpol (y-direction)
  1065. !====================================
  1066. ! pv northward flux through south grid box boundary
  1067. ! windspeed_v_interpol wind component from north
  1068. ddy =ae * twopi * dyr / 360.0 ! y-extension of grid cell [m]
  1069. js_south = js-1
  1070. if (js_south==0) js_south=1
  1071. js_north = js+1
  1072. if (js_north==(jm(region)+1)) js_north=jm(region)
  1073. !south border !north border
  1074. windspeed_v_interpol=(( &
  1075. (0.5-rjs)*pv(is,js,ls)/m(is,js_south,ls) + &
  1076. (0.5+rjs)*pv(is,js_north,ls)/ m(is,js,ls) ) * &
  1077. wcx * wcz + &
  1078. ((0.5-rjs)*pv(isn,js,ls)/m(isn,js_south,ls) + &
  1079. (0.5+rjs)*pv(isn,js_north,ls)/ m(isn,js,ls) ) * &
  1080. (1.0 - wcx)* wcz + &
  1081. ((0.5-rjs)*pv(is,js,lsn)/m(is,js_south,lsn) + &
  1082. (0.5+rjs)*pv(is,js_north,lsn)/ m(is,js,lsn) ) * &
  1083. wcx * (1.0-wcz) + &
  1084. ((0.5-rjs)*pv(isn,js,lsn)/m(isn,js_south,lsn) + &
  1085. (0.5+rjs)*pv(isn,js_north,lsn)/ m(isn,js,lsn) ) * &
  1086. (1.0 - wcx)* (1.0-wcz) ) * &
  1087. ddy
  1088. windspeed_interpol = &
  1089. sqrt(windspeed_u_interpol**2 + windspeed_v_interpol**2)
  1090. stat(i_stat)%metdat(3) = &
  1091. stat(i_stat)%metdat(3) + windspeed_u_interpol
  1092. stat(i_stat)%metdat(4) = &
  1093. stat(i_stat)%metdat(4) + windspeed_v_interpol
  1094. stat(i_stat)%metdat(5) = &
  1095. stat(i_stat)%metdat(5) + windspeed_interpol
  1096. !============================================
  1097. ! interpolate the blh to xy position of station
  1098. !============================================
  1099. blh_interpol = &
  1100. wcx * wcy* blh(is,js) + &
  1101. (1.0-wcx)* wcy* blh(isn,js) + &
  1102. wcx *(1.0-wcy)* blh(is,jsn) + &
  1103. (1.0-wcx)*(1.0-wcy)* blh(isn,jsn)
  1104. stat(i_stat)%metdat(7) = &
  1105. stat(i_stat)%metdat(7) + blh_interpol
  1106. endif ! meteo out...
  1107. stat(i_stat)%ncount = stat(i_stat)%ncount + 1
  1108. end if ! on current tile
  1109. end if ! on current region
  1110. end do ! end i_stat loop
  1111. nullify(m)
  1112. nullify(rm)
  1113. nullify(rxm)
  1114. nullify(rym)
  1115. nullify(rzm)
  1116. nullify(gph)
  1117. nullify(t)
  1118. nullify(pu)
  1119. nullify(pv)
  1120. nullify(phlb)
  1121. nullify(blh)
  1122. ! ok
  1123. status = 0
  1124. END SUBROUTINE OUTPUT_STATIONCONC
  1125. !EOC
  1126. !--------------------------------------------------------------------------
  1127. ! TM5 !
  1128. !--------------------------------------------------------------------------
  1129. !BOP
  1130. !
  1131. ! !IROUTINE: RESET_STATIONCONC_ACCUMULATOR
  1132. !
  1133. ! !DESCRIPTION: initialize to 0 accumulation arrays for average station
  1134. ! concentration
  1135. !\\
  1136. !\\
  1137. ! !INTERFACE:
  1138. !
  1139. SUBROUTINE RESET_STATIONCONC_ACCUMULATOR
  1140. !
  1141. ! !REVISION HISTORY:
  1142. !
  1143. !EOP
  1144. !------------------------------------------------------------------------
  1145. !BOC
  1146. integer i_stat
  1147. if (station_nspec > 0) then
  1148. do i_stat=1, n_stat+n_stat2
  1149. stat(i_stat)%c_mean(:,:) = 0.0
  1150. stat(i_stat)%c_std(:,:) = 0.0
  1151. end do
  1152. endif
  1153. if (output_stations_meteo) Then
  1154. Do i_stat=1,n_stat+n_stat2
  1155. stat(i_stat)%metdat(:) = 0.0
  1156. End Do
  1157. End If
  1158. Do i_stat=1,n_stat+n_stat2
  1159. stat(i_stat)%ncount = 0
  1160. End Do
  1161. ! You should also set the _nb-variables to zero. Otherwise, there is a random chance of crashing. Now I am not using them.
  1162. ! do i_stat=1, n_stat
  1163. ! stat(i_stat)%c_mean_nb = 0.0
  1164. ! stat(i_stat)%c_std_nb = 0.0
  1165. ! stat(i_stat)%ncount_nb = 0
  1166. ! end do
  1167. END SUBROUTINE RESET_STATIONCONC_ACCUMULATOR
  1168. !EOC
  1169. !--------------------------------------------------------------------------
  1170. ! TM5 !
  1171. !--------------------------------------------------------------------------
  1172. !BOP
  1173. !
  1174. ! !IROUTINE: EVALUATE_STATIONCONC
  1175. !
  1176. ! !DESCRIPTION: evaluate mean concentration and std
  1177. !\\
  1178. !\\
  1179. ! !INTERFACE:
  1180. !
  1181. SUBROUTINE EVALUATE_STATIONCONC( status )
  1182. !
  1183. ! !USES:
  1184. !
  1185. use dims, only : idate
  1186. use file_hdf, only : Init, WriteData, TSds, Done, select
  1187. use file_hdf, only : CheckInfo
  1188. use toolbox, only : escape_tm
  1189. !
  1190. ! !INPUT/OUTPUT PARAMETERS:
  1191. !
  1192. integer, intent(inout) :: status
  1193. !
  1194. ! !REVISION HISTORY:
  1195. ! 16 Mar 2012 - P. Le Sager -
  1196. !
  1197. ! !REMARKS:
  1198. !
  1199. !EOP
  1200. !------------------------------------------------------------------------
  1201. !BOC
  1202. integer i_stat, i, ii, io_status
  1203. integer n_data, isds, nsds, itp
  1204. real temp
  1205. character(len=12) :: xname
  1206. real, dimension(:,:), allocatable :: cout ! to get output
  1207. integer, dimension(:,:), allocatable :: iidate
  1208. real :: windspeed_u_interpol ! wind speed [m/s] x-direction , interpolated to station location
  1209. real :: windspeed_v_interpol ! wind speed [m/s] y-direction , interpolated to station location
  1210. real :: windspeed_interpol ! wind speed [m/s] , interpolated to station location
  1211. real :: winddir_interpol ! wind direction , interpolated to station location
  1212. character(len=*), parameter :: rname = mname//'/evaluate_stationconc'
  1213. !__START_SUBROUTINE______________________________________________________
  1214. !if(myid /= root) return
  1215. If (output_stations_meteo) Then
  1216. Do i_stat=1, n_stat+n_stat2
  1217. n_data = stat(i_stat)%ncount
  1218. if (n_data > 0) Then
  1219. stat(i_stat)%metdat(:) = stat(i_stat)%metdat(:) / n_data
  1220. Else
  1221. stat(i_stat)%metdat(:) = -999.
  1222. End If
  1223. End Do
  1224. End If
  1225. if (station_nspec > 0) then
  1226. do i_stat=1, n_stat+n_stat2
  1227. n_data = stat(i_stat)%ncount
  1228. if (n_data > 0) then
  1229. stat(i_stat)%c_mean(:,:) = stat(i_stat)%c_mean(:,:) / n_data
  1230. if (n_data > 1) then
  1231. do i=1, station_nspec
  1232. do ii= 1, n_interpol
  1233. temp = ((stat(i_stat)%c_std(i,ii) - n_data * ((stat(i_stat)%c_mean(i,ii))**2) ) / (n_data-1) )
  1234. if(temp > 0) then
  1235. stat(i_stat)%c_std(i,ii) = sqrt(temp)
  1236. else
  1237. stat(i_stat)%c_std(i,ii) = 0.0
  1238. endif
  1239. enddo
  1240. enddo
  1241. else
  1242. stat(i_stat)%c_std(:,:)=-1.0
  1243. end if
  1244. else
  1245. stat(i_stat)%c_mean(:,:)= -1.0
  1246. stat(i_stat)%c_std(:,:) = -1.0
  1247. end if
  1248. End Do
  1249. End If
  1250. ! Write down wind directions
  1251. if(output_stations_meteo) then
  1252. Do i_stat=1,n_stat+n_stat2
  1253. windspeed_u_interpol = stat(i_stat)%metdat(3)
  1254. windspeed_v_interpol = stat(i_stat)%metdat(4)
  1255. windspeed_interpol = stat(i_stat)%metdat(5)
  1256. !====================================
  1257. ! wind direction
  1258. !====================================
  1259. ! definition of winddirection:
  1260. ! east : 90
  1261. ! south : 180
  1262. ! west : 270
  1263. ! north : 360
  1264. if ((windspeed_u_interpol < 0) .and. (windspeed_v_interpol < 0))then ! wind from north east (0...90)
  1265. winddir_interpol = atan(windspeed_u_interpol / windspeed_v_interpol) * 360.0 / twopi
  1266. else if ((windspeed_u_interpol < 0) .and. (windspeed_v_interpol > 0)) then ! wind from south east (90...180)
  1267. winddir_interpol = 180.0+atan(windspeed_u_interpol / windspeed_v_interpol) * 360.0 / twopi
  1268. else if ((windspeed_u_interpol < 0) .and. (windspeed_v_interpol == 0)) then ! wind from east (90)
  1269. winddir_interpol = 90.0
  1270. else if ((windspeed_u_interpol > 0) .and. (windspeed_v_interpol < 0)) then ! wind from north west (270... 360)
  1271. winddir_interpol = 360.0+atan(windspeed_u_interpol / windspeed_v_interpol) * 360.0 / twopi
  1272. else if ((windspeed_u_interpol > 0) .and. (windspeed_v_interpol > 0)) then ! wind from south west (180...270)
  1273. winddir_interpol = 180.0+atan(windspeed_u_interpol / windspeed_v_interpol) * 360.0 / twopi
  1274. else if ((windspeed_u_interpol > 0) .and. (windspeed_v_interpol == 0)) then ! wind from west (270)
  1275. winddir_interpol = 270.0
  1276. else if ((windspeed_u_interpol == 0) .and. (windspeed_v_interpol < 0)) then ! wind from north (360)
  1277. winddir_interpol = 360.0
  1278. else if ((windspeed_u_interpol == 0) .and. (windspeed_v_interpol > 0)) then ! wind from south (180)
  1279. winddir_interpol = 180.0
  1280. else if ((windspeed_u_interpol == 0) .and. (windspeed_v_interpol == 0)) then ! no wind
  1281. winddir_interpol = -1.0
  1282. else
  1283. call escape_tm('output_stationconc: error wind direction')
  1284. end if
  1285. stat(i_stat)%metdat(6) = winddir_interpol
  1286. end do
  1287. endif
  1288. !ok
  1289. status = 0
  1290. END SUBROUTINE EVALUATE_STATIONCONC
  1291. !EOC
  1292. !--------------------------------------------------------------------------
  1293. ! TM5 !
  1294. !--------------------------------------------------------------------------
  1295. !BOP
  1296. !
  1297. ! !IROUTINE: WRITE_STATIONCONC
  1298. !
  1299. ! !DESCRIPTION: write mean concentration
  1300. !\\
  1301. !\\
  1302. ! !INTERFACE:
  1303. !
  1304. SUBROUTINE WRITE_STATIONCONC( status )
  1305. !
  1306. ! !USES:
  1307. !
  1308. use dims, only : idate
  1309. use file_hdf, only : Init, WriteData, TSds, Done
  1310. use file_hdf, only : WriteAttribute
  1311. use toolbox, only : escape_tm
  1312. !
  1313. ! !INPUT/OUTPUT PARAMETERS:
  1314. !
  1315. integer, intent(inout) :: status
  1316. !
  1317. ! !REVISION HISTORY:
  1318. !
  1319. !EOP
  1320. !------------------------------------------------------------------------
  1321. !BOC
  1322. integer i, ii, io_status, i_stat
  1323. integer n_data, isds, nsds, itp
  1324. real, dimension(:,:), allocatable :: cout ! to get output
  1325. integer, dimension(:,:), allocatable :: iidate
  1326. character(len=*), parameter :: rname = mname//'/write_stationconc'
  1327. !__START_SUBROUTINE______________________________________________________
  1328. ! output
  1329. if (io_record == 0) then
  1330. call WriteAttribute( io_hdf, 'station_ls', stat(:)%ls, status)
  1331. IF_NOTOK_RETURN(status=1)
  1332. call WriteAttribute( io_hdf, 'height_sample', stat(:)%height_sample, status)
  1333. IF_NOTOK_RETURN(status=1)
  1334. call WriteAttribute( io_hdf, 'height_surface', stat(:)%height_surface, status)
  1335. IF_NOTOK_RETURN(status=1)
  1336. call WriteAttribute( io_hdf, 'height_sample_above_surf', stat(:)%height_sample_above_surf, status)
  1337. IF_NOTOK_RETURN(status=1)
  1338. endif
  1339. allocate(cout(n_stat+n_stat2,1))
  1340. If (station_nspec > 0) Then
  1341. do i=1, station_nspec
  1342. do ii= 1,n_interpol
  1343. do i_stat = 1, n_stat+n_stat2
  1344. cout(i_stat,1) = stat(i_stat)%c_mean(i,ii)
  1345. enddo
  1346. call writedata(sds(i,ii), cout, status, start=(/0,io_record/))
  1347. IF_NOTOK_RETURN(status=1)
  1348. enddo
  1349. enddo
  1350. End If
  1351. if (output_stations_meteo) then
  1352. do i=1, n_metdat
  1353. do i_stat = 1, n_stat+n_stat2
  1354. cout(i_stat,1) = stat(i_stat)%metdat(i)
  1355. enddo
  1356. call writedata(sds_meteo(i), cout, status, start=(/0,io_record/))
  1357. IF_NOTOK_RETURN(status=1)
  1358. enddo
  1359. endif
  1360. deallocate(cout)
  1361. allocate(iidate(6,1))
  1362. iidate(:,1) = idate
  1363. call writedata(sds_idate, iidate, status, start=(/0,io_record/) )
  1364. IF_NOTOK_RETURN(status=1)
  1365. deallocate(iidate)
  1366. io_record = io_record + 1
  1367. ! ok
  1368. status = 0
  1369. END SUBROUTINE WRITE_STATIONCONC
  1370. !EOC
  1371. END MODULE USER_OUTPUT_STATION