iom.F90 100 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952
  1. MODULE iom
  2. !!=====================================================================
  3. !! *** MODULE iom ***
  4. !! Input/Output manager : Library to read input files
  5. !!====================================================================
  6. !! History : 2.0 ! 2005-12 (J. Belier) Original code
  7. !! 2.0 ! 2006-02 (S. Masson) Adaptation to NEMO
  8. !! 3.0 ! 2007-07 (D. Storkey) Changes to iom_gettime
  9. !! 3.4 ! 2012-12 (R. Bourdalle-Badie and G. Reffray) add C1D case
  10. !!--------------------------------------------------------------------
  11. !!--------------------------------------------------------------------
  12. !! iom_open : open a file read only
  13. !! iom_close : close a file or all files opened by iom
  14. !! iom_get : read a field (interfaced to several routines)
  15. !! iom_gettime : read the time axis cdvar in the file
  16. !! iom_varid : get the id of a variable in a file
  17. !! iom_rstput : write a field in a restart file (interfaced to several routines)
  18. !!--------------------------------------------------------------------
  19. USE dom_oce ! ocean space and time domain
  20. USE c1d ! 1D vertical configuration
  21. USE flo_oce ! floats module declarations
  22. USE lbclnk ! lateal boundary condition / mpp exchanges
  23. USE iom_def ! iom variables definitions
  24. USE iom_ioipsl ! NetCDF format with IOIPSL library
  25. USE iom_nf90 ! NetCDF format with native NetCDF library
  26. USE iom_rstdimg ! restarts access direct format "dimg" style...
  27. USE in_out_manager ! I/O manager
  28. USE lib_mpp ! MPP library
  29. #if defined key_iomput
  30. USE sbc_oce, ONLY : nn_fsbc ! ocean space and time domain
  31. USE trc_oce, ONLY : nn_dttrc ! !: frequency of step on passive tracers
  32. USE icb_oce, ONLY : nclasses, class_num ! !: iceberg classes
  33. #if defined key_lim3
  34. USE ice , ONLY : jpl
  35. #elif defined key_lim2
  36. USE par_ice_2
  37. #endif
  38. USE domngb ! ocean space and time domain
  39. USE phycst ! physical constants
  40. USE dianam ! build name of file
  41. USE xios
  42. # endif
  43. USE ioipsl, ONLY : ju2ymds ! for calendar
  44. USE crs ! Grid coarsening
  45. IMPLICIT NONE
  46. PUBLIC ! must be public to be able to access iom_def through iom
  47. #if defined key_iomput
  48. LOGICAL, PUBLIC, PARAMETER :: lk_iomput = .TRUE. !: iom_put flag
  49. #else
  50. LOGICAL, PUBLIC, PARAMETER :: lk_iomput = .FALSE. !: iom_put flag
  51. #endif
  52. PUBLIC iom_init, iom_swap, iom_open, iom_close, iom_setkt, iom_varid, iom_get, iom_gettime, iom_rstput, iom_put
  53. PUBLIC iom_getatt, iom_use, iom_context_finalize
  54. PRIVATE iom_rp0d, iom_rp1d, iom_rp2d, iom_rp3d
  55. PRIVATE iom_g0d, iom_g1d, iom_g2d, iom_g3d, iom_get_123d
  56. PRIVATE iom_p1d, iom_p2d, iom_p3d
  57. #if defined key_iomput
  58. PRIVATE iom_set_domain_attr, iom_set_axis_attr, iom_set_field_attr, iom_set_file_attr, iom_get_file_attr, iom_set_grid_attr
  59. PRIVATE set_grid, set_grid_bounds, set_scalar, set_xmlatt, set_mooring, iom_update_file_name, iom_sdate
  60. # endif
  61. INTERFACE iom_get
  62. MODULE PROCEDURE iom_g0d, iom_g1d, iom_g2d, iom_g3d
  63. END INTERFACE
  64. INTERFACE iom_getatt
  65. MODULE PROCEDURE iom_g0d_intatt
  66. END INTERFACE
  67. INTERFACE iom_rstput
  68. MODULE PROCEDURE iom_rp0d, iom_rp1d, iom_rp2d, iom_rp3d
  69. END INTERFACE
  70. INTERFACE iom_put
  71. MODULE PROCEDURE iom_p0d, iom_p1d, iom_p2d, iom_p3d
  72. END INTERFACE
  73. !!----------------------------------------------------------------------
  74. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  75. !! $Id: iom.F90 4990 2014-12-15 16:42:49Z timgraham $
  76. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  77. !!----------------------------------------------------------------------
  78. CONTAINS
  79. SUBROUTINE iom_init( cdname )
  80. !!----------------------------------------------------------------------
  81. !! *** ROUTINE ***
  82. !!
  83. !! ** Purpose :
  84. !!
  85. !!----------------------------------------------------------------------
  86. CHARACTER(len=*), INTENT(in) :: cdname
  87. #if defined key_iomput
  88. #if ! defined key_xios2
  89. TYPE(xios_time) :: dtime = xios_time(0, 0, 0, 0, 0, 0)
  90. CHARACTER(len=19) :: cldate
  91. #else
  92. TYPE(xios_duration) :: dtime = xios_duration(0, 0, 0, 0, 0, 0)
  93. TYPE(xios_date) :: start_date
  94. #endif
  95. CHARACTER(len=10) :: clname
  96. INTEGER :: ji
  97. !
  98. REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: z_bnds
  99. !!----------------------------------------------------------------------
  100. #if ! defined key_xios2
  101. ALLOCATE( z_bnds(jpk,2) )
  102. #else
  103. ALLOCATE( z_bnds(2,jpk) )
  104. #endif
  105. clname = cdname
  106. IF( TRIM(Agrif_CFixed()) /= '0' ) clname = TRIM(Agrif_CFixed())//"_"//TRIM(cdname)
  107. CALL xios_context_initialize(TRIM(clname), mpi_comm_opa)
  108. CALL iom_swap( cdname )
  109. ! calendar parameters
  110. #if ! defined key_xios2
  111. SELECT CASE ( nleapy ) ! Choose calendar for IOIPSL
  112. CASE ( 1) ; CALL xios_set_context_attr(TRIM(clname), calendar_type= "Gregorian")
  113. CASE ( 0) ; CALL xios_set_context_attr(TRIM(clname), calendar_type= "NoLeap")
  114. CASE (30) ; CALL xios_set_context_attr(TRIM(clname), calendar_type= "D360")
  115. END SELECT
  116. WRITE(cldate,"(i4.4,'-',i2.2,'-',i2.2,' 00:00:00')") nyear,nmonth,nday
  117. CALL xios_set_context_attr(TRIM(clname), start_date=cldate )
  118. #else
  119. ! Calendar type is now defined in xml file
  120. SELECT CASE ( nleapy ) ! Choose calendar for IOIPSL
  121. CASE ( 1) ; CALL xios_define_calendar( TYPE = "Gregorian", time_origin = xios_date(1900,01,01,00,00,00), &
  122. & start_date = xios_date(nyear,nmonth,nday,0,0,0) )
  123. CASE ( 0) ; CALL xios_define_calendar( TYPE = "NoLeap" , time_origin = xios_date(1900,01,01,00,00,00), &
  124. & start_date = xios_date(nyear,nmonth,nday,0,0,0) )
  125. CASE (30) ; CALL xios_define_calendar( TYPE = "D360" , time_origin = xios_date(1900,01,01,00,00,00), &
  126. & start_date = xios_date(nyear,nmonth,nday,0,0,0) )
  127. END SELECT
  128. #endif
  129. ! horizontal grid definition
  130. CALL set_scalar
  131. IF( TRIM(cdname) == TRIM(cxios_context) ) THEN
  132. CALL set_grid( "T", glamt, gphit )
  133. CALL set_grid( "U", glamu, gphiu )
  134. CALL set_grid( "V", glamv, gphiv )
  135. CALL set_grid( "W", glamt, gphit )
  136. CALL set_grid_znl( gphit )
  137. !
  138. IF( ln_cfmeta ) THEN ! Add additional grid metadata
  139. CALL iom_set_domain_attr("grid_T", area = e12t(nldi:nlei, nldj:nlej))
  140. CALL iom_set_domain_attr("grid_U", area = e12u(nldi:nlei, nldj:nlej))
  141. CALL iom_set_domain_attr("grid_V", area = e12v(nldi:nlei, nldj:nlej))
  142. CALL iom_set_domain_attr("grid_W", area = e12t(nldi:nlei, nldj:nlej))
  143. CALL set_grid_bounds( "T", glamf, gphif, glamt, gphit )
  144. CALL set_grid_bounds( "U", glamv, gphiv, glamu, gphiu )
  145. CALL set_grid_bounds( "V", glamu, gphiu, glamv, gphiv )
  146. CALL set_grid_bounds( "W", glamf, gphif, glamt, gphit )
  147. ENDIF
  148. ENDIF
  149. IF( TRIM(cdname) == TRIM(cxios_context)//"_crs" ) THEN
  150. CALL dom_grid_crs ! Save the parent grid information & Switch to coarse grid domain
  151. !
  152. CALL set_grid( "T", glamt_crs, gphit_crs )
  153. CALL set_grid( "U", glamu_crs, gphiu_crs )
  154. CALL set_grid( "V", glamv_crs, gphiv_crs )
  155. CALL set_grid( "W", glamt_crs, gphit_crs )
  156. CALL set_grid_znl( gphit_crs )
  157. !
  158. CALL dom_grid_glo ! Return to parent grid domain
  159. !
  160. IF( ln_cfmeta ) THEN ! Add additional grid metadata
  161. CALL iom_set_domain_attr("grid_T", area = e1e2t_crs(nldi:nlei, nldj:nlej))
  162. CALL iom_set_domain_attr("grid_U", area = e1u_crs(nldi:nlei, nldj:nlej) * e2u_crs(nldi:nlei, nldj:nlej))
  163. CALL iom_set_domain_attr("grid_V", area = e1v_crs(nldi:nlei, nldj:nlej) * e2v_crs(nldi:nlei, nldj:nlej))
  164. CALL iom_set_domain_attr("grid_W", area = e1e2t_crs(nldi:nlei, nldj:nlej))
  165. CALL set_grid_bounds( "T", glamf_crs, gphif_crs, glamt_crs, gphit_crs )
  166. CALL set_grid_bounds( "U", glamv_crs, gphiv_crs, glamu_crs, gphiu_crs )
  167. CALL set_grid_bounds( "V", glamu_crs, gphiu_crs, glamv_crs, gphiv_crs )
  168. CALL set_grid_bounds( "W", glamf_crs, gphif_crs, glamt_crs, gphit_crs )
  169. ENDIF
  170. ENDIF
  171. ! vertical grid definition
  172. CALL iom_set_axis_attr( "deptht", gdept_1d )
  173. CALL iom_set_axis_attr( "depthu", gdept_1d )
  174. CALL iom_set_axis_attr( "depthv", gdept_1d )
  175. CALL iom_set_axis_attr( "depthw", gdepw_1d )
  176. ! Add vertical grid bounds
  177. #if ! defined key_xios2
  178. z_bnds(: ,1) = gdepw_1d(:)
  179. z_bnds(1:jpkm1,2) = gdepw_1d(2:jpk)
  180. z_bnds(jpk: ,2) = gdepw_1d(jpk) + e3t_1d(jpk)
  181. #else
  182. z_bnds(1 ,:) = gdepw_1d(:)
  183. z_bnds(2,1:jpkm1) = gdepw_1d(2:jpk)
  184. z_bnds(2,jpk: ) = gdepw_1d(jpk) + e3t_1d(jpk)
  185. #endif
  186. CALL iom_set_axis_attr( "deptht", bounds=z_bnds )
  187. CALL iom_set_axis_attr( "depthu", bounds=z_bnds )
  188. CALL iom_set_axis_attr( "depthv", bounds=z_bnds )
  189. #if ! defined key_xios2
  190. z_bnds(: ,2) = gdept_1d(:)
  191. z_bnds(2:jpk,1) = gdept_1d(1:jpkm1)
  192. z_bnds(1 ,1) = gdept_1d(1) - e3w_1d(1)
  193. #else
  194. z_bnds(2,: ) = gdept_1d(:)
  195. z_bnds(1,2:jpk) = gdept_1d(1:jpkm1)
  196. z_bnds(1,1 ) = gdept_1d(1) - e3w_1d(1)
  197. #endif
  198. CALL iom_set_axis_attr( "depthw", bounds=z_bnds )
  199. # if defined key_floats
  200. CALL iom_set_axis_attr( "nfloat", (/ (REAL(ji,wp), ji=1, jpnfl) /) )
  201. # endif
  202. #if defined key_lim3 || defined key_lim2
  203. CALL iom_set_axis_attr( "ncatice", (/ (REAL(ji,wp), ji=1,jpl) /) )
  204. #endif
  205. CALL iom_set_axis_attr( "icbcla", class_num )
  206. CALL iom_set_axis_attr( "iax_20C", (/ REAL(20,wp) /) )
  207. CALL iom_set_axis_attr( "iax_28C", (/ REAL(28,wp) /) )
  208. ! automatic definitions of some of the xml attributs
  209. CALL set_xmlatt
  210. CALL set_1point
  211. ! end file definition
  212. dtime%second = rdt
  213. CALL xios_set_timestep(dtime)
  214. CALL xios_close_context_definition()
  215. CALL xios_update_calendar(0)
  216. DEALLOCATE( z_bnds )
  217. #endif
  218. END SUBROUTINE iom_init
  219. SUBROUTINE iom_swap( cdname )
  220. !!---------------------------------------------------------------------
  221. !! *** SUBROUTINE iom_swap ***
  222. !!
  223. !! ** Purpose : swap context between different agrif grid for xmlio_server
  224. !!---------------------------------------------------------------------
  225. CHARACTER(len=*), INTENT(in) :: cdname
  226. #if defined key_iomput
  227. TYPE(xios_context) :: nemo_hdl
  228. IF( TRIM(Agrif_CFixed()) == '0' ) THEN
  229. CALL xios_get_handle(TRIM(cdname),nemo_hdl)
  230. ELSE
  231. CALL xios_get_handle(TRIM(Agrif_CFixed())//"_"//TRIM(cdname),nemo_hdl)
  232. ENDIF
  233. !
  234. CALL xios_set_current_context(nemo_hdl)
  235. #endif
  236. !
  237. END SUBROUTINE iom_swap
  238. SUBROUTINE iom_open( cdname, kiomid, ldwrt, kdom, kiolib, ldstop, ldiof )
  239. !!---------------------------------------------------------------------
  240. !! *** SUBROUTINE iom_open ***
  241. !!
  242. !! ** Purpose : open an input file (return 0 if not found)
  243. !!---------------------------------------------------------------------
  244. CHARACTER(len=*), INTENT(in ) :: cdname ! File name
  245. INTEGER , INTENT( out) :: kiomid ! iom identifier of the opened file
  246. LOGICAL , INTENT(in ), OPTIONAL :: ldwrt ! open in write modeb (default = .FALSE.)
  247. INTEGER , INTENT(in ), OPTIONAL :: kdom ! Type of domain to be written (default = jpdom_local_noovlap)
  248. INTEGER , INTENT(in ), OPTIONAL :: kiolib ! library used to open the file (default = jpnf90)
  249. LOGICAL , INTENT(in ), OPTIONAL :: ldstop ! stop if open to read a non-existing file (default = .TRUE.)
  250. LOGICAL , INTENT(in ), OPTIONAL :: ldiof ! Interp On the Fly, needed for AGRIF (default = .FALSE.)
  251. CHARACTER(LEN=256) :: clname ! the name of the file based on cdname [[+clcpu]+clcpu]
  252. CHARACTER(LEN=256) :: cltmpn ! tempory name to store clname (in writting mode)
  253. CHARACTER(LEN=10) :: clsuffix ! ".nc" or ".dimg"
  254. CHARACTER(LEN=15) :: clcpu ! the cpu number (max jpmax_digits digits)
  255. CHARACTER(LEN=256) :: clinfo ! info character
  256. LOGICAL :: llok ! check the existence
  257. LOGICAL :: llwrt ! local definition of ldwrt
  258. LOGICAL :: llnoov ! local definition to read overlap
  259. LOGICAL :: llstop ! local definition of ldstop
  260. LOGICAL :: lliof ! local definition of ldiof
  261. INTEGER :: iolib ! library do we use to open the file
  262. INTEGER :: icnt ! counter for digits in clcpu (max = jpmax_digits)
  263. INTEGER :: iln, ils ! lengths of character
  264. INTEGER :: idom ! type of domain
  265. INTEGER :: istop !
  266. INTEGER, DIMENSION(2,5) :: idompar ! domain parameters:
  267. ! local number of points for x,y dimensions
  268. ! position of first local point for x,y dimensions
  269. ! position of last local point for x,y dimensions
  270. ! start halo size for x,y dimensions
  271. ! end halo size for x,y dimensions
  272. !---------------------------------------------------------------------
  273. ! Initializations and control
  274. ! =============
  275. kiomid = -1
  276. clinfo = ' iom_open ~~~ '
  277. istop = nstop
  278. ! if iom_open is called for the first time: initialize iom_file(:)%nfid to 0
  279. ! (could be done when defining iom_file in f95 but not in f90)
  280. IF( Agrif_Root() ) THEN
  281. IF( iom_open_init == 0 ) THEN
  282. iom_file(:)%nfid = 0
  283. iom_open_init = 1
  284. ENDIF
  285. ENDIF
  286. ! do we read or write the file?
  287. IF( PRESENT(ldwrt) ) THEN ; llwrt = ldwrt
  288. ELSE ; llwrt = .FALSE.
  289. ENDIF
  290. ! do we call ctl_stop if we try to open a non-existing file in read mode?
  291. IF( PRESENT(ldstop) ) THEN ; llstop = ldstop
  292. ELSE ; llstop = .TRUE.
  293. ENDIF
  294. ! what library do we use to open the file?
  295. IF( PRESENT(kiolib) ) THEN ; iolib = kiolib
  296. ELSE ; iolib = jpnf90
  297. ENDIF
  298. ! are we using interpolation on the fly?
  299. IF( PRESENT(ldiof) ) THEN ; lliof = ldiof
  300. ELSE ; lliof = .FALSE.
  301. ENDIF
  302. ! do we read the overlap
  303. ! ugly patch SM+JMM+RB to overwrite global definition in some cases
  304. llnoov = (jpni * jpnj ) == jpnij .AND. .NOT. lk_agrif
  305. ! create the file name by added, if needed, TRIM(Agrif_CFixed()) and TRIM(clsuffix)
  306. ! =============
  307. clname = trim(cdname)
  308. IF ( .NOT. Agrif_Root() .AND. .NOT. lliof ) THEN
  309. iln = INDEX(clname,'/')
  310. cltmpn = clname(1:iln)
  311. clname = clname(iln+1:LEN_TRIM(clname))
  312. clname=TRIM(cltmpn)//TRIM(Agrif_CFixed())//'_'//TRIM(clname)
  313. ENDIF
  314. ! which suffix should we use?
  315. SELECT CASE (iolib)
  316. CASE (jpioipsl ) ; clsuffix = '.nc'
  317. CASE (jpnf90 ) ; clsuffix = '.nc'
  318. CASE (jprstdimg) ; clsuffix = '.dimg'
  319. CASE DEFAULT ; clsuffix = ''
  320. CALL ctl_stop( TRIM(clinfo), 'accepted IO library are only jpioipsl, jpnf90 and jprstdimg' )
  321. END SELECT
  322. ! Add the suffix if needed
  323. iln = LEN_TRIM(clname)
  324. ils = LEN_TRIM(clsuffix)
  325. IF( iln <= ils .OR. INDEX( TRIM(clname), TRIM(clsuffix), back = .TRUE. ) /= iln - ils + 1 ) &
  326. & clname = TRIM(clname)//TRIM(clsuffix)
  327. cltmpn = clname ! store this name
  328. ! try to find if the file to be opened already exist
  329. ! =============
  330. INQUIRE( FILE = clname, EXIST = llok )
  331. IF( .NOT.llok ) THEN
  332. ! we try to add the cpu number to the name
  333. IF( iolib == jprstdimg ) THEN ; WRITE(clcpu,*) narea
  334. ELSE ; WRITE(clcpu,*) narea-1
  335. ENDIF
  336. clcpu = TRIM(ADJUSTL(clcpu))
  337. iln = INDEX(clname,TRIM(clsuffix), back = .TRUE.)
  338. clname = clname(1:iln-1)//'_'//TRIM(clcpu)//TRIM(clsuffix)
  339. icnt = 0
  340. INQUIRE( FILE = clname, EXIST = llok )
  341. ! we try different formats for the cpu number by adding 0
  342. DO WHILE( .NOT.llok .AND. icnt < jpmax_digits )
  343. clcpu = "0"//trim(clcpu)
  344. clname = clname(1:iln-1)//'_'//TRIM(clcpu)//TRIM(clsuffix)
  345. INQUIRE( FILE = clname, EXIST = llok )
  346. icnt = icnt + 1
  347. END DO
  348. ENDIF
  349. IF( llwrt ) THEN
  350. ! check the domain definition
  351. ! JMM + SM: ugly patch before getting the new version of lib_mpp)
  352. ! idom = jpdom_local_noovlap ! default definition
  353. IF( llnoov ) THEN ; idom = jpdom_local_noovlap ! default definition
  354. ELSE ; idom = jpdom_local_full ! default definition
  355. ENDIF
  356. IF( PRESENT(kdom) ) idom = kdom
  357. ! create the domain informations
  358. ! =============
  359. SELECT CASE (idom)
  360. CASE (jpdom_local_full)
  361. idompar(:,1) = (/ jpi , jpj /)
  362. idompar(:,2) = (/ nimpp , njmpp /)
  363. idompar(:,3) = (/ nimpp + jpi - 1 , njmpp + jpj - 1 /)
  364. idompar(:,4) = (/ nldi - 1 , nldj - 1 /)
  365. idompar(:,5) = (/ jpi - nlei , jpj - nlej /)
  366. CASE (jpdom_local_noextra)
  367. idompar(:,1) = (/ nlci , nlcj /)
  368. idompar(:,2) = (/ nimpp , njmpp /)
  369. idompar(:,3) = (/ nimpp + nlci - 1, njmpp + nlcj - 1 /)
  370. idompar(:,4) = (/ nldi - 1 , nldj - 1 /)
  371. idompar(:,5) = (/ nlci - nlei , nlcj - nlej /)
  372. CASE (jpdom_local_noovlap)
  373. idompar(:,1) = (/ nlei - nldi + 1, nlej - nldj + 1 /)
  374. idompar(:,2) = (/ nimpp + nldi - 1, njmpp + nldj - 1 /)
  375. idompar(:,3) = (/ nimpp + nlei - 1, njmpp + nlej - 1 /)
  376. idompar(:,4) = (/ 0 , 0 /)
  377. idompar(:,5) = (/ 0 , 0 /)
  378. CASE DEFAULT
  379. CALL ctl_stop( TRIM(clinfo), 'wrong value of kdom, only jpdom_local* cases are accepted' )
  380. END SELECT
  381. ENDIF
  382. ! Open the NetCDF or RSTDIMG file
  383. ! =============
  384. ! do we have some free file identifier?
  385. IF( MINVAL(iom_file(:)%nfid) /= 0 ) &
  386. & CALL ctl_stop( TRIM(clinfo), 'No more free file identifier', 'increase jpmax_files in iom_def' )
  387. ! if no file was found...
  388. IF( .NOT. llok ) THEN
  389. IF( .NOT. llwrt ) THEN ! we are in read mode
  390. IF( llstop ) THEN ; CALL ctl_stop( TRIM(clinfo), 'File '//TRIM(cltmpn)//'* not found' )
  391. ELSE ; istop = nstop + 1 ! make sure that istop /= nstop so we don't open the file
  392. ENDIF
  393. ELSE ! we are in write mode so we
  394. clname = cltmpn ! get back the file name without the cpu number
  395. ENDIF
  396. ELSE
  397. IF( llwrt .AND. .NOT. ln_clobber ) THEN ! we stop as we want to write in a new file
  398. CALL ctl_stop( TRIM(clinfo), 'We want to write in a new file but '//TRIM(clname)//' already exists...' )
  399. istop = nstop + 1 ! make sure that istop /= nstop so we don't open the file
  400. ELSEIF( llwrt ) THEN ! the file exists and we are in write mode with permission to
  401. clname = cltmpn ! overwrite so get back the file name without the cpu number
  402. ENDIF
  403. ENDIF
  404. IF( istop == nstop ) THEN ! no error within this routine
  405. SELECT CASE (iolib)
  406. CASE (jpioipsl ) ; CALL iom_ioipsl_open( clname, kiomid, llwrt, llok, idompar )
  407. CASE (jpnf90 ) ; CALL iom_nf90_open( clname, kiomid, llwrt, llok, idompar )
  408. CASE (jprstdimg) ; CALL iom_rstdimg_open( clname, kiomid, llwrt, llok, idompar )
  409. CASE DEFAULT
  410. CALL ctl_stop( TRIM(clinfo)//' accepted IO library are only jpioipsl, jpnf90 and jprstdimg' )
  411. END SELECT
  412. ENDIF
  413. !
  414. END SUBROUTINE iom_open
  415. SUBROUTINE iom_close( kiomid )
  416. !!--------------------------------------------------------------------
  417. !! *** SUBROUTINE iom_close ***
  418. !!
  419. !! ** Purpose : close an input file, or all files opened by iom
  420. !!--------------------------------------------------------------------
  421. INTEGER, INTENT(inout), OPTIONAL :: kiomid ! iom identifier of the file to be closed
  422. ! ! return 0 when file is properly closed
  423. ! ! No argument: all files opened by iom are closed
  424. INTEGER :: jf ! dummy loop indices
  425. INTEGER :: i_s, i_e ! temporary integer
  426. CHARACTER(LEN=100) :: clinfo ! info character
  427. !---------------------------------------------------------------------
  428. !
  429. clinfo = ' iom_close ~~~ '
  430. IF( PRESENT(kiomid) ) THEN
  431. i_s = kiomid
  432. i_e = kiomid
  433. ELSE
  434. i_s = 1
  435. i_e = jpmax_files
  436. ENDIF
  437. IF( i_s > 0 ) THEN
  438. DO jf = i_s, i_e
  439. IF( iom_file(jf)%nfid > 0 ) THEN
  440. SELECT CASE (iom_file(jf)%iolib)
  441. CASE (jpioipsl ) ; CALL iom_ioipsl_close( jf )
  442. CASE (jpnf90 ) ; CALL iom_nf90_close( jf )
  443. CASE (jprstdimg) ; CALL iom_rstdimg_close( jf )
  444. CASE DEFAULT
  445. CALL ctl_stop( TRIM(clinfo)//' accepted IO library are only jpioipsl, jpnf90 and jprstdimg' )
  446. END SELECT
  447. iom_file(jf)%nfid = 0 ! free the id
  448. IF( PRESENT(kiomid) ) kiomid = 0 ! return 0 as id to specify that the file was closed
  449. IF(lwp) WRITE(numout,*) TRIM(clinfo)//' close file: '//TRIM(iom_file(jf)%name)//' ok'
  450. ELSEIF( PRESENT(kiomid) ) THEN
  451. WRITE(ctmp1,*) '--->', kiomid
  452. CALL ctl_stop( TRIM(clinfo)//' Invalid file identifier', ctmp1 )
  453. ENDIF
  454. END DO
  455. ENDIF
  456. !
  457. END SUBROUTINE iom_close
  458. FUNCTION iom_varid ( kiomid, cdvar, kdimsz, kndims, ldstop )
  459. !!-----------------------------------------------------------------------
  460. !! *** FUNCTION iom_varid ***
  461. !!
  462. !! ** Purpose : get the id of a variable in a file (return 0 if not found)
  463. !!-----------------------------------------------------------------------
  464. INTEGER , INTENT(in ) :: kiomid ! file Identifier
  465. CHARACTER(len=*) , INTENT(in ) :: cdvar ! name of the variable
  466. INTEGER, DIMENSION(:), INTENT( out), OPTIONAL :: kdimsz ! size of the dimensions
  467. INTEGER, INTENT( out), OPTIONAL :: kndims ! size of the dimensions
  468. LOGICAL , INTENT(in ), OPTIONAL :: ldstop ! stop if looking for non-existing variable (default = .TRUE.)
  469. !
  470. INTEGER :: iom_varid, iiv, i_nvd
  471. LOGICAL :: ll_fnd
  472. CHARACTER(LEN=100) :: clinfo ! info character
  473. LOGICAL :: llstop ! local definition of ldstop
  474. !!-----------------------------------------------------------------------
  475. iom_varid = 0 ! default definition
  476. ! do we call ctl_stop if we look for non-existing variable?
  477. IF( PRESENT(ldstop) ) THEN ; llstop = ldstop
  478. ELSE ; llstop = .TRUE.
  479. ENDIF
  480. !
  481. IF( kiomid > 0 ) THEN
  482. clinfo = 'iom_varid, file: '//trim(iom_file(kiomid)%name)//', var: '//trim(cdvar)
  483. IF( iom_file(kiomid)%nfid == 0 ) THEN
  484. CALL ctl_stop( trim(clinfo), 'the file is not open' )
  485. ELSE
  486. ll_fnd = .FALSE.
  487. iiv = 0
  488. !
  489. DO WHILE ( .NOT.ll_fnd .AND. iiv < iom_file(kiomid)%nvars )
  490. iiv = iiv + 1
  491. ll_fnd = ( TRIM(cdvar) == TRIM(iom_file(kiomid)%cn_var(iiv)) )
  492. END DO
  493. !
  494. IF( .NOT.ll_fnd ) THEN
  495. iiv = iiv + 1
  496. IF( iiv <= jpmax_vars ) THEN
  497. SELECT CASE (iom_file(kiomid)%iolib)
  498. CASE (jpioipsl ) ; iom_varid = iom_ioipsl_varid( kiomid, cdvar, iiv, kdimsz )
  499. CASE (jpnf90 ) ; iom_varid = iom_nf90_varid ( kiomid, cdvar, iiv, kdimsz, kndims )
  500. CASE (jprstdimg) ; iom_varid = -1 ! all variables are listed in iom_file
  501. CASE DEFAULT
  502. CALL ctl_stop( TRIM(clinfo)//' accepted IO library are only jpioipsl, jpnf90 and jprstdimg' )
  503. END SELECT
  504. ELSE
  505. CALL ctl_stop( trim(clinfo), 'Too many variables in the file '//iom_file(kiomid)%name, &
  506. & 'increase the parameter jpmax_vars')
  507. ENDIF
  508. IF( llstop .AND. iom_varid == -1 ) CALL ctl_stop( TRIM(clinfo)//' not found' )
  509. ELSE
  510. iom_varid = iiv
  511. IF( PRESENT(kdimsz) ) THEN
  512. i_nvd = iom_file(kiomid)%ndims(iiv)
  513. IF( i_nvd == size(kdimsz) ) THEN
  514. kdimsz(:) = iom_file(kiomid)%dimsz(1:i_nvd,iiv)
  515. ELSE
  516. WRITE(ctmp1,*) i_nvd, size(kdimsz)
  517. CALL ctl_stop( trim(clinfo), 'error in kdimsz size'//trim(ctmp1) )
  518. ENDIF
  519. ENDIF
  520. IF( PRESENT(kndims) ) kndims = iom_file(kiomid)%ndims(iiv)
  521. ENDIF
  522. ENDIF
  523. ENDIF
  524. !
  525. END FUNCTION iom_varid
  526. !!----------------------------------------------------------------------
  527. !! INTERFACE iom_get
  528. !!----------------------------------------------------------------------
  529. SUBROUTINE iom_g0d( kiomid, cdvar, pvar, ktime )
  530. INTEGER , INTENT(in ) :: kiomid ! Identifier of the file
  531. CHARACTER(len=*), INTENT(in ) :: cdvar ! Name of the variable
  532. REAL(wp) , INTENT( out) :: pvar ! read field
  533. INTEGER , INTENT(in ), OPTIONAL :: ktime ! record number
  534. !
  535. INTEGER :: idvar ! variable id
  536. INTEGER :: idmspc ! number of spatial dimensions
  537. INTEGER , DIMENSION(1) :: itime ! record number
  538. CHARACTER(LEN=100) :: clinfo ! info character
  539. CHARACTER(LEN=100) :: clname ! file name
  540. CHARACTER(LEN=1) :: cldmspc !
  541. !
  542. itime = 1
  543. IF( PRESENT(ktime) ) itime = ktime
  544. !
  545. clname = iom_file(kiomid)%name
  546. clinfo = ' iom_g0d, file: '//trim(clname)//', var: '//trim(cdvar)
  547. !
  548. IF( kiomid > 0 ) THEN
  549. idvar = iom_varid( kiomid, cdvar )
  550. IF( iom_file(kiomid)%nfid > 0 .AND. idvar > 0 ) THEN
  551. idmspc = iom_file ( kiomid )%ndims( idvar )
  552. IF( iom_file(kiomid)%luld(idvar) ) idmspc = idmspc - 1
  553. WRITE(cldmspc , fmt='(i1)') idmspc
  554. IF( idmspc > 0 ) CALL ctl_stop( TRIM(clinfo), 'When reading to a 0D array, we do not accept data', &
  555. & 'with 1 or more spatial dimensions: '//cldmspc//' were found.' , &
  556. & 'Use ncwa -a to suppress the unnecessary dimensions' )
  557. SELECT CASE (iom_file(kiomid)%iolib)
  558. CASE (jpioipsl ) ; CALL iom_ioipsl_get( kiomid, idvar, pvar, itime )
  559. CASE (jpnf90 ) ; CALL iom_nf90_get( kiomid, idvar, pvar, itime )
  560. CASE (jprstdimg) ; CALL iom_rstdimg_get( kiomid, idvar, pvar )
  561. CASE DEFAULT
  562. CALL ctl_stop( 'iom_g0d: accepted IO library are only jpioipsl, jpnf90 and jprstdimg' )
  563. END SELECT
  564. ENDIF
  565. ENDIF
  566. END SUBROUTINE iom_g0d
  567. SUBROUTINE iom_g1d( kiomid, kdom, cdvar, pvar, ktime, kstart, kcount )
  568. INTEGER , INTENT(in ) :: kiomid ! Identifier of the file
  569. INTEGER , INTENT(in ) :: kdom ! Type of domain to be read
  570. CHARACTER(len=*), INTENT(in ) :: cdvar ! Name of the variable
  571. REAL(wp) , INTENT( out), DIMENSION(:) :: pvar ! read field
  572. INTEGER , INTENT(in ) , OPTIONAL :: ktime ! record number
  573. INTEGER , INTENT(in ), DIMENSION(1), OPTIONAL :: kstart ! start axis position of the reading
  574. INTEGER , INTENT(in ), DIMENSION(1), OPTIONAL :: kcount ! number of points in each axis
  575. !
  576. IF( kiomid > 0 ) THEN
  577. IF( iom_file(kiomid)%nfid > 0 ) CALL iom_get_123d( kiomid, kdom , cdvar , pv_r1d=pvar, &
  578. & ktime=ktime, kstart=kstart, kcount=kcount )
  579. ENDIF
  580. END SUBROUTINE iom_g1d
  581. SUBROUTINE iom_g2d( kiomid, kdom, cdvar, pvar, ktime, kstart, kcount, lrowattr )
  582. INTEGER , INTENT(in ) :: kiomid ! Identifier of the file
  583. INTEGER , INTENT(in ) :: kdom ! Type of domain to be read
  584. CHARACTER(len=*), INTENT(in ) :: cdvar ! Name of the variable
  585. REAL(wp) , INTENT( out), DIMENSION(:,:) :: pvar ! read field
  586. INTEGER , INTENT(in ) , OPTIONAL :: ktime ! record number
  587. INTEGER , INTENT(in ), DIMENSION(2) , OPTIONAL :: kstart ! start axis position of the reading
  588. INTEGER , INTENT(in ), DIMENSION(2) , OPTIONAL :: kcount ! number of points in each axis
  589. LOGICAL , INTENT(in ) , OPTIONAL :: lrowattr ! logical flag telling iom_get to
  590. ! look for and use a file attribute
  591. ! called open_ocean_jstart to set the start
  592. ! value for the 2nd dimension (netcdf only)
  593. !
  594. IF( kiomid > 0 ) THEN
  595. IF( iom_file(kiomid)%nfid > 0 ) CALL iom_get_123d( kiomid, kdom , cdvar , pv_r2d=pvar, &
  596. & ktime=ktime, kstart=kstart, kcount=kcount, &
  597. & lrowattr=lrowattr )
  598. ENDIF
  599. END SUBROUTINE iom_g2d
  600. SUBROUTINE iom_g3d( kiomid, kdom, cdvar, pvar, ktime, kstart, kcount, lrowattr )
  601. INTEGER , INTENT(in ) :: kiomid ! Identifier of the file
  602. INTEGER , INTENT(in ) :: kdom ! Type of domain to be read
  603. CHARACTER(len=*), INTENT(in ) :: cdvar ! Name of the variable
  604. REAL(wp) , INTENT( out), DIMENSION(:,:,:) :: pvar ! read field
  605. INTEGER , INTENT(in ) , OPTIONAL :: ktime ! record number
  606. INTEGER , INTENT(in ), DIMENSION(3) , OPTIONAL :: kstart ! start axis position of the reading
  607. INTEGER , INTENT(in ), DIMENSION(3) , OPTIONAL :: kcount ! number of points in each axis
  608. LOGICAL , INTENT(in ) , OPTIONAL :: lrowattr ! logical flag telling iom_get to
  609. ! look for and use a file attribute
  610. ! called open_ocean_jstart to set the start
  611. ! value for the 2nd dimension (netcdf only)
  612. !
  613. IF( kiomid > 0 ) THEN
  614. IF( iom_file(kiomid)%nfid > 0 ) CALL iom_get_123d( kiomid, kdom , cdvar , pv_r3d=pvar, &
  615. & ktime=ktime, kstart=kstart, kcount=kcount, &
  616. & lrowattr=lrowattr )
  617. ENDIF
  618. END SUBROUTINE iom_g3d
  619. !!----------------------------------------------------------------------
  620. SUBROUTINE iom_get_123d( kiomid, kdom , cdvar , &
  621. & pv_r1d, pv_r2d, pv_r3d, &
  622. & ktime , kstart, kcount, &
  623. & lrowattr )
  624. !!-----------------------------------------------------------------------
  625. !! *** ROUTINE iom_get_123d ***
  626. !!
  627. !! ** Purpose : read a 1D/2D/3D variable
  628. !!
  629. !! ** Method : read ONE record at each CALL
  630. !!-----------------------------------------------------------------------
  631. INTEGER , INTENT(in ) :: kiomid ! Identifier of the file
  632. INTEGER , INTENT(in ) :: kdom ! Type of domain to be read
  633. CHARACTER(len=*) , INTENT(in ) :: cdvar ! Name of the variable
  634. REAL(wp), DIMENSION(:) , INTENT( out), OPTIONAL :: pv_r1d ! read field (1D case)
  635. REAL(wp), DIMENSION(:,:) , INTENT( out), OPTIONAL :: pv_r2d ! read field (2D case)
  636. REAL(wp), DIMENSION(:,:,:) , INTENT( out), OPTIONAL :: pv_r3d ! read field (3D case)
  637. INTEGER , INTENT(in ), OPTIONAL :: ktime ! record number
  638. INTEGER , DIMENSION(:) , INTENT(in ), OPTIONAL :: kstart ! start position of the reading in each axis
  639. INTEGER , DIMENSION(:) , INTENT(in ), OPTIONAL :: kcount ! number of points to be read in each axis
  640. LOGICAL , INTENT(in ), OPTIONAL :: lrowattr ! logical flag telling iom_get to
  641. ! look for and use a file attribute
  642. ! called open_ocean_jstart to set the start
  643. ! value for the 2nd dimension (netcdf only)
  644. !
  645. LOGICAL :: llnoov ! local definition to read overlap
  646. LOGICAL :: luse_jattr ! local definition to read open_ocean_jstart file attribute
  647. INTEGER :: jstartrow ! start point for 2nd dimension optionally set by file attribute
  648. INTEGER :: jl ! loop on number of dimension
  649. INTEGER :: idom ! type of domain
  650. INTEGER :: idvar ! id of the variable
  651. INTEGER :: inbdim ! number of dimensions of the variable
  652. INTEGER :: idmspc ! number of spatial dimensions
  653. INTEGER :: itime ! record number
  654. INTEGER :: istop ! temporary value of nstop
  655. INTEGER :: ix1, ix2, iy1, iy2 ! subdomain indexes
  656. INTEGER :: ji, jj ! loop counters
  657. INTEGER :: irankpv !
  658. INTEGER :: ind1, ind2 ! substring index
  659. INTEGER, DIMENSION(jpmax_dims) :: istart ! starting point to read for each axis
  660. INTEGER, DIMENSION(jpmax_dims) :: icnt ! number of value to read along each axis
  661. INTEGER, DIMENSION(jpmax_dims) :: idimsz ! size of the dimensions of the variable
  662. INTEGER, DIMENSION(jpmax_dims) :: ishape ! size of the dimensions of the variable
  663. REAL(wp) :: zscf, zofs ! sacle_factor and add_offset
  664. INTEGER :: itmp ! temporary integer
  665. CHARACTER(LEN=256) :: clinfo ! info character
  666. CHARACTER(LEN=256) :: clname ! file name
  667. CHARACTER(LEN=1) :: clrankpv, cldmspc !
  668. !---------------------------------------------------------------------
  669. !
  670. clname = iom_file(kiomid)%name ! esier to read
  671. clinfo = ' iom_get_123d, file: '//trim(clname)//', var: '//trim(cdvar)
  672. ! local definition of the domain ?
  673. idom = kdom
  674. ! do we read the overlap
  675. ! ugly patch SM+JMM+RB to overwrite global definition in some cases
  676. llnoov = (jpni * jpnj ) == jpnij .AND. .NOT. lk_agrif
  677. ! check kcount and kstart optionals parameters...
  678. IF( PRESENT(kcount) .AND. (.NOT. PRESENT(kstart)) ) CALL ctl_stop(trim(clinfo), 'kcount present needs kstart present')
  679. IF( PRESENT(kstart) .AND. (.NOT. PRESENT(kcount)) ) CALL ctl_stop(trim(clinfo), 'kstart present needs kcount present')
  680. IF( PRESENT(kstart) .AND. idom /= jpdom_unknown ) CALL ctl_stop(trim(clinfo), 'kstart present needs kdom = jpdom_unknown')
  681. luse_jattr = .false.
  682. IF( PRESENT(lrowattr) ) THEN
  683. IF( lrowattr .AND. idom /= jpdom_data ) CALL ctl_stop(trim(clinfo), 'lrowattr present and true needs kdom = jpdom_data')
  684. IF( lrowattr .AND. idom == jpdom_data ) luse_jattr = .true.
  685. ENDIF
  686. IF( luse_jattr ) THEN
  687. SELECT CASE (iom_file(kiomid)%iolib)
  688. CASE (jpioipsl, jprstdimg )
  689. CALL ctl_warn(trim(clinfo), 'lrowattr present and true but this only works with netcdf (jpnf90)')
  690. luse_jattr = .false.
  691. CASE (jpnf90 )
  692. ! Ok
  693. CASE DEFAULT
  694. CALL ctl_stop( TRIM(clinfo)//' accepted IO library are only jpioipsl, jpnf90 and jprstdimg' )
  695. END SELECT
  696. ENDIF
  697. ! Search for the variable in the data base (eventually actualize data)
  698. istop = nstop
  699. idvar = iom_varid( kiomid, cdvar )
  700. !
  701. IF( idvar > 0 ) THEN
  702. ! to write iom_file(kiomid)%dimsz in a shorter way !
  703. idimsz(:) = iom_file(kiomid)%dimsz(:, idvar)
  704. inbdim = iom_file(kiomid)%ndims(idvar) ! number of dimensions in the file
  705. idmspc = inbdim ! number of spatial dimensions in the file
  706. IF( iom_file(kiomid)%luld(idvar) ) idmspc = inbdim - 1
  707. IF( idmspc > 3 ) CALL ctl_stop(trim(clinfo), 'the file has more than 3 spatial dimensions this case is not coded...')
  708. !
  709. ! update idom definition...
  710. ! Identify the domain in case of jpdom_auto(glo/dta) definition
  711. IF( idom == jpdom_autoglo .OR. idom == jpdom_autodta ) THEN
  712. IF( idom == jpdom_autoglo ) THEN ; idom = jpdom_global
  713. ELSE ; idom = jpdom_data
  714. ENDIF
  715. ind1 = INDEX( clname, '_', back = .TRUE. ) + 1
  716. ind2 = INDEX( clname, '.', back = .TRUE. ) - 1
  717. IF( ind2 > ind1 ) THEN ; IF( VERIFY( clname(ind1:ind2), '0123456789' ) == 0 ) idom = jpdom_local ; ENDIF
  718. ENDIF
  719. ! Identify the domain in case of jpdom_local definition
  720. IF( idom == jpdom_local ) THEN
  721. IF( idimsz(1) == jpi .AND. idimsz(2) == jpj ) THEN ; idom = jpdom_local_full
  722. ELSEIF( idimsz(1) == nlci .AND. idimsz(2) == nlcj ) THEN ; idom = jpdom_local_noextra
  723. ELSEIF( idimsz(1) == (nlei - nldi + 1) .AND. idimsz(2) == (nlej - nldj + 1) ) THEN ; idom = jpdom_local_noovlap
  724. ELSE ; CALL ctl_stop( trim(clinfo), 'impossible to identify the local domain' )
  725. ENDIF
  726. ENDIF
  727. !
  728. ! check the consistency between input array and data rank in the file
  729. !
  730. ! initializations
  731. itime = 1
  732. IF( PRESENT(ktime) ) itime = ktime
  733. irankpv = 1 * COUNT( (/PRESENT(pv_r1d)/) ) + 2 * COUNT( (/PRESENT(pv_r2d)/) ) + 3 * COUNT( (/PRESENT(pv_r3d)/) )
  734. WRITE(clrankpv, fmt='(i1)') irankpv
  735. WRITE(cldmspc , fmt='(i1)') idmspc
  736. !
  737. IF( idmspc < irankpv ) THEN
  738. CALL ctl_stop( TRIM(clinfo), 'The file has only '//cldmspc//' spatial dimension', &
  739. & 'it is impossible to read a '//clrankpv//'D array from this file...' )
  740. ELSEIF( idmspc == irankpv ) THEN
  741. IF( PRESENT(pv_r1d) .AND. idom /= jpdom_unknown ) &
  742. & CALL ctl_stop( TRIM(clinfo), 'case not coded...You must use jpdom_unknown' )
  743. ELSEIF( idmspc > irankpv ) THEN
  744. IF( PRESENT(pv_r2d) .AND. itime == 1 .AND. idimsz(3) == 1 .AND. idmspc == 3 ) THEN
  745. CALL ctl_warn( trim(clinfo), '2D array but 3 spatial dimensions for the data...' , &
  746. & 'As the size of the z dimension is 1 and as we try to read the first record, ', &
  747. & 'we accept this case, even if there is a possible mix-up between z and time dimension' )
  748. idmspc = idmspc - 1
  749. ELSE
  750. CALL ctl_stop( TRIM(clinfo), 'To keep iom lisibility, when reading a '//clrankpv//'D array,' , &
  751. & 'we do not accept data with '//cldmspc//' spatial dimensions', &
  752. & 'Use ncwa -a to suppress the unnecessary dimensions' )
  753. ENDIF
  754. ENDIF
  755. !
  756. ! definition of istart and icnt
  757. !
  758. icnt (:) = 1
  759. istart(:) = 1
  760. istart(idmspc+1) = itime
  761. IF( PRESENT(kstart) ) THEN ; istart(1:idmspc) = kstart(1:idmspc) ; icnt(1:idmspc) = kcount(1:idmspc)
  762. ELSE
  763. IF( idom == jpdom_unknown ) THEN ; icnt(1:idmspc) = idimsz(1:idmspc)
  764. ELSE
  765. IF( .NOT. PRESENT(pv_r1d) ) THEN ! not a 1D array
  766. IF( idom == jpdom_data ) THEN
  767. jstartrow = 1
  768. IF( luse_jattr ) THEN
  769. CALL iom_getatt(kiomid, 'open_ocean_jstart', jstartrow ) ! -999 is returned if the attribute is not found
  770. jstartrow = MAX(1,jstartrow)
  771. ENDIF
  772. istart(1:2) = (/ mig(1), mjg(1) + jstartrow - 1 /) ! icnt(1:2) done below
  773. ELSEIF( idom == jpdom_global ) THEN ; istart(1:2) = (/ nimpp , njmpp /) ! icnt(1:2) done below
  774. ENDIF
  775. ! we do not read the overlap -> we start to read at nldi, nldj
  776. ! JMM + SM: ugly patch before getting the new version of lib_mpp)
  777. ! IF( idom /= jpdom_local_noovlap ) istart(1:2) = istart(1:2) + (/ nldi - 1, nldj - 1 /)
  778. IF( llnoov .AND. idom /= jpdom_local_noovlap ) istart(1:2) = istart(1:2) + (/ nldi - 1, nldj - 1 /)
  779. ! we do not read the overlap and the extra-halos -> from nldi to nlei and from nldj to nlej
  780. ! JMM + SM: ugly patch before getting the new version of lib_mpp)
  781. ! icnt(1:2) = (/ nlei - nldi + 1, nlej - nldj + 1 /)
  782. IF( llnoov ) THEN ; icnt(1:2) = (/ nlei - nldi + 1, nlej - nldj + 1 /)
  783. ELSE ; icnt(1:2) = (/ nlci , nlcj /)
  784. ENDIF
  785. IF( PRESENT(pv_r3d) ) THEN
  786. IF( idom == jpdom_data ) THEN ; icnt(3) = jpkdta
  787. ELSE ; icnt(3) = jpk
  788. ENDIF
  789. ENDIF
  790. ENDIF
  791. ENDIF
  792. ENDIF
  793. ! check that istart and icnt can be used with this file
  794. !-
  795. DO jl = 1, jpmax_dims
  796. itmp = istart(jl)+icnt(jl)-1
  797. IF( itmp > idimsz(jl) .AND. idimsz(jl) /= 0 ) THEN
  798. WRITE( ctmp1, FMT="('(istart(', i1, ') + icnt(', i1, ') - 1) = ', i5)" ) jl, jl, itmp
  799. WRITE( ctmp2, FMT="(' is larger than idimsz(', i1,') = ', i5)" ) jl, idimsz(jl)
  800. CALL ctl_stop( trim(clinfo), 'start and count too big regarding to the size of the data, ', ctmp1, ctmp2 )
  801. ENDIF
  802. END DO
  803. ! check that icnt matches the input array
  804. !-
  805. IF( idom == jpdom_unknown ) THEN
  806. IF( irankpv == 1 ) ishape(1:1) = SHAPE(pv_r1d)
  807. IF( irankpv == 2 ) ishape(1:2) = SHAPE(pv_r2d)
  808. IF( irankpv == 3 ) ishape(1:3) = SHAPE(pv_r3d)
  809. ctmp1 = 'd'
  810. ELSE
  811. IF( irankpv == 2 ) THEN
  812. ! JMM + SM: ugly patch before getting the new version of lib_mpp)
  813. ! ishape(1:2) = SHAPE(pv_r2d(nldi:nlei,nldj:nlej )) ; ctmp1 = 'd(nldi:nlei,nldj:nlej)'
  814. IF( llnoov ) THEN ; ishape(1:2)=SHAPE(pv_r2d(nldi:nlei,nldj:nlej )) ; ctmp1='d(nldi:nlei,nldj:nlej)'
  815. ELSE ; ishape(1:2)=SHAPE(pv_r2d(1 :nlci,1 :nlcj )) ; ctmp1='d(1:nlci,1:nlcj)'
  816. ENDIF
  817. ENDIF
  818. IF( irankpv == 3 ) THEN
  819. ! JMM + SM: ugly patch before getting the new version of lib_mpp)
  820. ! ishape(1:3) = SHAPE(pv_r3d(nldi:nlei,nldj:nlej,:)) ; ctmp1 = 'd(nldi:nlei,nldj:nlej,:)'
  821. IF( llnoov ) THEN ; ishape(1:3)=SHAPE(pv_r3d(nldi:nlei,nldj:nlej,:)) ; ctmp1='d(nldi:nlei,nldj:nlej,:)'
  822. ELSE ; ishape(1:3)=SHAPE(pv_r3d(1 :nlci,1 :nlcj,:)) ; ctmp1='d(1:nlci,1:nlcj,:)'
  823. ENDIF
  824. ENDIF
  825. ENDIF
  826. DO jl = 1, irankpv
  827. WRITE( ctmp2, FMT="(', ', i1,'): ', i5,' /= icnt(', i1,'):', i5)" ) jl, ishape(jl), jl, icnt(jl)
  828. IF( ishape(jl) /= icnt(jl) ) CALL ctl_stop( TRIM(clinfo), 'size(pv_r'//clrankpv//TRIM(ctmp1)//TRIM(ctmp2) )
  829. END DO
  830. ENDIF
  831. ! read the data
  832. !-
  833. IF( idvar > 0 .AND. istop == nstop ) THEN ! no additional errors until this point...
  834. !
  835. ! find the right index of the array to be read
  836. ! JMM + SM: ugly patch before getting the new version of lib_mpp)
  837. ! IF( idom /= jpdom_unknown ) THEN ; ix1 = nldi ; ix2 = nlei ; iy1 = nldj ; iy2 = nlej
  838. ! ELSE ; ix1 = 1 ; ix2 = icnt(1) ; iy1 = 1 ; iy2 = icnt(2)
  839. ! ENDIF
  840. IF( llnoov ) THEN
  841. IF( idom /= jpdom_unknown ) THEN ; ix1 = nldi ; ix2 = nlei ; iy1 = nldj ; iy2 = nlej
  842. ELSE ; ix1 = 1 ; ix2 = icnt(1) ; iy1 = 1 ; iy2 = icnt(2)
  843. ENDIF
  844. ELSE
  845. IF( idom /= jpdom_unknown ) THEN ; ix1 = 1 ; ix2 = nlci ; iy1 = 1 ; iy2 = nlcj
  846. ELSE ; ix1 = 1 ; ix2 = icnt(1) ; iy1 = 1 ; iy2 = icnt(2)
  847. ENDIF
  848. ENDIF
  849. SELECT CASE (iom_file(kiomid)%iolib)
  850. CASE (jpioipsl ) ; CALL iom_ioipsl_get( kiomid, idvar, inbdim, istart, icnt, ix1, ix2, iy1, iy2, &
  851. & pv_r1d, pv_r2d, pv_r3d )
  852. CASE (jpnf90 ) ; CALL iom_nf90_get( kiomid, idvar, inbdim, istart, icnt, ix1, ix2, iy1, iy2, &
  853. & pv_r1d, pv_r2d, pv_r3d )
  854. CASE (jprstdimg) ; CALL iom_rstdimg_get( kiomid, idom, idvar, ix1, ix2, iy1, iy2, &
  855. & pv_r1d, pv_r2d, pv_r3d )
  856. CASE DEFAULT
  857. CALL ctl_stop( TRIM(clinfo)//' accepted IO library are only jpioipsl, jpnf90 and jprstdimg' )
  858. END SELECT
  859. IF( istop == nstop ) THEN ! no additional errors until this point...
  860. IF(lwp) WRITE(numout,"(10x,' read ',a,' (rec: ',i6,') in ',a,' ok')") TRIM(cdvar), itime, TRIM(iom_file(kiomid)%name)
  861. !--- overlap areas and extra hallows (mpp)
  862. IF( PRESENT(pv_r2d) .AND. idom /= jpdom_unknown ) THEN
  863. CALL lbc_lnk( pv_r2d,'Z',-999.,'no0' )
  864. ELSEIF( PRESENT(pv_r3d) .AND. idom /= jpdom_unknown ) THEN
  865. ! this if could be simplified with the new lbc_lnk that works with any size of the 3rd dimension
  866. IF( icnt(3) == jpk ) THEN
  867. CALL lbc_lnk( pv_r3d,'Z',-999.,'no0' )
  868. ELSE ! put some arbitrary value (a call to lbc_lnk will be done later...)
  869. DO jj = nlcj+1, jpj ; pv_r3d(1:nlci, jj, :) = pv_r3d(1:nlci, nlej, :) ; END DO
  870. DO ji = nlci+1, jpi ; pv_r3d(ji , : , :) = pv_r3d(nlei , : , :) ; END DO
  871. ENDIF
  872. ENDIF
  873. ! C1D case : always call lbc_lnk to replicate the central value over the whole 3X3 domain
  874. IF( lk_c1d .AND. PRESENT(pv_r2d) ) CALL lbc_lnk( pv_r2d,'Z',1. )
  875. IF( lk_c1d .AND. PRESENT(pv_r3d) ) CALL lbc_lnk( pv_r3d,'Z',1. )
  876. !--- Apply scale_factor and offset
  877. zscf = iom_file(kiomid)%scf(idvar) ! scale factor
  878. zofs = iom_file(kiomid)%ofs(idvar) ! offset
  879. IF( PRESENT(pv_r1d) ) THEN
  880. IF( zscf /= 1. ) pv_r1d(:) = pv_r1d(:) * zscf
  881. IF( zofs /= 0. ) pv_r1d(:) = pv_r1d(:) + zofs
  882. ELSEIF( PRESENT(pv_r2d) ) THEN
  883. !CDIR COLLAPSE
  884. IF( zscf /= 1.) pv_r2d(:,:) = pv_r2d(:,:) * zscf
  885. !CDIR COLLAPSE
  886. IF( zofs /= 0.) pv_r2d(:,:) = pv_r2d(:,:) + zofs
  887. ELSEIF( PRESENT(pv_r3d) ) THEN
  888. !CDIR COLLAPSE
  889. IF( zscf /= 1.) pv_r3d(:,:,:) = pv_r3d(:,:,:) * zscf
  890. !CDIR COLLAPSE
  891. IF( zofs /= 0.) pv_r3d(:,:,:) = pv_r3d(:,:,:) + zofs
  892. ENDIF
  893. !
  894. ENDIF
  895. !
  896. ENDIF
  897. !
  898. END SUBROUTINE iom_get_123d
  899. SUBROUTINE iom_gettime( kiomid, ptime, cdvar, kntime, cdunits, cdcalendar )
  900. !!--------------------------------------------------------------------
  901. !! *** SUBROUTINE iom_gettime ***
  902. !!
  903. !! ** Purpose : read the time axis cdvar in the file
  904. !!--------------------------------------------------------------------
  905. INTEGER , INTENT(in ) :: kiomid ! file Identifier
  906. REAL(wp), DIMENSION(:) , INTENT( out) :: ptime ! the time axis
  907. CHARACTER(len=*), OPTIONAL , INTENT(in ) :: cdvar ! time axis name
  908. INTEGER , OPTIONAL , INTENT( out) :: kntime ! number of times in file
  909. CHARACTER(len=*), OPTIONAL , INTENT( out) :: cdunits ! units attribute of time coordinate
  910. CHARACTER(len=*), OPTIONAL , INTENT( out) :: cdcalendar ! calendar attribute of
  911. !
  912. INTEGER, DIMENSION(1) :: kdimsz
  913. INTEGER :: idvar ! id of the variable
  914. CHARACTER(LEN=32) :: tname ! local name of time coordinate
  915. CHARACTER(LEN=100) :: clinfo ! info character
  916. !---------------------------------------------------------------------
  917. !
  918. IF ( PRESENT(cdvar) ) THEN
  919. tname = cdvar
  920. ELSE
  921. tname = iom_file(kiomid)%uldname
  922. ENDIF
  923. IF( kiomid > 0 ) THEN
  924. clinfo = 'iom_gettime, file: '//trim(iom_file(kiomid)%name)//', var: '//trim(tname)
  925. IF ( PRESENT(kntime) ) THEN
  926. idvar = iom_varid( kiomid, tname, kdimsz = kdimsz )
  927. kntime = kdimsz(1)
  928. ELSE
  929. idvar = iom_varid( kiomid, tname )
  930. ENDIF
  931. !
  932. ptime(:) = 0. ! default definition
  933. IF( idvar > 0 ) THEN
  934. IF( iom_file(kiomid)%ndims(idvar) == 1 ) THEN
  935. IF( iom_file(kiomid)%luld(idvar) ) THEN
  936. IF( iom_file(kiomid)%dimsz(1,idvar) <= size(ptime) ) THEN
  937. SELECT CASE (iom_file(kiomid)%iolib)
  938. CASE (jpioipsl ) ; CALL iom_ioipsl_gettime( kiomid, idvar, ptime, cdunits, cdcalendar )
  939. CASE (jpnf90 ) ; CALL iom_nf90_gettime( kiomid, idvar, ptime, cdunits, cdcalendar )
  940. CASE (jprstdimg) ; CALL ctl_stop( TRIM(clinfo)//' case IO library == jprstdimg not coded...' )
  941. CASE DEFAULT
  942. CALL ctl_stop( TRIM(clinfo)//' accepted IO library are only jpioipsl, jpnf90 and jprstdimg' )
  943. END SELECT
  944. ELSE
  945. WRITE(ctmp1,*) 'error with the size of ptime ',size(ptime),iom_file(kiomid)%dimsz(1,idvar)
  946. CALL ctl_stop( trim(clinfo), trim(ctmp1) )
  947. ENDIF
  948. ELSE
  949. CALL ctl_stop( trim(clinfo), 'variable dimension is not unlimited... use iom_get' )
  950. ENDIF
  951. ELSE
  952. CALL ctl_stop( trim(clinfo), 'the variable has more than 1 dimension' )
  953. ENDIF
  954. ELSE
  955. CALL ctl_stop( trim(clinfo), 'variable not found in '//iom_file(kiomid)%name )
  956. ENDIF
  957. ENDIF
  958. !
  959. END SUBROUTINE iom_gettime
  960. !!----------------------------------------------------------------------
  961. !! INTERFACE iom_getatt
  962. !!----------------------------------------------------------------------
  963. SUBROUTINE iom_g0d_intatt( kiomid, cdatt, pvar )
  964. INTEGER , INTENT(in ) :: kiomid ! Identifier of the file
  965. CHARACTER(len=*), INTENT(in ) :: cdatt ! Name of the attribute
  966. INTEGER , INTENT( out) :: pvar ! read field
  967. !
  968. IF( kiomid > 0 ) THEN
  969. IF( iom_file(kiomid)%nfid > 0 ) THEN
  970. SELECT CASE (iom_file(kiomid)%iolib)
  971. CASE (jpioipsl ) ; CALL ctl_stop('iom_getatt: only nf90 available')
  972. CASE (jpnf90 ) ; CALL iom_nf90_getatt( kiomid, cdatt, pvar )
  973. CASE (jprstdimg) ; CALL ctl_stop('iom_getatt: only nf90 available')
  974. CASE DEFAULT
  975. CALL ctl_stop( 'iom_g0d_att: accepted IO library are only jpioipsl, jpnf90 and jprstdimg' )
  976. END SELECT
  977. ENDIF
  978. ENDIF
  979. END SUBROUTINE iom_g0d_intatt
  980. !!----------------------------------------------------------------------
  981. !! INTERFACE iom_rstput
  982. !!----------------------------------------------------------------------
  983. SUBROUTINE iom_rp0d( kt, kwrite, kiomid, cdvar, pvar, ktype )
  984. INTEGER , INTENT(in) :: kt ! ocean time-step
  985. INTEGER , INTENT(in) :: kwrite ! writing time-step
  986. INTEGER , INTENT(in) :: kiomid ! Identifier of the file
  987. CHARACTER(len=*), INTENT(in) :: cdvar ! time axis name
  988. REAL(wp) , INTENT(in) :: pvar ! written field
  989. INTEGER , INTENT(in), OPTIONAL :: ktype ! variable external type
  990. INTEGER :: ivid ! variable id
  991. IF( kiomid > 0 ) THEN
  992. IF( iom_file(kiomid)%nfid > 0 ) THEN
  993. ivid = iom_varid( kiomid, cdvar, ldstop = .FALSE. )
  994. SELECT CASE (iom_file(kiomid)%iolib)
  995. CASE (jpioipsl ) ; CALL iom_ioipsl_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r0d = pvar )
  996. CASE (jpnf90 ) ; CALL iom_nf90_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r0d = pvar )
  997. CASE (jprstdimg) ; IF( kt == kwrite ) CALL iom_rstdimg_rstput( kiomid, cdvar, ivid, pvar )
  998. CASE DEFAULT
  999. CALL ctl_stop( 'iom_rp0d: accepted IO library are only jpioipsl, jpnf90 and jprstdimg' )
  1000. END SELECT
  1001. ENDIF
  1002. ENDIF
  1003. END SUBROUTINE iom_rp0d
  1004. SUBROUTINE iom_rp1d( kt, kwrite, kiomid, cdvar, pvar, ktype )
  1005. INTEGER , INTENT(in) :: kt ! ocean time-step
  1006. INTEGER , INTENT(in) :: kwrite ! writing time-step
  1007. INTEGER , INTENT(in) :: kiomid ! Identifier of the file
  1008. CHARACTER(len=*), INTENT(in) :: cdvar ! time axis name
  1009. REAL(wp) , INTENT(in), DIMENSION( :) :: pvar ! written field
  1010. INTEGER , INTENT(in), OPTIONAL :: ktype ! variable external type
  1011. INTEGER :: ivid ! variable id
  1012. IF( kiomid > 0 ) THEN
  1013. IF( iom_file(kiomid)%nfid > 0 ) THEN
  1014. ivid = iom_varid( kiomid, cdvar, ldstop = .FALSE. )
  1015. SELECT CASE (iom_file(kiomid)%iolib)
  1016. CASE (jpioipsl ) ; CALL iom_ioipsl_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r1d = pvar )
  1017. CASE (jpnf90 ) ; CALL iom_nf90_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r1d = pvar )
  1018. CASE (jprstdimg) ; IF( kt == kwrite ) CALL iom_rstdimg_rstput( kiomid, cdvar, ivid, pv_r1d = pvar )
  1019. CASE DEFAULT
  1020. CALL ctl_stop( 'iom_rp1d: accepted IO library are only jpioipsl, jpnf90 and jprstdimg' )
  1021. END SELECT
  1022. ENDIF
  1023. ENDIF
  1024. END SUBROUTINE iom_rp1d
  1025. SUBROUTINE iom_rp2d( kt, kwrite, kiomid, cdvar, pvar, ktype )
  1026. INTEGER , INTENT(in) :: kt ! ocean time-step
  1027. INTEGER , INTENT(in) :: kwrite ! writing time-step
  1028. INTEGER , INTENT(in) :: kiomid ! Identifier of the file
  1029. CHARACTER(len=*), INTENT(in) :: cdvar ! time axis name
  1030. REAL(wp) , INTENT(in), DIMENSION(:, : ) :: pvar ! written field
  1031. INTEGER , INTENT(in), OPTIONAL :: ktype ! variable external type
  1032. INTEGER :: ivid ! variable id
  1033. IF( kiomid > 0 ) THEN
  1034. IF( iom_file(kiomid)%nfid > 0 ) THEN
  1035. ivid = iom_varid( kiomid, cdvar, ldstop = .FALSE. )
  1036. SELECT CASE (iom_file(kiomid)%iolib)
  1037. CASE (jpioipsl ) ; CALL iom_ioipsl_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r2d = pvar )
  1038. CASE (jpnf90 ) ; CALL iom_nf90_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r2d = pvar )
  1039. CASE (jprstdimg) ; IF( kt == kwrite ) CALL iom_rstdimg_rstput( kiomid, cdvar, ivid, pv_r2d = pvar )
  1040. CASE DEFAULT
  1041. CALL ctl_stop( 'iom_rp2d: accepted IO library are only jpioipsl, jpnf90 and jprstdimg' )
  1042. END SELECT
  1043. ENDIF
  1044. ENDIF
  1045. END SUBROUTINE iom_rp2d
  1046. SUBROUTINE iom_rp3d( kt, kwrite, kiomid, cdvar, pvar, ktype )
  1047. INTEGER , INTENT(in) :: kt ! ocean time-step
  1048. INTEGER , INTENT(in) :: kwrite ! writing time-step
  1049. INTEGER , INTENT(in) :: kiomid ! Identifier of the file
  1050. CHARACTER(len=*), INTENT(in) :: cdvar ! time axis name
  1051. REAL(wp) , INTENT(in), DIMENSION(:,:,:) :: pvar ! written field
  1052. INTEGER , INTENT(in), OPTIONAL :: ktype ! variable external type
  1053. INTEGER :: ivid ! variable id
  1054. IF( kiomid > 0 ) THEN
  1055. IF( iom_file(kiomid)%nfid > 0 ) THEN
  1056. ivid = iom_varid( kiomid, cdvar, ldstop = .FALSE. )
  1057. SELECT CASE (iom_file(kiomid)%iolib)
  1058. CASE (jpioipsl ) ; CALL iom_ioipsl_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r3d = pvar )
  1059. CASE (jpnf90 ) ; CALL iom_nf90_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r3d = pvar )
  1060. CASE (jprstdimg) ; IF( kt == kwrite ) CALL iom_rstdimg_rstput( kiomid, cdvar, ivid, pv_r3d = pvar )
  1061. CASE DEFAULT
  1062. CALL ctl_stop( 'iom_rp3d: accepted IO library are only jpioipsl and jprstdimg' )
  1063. END SELECT
  1064. ENDIF
  1065. ENDIF
  1066. END SUBROUTINE iom_rp3d
  1067. !!----------------------------------------------------------------------
  1068. !! INTERFACE iom_put
  1069. !!----------------------------------------------------------------------
  1070. SUBROUTINE iom_p0d( cdname, pfield0d )
  1071. CHARACTER(LEN=*), INTENT(in) :: cdname
  1072. REAL(wp) , INTENT(in) :: pfield0d
  1073. REAL(wp) , DIMENSION(jpi,jpj) :: zz ! masson
  1074. #if defined key_iomput
  1075. zz(:,:)=pfield0d
  1076. CALL xios_send_field(cdname, zz)
  1077. !CALL xios_send_field(cdname, (/pfield0d/))
  1078. #else
  1079. IF( .FALSE. ) WRITE(numout,*) cdname, pfield0d ! useless test to avoid compilation warnings
  1080. #endif
  1081. END SUBROUTINE iom_p0d
  1082. SUBROUTINE iom_p1d( cdname, pfield1d )
  1083. CHARACTER(LEN=*) , INTENT(in) :: cdname
  1084. REAL(wp), DIMENSION(:), INTENT(in) :: pfield1d
  1085. #if defined key_iomput
  1086. CALL xios_send_field( cdname, RESHAPE( (/pfield1d/), (/1,1,SIZE(pfield1d)/) ) )
  1087. #else
  1088. IF( .FALSE. ) WRITE(numout,*) cdname, pfield1d ! useless test to avoid compilation warnings
  1089. #endif
  1090. END SUBROUTINE iom_p1d
  1091. SUBROUTINE iom_p2d( cdname, pfield2d )
  1092. CHARACTER(LEN=*) , INTENT(in) :: cdname
  1093. REAL(wp), DIMENSION(:,:), INTENT(in) :: pfield2d
  1094. #if defined key_iomput
  1095. CALL xios_send_field(cdname, pfield2d)
  1096. #else
  1097. IF( .FALSE. ) WRITE(numout,*) cdname, pfield2d ! useless test to avoid compilation warnings
  1098. #endif
  1099. END SUBROUTINE iom_p2d
  1100. SUBROUTINE iom_p3d( cdname, pfield3d )
  1101. CHARACTER(LEN=*) , INTENT(in) :: cdname
  1102. REAL(wp), DIMENSION(:,:,:), INTENT(in) :: pfield3d
  1103. #if defined key_iomput
  1104. CALL xios_send_field(cdname, pfield3d)
  1105. #else
  1106. IF( .FALSE. ) WRITE(numout,*) cdname, pfield3d ! useless test to avoid compilation warnings
  1107. #endif
  1108. END SUBROUTINE iom_p3d
  1109. !!----------------------------------------------------------------------
  1110. #if defined key_iomput
  1111. SUBROUTINE iom_set_domain_attr( cdid, ni_glo, nj_glo, ibegin, jbegin, ni, nj, zoom_ibegin, zoom_jbegin, zoom_ni, zoom_nj, &
  1112. & data_dim, data_ibegin, data_ni, data_jbegin, data_nj, lonvalue, latvalue, mask, &
  1113. & nvertex, bounds_lon, bounds_lat, area )
  1114. CHARACTER(LEN=*) , INTENT(in) :: cdid
  1115. INTEGER , OPTIONAL, INTENT(in) :: ni_glo, nj_glo, ibegin, jbegin, ni, nj
  1116. INTEGER , OPTIONAL, INTENT(in) :: data_dim, data_ibegin, data_ni, data_jbegin, data_nj
  1117. INTEGER , OPTIONAL, INTENT(in) :: zoom_ibegin, zoom_jbegin, zoom_ni, zoom_nj, nvertex
  1118. REAL(wp), DIMENSION(:) , OPTIONAL, INTENT(in) :: lonvalue, latvalue
  1119. REAL(wp), DIMENSION(:,:) , OPTIONAL, INTENT(in) :: bounds_lon, bounds_lat, area
  1120. #if ! defined key_xios2
  1121. LOGICAL, DIMENSION(:,:) , OPTIONAL, INTENT(in) :: mask
  1122. #else
  1123. LOGICAL, DIMENSION(:) , OPTIONAL, INTENT(in) :: mask
  1124. #endif
  1125. #if ! defined key_xios2
  1126. IF ( xios_is_valid_domain (cdid) ) THEN
  1127. CALL xios_set_domain_attr ( cdid, ni_glo=ni_glo, nj_glo=nj_glo, ibegin=ibegin, jbegin=jbegin, ni=ni, nj=nj, &
  1128. & data_dim=data_dim, data_ibegin=data_ibegin, data_ni=data_ni, data_jbegin=data_jbegin, data_nj=data_nj , &
  1129. & zoom_ibegin=zoom_ibegin, zoom_jbegin=zoom_jbegin, zoom_ni=zoom_ni, zoom_nj=zoom_nj, &
  1130. & lonvalue=lonvalue, latvalue=latvalue, mask=mask, nvertex=nvertex, bounds_lon=bounds_lon, &
  1131. & bounds_lat=bounds_lat, area=area )
  1132. ENDIF
  1133. IF ( xios_is_valid_domaingroup(cdid) ) THEN
  1134. CALL xios_set_domaingroup_attr( cdid, ni_glo=ni_glo, nj_glo=nj_glo, ibegin=ibegin, jbegin=jbegin, ni=ni, nj=nj, &
  1135. & data_dim=data_dim, data_ibegin=data_ibegin, data_ni=data_ni, data_jbegin=data_jbegin, data_nj=data_nj , &
  1136. & zoom_ibegin=zoom_ibegin, zoom_jbegin=zoom_jbegin, zoom_ni=zoom_ni, zoom_nj=zoom_nj, &
  1137. & lonvalue=lonvalue, latvalue=latvalue, mask=mask, nvertex=nvertex, bounds_lon=bounds_lon, &
  1138. & bounds_lat=bounds_lat, area=area )
  1139. ENDIF
  1140. #else
  1141. IF ( xios_is_valid_domain (cdid) ) THEN
  1142. CALL xios_set_domain_attr ( cdid, ni_glo=ni_glo, nj_glo=nj_glo, ibegin=ibegin, jbegin=jbegin, ni=ni, nj=nj, &
  1143. & data_dim=data_dim, data_ibegin=data_ibegin, data_ni=data_ni, data_jbegin=data_jbegin, data_nj=data_nj , &
  1144. & lonvalue_1D=lonvalue, latvalue_1D=latvalue, mask_1D=mask, nvertex=nvertex, bounds_lon_1D=bounds_lon, &
  1145. & bounds_lat_1D=bounds_lat, area=area, type='curvilinear')
  1146. ENDIF
  1147. IF ( xios_is_valid_domaingroup(cdid) ) THEN
  1148. CALL xios_set_domaingroup_attr( cdid, ni_glo=ni_glo, nj_glo=nj_glo, ibegin=ibegin, jbegin=jbegin, ni=ni, nj=nj, &
  1149. & data_dim=data_dim, data_ibegin=data_ibegin, data_ni=data_ni, data_jbegin=data_jbegin, data_nj=data_nj , &
  1150. & lonvalue_1D=lonvalue, latvalue_1D=latvalue, mask_1D=mask, nvertex=nvertex, bounds_lon_1D=bounds_lon, &
  1151. & bounds_lat_1D=bounds_lat, area=area, type='curvilinear' )
  1152. ENDIF
  1153. #endif
  1154. CALL xios_solve_inheritance()
  1155. END SUBROUTINE iom_set_domain_attr
  1156. #if defined key_xios2
  1157. SUBROUTINE iom_set_zoom_domain_attr( cdid, ibegin, jbegin, ni, nj)
  1158. CHARACTER(LEN=*) , INTENT(in) :: cdid
  1159. INTEGER , OPTIONAL, INTENT(in) :: ibegin, jbegin, ni, nj
  1160. IF ( xios_is_valid_zoom_domain (cdid) ) THEN
  1161. CALL xios_set_zoom_domain_attr ( cdid, ibegin=ibegin, jbegin=jbegin, ni=ni, &
  1162. & nj=nj)
  1163. ENDIF
  1164. END SUBROUTINE iom_set_zoom_domain_attr
  1165. #endif
  1166. SUBROUTINE iom_set_axis_attr( cdid, paxis, bounds )
  1167. CHARACTER(LEN=*) , INTENT(in) :: cdid
  1168. REAL(wp), DIMENSION(:) , OPTIONAL, INTENT(in) :: paxis
  1169. REAL(wp), DIMENSION(:,:), OPTIONAL, INTENT(in) :: bounds
  1170. IF ( PRESENT(paxis) ) THEN
  1171. #if ! defined key_xios2
  1172. IF ( xios_is_valid_axis (cdid) ) CALL xios_set_axis_attr ( cdid, size=SIZE(paxis), value=paxis )
  1173. IF ( xios_is_valid_axisgroup(cdid) ) CALL xios_set_axisgroup_attr( cdid, size=SIZE(paxis), value=paxis )
  1174. #else
  1175. IF ( xios_is_valid_axis (cdid) ) CALL xios_set_axis_attr ( cdid, n_glo=SIZE(paxis), value=paxis )
  1176. IF ( xios_is_valid_axisgroup(cdid) ) CALL xios_set_axisgroup_attr( cdid, n_glo=SIZE(paxis), value=paxis )
  1177. #endif
  1178. ENDIF
  1179. IF ( xios_is_valid_axis (cdid) ) CALL xios_set_axis_attr ( cdid, bounds=bounds )
  1180. IF ( xios_is_valid_axisgroup(cdid) ) CALL xios_set_axisgroup_attr( cdid, bounds=bounds )
  1181. CALL xios_solve_inheritance()
  1182. END SUBROUTINE iom_set_axis_attr
  1183. SUBROUTINE iom_set_field_attr( cdid, freq_op, freq_offset )
  1184. CHARACTER(LEN=*) , INTENT(in) :: cdid
  1185. #if ! defined key_xios2
  1186. CHARACTER(LEN=*) ,OPTIONAL , INTENT(in) :: freq_op
  1187. CHARACTER(LEN=*) ,OPTIONAL , INTENT(in) :: freq_offset
  1188. #else
  1189. TYPE(xios_duration),OPTIONAL , INTENT(in) :: freq_op
  1190. TYPE(xios_duration),OPTIONAL , INTENT(in) :: freq_offset
  1191. #endif
  1192. IF ( xios_is_valid_field (cdid) ) CALL xios_set_field_attr &
  1193. & ( cdid, freq_op=freq_op, freq_offset=freq_offset )
  1194. IF ( xios_is_valid_fieldgroup(cdid) ) CALL xios_set_fieldgroup_attr &
  1195. & ( cdid, freq_op=freq_op, freq_offset=freq_offset )
  1196. CALL xios_solve_inheritance()
  1197. END SUBROUTINE iom_set_field_attr
  1198. SUBROUTINE iom_set_file_attr( cdid, name, name_suffix )
  1199. CHARACTER(LEN=*) , INTENT(in) :: cdid
  1200. CHARACTER(LEN=*),OPTIONAL , INTENT(in) :: name, name_suffix
  1201. IF ( xios_is_valid_file (cdid) ) CALL xios_set_file_attr ( cdid, name=name, name_suffix=name_suffix )
  1202. IF ( xios_is_valid_filegroup(cdid) ) CALL xios_set_filegroup_attr( cdid, name=name, name_suffix=name_suffix )
  1203. CALL xios_solve_inheritance()
  1204. END SUBROUTINE iom_set_file_attr
  1205. SUBROUTINE iom_get_file_attr( cdid, name, name_suffix, output_freq )
  1206. CHARACTER(LEN=*) , INTENT(in ) :: cdid
  1207. CHARACTER(LEN=*),OPTIONAL , INTENT(out) :: name, name_suffix
  1208. #if ! defined key_xios2
  1209. CHARACTER(LEN=*),OPTIONAL , INTENT(out) :: output_freq
  1210. #else
  1211. TYPE(xios_duration) ,OPTIONAL , INTENT(out) :: output_freq
  1212. #endif
  1213. LOGICAL :: llexist1,llexist2,llexist3
  1214. !---------------------------------------------------------------------
  1215. IF( PRESENT( name ) ) name = '' ! default values
  1216. IF( PRESENT( name_suffix ) ) name_suffix = ''
  1217. #if ! defined key_xios2
  1218. IF( PRESENT( output_freq ) ) output_freq = ''
  1219. #else
  1220. IF( PRESENT( output_freq ) ) output_freq = xios_duration(0,0,0,0,0,0)
  1221. #endif
  1222. IF ( xios_is_valid_file (cdid) ) THEN
  1223. CALL xios_solve_inheritance()
  1224. CALL xios_is_defined_file_attr ( cdid, name = llexist1, name_suffix = llexist2, output_freq = llexist3)
  1225. IF(llexist1) CALL xios_get_file_attr ( cdid, name = name )
  1226. IF(llexist2) CALL xios_get_file_attr ( cdid, name_suffix = name_suffix )
  1227. IF(llexist3) CALL xios_get_file_attr ( cdid, output_freq = output_freq )
  1228. ENDIF
  1229. IF ( xios_is_valid_filegroup(cdid) ) THEN
  1230. CALL xios_solve_inheritance()
  1231. CALL xios_is_defined_filegroup_attr( cdid, name = llexist1, name_suffix = llexist2, output_freq = llexist3)
  1232. IF(llexist1) CALL xios_get_filegroup_attr( cdid, name = name )
  1233. IF(llexist2) CALL xios_get_filegroup_attr( cdid, name_suffix = name_suffix )
  1234. IF(llexist3) CALL xios_get_filegroup_attr( cdid, output_freq = output_freq )
  1235. ENDIF
  1236. END SUBROUTINE iom_get_file_attr
  1237. SUBROUTINE iom_set_grid_attr( cdid, mask )
  1238. CHARACTER(LEN=*) , INTENT(in) :: cdid
  1239. LOGICAL, DIMENSION(:,:,:), OPTIONAL, INTENT(in) :: mask
  1240. #if ! defined key_xios2
  1241. IF ( xios_is_valid_grid (cdid) ) CALL xios_set_grid_attr ( cdid, mask=mask )
  1242. IF ( xios_is_valid_gridgroup(cdid) ) CALL xios_set_gridgroup_attr( cdid, mask=mask )
  1243. #else
  1244. IF ( xios_is_valid_grid (cdid) ) CALL xios_set_grid_attr ( cdid, mask_3D=mask )
  1245. IF ( xios_is_valid_gridgroup(cdid) ) CALL xios_set_gridgroup_attr( cdid, mask_3D=mask )
  1246. #endif
  1247. CALL xios_solve_inheritance()
  1248. END SUBROUTINE iom_set_grid_attr
  1249. SUBROUTINE iom_setkt( kt, cdname )
  1250. INTEGER , INTENT(in) :: kt
  1251. CHARACTER(LEN=*), INTENT(in) :: cdname
  1252. !
  1253. CALL iom_swap( cdname ) ! swap to cdname context
  1254. CALL xios_update_calendar(kt)
  1255. IF( cdname /= TRIM(cxios_context) ) CALL iom_swap( TRIM(cxios_context) ) ! return back to nemo context
  1256. !
  1257. END SUBROUTINE iom_setkt
  1258. SUBROUTINE iom_context_finalize( cdname )
  1259. CHARACTER(LEN=*), INTENT(in) :: cdname
  1260. !
  1261. IF( xios_is_valid_context(cdname) ) THEN
  1262. CALL iom_swap( cdname ) ! swap to cdname context
  1263. CALL xios_context_finalize() ! finalize the context
  1264. IF( cdname /= TRIM(cxios_context) ) CALL iom_swap( TRIM(cxios_context) ) ! return back to nemo context
  1265. ENDIF
  1266. !
  1267. END SUBROUTINE iom_context_finalize
  1268. SUBROUTINE set_grid( cdgrd, plon, plat )
  1269. !!----------------------------------------------------------------------
  1270. !! *** ROUTINE set_grid ***
  1271. !!
  1272. !! ** Purpose : define horizontal grids
  1273. !!
  1274. !!----------------------------------------------------------------------
  1275. CHARACTER(LEN=1) , INTENT(in) :: cdgrd
  1276. REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: plon
  1277. REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: plat
  1278. !
  1279. REAL(wp), DIMENSION(jpi,jpj,jpk) :: zmask
  1280. INTEGER :: ni,nj
  1281. ni=nlei-nldi+1 ; nj=nlej-nldj+1
  1282. #if ! defined key_xios2
  1283. CALL iom_set_domain_attr("grid_"//cdgrd, ni_glo=jpiglo, nj_glo=jpjglo, ibegin=nimpp+nldi-1, jbegin=njmpp+nldj-1, ni=ni, nj=nj)
  1284. #else
  1285. CALL iom_set_domain_attr("grid_"//cdgrd, ni_glo=jpiglo, nj_glo=jpjglo, ibegin=nimpp+nldi-2, jbegin=njmpp+nldj-2, ni=ni, nj=nj)
  1286. #endif
  1287. CALL iom_set_domain_attr("grid_"//cdgrd, data_dim=2, data_ibegin = 1-nldi, data_ni = jpi, data_jbegin = 1-nldj, data_nj = jpj)
  1288. CALL iom_set_domain_attr("grid_"//cdgrd, lonvalue = RESHAPE(plon(nldi:nlei, nldj:nlej),(/ ni*nj /)), &
  1289. & latvalue = RESHAPE(plat(nldi:nlei, nldj:nlej),(/ ni*nj /)))
  1290. IF ( ln_mskland ) THEN
  1291. ! mask land points, keep values on coast line -> specific mask for U, V and W points
  1292. SELECT CASE ( cdgrd )
  1293. CASE('T') ; zmask(:,:,:) = tmask(:,:,:)
  1294. CASE('U') ; zmask(2:jpim1,:,:) = tmask(2:jpim1,:,:) + tmask(3:jpi,:,:) ; CALL lbc_lnk( zmask, 'U', 1. )
  1295. CASE('V') ; zmask(:,2:jpjm1,:) = tmask(:,2:jpjm1,:) + tmask(:,3:jpj,:) ; CALL lbc_lnk( zmask, 'V', 1. )
  1296. CASE('W') ; zmask(:,:,2:jpk ) = tmask(:,:,1:jpkm1) + tmask(:,:,2:jpk) ; zmask(:,:,1) = tmask(:,:,1)
  1297. END SELECT
  1298. !
  1299. #if ! defined key_xios2
  1300. CALL iom_set_domain_attr( "grid_"//cdgrd , mask = RESHAPE(zmask(nldi:nlei,nldj:nlej,1),(/ni,nj /)) /= 0. )
  1301. #else
  1302. CALL iom_set_domain_attr( "grid_"//cdgrd , mask = RESHAPE(zmask(nldi:nlei,nldj:nlej,1),(/ni*nj /)) /= 0. )
  1303. #endif
  1304. CALL iom_set_grid_attr ( "grid_"//cdgrd//"_3D", mask = RESHAPE(zmask(nldi:nlei,nldj:nlej,:),(/ni,nj,jpk/)) /= 0. )
  1305. ENDIF
  1306. END SUBROUTINE set_grid
  1307. SUBROUTINE set_grid_bounds( cdgrd, plon_cnr, plat_cnr, plon_pnt, plat_pnt )
  1308. !!----------------------------------------------------------------------
  1309. !! *** ROUTINE set_grid_bounds ***
  1310. !!
  1311. !! ** Purpose : define horizontal grid corners
  1312. !!
  1313. !!----------------------------------------------------------------------
  1314. CHARACTER(LEN=1) , INTENT(in) :: cdgrd
  1315. !
  1316. REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: plon_cnr, plat_cnr ! Lat/lon coordinates of a contiguous vertex of cell (i,j)
  1317. REAL(wp), DIMENSION(jpi,jpj), OPTIONAL, INTENT(in) :: plon_pnt, plat_pnt ! Lat/lon coordinates of the point of cell (i,j)
  1318. !
  1319. REAL(wp), ALLOCATABLE, DIMENSION(:,:,:,:) :: z_bnds ! Lat/lon coordinates of the vertices of cell (i,j)
  1320. REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: z_fld ! Working array to determine where to rotate cells
  1321. REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: z_rot ! Lat/lon working array for rotation of cells
  1322. !
  1323. INTEGER :: icnr, jcnr ! Offset such that the vertex coordinate (i+icnr,j+jcnr)
  1324. ! ! represents the bottom-left corner of cell (i,j)
  1325. INTEGER :: ji, jj, jn, ni, nj
  1326. ALLOCATE( z_bnds(4,jpi,jpj,2), z_fld(jpi,jpj), z_rot(4,2) )
  1327. ! Offset of coordinate representing bottom-left corner
  1328. SELECT CASE ( TRIM(cdgrd) )
  1329. CASE ('T', 'W')
  1330. icnr = -1 ; jcnr = -1
  1331. CASE ('U')
  1332. icnr = 0 ; jcnr = -1
  1333. CASE ('V')
  1334. icnr = -1 ; jcnr = 0
  1335. END SELECT
  1336. ni = nlei-nldi+1 ; nj = nlej-nldj+1 ! Dimensions of subdomain interior
  1337. z_fld(:,:) = 1._wp
  1338. CALL lbc_lnk( z_fld, cdgrd, -1. ) ! Working array for location of northfold
  1339. ! Cell vertices that can be defined
  1340. DO jj = 2, jpjm1
  1341. DO ji = 2, jpim1
  1342. z_bnds(1,ji,jj,1) = plat_cnr(ji+icnr, jj+jcnr ) ! Bottom-left
  1343. z_bnds(2,ji,jj,1) = plat_cnr(ji+icnr+1,jj+jcnr ) ! Bottom-right
  1344. z_bnds(3,ji,jj,1) = plat_cnr(ji+icnr+1,jj+jcnr+1) ! Top-right
  1345. z_bnds(4,ji,jj,1) = plat_cnr(ji+icnr, jj+jcnr+1) ! Top-left
  1346. z_bnds(1,ji,jj,2) = plon_cnr(ji+icnr, jj+jcnr ) ! Bottom-left
  1347. z_bnds(2,ji,jj,2) = plon_cnr(ji+icnr+1,jj+jcnr ) ! Bottom-right
  1348. z_bnds(3,ji,jj,2) = plon_cnr(ji+icnr+1,jj+jcnr+1) ! Top-right
  1349. z_bnds(4,ji,jj,2) = plon_cnr(ji+icnr, jj+jcnr+1) ! Top-left
  1350. END DO
  1351. END DO
  1352. ! Cell vertices on boundries
  1353. DO jn = 1, 4
  1354. CALL lbc_lnk( z_bnds(jn,:,:,1), cdgrd, 1., pval=999._wp )
  1355. CALL lbc_lnk( z_bnds(jn,:,:,2), cdgrd, 1., pval=999._wp )
  1356. END DO
  1357. ! Zero-size cells at closed boundaries if cell points provided,
  1358. ! otherwise they are closed cells with unrealistic bounds
  1359. IF( PRESENT(plon_pnt) .AND. PRESENT(plat_pnt) ) THEN
  1360. IF( (nbondi == -1 .OR. nbondi == 2) .AND. .NOT. (jperio == 1 .OR. jperio == 4 .OR. jperio == 6) ) THEN
  1361. DO jn = 1, 4 ! (West or jpni = 1), closed E-W
  1362. z_bnds(jn,1,:,1) = plat_pnt(1,:) ; z_bnds(jn,1,:,2) = plon_pnt(1,:)
  1363. END DO
  1364. ENDIF
  1365. IF( (nbondi == 1 .OR. nbondi == 2) .AND. .NOT. (jperio == 1 .OR. jperio == 4 .OR. jperio == 6) ) THEN
  1366. DO jn = 1, 4 ! (East or jpni = 1), closed E-W
  1367. z_bnds(jn,nlci,:,1) = plat_pnt(nlci,:) ; z_bnds(jn,nlci,:,2) = plon_pnt(nlci,:)
  1368. END DO
  1369. ENDIF
  1370. IF( nbondj == -1 .OR. (nbondj == 2 .AND. jperio /= 2) ) THEN
  1371. DO jn = 1, 4 ! South or (jpnj = 1, not symmetric)
  1372. z_bnds(jn,:,1,1) = plat_pnt(:,1) ; z_bnds(jn,:,1,2) = plon_pnt(:,1)
  1373. END DO
  1374. ENDIF
  1375. IF( (nbondj == 1 .OR. nbondj == 2) .AND. jperio < 3 ) THEN
  1376. DO jn = 1, 4 ! (North or jpnj = 1), no north fold
  1377. z_bnds(jn,:,nlcj,1) = plat_pnt(:,nlcj) ; z_bnds(jn,:,nlcj,2) = plon_pnt(:,nlcj)
  1378. END DO
  1379. ENDIF
  1380. ENDIF
  1381. ! Rotate cells at the north fold
  1382. IF( (nbondj == 1 .OR. nbondj == 2) .AND. jperio >= 3 ) THEN
  1383. DO jj = 1, jpj
  1384. DO ji = 1, jpi
  1385. IF( z_fld(ji,jj) == -1. ) THEN
  1386. z_rot(1,:) = z_bnds(3,ji,jj,:) ; z_rot(2,:) = z_bnds(4,ji,jj,:)
  1387. z_rot(3,:) = z_bnds(1,ji,jj,:) ; z_rot(4,:) = z_bnds(2,ji,jj,:)
  1388. z_bnds(:,ji,jj,:) = z_rot(:,:)
  1389. ENDIF
  1390. END DO
  1391. END DO
  1392. ! Invert cells at the symmetric equator
  1393. ELSE IF( nbondj == 2 .AND. jperio == 2 ) THEN
  1394. DO ji = 1, jpi
  1395. z_rot(1:2,:) = z_bnds(3:4,ji,1,:)
  1396. z_rot(3:4,:) = z_bnds(1:2,ji,1,:)
  1397. z_bnds(:,ji,1,:) = z_rot(:,:)
  1398. END DO
  1399. ENDIF
  1400. CALL iom_set_domain_attr("grid_"//cdgrd, bounds_lat = RESHAPE(z_bnds(:,nldi:nlei,nldj:nlej,1),(/ 4,ni*nj /)), &
  1401. bounds_lon = RESHAPE(z_bnds(:,nldi:nlei,nldj:nlej,2),(/ 4,ni*nj /)), nvertex=4 )
  1402. DEALLOCATE( z_bnds, z_fld, z_rot )
  1403. END SUBROUTINE set_grid_bounds
  1404. SUBROUTINE set_grid_znl( plat )
  1405. !!----------------------------------------------------------------------
  1406. !! *** ROUTINE set_grid_znl ***
  1407. !!
  1408. !! ** Purpose : define grids for zonal mean
  1409. !!
  1410. !!----------------------------------------------------------------------
  1411. REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: plat
  1412. !
  1413. REAL(wp), DIMENSION(:), ALLOCATABLE :: zlon
  1414. INTEGER :: ni,nj, ix, iy
  1415. ni=nlei-nldi+1 ; nj=nlej-nldj+1 ! define zonal mean domain (jpj*jpk)
  1416. ALLOCATE( zlon(ni*nj) ) ; zlon(:) = 0.
  1417. CALL dom_ngb( -168.53, 65.03, ix, iy, 'T' ) ! i-line that passes through Bering Strait: Reference latitude (used in plots)
  1418. #if ! defined key_xios2
  1419. CALL iom_set_domain_attr("gznl", ni_glo=jpiglo, nj_glo=jpjglo, ibegin=nimpp+nldi-1, jbegin=njmpp+nldj-1, ni=ni, nj=nj)
  1420. CALL iom_set_domain_attr("gznl", data_dim=2, data_ibegin = 1-nldi, data_ni = jpi, data_jbegin = 1-nldj, data_nj = jpj)
  1421. CALL iom_set_domain_attr("gznl", lonvalue = zlon, &
  1422. & latvalue = RESHAPE(plat(nldi:nlei, nldj:nlej),(/ ni*nj /)))
  1423. !
  1424. CALL iom_set_domain_attr ('ptr', zoom_ibegin=ix, zoom_nj=jpjglo)
  1425. #else
  1426. ! Pas teste : attention aux indices !
  1427. CALL iom_set_domain_attr("gznl", ni_glo=jpiglo, nj_glo=jpjglo, ibegin=nimpp+nldi-2, jbegin=njmpp+nldj-2, ni=ni, nj=nj)
  1428. CALL iom_set_domain_attr("gznl", data_dim=2, data_ibegin = 1-nldi, data_ni = jpi, data_jbegin = 1-nldj, data_nj = jpj)
  1429. CALL iom_set_domain_attr("gznl", lonvalue = zlon, &
  1430. & latvalue = RESHAPE(plat(nldi:nlei, nldj:nlej),(/ ni*nj /)))
  1431. CALL iom_set_zoom_domain_attr ("ptr", ibegin=ix-1, jbegin=0, ni=1, nj=jpjglo)
  1432. #endif
  1433. CALL iom_update_file_name('ptr')
  1434. !
  1435. END SUBROUTINE set_grid_znl
  1436. SUBROUTINE set_scalar
  1437. !!----------------------------------------------------------------------
  1438. !! *** ROUTINE set_scalar ***
  1439. !!
  1440. !! ** Purpose : define fake grids for scalar point
  1441. !!
  1442. !!----------------------------------------------------------------------
  1443. REAL(wp), DIMENSION(1) :: zz = 1.
  1444. !!----------------------------------------------------------------------
  1445. #if ! defined key_xios2
  1446. CALL iom_set_domain_attr('scalarpoint', ni_glo=jpnij, nj_glo=1, ibegin=narea, jbegin=1, ni=1, nj=1)
  1447. #else
  1448. CALL iom_set_domain_attr('scalarpoint', ni_glo=jpnij, nj_glo=1, ibegin=narea-1, jbegin=0, ni=1, nj=1)
  1449. #endif
  1450. CALL iom_set_domain_attr('scalarpoint', data_dim=2, data_ibegin = 1, data_ni = 1, data_jbegin = 1, data_nj = 1)
  1451. zz=REAL(narea,wp)
  1452. CALL iom_set_domain_attr('scalarpoint', lonvalue=zz, latvalue=zz)
  1453. END SUBROUTINE set_scalar
  1454. SUBROUTINE set_1point
  1455. !!----------------------------------------------------------------------
  1456. !! *** ROUTINE set_1point ***
  1457. !!
  1458. !! ** Purpose : define zoom grid for scalar fields
  1459. !!
  1460. !!----------------------------------------------------------------------
  1461. REAL(wp), DIMENSION(1) :: zz = 1.
  1462. INTEGER :: ix, iy
  1463. !!----------------------------------------------------------------------
  1464. CALL dom_ngb( 180., 90., ix, iy, 'T' ) ! Nearest point to north pole should be ocean
  1465. CALL iom_set_domain_attr('1point', zoom_ibegin=ix, zoom_jbegin=iy)
  1466. END SUBROUTINE set_1point
  1467. SUBROUTINE set_xmlatt
  1468. !!----------------------------------------------------------------------
  1469. !! *** ROUTINE set_xmlatt ***
  1470. !!
  1471. !! ** Purpose : automatic definitions of some of the xml attributs...
  1472. !!
  1473. !!----------------------------------------------------------------------
  1474. CHARACTER(len=1),DIMENSION( 3) :: clgrd ! suffix name
  1475. CHARACTER(len=256) :: clsuff ! suffix name
  1476. CHARACTER(len=1) :: cl1 ! 1 character
  1477. CHARACTER(len=2) :: cl2 ! 2 characters
  1478. CHARACTER(len=3) :: cl3 ! 3 characters
  1479. INTEGER :: ji, jg ! loop counters
  1480. INTEGER :: ix, iy ! i-,j- index
  1481. REAL(wp) ,DIMENSION(11) :: zlontao ! longitudes of tao moorings
  1482. REAL(wp) ,DIMENSION( 7) :: zlattao ! latitudes of tao moorings
  1483. REAL(wp) ,DIMENSION( 4) :: zlonrama ! longitudes of rama moorings
  1484. REAL(wp) ,DIMENSION(11) :: zlatrama ! latitudes of rama moorings
  1485. REAL(wp) ,DIMENSION( 3) :: zlonpira ! longitudes of pirata moorings
  1486. REAL(wp) ,DIMENSION( 9) :: zlatpira ! latitudes of pirata moorings
  1487. #if defined key_xios2
  1488. TYPE(xios_duration) :: f_op, f_of
  1489. #endif
  1490. !!----------------------------------------------------------------------
  1491. !
  1492. ! frequency of the call of iom_put (attribut: freq_op)
  1493. #if ! defined key_xios2
  1494. WRITE(cl1,'(i1)') 1 ; CALL iom_set_field_attr('field_definition', freq_op=cl1//'ts', freq_offset='0ts')
  1495. WRITE(cl1,'(i1)') 2 ; CALL iom_set_field_attr('trendT_even' , freq_op=cl1//'ts', freq_offset='0ts')
  1496. WRITE(cl1,'(i1)') 2 ; CALL iom_set_field_attr('trendT_odd' , freq_op=cl1//'ts', freq_offset='-1ts')
  1497. WRITE(cl1,'(i1)') nn_fsbc ; CALL iom_set_field_attr('SBC' , freq_op=cl1//'ts', freq_offset='0ts')
  1498. WRITE(cl1,'(i1)') nn_fsbc ; CALL iom_set_field_attr('SBC_scalar' , freq_op=cl1//'ts', freq_offset='0ts')
  1499. WRITE(cl1,'(i1)') nn_dttrc ; CALL iom_set_field_attr('ptrc_T' , freq_op=cl1//'ts', freq_offset='0ts')
  1500. WRITE(cl1,'(i1)') nn_dttrc ; CALL iom_set_field_attr('diad_T' , freq_op=cl1//'ts', freq_offset='0ts')
  1501. #else
  1502. f_op%timestep = 1 ; f_of%timestep = 0 ; CALL iom_set_field_attr('field_definition', freq_op=f_op, freq_offset=f_of)
  1503. f_op%timestep = 2 ; f_of%timestep = 0 ; CALL iom_set_field_attr('trendT_even' , freq_op=f_op, freq_offset=f_of)
  1504. f_op%timestep = 2 ; f_of%timestep = -1 ; CALL iom_set_field_attr('trendT_odd' , freq_op=f_op, freq_offset=f_of)
  1505. f_op%timestep = nn_fsbc ; f_of%timestep = 0 ; CALL iom_set_field_attr('SBC' , freq_op=f_op, freq_offset=f_of)
  1506. f_op%timestep = nn_fsbc ; f_of%timestep = 0 ; CALL iom_set_field_attr('SBC_scalar' , freq_op=f_op, freq_offset=f_of)
  1507. f_op%timestep = nn_dttrc ; f_of%timestep = 0 ; CALL iom_set_field_attr('ptrc_T' , freq_op=f_op, freq_offset=f_of)
  1508. f_op%timestep = nn_dttrc ; f_of%timestep = 0 ; CALL iom_set_field_attr('diad_T' , freq_op=f_op, freq_offset=f_of)
  1509. #endif
  1510. ! output file names (attribut: name)
  1511. DO ji = 1, 9
  1512. WRITE(cl1,'(i1)') ji
  1513. CALL iom_update_file_name('file'//cl1)
  1514. END DO
  1515. DO ji = 1, 99
  1516. WRITE(cl2,'(i2.2)') ji
  1517. CALL iom_update_file_name('file'//cl2)
  1518. END DO
  1519. DO ji = 1, 999
  1520. WRITE(cl3,'(i3.3)') ji
  1521. CALL iom_update_file_name('file'//cl3)
  1522. END DO
  1523. ! Zooms...
  1524. clgrd = (/ 'T', 'U', 'W' /)
  1525. DO jg = 1, SIZE(clgrd) ! grid type
  1526. cl1 = clgrd(jg)
  1527. ! Equatorial section (attributs: jbegin, ni, name_suffix)
  1528. CALL dom_ngb( 0., 0., ix, iy, cl1 )
  1529. #if ! defined key_xios2
  1530. CALL iom_set_domain_attr ('Eq'//cl1, zoom_jbegin=iy, zoom_ni=jpiglo)
  1531. #else
  1532. CALL iom_set_zoom_domain_attr ('Eq'//cl1, jbegin=iy-1, ni=jpiglo)
  1533. #endif
  1534. CALL iom_get_file_attr ('Eq'//cl1, name_suffix = clsuff )
  1535. CALL iom_set_file_attr ('Eq'//cl1, name_suffix = TRIM(clsuff)//'_Eq')
  1536. CALL iom_update_file_name('Eq'//cl1)
  1537. END DO
  1538. ! TAO moorings (attributs: ibegin, jbegin, name_suffix)
  1539. zlontao = (/ 137.0, 147.0, 156.0, 165.0, -180.0, -170.0, -155.0, -140.0, -125.0, -110.0, -95.0 /)
  1540. zlattao = (/ -8.0, -5.0, -2.0, 0.0, 2.0, 5.0, 8.0 /)
  1541. CALL set_mooring( zlontao, zlattao )
  1542. ! RAMA moorings (attributs: ibegin, jbegin, name_suffix)
  1543. zlonrama = (/ 55.0, 67.0, 80.5, 90.0 /)
  1544. zlatrama = (/ -16.0, -12.0, -8.0, -4.0, -1.5, 0.0, 1.5, 4.0, 8.0, 12.0, 15.0 /)
  1545. CALL set_mooring( zlonrama, zlatrama )
  1546. ! PIRATA moorings (attributs: ibegin, jbegin, name_suffix)
  1547. zlonpira = (/ -38.0, -23.0, -10.0 /)
  1548. zlatpira = (/ -19.0, -14.0, -8.0, 0.0, 4.0, 8.0, 12.0, 15.0, 20.0 /)
  1549. CALL set_mooring( zlonpira, zlatpira )
  1550. END SUBROUTINE set_xmlatt
  1551. SUBROUTINE set_mooring( plon, plat)
  1552. !!----------------------------------------------------------------------
  1553. !! *** ROUTINE set_mooring ***
  1554. !!
  1555. !! ** Purpose : automatic definitions of moorings xml attributs...
  1556. !!
  1557. !!----------------------------------------------------------------------
  1558. REAL(wp), DIMENSION(:), INTENT(in) :: plon, plat ! longitudes/latitudes oft the mooring
  1559. !
  1560. !!$ CHARACTER(len=1),DIMENSION(4) :: clgrd = (/ 'T', 'U', 'V', 'W' /) ! suffix name
  1561. CHARACTER(len=1),DIMENSION(1) :: clgrd = (/ 'T' /) ! suffix name
  1562. CHARACTER(len=256) :: clname ! file name
  1563. CHARACTER(len=256) :: clsuff ! suffix name
  1564. CHARACTER(len=1) :: cl1 ! 1 character
  1565. CHARACTER(len=6) :: clon,clat ! name of longitude, latitude
  1566. INTEGER :: ji, jj, jg ! loop counters
  1567. INTEGER :: ix, iy ! i-,j- index
  1568. REAL(wp) :: zlon, zlat
  1569. !!----------------------------------------------------------------------
  1570. DO jg = 1, SIZE(clgrd)
  1571. cl1 = clgrd(jg)
  1572. DO ji = 1, SIZE(plon)
  1573. DO jj = 1, SIZE(plat)
  1574. zlon = plon(ji)
  1575. zlat = plat(jj)
  1576. ! modifications for RAMA moorings
  1577. IF( zlon == 67. .AND. zlat == 15. ) zlon = 65.
  1578. IF( zlon == 90. .AND. zlat <= -4. ) zlon = 95.
  1579. IF( zlon == 95. .AND. zlat == -4. ) zlat = -5.
  1580. ! modifications for PIRATA moorings
  1581. IF( zlon == -38. .AND. zlat == -19. ) zlon = -34.
  1582. IF( zlon == -38. .AND. zlat == -14. ) zlon = -32.
  1583. IF( zlon == -38. .AND. zlat == -8. ) zlon = -30.
  1584. IF( zlon == -38. .AND. zlat == 0. ) zlon = -35.
  1585. IF( zlon == -23. .AND. zlat == 20. ) zlat = 21.
  1586. IF( zlon == -10. .AND. zlat == -14. ) zlat = -10.
  1587. IF( zlon == -10. .AND. zlat == -8. ) zlat = -6.
  1588. IF( zlon == -10. .AND. zlat == 4. ) THEN ; zlon = 0. ; zlat = 0. ; ENDIF
  1589. CALL dom_ngb( zlon, zlat, ix, iy, cl1 )
  1590. IF( zlon >= 0. ) THEN
  1591. IF( zlon == REAL(NINT(zlon), wp) ) THEN ; WRITE(clon, '(i3, a)') NINT( zlon), 'e'
  1592. ELSE ; WRITE(clon, '(f5.1,a)') zlon , 'e'
  1593. ENDIF
  1594. ELSE
  1595. IF( zlon == REAL(NINT(zlon), wp) ) THEN ; WRITE(clon, '(i3, a)') NINT(-zlon), 'w'
  1596. ELSE ; WRITE(clon, '(f5.1,a)') -zlon , 'w'
  1597. ENDIF
  1598. ENDIF
  1599. IF( zlat >= 0. ) THEN
  1600. IF( zlat == REAL(NINT(zlat), wp) ) THEN ; WRITE(clat, '(i2, a)') NINT( zlat), 'n'
  1601. ELSE ; WRITE(clat, '(f4.1,a)') zlat , 'n'
  1602. ENDIF
  1603. ELSE
  1604. IF( zlat == REAL(NINT(zlat), wp) ) THEN ; WRITE(clat, '(i2, a)') NINT(-zlat), 's'
  1605. ELSE ; WRITE(clat, '(f4.1,a)') -zlat , 's'
  1606. ENDIF
  1607. ENDIF
  1608. clname = TRIM(ADJUSTL(clat))//TRIM(ADJUSTL(clon))
  1609. #if ! defined key_xios2
  1610. CALL iom_set_domain_attr (TRIM(clname)//cl1, zoom_ibegin= ix, zoom_jbegin= iy)
  1611. #else
  1612. CALL iom_set_zoom_domain_attr (TRIM(clname)//cl1, ibegin= ix-1, jbegin= iy-1)
  1613. #endif
  1614. CALL iom_get_file_attr (TRIM(clname)//cl1, name_suffix = clsuff )
  1615. CALL iom_set_file_attr (TRIM(clname)//cl1, name_suffix = TRIM(clsuff)//'_'//TRIM(clname))
  1616. CALL iom_update_file_name(TRIM(clname)//cl1)
  1617. END DO
  1618. END DO
  1619. END DO
  1620. END SUBROUTINE set_mooring
  1621. SUBROUTINE iom_update_file_name( cdid )
  1622. !!----------------------------------------------------------------------
  1623. !! *** ROUTINE iom_update_file_name ***
  1624. !!
  1625. !! ** Purpose :
  1626. !!
  1627. !!----------------------------------------------------------------------
  1628. CHARACTER(LEN=*) , INTENT(in) :: cdid
  1629. !
  1630. CHARACTER(LEN=256) :: clname
  1631. CHARACTER(LEN=20) :: clfreq
  1632. CHARACTER(LEN=20) :: cldate
  1633. INTEGER :: idx
  1634. INTEGER :: jn
  1635. INTEGER :: itrlen
  1636. INTEGER :: iyear, imonth, iday, isec
  1637. REAL(wp) :: zsec
  1638. LOGICAL :: llexist
  1639. #if defined key_xios2
  1640. TYPE(xios_duration) :: output_freq
  1641. #endif
  1642. !!----------------------------------------------------------------------
  1643. DO jn = 1,2
  1644. #if ! defined key_xios2
  1645. IF( jn == 1 ) CALL iom_get_file_attr( cdid, name = clname, output_freq = clfreq )
  1646. #else
  1647. output_freq = xios_duration(0,0,0,0,0,0)
  1648. IF( jn == 1 ) CALL iom_get_file_attr( cdid, name = clname, output_freq = output_freq )
  1649. #endif
  1650. IF( jn == 2 ) CALL iom_get_file_attr( cdid, name_suffix = clname )
  1651. IF ( TRIM(clname) /= '' ) THEN
  1652. idx = INDEX(clname,'@expname@') + INDEX(clname,'@EXPNAME@')
  1653. DO WHILE ( idx /= 0 )
  1654. clname = clname(1:idx-1)//TRIM(cexper)//clname(idx+9:LEN_TRIM(clname))
  1655. idx = INDEX(clname,'@expname@') + INDEX(clname,'@EXPNAME@')
  1656. END DO
  1657. #if ! defined key_xios2
  1658. idx = INDEX(clname,'@freq@') + INDEX(clname,'@FREQ@')
  1659. DO WHILE ( idx /= 0 )
  1660. IF ( TRIM(clfreq) /= '' ) THEN
  1661. itrlen = LEN_TRIM(clfreq)
  1662. IF ( clfreq(itrlen-1:itrlen) == 'mo' ) clfreq = clfreq(1:itrlen-1)
  1663. clname = clname(1:idx-1)//TRIM(clfreq)//clname(idx+6:LEN_TRIM(clname))
  1664. ELSE
  1665. CALL ctl_stop('error in the name of file id '//TRIM(cdid), &
  1666. & ' attribute output_freq is undefined -> cannot replace @freq@ in '//TRIM(clname) )
  1667. ENDIF
  1668. idx = INDEX(clname,'@freq@') + INDEX(clname,'@FREQ@')
  1669. END DO
  1670. #else
  1671. idx = INDEX(clname,'@freq@') + INDEX(clname,'@FREQ@')
  1672. DO WHILE ( idx /= 0 )
  1673. IF ( output_freq%timestep /= 0) THEN
  1674. WRITE(clfreq,'(I18,A2)')INT(output_freq%timestep),'ts'
  1675. itrlen = LEN_TRIM(ADJUSTL(clfreq))
  1676. ELSE IF ( output_freq%hour /= 0 ) THEN
  1677. WRITE(clfreq,'(I19,A1)')INT(output_freq%hour),'h'
  1678. itrlen = LEN_TRIM(ADJUSTL(clfreq))
  1679. ELSE IF ( output_freq%day /= 0 ) THEN
  1680. WRITE(clfreq,'(I19,A1)')INT(output_freq%day),'d'
  1681. itrlen = LEN_TRIM(ADJUSTL(clfreq))
  1682. ELSE IF ( output_freq%month /= 0 ) THEN
  1683. WRITE(clfreq,'(I19,A1)')INT(output_freq%month),'m'
  1684. itrlen = LEN_TRIM(ADJUSTL(clfreq))
  1685. ELSE IF ( output_freq%year /= 0 ) THEN
  1686. WRITE(clfreq,'(I19,A1)')INT(output_freq%year),'y'
  1687. itrlen = LEN_TRIM(ADJUSTL(clfreq))
  1688. ELSE
  1689. CALL ctl_stop('error in the name of file id '//TRIM(cdid), &
  1690. & ' attribute output_freq is undefined -> cannot replace @freq@ in '//TRIM(clname) )
  1691. ENDIF
  1692. clname = clname(1:idx-1)//TRIM(ADJUSTL(clfreq))//clname(idx+6:LEN_TRIM(clname))
  1693. idx = INDEX(clname,'@freq@') + INDEX(clname,'@FREQ@')
  1694. END DO
  1695. #endif
  1696. idx = INDEX(clname,'@startdate@') + INDEX(clname,'@STARTDATE@')
  1697. DO WHILE ( idx /= 0 )
  1698. cldate = iom_sdate( fjulday - rdttra(1) / rday )
  1699. clname = clname(1:idx-1)//TRIM(cldate)//clname(idx+11:LEN_TRIM(clname))
  1700. idx = INDEX(clname,'@startdate@') + INDEX(clname,'@STARTDATE@')
  1701. END DO
  1702. idx = INDEX(clname,'@startdatefull@') + INDEX(clname,'@STARTDATEFULL@')
  1703. DO WHILE ( idx /= 0 )
  1704. cldate = iom_sdate( fjulday - rdttra(1) / rday, ldfull = .TRUE. )
  1705. clname = clname(1:idx-1)//TRIM(cldate)//clname(idx+15:LEN_TRIM(clname))
  1706. idx = INDEX(clname,'@startdatefull@') + INDEX(clname,'@STARTDATEFULL@')
  1707. END DO
  1708. idx = INDEX(clname,'@enddate@') + INDEX(clname,'@ENDDATE@')
  1709. DO WHILE ( idx /= 0 )
  1710. cldate = iom_sdate( fjulday + rdttra(1) / rday * REAL( nitend - nit000, wp ), ld24 = .TRUE. )
  1711. clname = clname(1:idx-1)//TRIM(cldate)//clname(idx+9:LEN_TRIM(clname))
  1712. idx = INDEX(clname,'@enddate@') + INDEX(clname,'@ENDDATE@')
  1713. END DO
  1714. idx = INDEX(clname,'@enddatefull@') + INDEX(clname,'@ENDDATEFULL@')
  1715. DO WHILE ( idx /= 0 )
  1716. cldate = iom_sdate( fjulday + rdttra(1) / rday * REAL( nitend - nit000, wp ), ld24 = .TRUE., ldfull = .TRUE. )
  1717. clname = clname(1:idx-1)//TRIM(cldate)//clname(idx+13:LEN_TRIM(clname))
  1718. idx = INDEX(clname,'@enddatefull@') + INDEX(clname,'@ENDDATEFULL@')
  1719. END DO
  1720. IF( jn == 1 .AND. TRIM(Agrif_CFixed()) /= '0' ) clname = TRIM(Agrif_CFixed())//"_"//TRIM(clname)
  1721. IF( jn == 1 ) CALL iom_set_file_attr( cdid, name = clname )
  1722. IF( jn == 2 ) CALL iom_set_file_attr( cdid, name_suffix = clname )
  1723. ENDIF
  1724. END DO
  1725. END SUBROUTINE iom_update_file_name
  1726. FUNCTION iom_sdate( pjday, ld24, ldfull )
  1727. !!----------------------------------------------------------------------
  1728. !! *** ROUTINE iom_sdate ***
  1729. !!
  1730. !! ** Purpose : send back the date corresponding to the given julian day
  1731. !!
  1732. !!----------------------------------------------------------------------
  1733. REAL(wp), INTENT(in ) :: pjday ! julian day
  1734. LOGICAL , INTENT(in ), OPTIONAL :: ld24 ! true to force 24:00 instead of 00:00
  1735. LOGICAL , INTENT(in ), OPTIONAL :: ldfull ! true to get the compleate date: yyyymmdd_hh:mm:ss
  1736. !
  1737. CHARACTER(LEN=20) :: iom_sdate
  1738. CHARACTER(LEN=50) :: clfmt ! format used to write the date
  1739. INTEGER :: iyear, imonth, iday, ihour, iminute, isec
  1740. REAL(wp) :: zsec
  1741. LOGICAL :: ll24, llfull
  1742. !
  1743. IF( PRESENT(ld24) ) THEN ; ll24 = ld24
  1744. ELSE ; ll24 = .FALSE.
  1745. ENDIF
  1746. IF( PRESENT(ldfull) ) THEN ; llfull = ldfull
  1747. ELSE ; llfull = .FALSE.
  1748. ENDIF
  1749. CALL ju2ymds( pjday, iyear, imonth, iday, zsec )
  1750. isec = NINT(zsec)
  1751. IF ( ll24 .AND. isec == 0 ) THEN ! 00:00 of the next day -> move to 24:00 of the current day
  1752. CALL ju2ymds( pjday - 1., iyear, imonth, iday, zsec )
  1753. isec = 86400
  1754. ENDIF
  1755. IF( iyear < 10000 ) THEN ; clfmt = "i4.4,2i2.2" ! format used to write the date
  1756. ELSE ; WRITE(clfmt, "('i',i1,',2i2.2')") INT(LOG10(REAL(iyear,wp))) + 1
  1757. ENDIF
  1758. !$AGRIF_DO_NOT_TREAT
  1759. ! Should be fixed in the conv
  1760. IF( llfull ) THEN
  1761. clfmt = TRIM(clfmt)//",'_',i2.2,':',i2.2,':',i2.2"
  1762. ihour = isec / 3600
  1763. isec = MOD(isec, 3600)
  1764. iminute = isec / 60
  1765. isec = MOD(isec, 60)
  1766. WRITE(iom_sdate, '('//TRIM(clfmt)//')') iyear, imonth, iday, ihour, iminute, isec ! date of the end of run
  1767. ELSE
  1768. WRITE(iom_sdate, '('//TRIM(clfmt)//')') iyear, imonth, iday ! date of the end of run
  1769. ENDIF
  1770. !$AGRIF_END_DO_NOT_TREAT
  1771. END FUNCTION iom_sdate
  1772. #else
  1773. SUBROUTINE iom_setkt( kt, cdname )
  1774. INTEGER , INTENT(in):: kt
  1775. CHARACTER(LEN=*), INTENT(in) :: cdname
  1776. IF( .FALSE. ) WRITE(numout,*) kt, cdname ! useless test to avoid compilation warnings
  1777. END SUBROUTINE iom_setkt
  1778. SUBROUTINE iom_context_finalize( cdname )
  1779. CHARACTER(LEN=*), INTENT(in) :: cdname
  1780. IF( .FALSE. ) WRITE(numout,*) cdname ! useless test to avoid compilation warnings
  1781. END SUBROUTINE iom_context_finalize
  1782. #endif
  1783. LOGICAL FUNCTION iom_use( cdname )
  1784. CHARACTER(LEN=*), INTENT(in) :: cdname
  1785. #if defined key_iomput
  1786. iom_use = xios_field_is_active( cdname )
  1787. #else
  1788. iom_use = .FALSE.
  1789. #endif
  1790. END FUNCTION iom_use
  1791. !!======================================================================
  1792. END MODULE iom