iom.F90 113 KB

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