iom.F90 115 KB

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