Changeset 6647 for TOOLS


Ignore:
Timestamp:
10/10/23 12:58:04 (7 months ago)
Author:
omamce
Message:

O.M. :

New version of WATER_BUDGET

  • Conservation in NEMO are OK
  • Conservation in Sechiba are OK, for both ICO and latlon grids
  • Problems in atmosphere, LIC surface and ocean/atmosphere coherence
Location:
TOOLS/WATER_BUDGET
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • TOOLS/WATER_BUDGET/ATM_waterbudget.py

    r6620 r6647  
    3434    raise Exception ( "Minimum Python version is 3.8" ) 
    3535 
    36 ## Import local module 
     36## Import local modules 
    3737import WaterUtils as wu 
    3838import libIGCM_sys 
    3939import nemo, lmdz 
     40 
     41from WaterUtils import VarInt, Rho, Ra, Grav, ICE_rho_ice, ICE_rho_sno, OCE_rho_liq, ATM_rho, SRF_rho, RUN_rho, ICE_rho_pnd, YearLength 
    4042 
    4143## Creates parser for reading .ini input file 
     
    4749## --------------------- 
    4850ATM=None ; ATM_HIS='latlon' ; SRF_HIS='latlon' ; RUN_HIS='latlon' ; ORCA=None ; NEMO=None ; OCE_relax=False 
    49 OCE_icb=False ; Coupled=False ; Routing=None 
     51OCE_icb=False ; Coupled=False ; Routing=None ; TestInterp=None 
    5052TarRestartPeriod_beg=None ; TarRestartPeriod_end=None ; Comment=None ; Period=None ; Title=None 
     53YearBegin=None ; YearEnd=None ; DateBegin=None ; DateEnd=None 
    5154 
    5255## 
     
    6669tar_restart_end_RUN=None ; tar_restart_end_OCE=None ; tar_restart_end_ICE=None 
    6770ContinueOnError=False ; ErrorCount=0 ; SortIco = False 
     71 
     72## 
     73## Precision of history file reading 
     74## --------------------------------- 
     75# Default is float (full precision). Degrade the precision by using np.float32 
     76# Restart file are always read at the full precision 
     77readPrec=float 
    6878 
    6979## Read command line arguments 
     
    138148print ( f'\nConfig file readed : {IniFile} ' ) 
    139149 
     150## 
     151## Reading prec 
     152if wu.unDefined ( 'readPrec' )  : 
     153    readPrec = np.float64 
     154else : 
     155    if readPrec in ["float", "float64", "r8", "double", "<class 'float'>"         ] : readPrec = float 
     156    if readPrec in [         "float32", "r4", "single", "<class 'numpy.float32'>" ] : readPrec = np.float32 
     157    if readPrec in [         "float16", "r2", "half"  , "<class 'numpy.float16'>" ] : readPrec = np.float16 
     158     
    140159## Some physical constants 
    141160## ======================= 
     
    155174if not 'Files' in config.keys () : config['Files'] = {} 
    156175 
    157 config['Physics'] = { 'Ra':Ra, 'Grav':Grav, 'ICE_rho_ice':ICE_rho_ice, 'ICE_rho_sno':ICE_rho_sno, 
    158                       'OCE_rho_liq':OCE_rho_liq, 'ATM_rho':ATM_rho, 'SRF_rho':SRF_rho, 'RUN_rho':RUN_rho} 
    159  
    160 config['Config'] = { 'ContinueOnError':ContinueOnError, 'SortIco':SortIco } 
     176config['Physics'] = { 'Ra':str(Ra), 'Grav':str(Grav), 'ICE_rho_ice':str(ICE_rho_ice), 'ICE_rho_sno':str(ICE_rho_sno), 
     177                      'OCE_rho_liq':str(OCE_rho_liq), 'ATM_rho':str(ATM_rho), 'SRF_rho':str(SRF_rho), 'RUN_rho':str(RUN_rho)} 
     178 
     179config['Config'] = { 'ContinueOnError':str(ContinueOnError), 'SortIco':str(SortIco), 'TestInterp':str(TestInterp), 'readPrec':str(readPrec) } 
    161180 
    162181## -------------------------- 
     
    176195if wu.unDefined ( 'DateBegin' ) : 
    177196    DateBegin = f'{YearBegin}0101' 
    178     config['Experiment']['DateBegin'] = DateBegin 
     197    config['Experiment']['DateBegin'] = str(DateBegin) 
    179198else : 
    180     YearBegin, MonthBegin, DayBegin = wu.DateSplit ( DateBegin ) 
    181     DateBegin = wu.FormatToGregorian ( DateBegin) 
    182     config['Experiment']['YearBegin'] = YearBegin 
     199    YearBegin, MonthBegin, DayBegin = wu.SplitDate ( DateBegin ) 
     200    DateBegin = wu.FormatToGregorian (DateBegin) 
     201    config['Experiment']['YearBegin'] = str(YearBegin) 
    183202 
    184203if wu.unDefined ( 'DateEnd' )   : 
    185204    DateEnd   = f'{YearEnd}1231' 
    186     config['Experiment']['DateEnd']   = DateEnd 
     205    config['Experiment']['DateEnd'] = str(DateEnd) 
    187206else : 
    188     YearEnd, MonthEnd, DayEnd = wu.DateSplit ( DateEnd ) 
    189     DateEnd   = wu.FormatToGregorian ( DateEnd) 
     207    YearEnd, MonthEnd, DayEnd = wu.SplitDate ( DateEnd ) 
     208    DateEnd   = wu.FormatToGregorian (DateEnd) 
     209    config['Experiment']['DateEnd'] = str(DateEnd) 
    190210 
    191211if wu.unDefined ( 'PackFrequency' ) : 
     
    200220## Output file with water budget diagnostics 
    201221## ----------------------------------------- 
    202 if wu.unDefined ( 'FileOut' ) : FileOut = f'ATM_waterbudget_{JobName}_{DateBegin}_{DateEnd}.out' 
     222if wu.unDefined ( 'FileOut' ) : 
     223    FileOut = f'ATM_waterbudget_{JobName}_{YearBegin}_{YearEnd}' 
     224    if ICO :  
     225        if ATM_HIS == 'latlon' : FileOut = f'{FileOut}_LATLON' 
     226        if ATM_HIS == 'ico'    : FileOut = f'{FileOut}_ICO' 
     227    if readPrec == np.float32  : FileOut = f'{FileOut}_float32' 
     228    FileOut = f'{FileOut}.out' 
     229 
    203230config['Files']['FileOut'] = FileOut 
    204231 
     
    207234## Useful functions 
    208235## ---------------- 
     236if readPrec == float : 
     237    def rprec (tab) : return tab 
     238else :  
     239    def rprec (tab) : return tab.astype(readPrec).astype(float) 
     240     
    209241def kg2Sv    (val, rho=ATM_rho) : 
    210242    '''From kg to Sverdrup''' 
     
    216248 
    217249def var2prt (var, small=False, rho=ATM_rho) : 
    218     if small :  return var , kg2Sv(var, rho=rho)*1000., kg2myear(var, rho=rho)*100# 
     250    if small :  return var , kg2Sv(var, rho=rho)*1000., kg2myear(var, rho=rho)*1000 
    219251    else     :  return var , kg2Sv(var, rho=rho)      , kg2myear(var, rho=rho) 
    220252 
     
    236268    f_out.flush () 
    237269    return None 
    238      
     270 
     271echo ( f'{ContinueOnError = }' ) 
     272echo ( f'{SortIco         = }' ) 
     273echo ( f'{readPrec        = }' ) 
     274 
     275echo ( f'{JobName         = }' ) 
     276echo ( f'{ConfigCard      = }' ) 
     277echo ( f'{libIGCM         = }' )      
     278echo ( f'{User            = }' )        
     279echo ( f'{Group           = }' )        
     280echo ( f'{Freq            = }' )        
     281echo ( f'{YearBegin       = }' )      
     282echo ( f'{YearEnd         = }' )      
     283echo ( f'{DateBegin       = }' ) 
     284echo ( f'{DateEnd         = }' ) 
     285echo ( f'{PackFrequency   = }' )  
     286echo ( f'{ATM             = }' )        
     287echo ( f'{Routing         = }' )        
     288echo ( f'{ORCA            = }' )       
     289echo ( f'{NEMO            = }' )       
     290echo ( f'{Coupled         = }' )       
     291echo ( f'{ATM_HIS         = }' )       
     292echo ( f'{SRF_HIS         = }' )       
     293echo ( f'{RUN_HIS         = }' )       
     294 
    239295## Set libIGCM directories 
    240296## ----------------------- 
     
    266322 
    267323echo (' ') 
    268 echo ( f'JobName    : {JobName}'   ) 
    269 echo ( f'Comment    : {Comment}'   ) 
    270 echo ( f'TmpDir     : {TmpDir}'    ) 
     324echo ( f'JobName     : {JobName}'    ) 
     325echo ( f'Comment     : {Comment}'    ) 
     326echo ( f'TmpDir      : {TmpDir}'     ) 
    271327echo ( f'FileDir     : {FileDir}'    ) 
    272328echo ( f'FileDirOCE  : {FileDirOCE}' ) 
     
    598654# ATM grid with cell surfaces 
    599655if LMDZ : 
    600     ATM_lat  = lmdz.geo2point (   d_ATM_his ['lat']+0*d_ATM_his ['lon'], dim1D='cell_latlon' ) 
    601     ATM_lon  = lmdz.geo2point ( 0*d_ATM_his ['lat']+  d_ATM_his ['lon'], dim1D='cell_latlon' ) 
    602     ATM_aire = lmdz.geo2point ( d_ATM_his ['aire']     [0], cumulPoles=True, dim1D='cell_latlon' ) 
    603     ATM_fter = lmdz.geo2point ( d_ATM_his ['fract_ter'][0], dim1D='cell_latlon' ) 
    604     ATM_foce = lmdz.geo2point ( d_ATM_his ['fract_oce'][0], dim1D='cell_latlon' ) 
    605     ATM_fsic = lmdz.geo2point ( d_ATM_his ['fract_sic'][0], dim1D='cell_latlon' ) 
    606     ATM_flic = lmdz.geo2point ( d_ATM_his ['fract_lic'][0], dim1D='cell_latlon' ) 
    607     SRF_lat  = lmdz.geo2point (   d_SRF_his ['lat']+0*d_SRF_his ['lon'], dim1D='cell_latlon' ) 
    608     SRF_lon  = lmdz.geo2point ( 0*d_SRF_his ['lat']+  d_SRF_his ['lon'], dim1D='cell_latlon' ) 
    609     SRF_aire      = lmdz.geo2point ( d_SRF_his ['Areas'] * d_SRF_his ['Contfrac'], dim1D='cell_latlonl', cumulPoles=True ) 
    610     SRF_areas     = lmdz.geo2point ( d_SRF_his ['Areas'],  dim1D='cell_latlonl', cumulPoles=True ) 
    611     SRF_contfrac  = lmdz.geo2point ( d_SRF_his ['Contfrac'], dim1D='cell_latlonl' ) 
    612  
    613     #SRF_res_aire = SRF_aire 
    614      
     656    echo ('ATM grid with cell surfaces : LMDZ') 
     657    ATM_lat       = lmdz.geo2point (   rprec (d_ATM_his ['lat'])+0*rprec (d_ATM_his ['lon']), dim1D='cell' ) 
     658    ATM_lon       = lmdz.geo2point ( 0*rprec (d_ATM_his ['lat'])+  rprec (d_ATM_his ['lon']), dim1D='cell' ) 
     659    ATM_aire      = lmdz.geo2point ( rprec (d_ATM_his ['aire'] )    [0], cumulPoles=True, dim1D='cell' ) 
     660    ATM_fter      = lmdz.geo2point ( rprec (d_ATM_his ['fract_ter'][0]), dim1D='cell' ) 
     661    ATM_foce      = lmdz.geo2point ( rprec (d_ATM_his ['fract_oce'][0]), dim1D='cell' ) 
     662    ATM_fsic      = lmdz.geo2point ( rprec (d_ATM_his ['fract_sic'][0]), dim1D='cell' ) 
     663    ATM_flic      = lmdz.geo2point ( rprec (d_ATM_his ['fract_lic'][0]), dim1D='cell' ) 
     664    SRF_lat       = lmdz.geo2point (   rprec (d_SRF_his ['lat'])+0*rprec (d_SRF_his ['lon']), dim1D='cell' ) 
     665    SRF_lon       = lmdz.geo2point ( 0*rprec (d_SRF_his ['lat'])+  rprec (d_SRF_his ['lon']), dim1D='cell' ) 
     666    SRF_aire      = lmdz.geo2point ( rprec (d_SRF_his ['Areas']) * rprec (d_SRF_his ['Contfrac']), dim1D='cell', cumulPoles=True ) 
     667    SRF_areas     = lmdz.geo2point ( rprec (d_SRF_his ['Areas'])  ,  dim1D='cell', cumulPoles=True ) 
     668    SRF_contfrac  = lmdz.geo2point ( rprec (d_SRF_his ['Contfrac']), dim1D='cell' ) 
     669 
    615670if ICO : 
    616671    if ATM_HIS == 'latlon' : 
    617         jpja, jpia = d_ATM_his['aire'][0].shape 
    618         if wu.unDefined ( 'file_ATM_aire' ) :  
    619             file_ATM_aire = os.path.join ( R_IN, 'ATM', 'GRID', f'aire_{ATM}_to_{jpia}x{jpja}.nc' ) 
    620             config['Files']['file_ATM_aire'] = file_ATM_aire 
    621         echo ( f'Aire sur grille reguliere : {file_ATM_aire = }' ) 
    622         d_ATM_aire = xr.open_dataset ( file_ATM_aire, decode_times=False ).squeeze() 
    623         try : 
    624             ATM_lat  = lmdz.geo2point (   d_ATM_his ['lat']+0*d_ATM_his ['lon'], dim1D='cell_latlon' ) 
    625             ATM_lon  = lmdz.geo2point ( 0*d_ATM_his ['lat']+  d_ATM_his ['lon'], dim1D='cell_latlon' ) 
    626         except : 
    627             ATM_lat  = lmdz.geo2point (   d_ATM_his ['lat_dom_out']+0*d_ATM_his ['lon_dom_out'], dim1D='cell_latlon' ) 
    628             ATM_lon  = lmdz.geo2point ( 0*d_ATM_his ['lat_dom_out']+  d_ATM_his ['lon_dom_out'], dim1D='cell_latlon' ) 
    629         ATM_aire = lmdz.geo2point ( d_ATM_aire ['aire'].squeeze(), cumulPoles=True, dim1D='cell_latlon' ) 
    630         ATM_fter = lmdz.geo2point ( d_ATM_his ['fract_ter'][0], dim1D='cell_latlon' ) 
    631         ATM_foce = lmdz.geo2point ( d_ATM_his ['fract_oce'][0], dim1D='cell_latlon' ) 
    632         ATM_fsic = lmdz.geo2point ( d_ATM_his ['fract_sic'][0], dim1D='cell_latlon' ) 
    633         ATM_flic = lmdz.geo2point ( d_ATM_his ['fract_lic'][0], dim1D='cell_latlon' ) 
     672        echo ( 'ATM areas and fractions on latlon grid' ) 
     673        if 'lat_dom_out' in d_ATM_his.variables : 
     674            ATM_lat  = lmdz.geo2point (   rprec (d_ATM_his ['lat_dom_out'])+0*rprec (d_ATM_his ['lon_dom_out']), dim1D='cell' ) 
     675            ATM_lon  = lmdz.geo2point ( 0*rprec (d_ATM_his ['lat_dom_out'])+  rprec (d_ATM_his ['lon_dom_out']), dim1D='cell' ) 
     676        else : 
     677            ATM_lat  = lmdz.geo2point (   rprec (d_ATM_his ['lat'])+0*rprec (d_ATM_his ['lon']), dim1D='cell' ) 
     678            ATM_lon  = lmdz.geo2point ( 0*rprec (d_ATM_his ['lat'])+  rprec (d_ATM_his ['lon']), dim1D='cell' ) 
     679        ATM_aire = lmdz.geo2point ( rprec (d_ATM_his ['aire'][0]).squeeze(), cumulPoles=True, dim1D='cell' ) 
     680        ATM_fter = lmdz.geo2point ( rprec (d_ATM_his ['fract_ter'][0]), dim1D='cell' ) 
     681        ATM_foce = lmdz.geo2point ( rprec (d_ATM_his ['fract_oce'][0]), dim1D='cell' ) 
     682        ATM_fsic = lmdz.geo2point ( rprec (d_ATM_his ['fract_sic'][0]), dim1D='cell' ) 
     683        ATM_flic = lmdz.geo2point ( rprec (d_ATM_his ['fract_lic'][0]), dim1D='cell' ) 
     684 
     685    if ATM_HIS == 'ico' : 
     686        echo ( 'ATM areas and fractions on ICO grid' ) 
     687        ATM_aire =  rprec (d_ATM_his ['aire']     [0])[ATM_his_keysort].squeeze() 
     688        ATM_lat  =  rprec (d_ATM_his ['lat']         )[ATM_his_keysort] 
     689        ATM_lon  =  rprec (d_ATM_his ['lon']         )[ATM_his_keysort] 
     690        ATM_fter =  rprec (d_ATM_his ['fract_ter'][0])[ATM_his_keysort] 
     691        ATM_foce =  rprec (d_ATM_his ['fract_oce'][0])[ATM_his_keysort] 
     692        ATM_fsic =  rprec (d_ATM_his ['fract_sic'][0])[ATM_his_keysort] 
     693        ATM_flic =  rprec (d_ATM_his ['fract_lic'][0])[ATM_his_keysort] 
    634694 
    635695    if SRF_HIS == 'latlon' : 
    636         try : 
    637             SRF_lat  = lmdz.geo2point (   d_SRF_his ['lat']+0*d_SRF_his ['lon'], dim1D='cell_latlon' ) 
    638             SRF_lon  = lmdz.geo2point ( 0*d_SRF_his ['lat']+  d_SRF_his ['lon'], dim1D='cell_latlon' ) 
    639         except : 
    640             try :  
    641                 SRF_lat  = lmdz.geo2point (   d_SRF_his ['lat_dom_out']+0*d_SRF_his ['lon_dom_out'], dim1D='cell_latlon' ) 
    642                 SRF_lon  = lmdz.geo2point ( 0*d_SRF_his ['lat_dom_out']+  d_SRF_his ['lon_dom_out'], dim1D='cell_latlon' ) 
    643             except :  
    644                 SRF_lat  = lmdz.geo2point (   d_SRF_his ['lat_domain_landpoints_out']+0*d_SRF_his ['lon_domain_landpoints_out'], dim1D='cell_latlon' ) 
    645                 SRF_lon  = lmdz.geo2point ( 0*d_SRF_his ['lat_domain_landpoints_out']+  d_SRF_his ['lon_domain_landpoints_out'], dim1D='cell_latlon' ) 
    646         SRF_areas    = d_SRF_his ['Areas'].values 
    647         SRF_areafrac = d_SRF_his ['AreaFrac'].values 
    648         SRF_areas    = xr.DataArray ( SRF_areas   , coords=d_SRF_his ['Contfrac'].coords, dims=d_SRF_his ['Contfrac'].dims) 
    649         SRF_areafrac = xr.DataArray ( SRF_areafrac, coords=d_SRF_his ['Contfrac'].coords, dims=d_SRF_his ['Contfrac'].dims) 
    650  
    651         SRF_areas     = lmdz.geo2point ( SRF_areas   , dim1D='cell_latlon', cumulPoles=True ) 
    652         SRF_areafrac  = lmdz.geo2point ( SRF_areafrac, dim1D='cell_latlon', cumulPoles=True ) 
    653         SRF_contfrac  = SRF_areafrac / SRF_areas 
    654         SRF_aire      = SRF_areafrac 
    655  
    656     if ATM_HIS == 'ico' : 
    657         echo ( f'Grille icosaedre' ) 
    658         ATM_aire =  d_ATM_his ['aire']     [0][ATM_his_keysort].squeeze() 
    659         ATM_lat  =  d_ATM_his ['lat']         [ATM_his_keysort] 
    660         ATM_lon  =  d_ATM_his ['lon']         [ATM_his_keysort] 
    661         ATM_fter =  d_ATM_his ['fract_ter'][0][ATM_his_keysort] 
    662         ATM_foce =  d_ATM_his ['fract_oce'][0][ATM_his_keysort] 
    663         ATM_fsic =  d_ATM_his ['fract_sic'][0][ATM_his_keysort] 
    664         ATM_flic =  d_ATM_his ['fract_lic'][0][ATM_his_keysort] 
    665          
    666     if SRF_HIS == 'ico' :  
    667         SRF_lat       =  d_SRF_his ['lat']      [SRF_his_keysort] 
    668         SRF_lon       =  d_SRF_his ['lon']      [SRF_his_keysort] 
    669         SRF_areas     =  d_SRF_his ['Areas']    [SRF_his_keysort]  
    670         #SRF_areafrac =  d_SRF_his ['AreaFrac'] [SRF_his_keysort]  
    671         SRF_contfrac  =  d_SRF_his ['Contfrac'][SRF_his_keysort] 
     696        echo ( 'SRF areas and fractions on latlon grid' ) 
     697        if 'lat_domain_landpoints_out' in d_SRF_his  :  
     698            SRF_lat  = lmdz.geo2point (   rprec (d_SRF_his ['lat_domain_landpoints_out'])+0*rprec (d_SRF_his ['lon_domain_landpoints_out']), dim1D='cell' ) 
     699            SRF_lon  = lmdz.geo2point ( 0*rprec (d_SRF_his ['lat_domain_landpoints_out'])+  rprec (d_SRF_his ['lon_domain_landpoints_out']), dim1D='cell' ) 
     700        else :  
     701            if 'lat_domain_landpoints_out' in d_SRF_his : 
     702                SRF_lat  = lmdz.geo2point (   rprec (d_SRF_his ['lat_dom_out'])+0*rprec (d_SRF_his ['lon_dom_out']), dim1D='cell' ) 
     703                SRF_lon  = lmdz.geo2point ( 0*rprec (d_SRF_his ['lat_dom_out'])+  rprec (d_SRF_his ['lon_dom_out']), dim1D='cell' ) 
     704            else : 
     705                SRF_lat  = lmdz.geo2point (   rprec (d_SRF_his ['lat'])+0*rprec (d_SRF_his ['lon']), dim1D='cell' ) 
     706                SRF_lon  = lmdz.geo2point ( 0*rprec (d_SRF_his ['lat'])+  rprec (d_SRF_his ['lon']), dim1D='cell' ) 
     707                 
     708        SRF_areas     = lmdz.geo2point ( rprec (d_SRF_his ['Areas']   )   , dim1D='cell', cumulPoles=True ) 
     709        SRF_areafrac  = lmdz.geo2point ( rprec (d_SRF_his ['AreaFrac'])   , dim1D='cell', cumulPoles=True ) 
     710        SRF_contfrac  = lmdz.geo2point ( rprec (d_SRF_his ['Contfrac'])   , dim1D='cell', cumulPoles=True ) 
     711        SRF_aire = SRF_areafrac 
     712  
     713    if SRF_HIS == 'ico' : 
     714        echo ( 'SRF areas and fractions on latlon grid' ) 
     715        SRF_lat       =  rprec (d_SRF_his ['lat']     ) [SRF_his_keysort] 
     716        SRF_lon       =  rprec (d_SRF_his ['lon']     ) [SRF_his_keysort] 
     717        SRF_areas     =  rprec (d_SRF_his ['Areas']   ) [SRF_his_keysort]  
     718        SRF_contfrac  =  rprec (d_SRF_his ['Contfrac']) [SRF_his_keysort] 
    672719        SRF_aire      =  SRF_areas * SRF_contfrac 
    673720 
     
    681728ATM_aire_fsea = ATM_aire * ATM_fsea 
    682729 
    683 SRF_aire = SRF_aire.where ( np.abs (SRF_aire) < 1E15, 0. ) 
     730#SRF_aire = SRF_aire.where ( np.abs (SRF_aire) < 1E15, 0. ) 
    684731 
    685732## Write the full configuration 
     
    713760    DYN_fsea = ATM_fsea 
    714761    DYN_flnd = ATM_flnd 
    715     DYN_fter = d_ATM_beg['FTER'] 
    716     DYN_flic = d_ATM_beg['FLIC'] 
     762    DYN_fter = rprec (d_ATM_beg['FTER']) 
     763    DYN_flic = rprec (d_ATM_beg['FLIC']) 
    717764    DYN_aire_fter = DYN_aire * DYN_fter 
    718765 
     
    728775    return ATM_flux_int 
    729776 
     777def LIC_flux_int (flux) : 
     778    '''Integrate (* time * surface) flux on land ice grid''' 
     779    LIC_flux_int  = wu.Psum ( (flux * dtime_per_sec * ATM_aire_flic).to_masked_array().ravel() ) 
     780    return LIC_flux_int 
     781 
    730782def SRF_stock_int (stock) : 
    731783    '''Integrate (* surface) stock on land grid''' 
     
    749801    return ONE_flux_int 
    750802 
     803def Sprec ( tlist ) : 
     804    '''Accurate sum of list of scalar elements''' 
     805    return wu.Psum ( np.array ( tlist) ) 
     806 
    751807ATM_aire_sea     = ATM_aire * ATM_fsea 
     808 
    752809ATM_aire_tot     = ONE_stock_int (ATM_aire) 
    753 ATM_aire_sea_tot = ONE_stock_int (ATM_aire*ATM_fsea) 
    754  
    755 DYN_aire_tot     =  ONE_stock_int ( DYN_aire ) 
    756 SRF_aire_tot     =  ONE_stock_int ( SRF_aire ) 
     810ATM_aire_sea_tot = ONE_stock_int (ATM_aire_fsea) 
     811ATM_aire_ter_tot = ONE_stock_int (ATM_aire_fter) 
     812ATM_aire_lic_tot = ONE_stock_int (ATM_aire_flic) 
     813 
     814DYN_aire_tot     = ONE_stock_int ( DYN_aire ) 
     815SRF_aire_tot     = ONE_stock_int ( SRF_aire ) 
    757816 
    758817echo ('') 
    759 echo ( f'ATM DYN : Area of atmosphere : {DYN_aire_tot:18.9e}' ) 
    760 echo ( f'ATM HIS : Area of atmosphere : {ATM_aire_tot:18.9e}' ) 
    761 echo ( f'ATM SRF : Area of atmosphere : {SRF_aire_tot:18.9e}' ) 
     818echo ( f'ATM DYN : Area of atmosphere        : {DYN_aire_tot:18.9e}' ) 
     819echo ( f'ATM HIS : Area of atmosphere        : {ATM_aire_tot:18.9e}' ) 
     820echo ( f'ATM HIS : Area of ter in atmosphere : {ATM_aire_ter_tot:18.9e}' ) 
     821echo ( f'ATM HIS : Area of lic in atmosphere : {ATM_aire_lic_tot:18.9e}' ) 
     822echo ( f'ATM SRF : Area of atmosphere        : {SRF_aire_tot:18.9e}' ) 
    762823echo ('') 
    763 echo ( 'ATM DYN : Area of atmosphere/(4pi R^2) : {:18.9f}'.format(DYN_aire_tot/(Ra*Ra*4*np.pi) ) ) 
    764 echo ( 'ATM HIS : Area of atmosphere/(4pi R^2) : {:18.9f}'.format(ATM_aire_tot/(Ra*Ra*4*np.pi) ) ) 
    765 echo ( 'ATM SRF : Area of atmosphere/(4pi R^2) : {:18.9f}'.format(SRF_aire_tot/(Ra*Ra*4*np.pi) ) ) 
     824echo ( 'ATM DYN : Area of atmosphere/(4pi R^2)        : {:18.9f}'.format(DYN_aire_tot/(Ra*Ra*4*np.pi) ) ) 
     825echo ( 'ATM HIS : Area of atmosphere/(4pi R^2)        : {:18.9f}'.format(ATM_aire_tot/(Ra*Ra*4*np.pi) ) ) 
     826echo ( 'ATM HIS : Area of ter in atmosphere/(4pi R^2) : {:18.9f}'.format(ATM_aire_ter_tot/(Ra*Ra*4*np.pi) ) ) 
     827echo ( 'ATM SRF : Area of atmosphere/(4pi R^2)        : {:18.9f}'.format(SRF_aire_tot/(Ra*Ra*4*np.pi) ) ) 
    766828echo ('') 
    767829echo ( f'ATM SRF : Area of atmosphere (no contfrac): {ONE_stock_int (SRF_areas):18.9e}' ) 
     
    786848    DYN_psol_end = d_DYN_end['ps'][DYN_end_keysort] 
    787849if LMDZ :  
    788     DYN_psol_beg = lmdz.geo2point ( d_DYN_beg['ps'].isel(rlonv=slice(0,-1)), dim1D='cell_latlon' ) 
    789     DYN_psol_end = lmdz.geo2point ( d_DYN_end['ps'].isel(rlonv=slice(0,-1)), dim1D='cell_latlon' ) 
     850    DYN_psol_beg = lmdz.geo2point ( d_DYN_beg['ps'].isel(rlonv=slice(0,-1)), dim1D='cell' ) 
     851    DYN_psol_end = lmdz.geo2point ( d_DYN_end['ps'].isel(rlonv=slice(0,-1)), dim1D='cell' ) 
    790852     
    791853echo ( '3D Pressure at the interface layers (not scalar points)' ) 
     
    793855DYN_pres_end = ATM_Ahyb + ATM_Bhyb * DYN_psol_end 
    794856 
     857echo ( 'Check computation of pressure levels' ) 
     858 
     859ind = np.empty (8) 
     860 
     861ind[0] = (DYN_pres_beg[ 0]-DYN_psol_beg).min().item() 
     862ind[1] = (DYN_pres_beg[ 0]-DYN_psol_beg).max().item() 
     863ind[2] = (DYN_pres_beg[-1]).min().item() 
     864ind[3] = (DYN_pres_beg[-1]).max().item() 
     865ind[4] = (DYN_pres_end[ 0]-DYN_psol_end).min().item() 
     866ind[5] = (DYN_pres_end[ 0]-DYN_psol_end).max().item() 
     867ind[6] = (DYN_pres_end[-1]).min().item() 
     868ind[7] = (DYN_pres_end[-1]).max().item() 
     869 
     870if any ( ind != 0) : 
     871    echo ( 'All values should be zero' ) 
     872    echo ( f'(DYN_pres_beg[ 0]-DYN_psol_beg).min().item() = {ind[0]}' ) 
     873    echo ( f'(DYN_pres_beg[ 0]-DYN_psol_beg).max().item() = {ind[1]}' ) 
     874    echo ( f'(DYN_pres_beg[-1]).min().item()              = {ind[2]}' ) 
     875    echo ( f'(DYN_pres_beg[-1]).max().item()              = {ind[3]}' ) 
     876    echo ( f'(DYN_pres_end[ 0]-DYN_psol_end).min().item() = {ind[4]}' ) 
     877    echo ( f'(DYN_pres_end[ 0]-DYN_psol_end).max().item() = {ind[5]}' ) 
     878    echo ( f'(DYN_pres_end[-1]).min().item()              = {ind[6]}' ) 
     879    echo ( f'(DYN_pres_end[-1]).max().item()              = {ind[7]}' ) 
     880    raise Exception 
     881     
    795882klevp1 = ATM_Bhyb.shape[-1] 
    796883cell   = DYN_psol_beg.shape[-1] 
     
    798885 
    799886echo ( 'Layer thickness (pressure)' ) 
    800 DYN_dpres_beg = xr.DataArray ( np.empty( (klev, cell )), dims = ('sigs', 'cell'), coords=(np.arange(klev), np.arange(cell) ) ) 
    801 DYN_dpres_end = xr.DataArray ( np.empty( (klev, cell )), dims = ('sigs', 'cell'), coords=(np.arange(klev), np.arange(cell) ) ) 
    802      
    803 for k in np.arange (klevp1-1) : 
    804     DYN_dpres_beg[k,:] = DYN_pres_beg[k,:] - DYN_pres_beg[k+1,:] 
    805     DYN_dpres_end[k,:] = DYN_pres_end[k,:] - DYN_pres_end[k+1,:] 
     887DYN_mass_beg = xr.DataArray ( np.empty( (klev, cell)), dims = ('sigs', 'cell'), coords=(np.arange(klev), np.arange(cell) ) ) 
     888DYN_mass_end = xr.DataArray ( np.empty( (klev, cell)), dims = ('sigs', 'cell'), coords=(np.arange(klev), np.arange(cell) ) ) 
     889     
     890for k in np.arange (klev) : 
     891    DYN_mass_beg[k,:] = ( DYN_pres_beg[k,:] - DYN_pres_beg[k+1,:] ) / Grav 
     892    DYN_mass_end[k,:] = ( DYN_pres_end[k,:] - DYN_pres_end[k+1,:] ) / Grav 
     893 
     894DYN_mass_beg_2D = DYN_mass_beg.sum (dim='sigs') 
     895DYN_mass_end_2D = DYN_mass_end.sum (dim='sigs') 
     896 
     897DYN_mas_air_beg = DYN_stock_int ( DYN_mass_beg_2D ) 
     898DYN_mas_air_end = DYN_stock_int ( DYN_mass_end_2D ) 
    806899 
    807900echo ( 'Vertical and horizontal integral, and sum of liquid, solid and vapor water phases' ) 
    808901if LMDZ : 
    809     try :  
    810         DYN_wat_beg = lmdz.geo3point ( (d_DYN_beg['H2Ov']  + d_DYN_beg['H2Ol']  + d_DYN_beg['H2Oi'] ).isel(rlonv=slice(0,-1) ), dim1D='cell' ) 
    811         DYN_wat_end = lmdz.geo3point ( (d_DYN_end['H2Ov']  + d_DYN_end['H2Ol']  + d_DYN_end['H2Oi'] ).isel(rlonv=slice(0,-1) ), dim1D='cell' ) 
    812     except : 
     902    if 'H2Ov' in d_DYN_beg.variables : 
     903        echo ('reading LATLON : H2Ov, H2Ol, H2Oi' ) 
     904        DYN_wat_beg = lmdz.geo3point ( d_DYN_beg['H2Ov'] + d_DYN_beg['H2Ol'] + d_DYN_beg['H2Oi'].isel(rlonv=slice(0,-1) ), dim1D='cell' ) 
     905        DYN_wat_end = lmdz.geo3point ( d_DYN_end['H2Ov'] + d_DYN_end['H2Ol'] + d_DYN_end['H2Oi'].isel(rlonv=slice(0,-1) ), dim1D='cell' ) 
     906    if 'H2Ov_g' in d_DYN_beg.variables : 
     907        echo ('reading LATLON : H2O_g, H2O_l, H2O_s' ) 
    813908        DYN_wat_beg = lmdz.geo3point ( (d_DYN_beg['H2O_g'] + d_DYN_beg['H2O_l'] + d_DYN_beg['H2O_s']).isel(rlonv=slice(0,-1) ), dim1D='cell' ) 
    814909        DYN_wat_end = lmdz.geo3point ( (d_DYN_end['H2O_g'] + d_DYN_end['H2O_l'] + d_DYN_end['H2O_s']).isel(rlonv=slice(0,-1) ), dim1D='cell' ) 
    815910if ICO : 
    816     try : 
     911    if 'H2Ov_g' in d_DYN_beg.variables : 
     912        echo ('reading ICO : H2O_g, H2O_l, H2O_s' ) 
    817913        DYN_wat_beg = (d_DYN_beg['H2O_g'] + d_DYN_beg['H2O_l'] + d_DYN_beg['H2O_s'])[..., DYN_beg_keysort] 
    818914        DYN_wat_end = (d_DYN_end['H2O_g'] + d_DYN_end['H2O_l'] + d_DYN_end['H2O_s'])[..., DYN_beg_keysort] 
    819          
    820     except :  
     915    elif 'H2O_g' in d_DYN_beg.variables : 
     916        echo ('reading ICO : H2O_g, H2O_l, H2O_s' ) 
     917        DYN_wat_beg = (d_DYN_beg['H2O_g'] + d_DYN_beg['H2O_l'] + d_DYN_beg['H2O_s'])[..., DYN_beg_keysort] 
     918        DYN_wat_end = (d_DYN_end['H2O_g'] + d_DYN_end['H2O_l'] + d_DYN_end['H2O_s'])[..., DYN_beg_keysort] 
     919    elif 'q' in d_DYN_beg.variables : 
     920        echo ('reading ICO : q' ) 
    821921        DYN_wat_beg = (d_DYN_beg['q'].isel(nq=0) + d_DYN_beg['q'].isel(nq=1) + d_DYN_beg['q'].isel(nq=2) )[..., DYN_beg_keysort] 
    822922        DYN_wat_end = (d_DYN_end['q'].isel(nq=0) + d_DYN_end['q'].isel(nq=1) + d_DYN_end['q'].isel(nq=2) )[..., DYN_beg_keysort] 
    823          
     923 
     924if 'lev' in DYN_wat_beg.dims :  
    824925    DYN_wat_beg = DYN_wat_beg.rename ( {'lev':'sigs'} ) 
    825     DYN_wat_beg = DYN_wat_end.rename ( {'lev':'sigs'} ) 
     926    DYN_wat_end = DYN_wat_end.rename ( {'lev':'sigs'} ) 
    826927     
    827928echo ( 'Compute water content : vertical and horizontal integral' ) 
    828 DYN_mas_wat_beg = DYN_stock_int ( (DYN_dpres_beg * DYN_wat_beg).sum (dim='sigs') ) / Grav 
    829 DYN_mas_wat_end = DYN_stock_int ( (DYN_dpres_end * DYN_wat_end).sum (dim='sigs') ) / Grav 
     929 
     930DYN_wat_beg_2D =  (DYN_mass_beg * DYN_wat_beg).sum (dim='sigs') 
     931DYN_wat_end_2D =  (DYN_mass_end * DYN_wat_end).sum (dim='sigs') 
     932 
     933DYN_mas_wat_beg = DYN_stock_int ( DYN_wat_beg_2D ) 
     934DYN_mas_wat_end = DYN_stock_int ( DYN_wat_end_2D ) 
    830935 
    831936echo ( 'Variation of water content' ) 
    832937dDYN_mas_wat = DYN_mas_wat_end - DYN_mas_wat_beg 
    833938 
    834 # \([a-z,A-Z,_]*\)/dtime_sec\*1e-9  kg2Sv(\1) 
    835 # \([a-z,A-Z,_]*\)\/ATM_aire_sea_tot\/ATM_rho\/NbYear  kg2myear(\1) 
    836  
    837939echo ( f'\nChange of atmosphere water content (dynamics)  -- {Title} ' ) 
    838940echo ( '------------------------------------------------------------------------------------' ) 
    839 echo ( 'DYN_mas_beg = {:12.6e} kg | DYN_mas_end = {:12.6e} kg'.format (DYN_mas_wat_beg, DYN_mas_wat_end) ) 
     941echo ( 'DYN_mas_air_beg = {:12.6e} kg | DYN_mas_air_end = {:12.6e} kg'.format (DYN_mas_air_beg, DYN_mas_air_end) ) 
     942echo ( 'DYN_mas_wat_beg = {:12.6e} kg | DYN_mas_wat_end = {:12.6e} kg'.format (DYN_mas_wat_beg, DYN_mas_wat_end) ) 
    840943prtFlux ( 'dMass (atm)  ', dDYN_mas_wat, 'e', True ) 
    841944 
     
    850953              d_ATM_end['QS03']  *d_ATM_end['FOCE'] + d_ATM_end['QS04']  *d_ATM_end['FSIC'] 
    851954 
    852 ATM_qsol_beg = d_ATM_beg['QSOL'] 
    853 ATM_qsol_end = d_ATM_end['QSOL'] 
     955ATM_qsol_beg     = d_ATM_beg['QSOL'] 
     956ATM_qsol_end     = d_ATM_end['QSOL'] 
    854957 
    855958LIC_sno_beg      = d_ATM_beg['SNOW02']*d_ATM_beg['FLIC'] 
     
    859962LIC_runlic0_end  = d_ATM_end['RUNOFFLIC0'] 
    860963 
    861 ATM_qs01_beg  = d_ATM_beg['QS01'] * d_ATM_beg['FTER'] 
    862 ATM_qs01_end  = d_ATM_end['QS01'] * d_ATM_end['FTER'] 
    863 ATM_qs02_beg  = d_ATM_beg['QS02'] * d_ATM_beg['FLIC'] 
    864 ATM_qs02_end  = d_ATM_end['QS02'] * d_ATM_end['FLIC'] 
    865 ATM_qs03_beg  = d_ATM_beg['QS03'] * d_ATM_beg['FOCE'] 
    866 ATM_qs03_end  = d_ATM_end['QS03'] * d_ATM_end['FOCE'] 
    867 ATM_qs04_beg  = d_ATM_beg['QS04'] * d_ATM_beg['FSIC'] 
    868 ATM_qs04_end  = d_ATM_end['QS04'] * d_ATM_end['FSIC']   
     964ATM_qs01_beg     = d_ATM_beg['QS01'] * d_ATM_beg['FTER'] 
     965ATM_qs02_beg     = d_ATM_beg['QS02'] * d_ATM_beg['FLIC'] 
     966ATM_qs03_beg     = d_ATM_beg['QS03'] * d_ATM_beg['FOCE'] 
     967ATM_qs04_beg     = d_ATM_beg['QS04'] * d_ATM_beg['FSIC'] 
     968 
     969ATM_qs01_end     = d_ATM_end['QS01'] * d_ATM_end['FTER'] 
     970ATM_qs02_end     = d_ATM_end['QS02'] * d_ATM_end['FLIC'] 
     971ATM_qs03_end     = d_ATM_end['QS03'] * d_ATM_end['FOCE'] 
     972ATM_qs04_end     = d_ATM_end['QS04'] * d_ATM_end['FSIC']   
    869973 
    870974if ICO : 
    871      ATM_sno_beg       = ATM_sno_beg    [ATM_beg_keysort] 
    872      ATM_sno_end       = ATM_sno_end    [ATM_end_keysort] 
    873      ATM_qs_beg        = ATM_qs_beg     [ATM_beg_keysort] 
    874      ATM_qs_end        = ATM_qs_end     [ATM_end_keysort] 
    875      ATM_qsol_beg      = ATM_qsol_beg   [ATM_beg_keysort] 
    876      ATM_qsol_end      = ATM_qsol_end   [ATM_end_keysort] 
    877      ATM_qs01_beg      = ATM_qs01_beg   [ATM_beg_keysort] 
    878      ATM_qs01_end      = ATM_qs01_end   [ATM_end_keysort] 
    879      ATM_qs02_beg      = ATM_qs02_beg   [ATM_beg_keysort] 
    880      ATM_qs02_end      = ATM_qs02_end   [ATM_end_keysort] 
    881      ATM_qs03_beg      = ATM_qs03_beg   [ATM_beg_keysort] 
    882      ATM_qs03_end      = ATM_qs03_end   [ATM_end_keysort] 
    883      ATM_qs04_beg      = ATM_qs04_beg   [ATM_beg_keysort] 
    884      ATM_qs04_end      = ATM_qs04_end   [ATM_end_keysort] 
    885      LIC_sno_beg       = LIC_sno_beg    [ATM_beg_keysort] 
    886      LIC_sno_end       = LIC_sno_end    [ATM_end_keysort] 
    887      LIC_runlic0_beg   = LIC_runlic0_beg[ATM_beg_keysort] 
    888      LIC_runlic0_end   = LIC_runlic0_end[ATM_end_keysort] 
     975     ATM_sno_beg     = ATM_sno_beg    [ATM_beg_keysort] 
     976     ATM_sno_end     = ATM_sno_end    [ATM_end_keysort] 
     977     ATM_qs_beg      = ATM_qs_beg     [ATM_beg_keysort] 
     978     ATM_qs_end      = ATM_qs_end     [ATM_end_keysort] 
     979     ATM_qsol_beg    = ATM_qsol_beg   [ATM_beg_keysort] 
     980     ATM_qs01_beg    = ATM_qs01_beg   [ATM_beg_keysort] 
     981     ATM_qs02_beg    = ATM_qs02_beg   [ATM_beg_keysort] 
     982     ATM_qs03_beg    = ATM_qs03_beg   [ATM_beg_keysort] 
     983     ATM_qs04_beg    = ATM_qs04_beg   [ATM_beg_keysort] 
     984     ATM_qsol_end    = ATM_qsol_end   [ATM_end_keysort] 
     985     ATM_qs01_end    = ATM_qs01_end   [ATM_end_keysort] 
     986     ATM_qs02_end    = ATM_qs02_end   [ATM_end_keysort] 
     987     ATM_qs03_end    = ATM_qs03_end   [ATM_end_keysort] 
     988     ATM_qs04_end    = ATM_qs04_end   [ATM_end_keysort] 
     989     LIC_sno_beg     = LIC_sno_beg    [ATM_beg_keysort] 
     990     LIC_sno_end     = LIC_sno_end    [ATM_end_keysort] 
     991     LIC_runlic0_beg = LIC_runlic0_beg[ATM_beg_keysort] 
     992     LIC_runlic0_end = LIC_runlic0_end[ATM_end_keysort] 
    889993    
    890994LIC_qs_beg = ATM_qs02_beg 
     
    8971001ATM_mas_qs_end      = DYN_stock_int ( ATM_qs_end   ) 
    8981002ATM_mas_qsol_beg    = DYN_stock_int ( ATM_qsol_beg ) 
     1003ATM_mas_qs01_beg    = DYN_stock_int ( ATM_qs01_beg ) 
     1004ATM_mas_qs02_beg    = DYN_stock_int ( ATM_qs02_beg ) 
     1005ATM_mas_qs03_beg    = DYN_stock_int ( ATM_qs03_beg ) 
     1006ATM_mas_qs04_beg    = DYN_stock_int ( ATM_qs04_beg ) 
    8991007ATM_mas_qsol_end    = DYN_stock_int ( ATM_qsol_end ) 
    900 ATM_mas_qs01_beg    = DYN_stock_int ( ATM_qs01_beg ) 
    9011008ATM_mas_qs01_end    = DYN_stock_int ( ATM_qs01_end ) 
    902 ATM_mas_qs02_beg    = DYN_stock_int ( ATM_qs02_beg ) 
    9031009ATM_mas_qs02_end    = DYN_stock_int ( ATM_qs02_end ) 
    904 ATM_mas_qs03_beg    = DYN_stock_int ( ATM_qs03_beg ) 
    9051010ATM_mas_qs03_end    = DYN_stock_int ( ATM_qs03_end ) 
    906 ATM_mas_qs04_beg    = DYN_stock_int ( ATM_qs04_beg ) 
    9071011ATM_mas_qs04_end    = DYN_stock_int ( ATM_qs04_end ) 
    9081012 
     
    9291033dLIC_mas_sno     = LIC_mas_sno_end     - LIC_mas_sno_beg 
    9301034dLIC_mas_runlic0 = LIC_mas_runlic0_end - LIC_mas_runlic0_beg 
    931 dLIC_mas_wat     = dLIC_mas_qs + dLIC_mas_sno 
     1035 
     1036dLIC_mas_wat     = dLIC_mas_qs + dLIC_mas_sno # + dLIC_mas_runlic0 
    9321037 
    9331038echo ( f'\nChange of atmosphere snow content (Land ice) -- {Title} ' ) 
     
    9801085    RUN_mas_wat_pond_end   = ONE_stock_int ( d_SRF_end ['pondres']   ) 
    9811086 
    982 RUN_mas_wat_beg = RUN_mas_wat_fast_beg  + RUN_mas_wat_slow_beg + RUN_mas_wat_stream_beg + \ 
    983                   RUN_mas_wat_flood_beg + RUN_mas_wat_lake_beg + RUN_mas_wat_pond_beg 
    984 RUN_mas_wat_end = RUN_mas_wat_fast_end  + RUN_mas_wat_slow_end + RUN_mas_wat_stream_end + \ 
    985                   RUN_mas_wat_flood_end + RUN_mas_wat_lake_end + RUN_mas_wat_pond_end 
     1087RUN_mas_wat_beg = Sprec ( [RUN_mas_wat_fast_beg , RUN_mas_wat_slow_beg, RUN_mas_wat_stream_beg, 
     1088                           RUN_mas_wat_flood_beg, RUN_mas_wat_lake_beg, RUN_mas_wat_pond_beg] ) 
     1089                   
     1090RUN_mas_wat_end = Sprec ( [RUN_mas_wat_fast_end  , RUN_mas_wat_slow_end , RUN_mas_wat_stream_end, 
     1091                           RUN_mas_wat_flood_end , RUN_mas_wat_lake_end , RUN_mas_wat_pond_end] ) 
    9861092 
    9871093dRUN_mas_wat_fast   = RUN_mas_wat_fast_end   - RUN_mas_wat_fast_beg 
     
    10321138 
    10331139if LMDZ : 
    1034     SRF_tot_watveg_beg  = lmdz.geo2point (SRF_tot_watveg_beg , dim1D='cell_latlon') 
    1035     SRF_tot_watsoil_beg = lmdz.geo2point (SRF_tot_watsoil_beg, dim1D='cell_latlon') 
    1036     SRF_snow_beg        = lmdz.geo2point (SRF_snow_beg       , dim1D='cell_latlon') 
    1037     SRF_lakeres_beg     = lmdz.geo2point (SRF_lakeres_beg    , dim1D='cell_latlon') 
    1038     SRF_tot_watveg_end  = lmdz.geo2point (SRF_tot_watveg_end , dim1D='cell_latlon') 
    1039     SRF_tot_watsoil_end = lmdz.geo2point (SRF_tot_watsoil_end, dim1D='cell_latlon') 
    1040     SRF_snow_end        = lmdz.geo2point (SRF_snow_end       , dim1D='cell_latlon') 
    1041     SRF_lakeres_end     = lmdz.geo2point (SRF_lakeres_end    , dim1D='cell_latlon') 
     1140    SRF_tot_watveg_beg  = lmdz.geo2point (SRF_tot_watveg_beg , dim1D='cell') 
     1141    SRF_tot_watsoil_beg = lmdz.geo2point (SRF_tot_watsoil_beg, dim1D='cell') 
     1142    SRF_snow_beg        = lmdz.geo2point (SRF_snow_beg       , dim1D='cell') 
     1143    SRF_lakeres_beg     = lmdz.geo2point (SRF_lakeres_beg    , dim1D='cell') 
     1144    SRF_tot_watveg_end  = lmdz.geo2point (SRF_tot_watveg_end , dim1D='cell') 
     1145    SRF_tot_watsoil_end = lmdz.geo2point (SRF_tot_watsoil_end, dim1D='cell') 
     1146    SRF_snow_end        = lmdz.geo2point (SRF_snow_end       , dim1D='cell') 
     1147    SRF_lakeres_end     = lmdz.geo2point (SRF_lakeres_end    , dim1D='cell') 
    10421148   
    10431149if ICO : 
     
    10531159# Stock dSoilHum dInterce dSWE dStream dFastR dSlowR dLake dPond dFlood 
    10541160 
    1055 SRF_wat_beg = SRF_tot_watveg_beg + SRF_tot_watsoil_beg + SRF_snow_beg  
     1161SRF_wat_beg = SRF_tot_watveg_beg + SRF_tot_watsoil_beg + SRF_snow_beg 
    10561162SRF_wat_end = SRF_tot_watveg_end + SRF_tot_watsoil_end + SRF_snow_end 
    10571163 
     
    10791185print (' -- ') ; sys.stdout.flush () 
    10801186 
    1081 dSRF_mas_watveg   = SRF_mas_watveg_end  - SRF_mas_watveg_beg 
    1082 dSRF_mas_watsoil  = SRF_mas_watsoil_end - SRF_mas_watsoil_beg 
    1083 dSRF_mas_snow     = SRF_mas_snow_end    - SRF_mas_snow_beg 
    1084 dSRF_mas_lake     = SRF_mas_lake_end    - SRF_mas_lake_beg 
     1187dSRF_mas_watveg   = Sprec ( [SRF_mas_watveg_end , -SRF_mas_watveg_beg] ) 
     1188dSRF_mas_watsoil  = Sprec ( [SRF_mas_watsoil_end, -SRF_mas_watsoil_beg] ) 
     1189dSRF_mas_snow     = Sprec ( [SRF_mas_snow_end   , -SRF_mas_snow_beg] ) 
     1190dSRF_mas_lake     = Sprec ( [SRF_mas_lake_end   , -SRF_mas_lake_beg] ) 
    10851191 
    10861192echo ( '------------------------------------------------------------------------------------' ) 
     
    10961202prtFlux ( 'dMass (lake)   ', dSRF_mas_lake   , 'e' , True ) 
    10971203 
    1098 SRF_mas_wat_beg = SRF_mas_watveg_beg + SRF_mas_watsoil_beg + SRF_mas_snow_beg  
    1099 SRF_mas_wat_end = SRF_mas_watveg_end + SRF_mas_watsoil_end + SRF_mas_snow_end  
    1100 dSRF_mas_wat    = SRF_mas_wat_end - SRF_mas_wat_beg 
     1204SRF_mas_wat_beg = Sprec ( [SRF_mas_watveg_beg , SRF_mas_watsoil_beg, SRF_mas_snow_beg] ) 
     1205SRF_mas_wat_end = Sprec ( [SRF_mas_watveg_end , SRF_mas_watsoil_end, SRF_mas_snow_end] ) 
     1206 
     1207dSRF_mas_wat    = Sprec ( [+SRF_mas_watveg_end , +SRF_mas_watsoil_end, +SRF_mas_snow_end,  
     1208                           -SRF_mas_watveg_beg , -SRF_mas_watsoil_beg, -SRF_mas_snow_beg]  ) 
    11011209 
    11021210echo ( '------------------------------------------------------------------------------------' ) 
     
    11151223echo ( f'-- ATM Fluxes  -- {Title} ' ) 
    11161224 
    1117 Step=1 
    1118 print ( 'Step {Step}', end='' ) ; Step += 1 
    11191225if ATM_HIS == 'latlon' : 
    1120     ATM_wbilo_oce   = lmdz.geo2point ( d_ATM_his ['wbilo_oce'], dim1D='cell_latlon' ) 
    1121     ATM_wbilo_sic   = lmdz.geo2point ( d_ATM_his ['wbilo_sic'], dim1D='cell_latlon' ) 
    1122     ATM_wbilo_ter   = lmdz.geo2point ( d_ATM_his ['wbilo_ter'], dim1D='cell_latlon' ) 
    1123     ATM_wbilo_lic   = lmdz.geo2point ( d_ATM_his ['wbilo_lic'], dim1D='cell_latlon' ) 
    1124     ATM_runofflic   = lmdz.geo2point ( d_ATM_his ['runofflic'], dim1D='cell_latlon' ) 
    1125     ATM_fqcalving   = lmdz.geo2point ( d_ATM_his ['fqcalving'], dim1D='cell_latlon' ) 
    1126     ATM_fqfonte     = lmdz.geo2point ( d_ATM_his ['fqfonte']  , dim1D='cell_latlon' ) 
    1127     ATM_precip      = lmdz.geo2point ( d_ATM_his ['precip']   , dim1D='cell_latlon' ) 
    1128     ATM_snowf       = lmdz.geo2point ( d_ATM_his ['snow']     , dim1D='cell_latlon' ) 
    1129     ATM_evap        = lmdz.geo2point ( d_ATM_his ['evap']     , dim1D='cell_latlon' ) 
    1130     ATM_wevap_ter   = lmdz.geo2point ( d_ATM_his ['wevap_ter'], dim1D='cell_latlon' ) 
    1131     ATM_wevap_oce   = lmdz.geo2point ( d_ATM_his ['wevap_oce'], dim1D='cell_latlon' ) 
    1132     ATM_wevap_lic   = lmdz.geo2point ( d_ATM_his ['wevap_lic'], dim1D='cell_latlon' ) 
    1133     ATM_wevap_sic   = lmdz.geo2point ( d_ATM_his ['wevap_sic'], dim1D='cell_latlon' ) 
    1134  
    1135     ATM_wrain_ter   = lmdz.geo2point ( d_ATM_his ['wrain_ter'], dim1D='cell_latlon' ) 
    1136     ATM_wrain_oce   = lmdz.geo2point ( d_ATM_his ['wrain_oce'], dim1D='cell_latlon' ) 
    1137     ATM_wrain_lic   = lmdz.geo2point ( d_ATM_his ['wrain_lic'], dim1D='cell_latlon' ) 
    1138     ATM_wrain_sic   = lmdz.geo2point ( d_ATM_his ['wrain_sic'], dim1D='cell_latlon' ) 
    1139  
    1140     ATM_wsnow_ter   = lmdz.geo2point ( d_ATM_his ['wsnow_ter'], dim1D='cell_latlon' ) 
    1141     ATM_wsnow_oce   = lmdz.geo2point ( d_ATM_his ['wsnow_oce'], dim1D='cell_latlon' ) 
    1142     ATM_wsnow_lic   = lmdz.geo2point ( d_ATM_his ['wsnow_lic'], dim1D='cell_latlon' ) 
    1143     ATM_wsnow_sic   = lmdz.geo2point ( d_ATM_his ['wsnow_sic'], dim1D='cell_latlon' ) 
    1144  
    1145     ATM_wevap_ter   = lmdz.geo2point ( d_ATM_his ['wevap_ter'], dim1D='cell_latlon' ) 
    1146     ATM_wevap_oce   = lmdz.geo2point ( d_ATM_his ['wevap_oce'], dim1D='cell_latlon' ) 
    1147     ATM_wevap_lic   = lmdz.geo2point ( d_ATM_his ['wevap_lic'], dim1D='cell_latlon' ) 
    1148     ATM_wevap_sic   = lmdz.geo2point ( d_ATM_his ['wevap_sic'], dim1D='cell_latlon' ) 
    1149      
    1150     ATM_runofflic   = lmdz.geo2point ( d_ATM_his ['runofflic'], dim1D='cell_latlon' ) 
    1151      
    1152 print ( 'Step {Step}', end='' ) ; Step += 1 
     1226    echo ( ' latlon case' ) 
     1227    ATM_wbilo_oce   = lmdz.geo2point ( rprec (d_ATM_his ['wbilo_oce']), dim1D='cell' ) 
     1228    ATM_wbilo_sic   = lmdz.geo2point ( rprec (d_ATM_his ['wbilo_sic']), dim1D='cell' ) 
     1229    ATM_wbilo_ter   = lmdz.geo2point ( rprec (d_ATM_his ['wbilo_ter']), dim1D='cell' ) 
     1230    ATM_wbilo_lic   = lmdz.geo2point ( rprec (d_ATM_his ['wbilo_lic']), dim1D='cell' ) 
     1231    ATM_runofflic   = lmdz.geo2point ( rprec (d_ATM_his ['runofflic']), dim1D='cell' ) 
     1232    ATM_fqcalving   = lmdz.geo2point ( rprec (d_ATM_his ['fqcalving']), dim1D='cell' ) 
     1233    ATM_fqfonte     = lmdz.geo2point ( rprec (d_ATM_his ['fqfonte']  ), dim1D='cell' ) 
     1234    ATM_precip      = lmdz.geo2point ( rprec (d_ATM_his ['precip']   ), dim1D='cell' ) 
     1235    ATM_snowf       = lmdz.geo2point ( rprec (d_ATM_his ['snow']     ), dim1D='cell' ) 
     1236    ATM_evap        = lmdz.geo2point ( rprec (d_ATM_his ['evap']     ), dim1D='cell' ) 
     1237    ATM_wevap_ter   = lmdz.geo2point ( rprec (d_ATM_his ['wevap_ter']), dim1D='cell' ) 
     1238    ATM_wevap_oce   = lmdz.geo2point ( rprec (d_ATM_his ['wevap_oce']), dim1D='cell' ) 
     1239    ATM_wevap_lic   = lmdz.geo2point ( rprec (d_ATM_his ['wevap_lic']), dim1D='cell' ) 
     1240    ATM_wevap_sic   = lmdz.geo2point ( rprec (d_ATM_his ['wevap_sic']), dim1D='cell' ) 
     1241    ATM_wrain_ter   = lmdz.geo2point ( rprec (d_ATM_his ['wrain_ter']), dim1D='cell' ) 
     1242    ATM_wrain_oce   = lmdz.geo2point ( rprec (d_ATM_his ['wrain_oce']), dim1D='cell' ) 
     1243    ATM_wrain_lic   = lmdz.geo2point ( rprec (d_ATM_his ['wrain_lic']), dim1D='cell' ) 
     1244    ATM_wrain_sic   = lmdz.geo2point ( rprec (d_ATM_his ['wrain_sic']), dim1D='cell' ) 
     1245    ATM_wsnow_ter   = lmdz.geo2point ( rprec (d_ATM_his ['wsnow_ter']), dim1D='cell' ) 
     1246    ATM_wsnow_oce   = lmdz.geo2point ( rprec (d_ATM_his ['wsnow_oce']), dim1D='cell' ) 
     1247    ATM_wsnow_lic   = lmdz.geo2point ( rprec (d_ATM_his ['wsnow_lic']), dim1D='cell' ) 
     1248    ATM_wsnow_sic   = lmdz.geo2point ( rprec (d_ATM_his ['wsnow_sic']), dim1D='cell' ) 
     1249    ATM_runofflic   = lmdz.geo2point ( rprec (d_ATM_his ['runofflic']), dim1D='cell' ) 
     1250    echo ( f'End of LATLON case') 
     1251     
    11531252if ATM_HIS == 'ico' : 
    1154     ATM_wbilo_oce   = d_ATM_his ['wbilo_oce'][..., ATM_his_keysort] 
    1155     ATM_wbilo_sic   = d_ATM_his ['wbilo_sic'][..., ATM_his_keysort] 
    1156     ATM_wbilo_ter   = d_ATM_his ['wbilo_ter'][..., ATM_his_keysort] 
    1157     ATM_wbilo_lic   = d_ATM_his ['wbilo_lic'][..., ATM_his_keysort] 
    1158     ATM_runofflic   = d_ATM_his ['runofflic'][..., ATM_his_keysort] 
    1159     ATM_fqcalving   = d_ATM_his ['fqcalving'][..., ATM_his_keysort] 
    1160     ATM_fqfonte     = d_ATM_his ['fqfonte']  [..., ATM_his_keysort] 
    1161     ATM_precip      = d_ATM_his ['precip']   [..., ATM_his_keysort] 
    1162     ATM_snowf       = d_ATM_his ['snow']     [..., ATM_his_keysort] 
    1163     ATM_evap        = d_ATM_his ['evap']     [..., ATM_his_keysort] 
    1164     ATM_wevap_ter   = d_ATM_his ['wevap_ter'][..., ATM_his_keysort] 
    1165     ATM_wevap_oce   = d_ATM_his ['wevap_oce'][..., ATM_his_keysort] 
    1166     ATM_wevap_lic   = d_ATM_his ['wevap_lic'][..., ATM_his_keysort] 
    1167     ATM_wevap_sic   = d_ATM_his ['wevap_sic'][..., ATM_his_keysort] 
    1168     ATM_runofflic   = d_ATM_his ['runofflic'][..., ATM_his_keysort] 
    1169  
    1170     ATM_wevap_ter   = d_ATM_his ['wevap_ter'][..., ATM_his_keysort] 
    1171     ATM_wevap_oce   = d_ATM_his ['wevap_oce'][..., ATM_his_keysort] 
    1172     ATM_wevap_lic   = d_ATM_his ['wevap_lic'][..., ATM_his_keysort] 
    1173     ATM_wevap_sic   = d_ATM_his ['wevap_sic'][..., ATM_his_keysort] 
    1174  
    1175     ATM_wrain_ter   = d_ATM_his ['wrain_ter'][..., ATM_his_keysort] 
    1176     ATM_wrain_oce   = d_ATM_his ['wrain_oce'][..., ATM_his_keysort] 
    1177     ATM_wrain_lic   = d_ATM_his ['wrain_lic'][..., ATM_his_keysort] 
    1178     ATM_wrain_sic   = d_ATM_his ['wrain_sic'][..., ATM_his_keysort] 
    1179  
    1180     ATM_wsnow_ter   = d_ATM_his ['wsnow_ter'][..., ATM_his_keysort] 
    1181     ATM_wsnow_oce   = d_ATM_his ['wsnow_oce'][..., ATM_his_keysort] 
    1182     ATM_wsnow_lic   = d_ATM_his ['wsnow_lic'][..., ATM_his_keysort] 
    1183     ATM_wsnow_sic   = d_ATM_his ['wsnow_sic'][..., ATM_his_keysort] 
    1184  
    1185 print ( 'Step {Step}', end='' ) ; Step += 1 
    1186  
     1253    echo (' ico case') 
     1254    ATM_wbilo_oce   = rprec (d_ATM_his ['wbilo_oce'])[..., ATM_his_keysort] 
     1255    ATM_wbilo_sic   = rprec (d_ATM_his ['wbilo_sic'])[..., ATM_his_keysort] 
     1256    ATM_wbilo_ter   = rprec (d_ATM_his ['wbilo_ter'])[..., ATM_his_keysort] 
     1257    ATM_wbilo_lic   = rprec (d_ATM_his ['wbilo_lic'])[..., ATM_his_keysort] 
     1258    ATM_runofflic   = rprec (d_ATM_his ['runofflic'])[..., ATM_his_keysort] 
     1259    ATM_fqcalving   = rprec (d_ATM_his ['fqcalving'])[..., ATM_his_keysort] 
     1260    ATM_fqfonte     = rprec (d_ATM_his ['fqfonte']  )[..., ATM_his_keysort] 
     1261    ATM_precip      = rprec (d_ATM_his ['precip']   )[..., ATM_his_keysort] 
     1262    ATM_snowf       = rprec (d_ATM_his ['snow']     )[..., ATM_his_keysort] 
     1263    ATM_evap        = rprec (d_ATM_his ['evap']     )[..., ATM_his_keysort] 
     1264    ATM_wevap_ter   = rprec (d_ATM_his ['wevap_ter'])[..., ATM_his_keysort] 
     1265    ATM_wevap_oce   = rprec (d_ATM_his ['wevap_oce'])[..., ATM_his_keysort] 
     1266    ATM_wevap_lic   = rprec (d_ATM_his ['wevap_lic'])[..., ATM_his_keysort] 
     1267    ATM_wevap_sic   = rprec (d_ATM_his ['wevap_sic'])[..., ATM_his_keysort] 
     1268    ATM_runofflic   = rprec (d_ATM_his ['runofflic'])[..., ATM_his_keysort] 
     1269    ATM_wevap_ter   = rprec (d_ATM_his ['wevap_ter'])[..., ATM_his_keysort] 
     1270    ATM_wevap_oce   = rprec (d_ATM_his ['wevap_oce'])[..., ATM_his_keysort] 
     1271    ATM_wevap_lic   = rprec (d_ATM_his ['wevap_lic'])[..., ATM_his_keysort] 
     1272    ATM_wevap_sic   = rprec (d_ATM_his ['wevap_sic'])[..., ATM_his_keysort] 
     1273    ATM_wrain_ter   = rprec (d_ATM_his ['wrain_ter'])[..., ATM_his_keysort] 
     1274    ATM_wrain_oce   = rprec (d_ATM_his ['wrain_oce'])[..., ATM_his_keysort] 
     1275    ATM_wrain_lic   = rprec (d_ATM_his ['wrain_lic'])[..., ATM_his_keysort] 
     1276    ATM_wrain_sic   = rprec (d_ATM_his ['wrain_sic'])[..., ATM_his_keysort] 
     1277    ATM_wsnow_ter   = rprec (d_ATM_his ['wsnow_ter'])[..., ATM_his_keysort] 
     1278    ATM_wsnow_oce   = rprec (d_ATM_his ['wsnow_oce'])[..., ATM_his_keysort] 
     1279    ATM_wsnow_lic   = rprec (d_ATM_his ['wsnow_lic'])[..., ATM_his_keysort] 
     1280    ATM_wsnow_sic   = rprec (d_ATM_his ['wsnow_sic'])[..., ATM_his_keysort] 
     1281    echo ( f'End of ico case ') 
     1282 
     1283echo ( 'ATM wprecip_oce' ) 
    11871284ATM_wprecip_oce = ATM_wrain_oce + ATM_wsnow_oce 
    11881285ATM_wprecip_ter = ATM_wrain_ter + ATM_wsnow_ter 
     
    11901287ATM_wprecip_lic = ATM_wrain_lic + ATM_wsnow_lic 
    11911288 
    1192 ATM_wbilo       = ATM_wbilo_oce + ATM_wbilo_sic + ATM_wbilo_ter + ATM_wbilo_lic 
    1193 ATM_emp         = ATM_evap - ATM_precip 
     1289ATM_wbilo       = ATM_wbilo_oce   + ATM_wbilo_sic   + ATM_wbilo_ter   + ATM_wbilo_lic 
     1290ATM_wevap       = ATM_wevap_oce   + ATM_wevap_sic   + ATM_wevap_ter   + ATM_wevap_lic 
     1291ATM_wprecip     = ATM_wprecip_oce + ATM_wprecip_sic + ATM_wprecip_ter + ATM_wprecip_lic 
     1292ATM_wsnow       = ATM_wsnow_oce   + ATM_wsnow_sic   + ATM_wsnow_ter   + ATM_wsnow_lic 
     1293ATM_wrain       = ATM_wrain_oce   + ATM_wrain_sic   + ATM_wrain_ter   + ATM_wrain_lic 
     1294ATM_wemp        = ATM_wevap - ATM_wprecip 
     1295ATM_emp         = ATM_evap  - ATM_precip 
     1296 
    11941297ATM_wprecip_sea = ATM_wprecip_oce + ATM_wprecip_sic 
    11951298ATM_wsnow_sea   = ATM_wsnow_oce   + ATM_wsnow_sic 
     
    11981301ATM_wevap_sea   = ATM_wevap_sic   + ATM_wevap_oce 
    11991302 
    1200 #ATM_wemp_ter = ATM_wevap_ter - ATM_precip * ATM_fter 
    1201 #ATM_wemp_oce = ATM_wevap_oce - ATM_precip * ATM_foce 
    1202 #ATM_wemp_sic = ATM_wevap_sic - ATM_precip * ATM_fsic 
    1203 #ATM_wemp_lic = ATM_wevap_lic - ATM_precip * ATM_flic 
    1204 #ATM_wemp_sea = ATM_wevap_sic + ATM_wevap_oce - ATM_precip * ATM_fsea 
    1205  
    1206 ATM_wemp_ter = ATM_wevap_ter - ATM_wprecip_ter  
    1207 ATM_wemp_oce = ATM_wevap_oce - ATM_wprecip_oce 
    1208 ATM_wemp_sic = ATM_wevap_sic - ATM_wprecip_sic 
    1209 ATM_wemp_lic = ATM_wevap_lic - ATM_wprecip_lic 
    1210 ATM_wemp_sea = ATM_wevap_sic - ATM_wprecip_oce 
    1211  
    1212 print ( 'Step {Step}', end='' ) ; Step += 1 
    1213 if RUN_HIS == 'latlon' :  
    1214     RUN_coastalflow = lmdz.geo2point ( d_RUN_his ['coastalflow'], dim1D='cell_latlon' )  
    1215     RUN_riverflow   = lmdz.geo2point ( d_RUN_his ['riverflow']  , dim1D='cell_latlon' ) 
    1216     RUN_runoff      = lmdz.geo2point ( d_RUN_his ['runoff']     , dim1D='cell_latlon' ) 
    1217     RUN_drainage    = lmdz.geo2point ( d_RUN_his ['drainage']   , dim1D='cell_latlon' ) 
    1218     RUN_riversret   = lmdz.geo2point ( d_RUN_his ['riversret']  , dim1D='cell_latlon' ) 
    1219      
    1220     RUN_coastalflow_cpl = lmdz.geo2point ( d_RUN_his ['coastalflow_cpl'], dim1D='cell_latlon' )  
    1221     RUN_riverflow_cpl   = lmdz.geo2point ( d_RUN_his ['riverflow_cpl']  , dim1D='cell_latlon' ) 
    1222  
    1223 print ( 'Step {Step}', end='' ) ; Step += 1 
     1303ATM_wemp_ter    = ATM_wevap_ter - ATM_wprecip_ter 
     1304ATM_wemp_oce    = ATM_wevap_oce - ATM_wprecip_oce 
     1305ATM_wemp_sic    = ATM_wevap_sic - ATM_wprecip_sic 
     1306ATM_wemp_lic    = ATM_wevap_lic - ATM_wprecip_lic 
     1307ATM_wemp_sea    = ATM_wevap_sic - ATM_wprecip_oce 
     1308 
     1309if RUN_HIS == 'latlon' : 
     1310    echo ( f'RUN costalflow Grille LATLON' ) 
     1311    if TestInterp : 
     1312         echo ( f'RUN runoff TestInterp' ) 
     1313         RUN_runoff      = lmdz.geo2point ( rprec (d_RUN_his ['runoff_contfrac_interp']  )   , dim1D='cell' ) 
     1314         RUN_drainage    = lmdz.geo2point ( rprec (d_RUN_his ['drainage_contfrac_interp'])   , dim1D='cell' ) 
     1315    else :  
     1316        echo ( f'RUN runoff' ) 
     1317        RUN_runoff      = lmdz.geo2point ( rprec (d_RUN_his ['runoff']         ), dim1D='cell' ) 
     1318        RUN_drainage    = lmdz.geo2point ( rprec (d_RUN_his ['drainage']       ), dim1D='cell' ) 
     1319         
     1320    RUN_coastalflow     = lmdz.geo2point ( rprec (d_RUN_his ['coastalflow']    ), dim1D='cell' )  
     1321    RUN_riverflow       = lmdz.geo2point ( rprec (d_RUN_his ['riverflow']      ), dim1D='cell' ) 
     1322    RUN_riversret       = lmdz.geo2point ( rprec (d_RUN_his ['riversret']      ), dim1D='cell' ) 
     1323    RUN_coastalflow_cpl = lmdz.geo2point ( rprec (d_RUN_his ['coastalflow_cpl']), dim1D='cell' )  
     1324    RUN_riverflow_cpl   = lmdz.geo2point ( rprec (d_RUN_his ['riverflow_cpl']  ), dim1D='cell' ) 
     1325 
    12241326if RUN_HIS == 'ico' : 
    1225     RUN_coastalflow =  d_RUN_his ['coastalflow'][..., RUN_his_keysort] 
    1226     RUN_riverflow   =  d_RUN_his ['riverflow']  [..., RUN_his_keysort] 
    1227     RUN_runoff      =  d_RUN_his ['runoff']     [..., RUN_his_keysort] 
    1228     RUN_drainage    =  d_RUN_his ['drainage']   [..., RUN_his_keysort] 
    1229     RUN_riversret   =  d_RUN_his ['riversret']  [..., RUN_his_keysort] 
    1230      
    1231     RUN_coastalflow_cpl = d_RUN_his ['coastalflow_cpl'][..., RUN_his_keysort] 
    1232     RUN_riverflow_cpl   = d_RUN_his ['riverflow_cpl']  [..., RUN_his_keysort] 
    1233  
    1234 print ( 'Step {Step}', end='' ) ; Step += 1 
     1327    echo ( f'RUN costalflow Grille ICO' ) 
     1328    RUN_coastalflow =  rprec (d_RUN_his ['coastalflow'])[..., RUN_his_keysort] 
     1329    RUN_riverflow   =  rprec (d_RUN_his ['riverflow']  )[..., RUN_his_keysort] 
     1330    RUN_runoff      =  rprec (d_RUN_his ['runoff']     )[..., RUN_his_keysort] 
     1331    RUN_drainage    =  rprec (d_RUN_his ['drainage']   )[..., RUN_his_keysort] 
     1332    RUN_riversret   =  rprec (d_RUN_his ['riversret']  )[..., RUN_his_keysort] 
     1333     
     1334    RUN_coastalflow_cpl = rprec (d_RUN_his ['coastalflow_cpl'])[..., RUN_his_keysort] 
     1335    RUN_riverflow_cpl   = rprec (d_RUN_his ['riverflow_cpl']  )[..., RUN_his_keysort] 
     1336 
     1337Step = 0 
     1338 
    12351339if SRF_HIS == 'latlon' : 
    1236     SRF_rain     = lmdz.geo2point ( d_SRF_his ['rain']  , dim1D='cell_latlon') 
    1237     SRF_evap     = lmdz.geo2point ( d_SRF_his ['evap']  , dim1D='cell_latlon') 
    1238     SRF_snowf    = lmdz.geo2point ( d_SRF_his ['snowf'] , dim1D='cell_latlon') 
    1239     SRF_subli    = lmdz.geo2point ( d_SRF_his ['subli'] , dim1D='cell_latlon') 
    1240     SRF_transpir = lmdz.geo2point ( np.sum (d_SRF_his ['transpir'], axis=1), dim1D='cell_latlon' ) 
    1241  
    1242 print ( 'Step {Step}', end='' ) ; Step += 1 
     1340    if TestInterp : 
     1341         echo ( f'SRF rain TestInterp' ) 
     1342         SRF_rain     = lmdz.geo2point ( rprec (d_SRF_his ['rain_contfrac_interp'] ), dim1D='cell') 
     1343         SRF_evap     = lmdz.geo2point ( rprec (d_SRF_his ['evap_contfrac_interp'] ), dim1D='cell') 
     1344         SRF_snowf    = lmdz.geo2point ( rprec (d_SRF_his ['snow_contfrac_interp'] ), dim1D='cell') 
     1345         SRF_subli    = lmdz.geo2point ( rprec (d_SRF_his ['subli_contfrac_interp']), dim1D='cell') 
     1346         SRF_transpir = lmdz.geo2point ( rprec (d_SRF_his ['transpir_contfrac_interp']).sum(dim='veget'), dim1D='cell' ) 
     1347         SRF_rain.attrs     = d_SRF_his ['rain_contfrac_interp'].attrs 
     1348         SRF_evap.attrs     = d_SRF_his ['evap_contfrac_interp'].attrs 
     1349         SRF_snowf.attrs    = d_SRF_his ['snow_contfrac_interp'].attrs 
     1350         SRF_subli.attrs    = d_SRF_his ['subli_contfrac_interp'].attrs 
     1351         SRF_transpir.attrs = d_SRF_his ['transpir_contfrac_interp'].attrs 
     1352    else :  
     1353        echo ( f'SRF rain' ) 
     1354        SRF_rain     = lmdz.geo2point ( rprec (d_SRF_his ['rain'] ) , dim1D='cell') 
     1355        SRF_evap     = lmdz.geo2point ( rprec (d_SRF_his ['evap'] ) , dim1D='cell') 
     1356        SRF_snowf    = lmdz.geo2point ( rprec (d_SRF_his ['snowf']) , dim1D='cell') 
     1357        SRF_subli    = lmdz.geo2point ( rprec (d_SRF_his ['subli']) , dim1D='cell') 
     1358        SRF_transpir = lmdz.geo2point ( rprec (d_SRF_his ['transpir']).sum(dim='veget'), dim1D='cell' ) 
     1359 
    12431360if SRF_HIS == 'ico' : 
    1244     SRF_rain     = d_SRF_his ['rain'] [..., SRF_his_keysort] 
    1245     SRF_evap     = d_SRF_his ['evap'] [..., SRF_his_keysort] 
    1246     SRF_snowf    = d_SRF_his ['snowf'][..., SRF_his_keysort] 
    1247     SRF_subli    = d_SRF_his ['subli'][..., SRF_his_keysort] 
    1248     SRF_transpir = np.sum (d_SRF_his ['transpir'], axis=1)[..., SRF_his_keysort] 
    1249  
    1250 print ( 'Step {Step}', end='' ) ; Step += 1 
     1361    echo ( f'SRF rain') 
     1362    SRF_rain     = rprec (d_SRF_his ['rain'] )[..., SRF_his_keysort] 
     1363    SRF_evap     = rprec (d_SRF_his ['evap'] )[..., SRF_his_keysort] 
     1364    SRF_snowf    = rprec (d_SRF_his ['snowf'])[..., SRF_his_keysort] 
     1365    SRF_subli    = rprec (d_SRF_his ['subli'])[..., SRF_his_keysort] 
     1366    SRF_transpir = rprec (d_SRF_his ['transpir']).sum(dim='veget')[..., SRF_his_keysort] 
     1367 
     1368echo ( f'SRF emp' ) 
    12511369SRF_transpir.attrs['units'] = d_SRF_his ['transpir'].attrs['units'] 
    12521370SRF_emp      = SRF_evap - SRF_rain - SRF_snowf ; SRF_emp.attrs['units'] = SRF_rain.attrs['units'] 
     
    12711389    mmd2SI (VarT) 
    12721390 
    1273 print ( 'Step {Step}', end='' ) ; Step += 1 
     1391echo ( f'RUN input' ) 
    12741392RUN_input  = RUN_runoff      + RUN_drainage 
    12751393RUN_output = RUN_coastalflow + RUN_riverflow 
    12761394 
    1277 print ( 'Step {Step}', end='' ) ; Step += 1 
     1395echo ( f'ATM flw_wbilo' ) 
    12781396ATM_flx_wbilo       = ATM_flux_int ( ATM_wbilo      ) 
     1397ATM_flx_wevap       = ATM_flux_int ( ATM_wevap      ) 
     1398ATM_flx_wprecip     = ATM_flux_int ( ATM_wprecip    ) 
     1399ATM_flx_wsnow       = ATM_flux_int ( ATM_wsnow      ) 
     1400ATM_flx_wrain       = ATM_flux_int ( ATM_wrain      ) 
     1401ATM_flx_wemp        = ATM_flux_int ( ATM_wemp       ) 
     1402 
    12791403ATM_flx_wbilo_lic   = ATM_flux_int ( ATM_wbilo_lic  ) 
    12801404ATM_flx_wbilo_oce   = ATM_flux_int ( ATM_wbilo_oce  ) 
     
    12851409ATM_flx_fqfonte     = ATM_flux_int ( ATM_fqfonte    ) 
    12861410 
    1287 print ( 'Step {Step}', end='' ) ; Step += 1 
     1411LIC_flx_calving     = LIC_flux_int ( ATM_fqcalving  ) 
     1412LIC_flx_fqfonte     = LIC_flux_int ( ATM_fqfonte    ) 
     1413 
     1414echo ( f'ATM flx precip' ) 
    12881415ATM_flx_precip      = ATM_flux_int ( ATM_precip     ) 
    12891416ATM_flx_snowf       = ATM_flux_int ( ATM_snowf      ) 
     
    12911418ATM_flx_runlic      = ATM_flux_int ( ATM_runofflic  ) 
    12921419 
    1293 print ( 'Step {Step}', end='' ) ; Step += 1 
     1420LIC_flx_precip      = LIC_flux_int ( ATM_precip     ) 
     1421LIC_flx_snowf       = LIC_flux_int ( ATM_snowf      ) 
     1422LIC_flx_evap        = LIC_flux_int ( ATM_evap       ) 
     1423LIC_flx_runlic      = LIC_flux_int ( ATM_runofflic  ) 
     1424 
     1425echo ( f'ATM flx_wrain_ter' ) 
    12941426ATM_flx_wrain_ter    = ATM_flux_int ( ATM_wrain_ter ) 
    12951427ATM_flx_wrain_oce    = ATM_flux_int ( ATM_wrain_oce ) 
     
    13031435ATM_flx_wsnow_sic    = ATM_flux_int ( ATM_wsnow_sic ) 
    13041436ATM_flx_wsnow_sea    = ATM_flux_int ( ATM_wsnow_sea ) 
    1305 print ( 'Step {Step}', end='' ) ; Step += 1 
    1306 ATM_flx_wrain_ter    = ATM_flux_int ( ATM_wrain_ter ) 
    1307 ATM_flx_wrain_oce    = ATM_flux_int ( ATM_wrain_oce ) 
    1308 ATM_flx_wrain_lic    = ATM_flux_int ( ATM_wrain_lic ) 
    1309 ATM_flx_wrain_sic    = ATM_flux_int ( ATM_wrain_sic ) 
    1310 ATM_flx_wrain_sea    = ATM_flux_int ( ATM_wrain_sea ) 
     1437 
     1438echo ( f'ATM flx_evap_ter' )  
    13111439ATM_flx_wevap_ter    = ATM_flux_int ( ATM_wevap_ter ) 
    13121440ATM_flx_wevap_oce    = ATM_flux_int ( ATM_wevap_oce ) 
     
    13251453ATM_flx_wemp_sea     = ATM_flux_int ( ATM_wemp_sea ) 
    13261454 
    1327 ATM_flx_emp          = ATM_flux_int ( ATM_emp) 
    1328  
    1329 print ( 'Step {Step}', end='' ) ; Step += 1 
     1455ATM_flx_emp          = ATM_flux_int ( ATM_emp ) 
     1456 
     1457echo ( f'RUN flx_coastal' ) 
    13301458RUN_flx_coastal     = ONE_flux_int ( RUN_coastalflow) 
     1459echo ( f'RUN flx_river' ) 
    13311460RUN_flx_river       = ONE_flux_int ( RUN_riverflow  ) 
     1461echo ( f'RUN flx_coastal_cpl' ) 
    13321462RUN_flx_coastal_cpl = ONE_flux_int ( RUN_coastalflow_cpl) 
     1463echo ( f'RUN flx_river_cpl' ) 
    13331464RUN_flx_river_cpl   = ONE_flux_int ( RUN_riverflow_cpl  ) 
     1465echo ( f'RUN flx_drainage' ) 
    13341466RUN_flx_drainage    = SRF_flux_int ( RUN_drainage   ) 
     1467echo ( f'RUN flx_riversset' ) 
    13351468RUN_flx_riversret   = SRF_flux_int ( RUN_riversret  ) 
     1469echo ( f'RUN flx_runoff' ) 
    13361470RUN_flx_runoff      = SRF_flux_int ( RUN_runoff     ) 
     1471echo ( f'RUN flx_input' ) 
    13371472RUN_flx_input       = SRF_flux_int ( RUN_input      ) 
     1473echo ( f'RUN flx_output' ) 
    13381474RUN_flx_output      = ONE_flux_int ( RUN_output     ) 
    13391475 
    1340 print ( 'Step {Step}', end='' ) ; Step += 1 
    1341 RUN_flx_bil    = RUN_flx_input   - RUN_flx_output 
    1342 RUN_flx_rivcoa = RUN_flx_coastal + RUN_flx_river 
    1343  
    1344 prtFlux ('wbilo_oce     ', ATM_flx_wbilo_oce  , 'f' )           
    1345 prtFlux ('wbilo_sic     ', ATM_flx_wbilo_sic  , 'f' )           
    1346 prtFlux ('wbilo_sic+oce ', ATM_flx_wbilo_sea  , 'f' )           
    1347 prtFlux ('wbilo_ter     ', ATM_flx_wbilo_ter  , 'f' )           
    1348 prtFlux ('wbilo_lic     ', ATM_flx_wbilo_lic  , 'f' )           
    1349 prtFlux ('Sum wbilo_*   ', ATM_flx_wbilo      , 'f', True)   
    1350 prtFlux ('E-P           ', ATM_flx_emp        , 'f', True)   
    1351 prtFlux ('calving       ', ATM_flx_calving    , 'f' )  
    1352 prtFlux ('fqfonte       ', ATM_flx_fqfonte    , 'f' )        
    1353 prtFlux ('precip        ', ATM_flx_precip     , 'f' )        
    1354 prtFlux ('snowf         ', ATM_flx_snowf      , 'f' )         
    1355 prtFlux ('evap          ', ATM_flx_evap       , 'f' ) 
    1356 prtFlux ('runoff lic    ', ATM_flx_runlic     , 'f' ) 
    1357  
    1358 prtFlux ('ATM_flx_wemp_lic     ', ATM_flx_wemp_lic      , 'f' ) 
    1359 prtFlux ('ATM_flx_wemp_oce     ', ATM_flx_wemp_oce      , 'f' ) 
    1360 prtFlux ('ATM_flx_wemp_sic     ', ATM_flx_wemp_sic      , 'f' ) 
    1361 prtFlux ('ATM_flx_wemp_ter     ', ATM_flx_wemp_ter      , 'f' ) 
    1362  
    1363 prtFlux ('ATM_flx_wprecip_lic  ', ATM_flx_wprecip_lic   , 'f' ) 
    1364 prtFlux ('ATM_flx_wprecip_oce  ', ATM_flx_wprecip_oce   , 'f' ) 
    1365 prtFlux ('ATM_flx_wprecip_sic  ', ATM_flx_wprecip_sic   , 'f' ) 
    1366 prtFlux ('ATM_flx_wprecip_ter  ', ATM_flx_wprecip_ter   , 'f' ) 
    1367  
    1368 prtFlux ('ATM_flx_wrain_lic    ', ATM_flx_wrain_lic     , 'f' ) 
    1369 prtFlux ('ATM_flx_wrain_oce    ', ATM_flx_wrain_oce     , 'f' ) 
    1370 prtFlux ('ATM_flx_wrain_sic    ', ATM_flx_wrain_sic     , 'f' ) 
    1371 prtFlux ('ATM_flx_wrain_ter    ', ATM_flx_wrain_ter     , 'f' ) 
    1372  
    1373 prtFlux ('ATM_flx_wsnow_lic    ', ATM_flx_wsnow_lic     , 'f' ) 
    1374 prtFlux ('ATM_flx_wsnow_oce    ', ATM_flx_wsnow_oce     , 'f' ) 
    1375 prtFlux ('ATM_flx_wsnow_sic    ', ATM_flx_wsnow_sic     , 'f' ) 
    1376 prtFlux ('ATM_flx_wsnow_ter    ', ATM_flx_wsnow_ter     , 'f' ) 
    1377  
    1378 prtFlux ('ATM_flx_wevap_lic    ', ATM_flx_wevap_lic     , 'f' ) 
    1379 prtFlux ('ATM_flx_wevap_oce    ', ATM_flx_wevap_oce     , 'f' ) 
    1380 prtFlux ('ATM_flx_wevap_sic    ', ATM_flx_wevap_sic     , 'f' ) 
    1381 prtFlux ('ATM_flx_wevap_ter    ', ATM_flx_wevap_ter     , 'f' ) 
    1382  
    1383 prtFlux ('ATM_flx_wevap_lic    ', ATM_flx_wevap_lic     , 'f' ) 
    1384 prtFlux ('ATM_flx_wevap_oce    ', ATM_flx_wevap_oce     , 'f' ) 
    1385 prtFlux ('ATM_flx_wevap_sic    ', ATM_flx_wevap_sic     , 'f' ) 
    1386 prtFlux ('ATM_flx_wevap_ter    ', ATM_flx_wevap_ter     , 'f' ) 
     1476echo ( f'RUN flx_bil' ) ; Step += 1 
     1477#RUN_flx_bil    = RUN_flx_input   - RUN_flx_output 
     1478#RUN_flx_rivcoa = RUN_flx_coastal + RUN_flx_river 
     1479 
     1480RUN_flx_bil    = ONE_flux_int ( RUN_input       - RUN_output) 
     1481RUN_flx_rivcoa = ONE_flux_int ( RUN_coastalflow + RUN_riverflow) 
     1482 
     1483prtFlux ('wbilo_oce            ', ATM_flx_wbilo_oce     , 'f' )           
     1484prtFlux ('wbilo_sic            ', ATM_flx_wbilo_sic     , 'f' )           
     1485prtFlux ('wbilo_sic+oce        ', ATM_flx_wbilo_sea     , 'f' )           
     1486prtFlux ('wbilo_ter            ', ATM_flx_wbilo_ter     , 'f' )           
     1487prtFlux ('wbilo_lic            ', ATM_flx_wbilo_lic     , 'f' )           
     1488prtFlux ('Sum wbilo_*          ', ATM_flx_wbilo         , 'f', True)   
     1489prtFlux ('E-P                  ', ATM_flx_emp           , 'f', True)   
     1490prtFlux ('calving              ', ATM_flx_calving       , 'f' )  
     1491prtFlux ('fqfonte              ', ATM_flx_fqfonte       , 'f' )        
     1492prtFlux ('precip               ', ATM_flx_precip        , 'f' )        
     1493prtFlux ('snowf                ', ATM_flx_snowf         , 'f' )         
     1494prtFlux ('evap                 ', ATM_flx_evap          , 'f' ) 
     1495prtFlux ('runoff lic           ', ATM_flx_runlic        , 'f' ) 
     1496 
     1497prtFlux ('ATM_flx_wevap*       ', ATM_flx_wevap         , 'f' ) 
     1498prtFlux ('ATM_flx_wrain*       ', ATM_flx_wrain         , 'f' ) 
     1499prtFlux ('ATM_flx_wsnow*       ', ATM_flx_wsnow         , 'f' ) 
     1500prtFlux ('ATM_flx_wprecip*     ', ATM_flx_wprecip       , 'f' ) 
     1501prtFlux ('ATM_flx_wemp*        ', ATM_flx_wemp          , 'f', True ) 
     1502 
     1503prtFlux ('ERROR evap           ', ATM_flx_wevap   - ATM_flx_evap  , 'e', True ) 
     1504prtFlux ('ERROR precip         ', ATM_flx_wprecip - ATM_flx_precip, 'e', True ) 
     1505prtFlux ('ERROR snow           ', ATM_flx_wsnow   - ATM_flx_snowf , 'e', True ) 
     1506prtFlux ('ERROR emp            ', ATM_flx_wemp    - ATM_flx_emp   , 'e', True ) 
     1507 
    13871508 
    13881509echo ( '\n====================================================================================' ) 
     
    14011522 
    14021523ATM_flx_budget = -ATM_flx_wbilo + ATM_flx_calving + ATM_flx_runlic #+ ATM_flx_fqfonte + RUN_flx_river 
     1524 
     1525 
    14031526echo ('') 
    14041527#echo ('  Global        {:12.3e} kg | {:12.4f} Sv | {:12.4f} m '.format ( ATM_flx_budget , ATM_flx_budget / dtime_sec*1E-9, ATM_flx_budget /ATM_aire_sea_tot/ATM_rho )) 
     
    14271550echo ( '\n====================================================================================' ) 
    14281551 
    1429 ATM_flx_runofflic_lic = ATM_flux_int ( ATM_runofflic * ATM_flic ) 
    1430  
    1431 LIC_flx_budget1 = -ATM_flx_wemp_lic  - ATM_flx_calving - ATM_flx_fqfonte 
    1432 LIC_flx_budget2 = -ATM_flx_wbilo_lic - ATM_flx_calving - ATM_flx_fqfonte 
    1433 LIC_flx_budget3 = -ATM_flx_wbilo_lic - ATM_flx_runofflic_lic 
     1552LIC_flx_budget1 = Sprec ( [-ATM_flx_wemp_lic  , -LIC_flx_calving , -LIC_flx_fqfonte] ) 
     1553LIC_flx_budget2 = Sprec ( [-ATM_flx_wbilo_lic , -LIC_flx_calving , -LIC_flx_fqfonte] ) 
     1554LIC_flx_budget3 = Sprec ( [-ATM_flx_wbilo_lic , -LIC_flx_runlic] ) 
     1555LIC_flx_budget4 = Sprec ( [-ATM_flx_wemp_lic  , -LIC_flx_runlic] ) 
    14341556 
    14351557echo ( f'--  LIC  -- {Title} ' ) 
     
    14381560echo ( f'Mass qs      begin = {LIC_mas_qs_beg     :12.6e} kg | Mass end = {LIC_mas_qs_end     :12.6e} kg' ) 
    14391561echo ( f'Mass runlic0 begin = {LIC_mas_runlic0_beg:12.6e} kg | Mass end = {LIC_mas_runlic0_end:12.6e} kg' ) 
    1440 prtFlux ( 'dmass (LIC sno)       ', dLIC_mas_sno          , 'f', True, width=65 ) 
    1441 prtFlux ( 'dmass (LIC qs)        ', dLIC_mas_qs           , 'e', True, width=65 ) 
    1442 prtFlux ( 'dmass (LIC wat)       ', dLIC_mas_wat          , 'f', True, width=65 ) 
    1443 prtFlux ( 'dmass (LIC runlic0)   ', dLIC_mas_runlic0      , 'e', True, width=65 ) 
    1444 prtFlux ( 'dmass (LIC total)     ', dLIC_mas_wat          , 'e', True, width=65 ) 
    1445 prtFlux ( 'LIC ATM_flx_wemp_lic  ', ATM_flx_wemp_lic      , 'f', True, width=65 ) 
    1446 prtFlux ( 'LIC ATM_flx_fqfonte   ', ATM_flx_fqfonte       , 'f', True, width=65 ) 
    1447 prtFlux ( 'LIC ATM_flx_calving   ', ATM_flx_calving       , 'f', True, width=65 ) 
    1448 prtFlux ( 'LIC ATM_flx_runofflic ', ATM_flx_runofflic_lic , 'f', True, width=65 ) 
    1449 prtFlux ( 'LIC fqfonte + calving ', ATM_flx_calving+ATM_flx_fqfonte , 'f', True, width=65 ) 
    1450 prtFlux ( 'LIC fluxes 1 (wevap - precip*frac_lic  - fqcalving - fqfonte) ', LIC_flx_budget1              , 'f', True, width=65 ) 
    1451 prtFlux ( 'LIC fluxes 2 (-wbilo_lic - fqcalving - fqfonte)               ', LIC_flx_budget2              , 'f', True, width=65 ) 
    1452 prtFlux ( 'LIC fluxes 3 (-wbilo_lic - runofflic*frac_lic)                ', LIC_flx_budget3              , 'f', True, width=65 ) 
    1453 prtFlux ( 'LIC error 1                                                   ', LIC_flx_budget1-dLIC_mas_wat , 'e', True, width=65 ) 
    1454 prtFlux ( 'LIC error 2                                                   ', LIC_flx_budget2-dLIC_mas_wat , 'e', True, width=65 ) 
    1455 prtFlux ( 'LIC error 3                                                   ', LIC_flx_budget3-dLIC_mas_wat , 'e', True, width=65 ) 
     1562prtFlux ( 'dmass (LIC sno)       ', dLIC_mas_sno          , 'f', True, width=45 ) 
     1563prtFlux ( 'dmass (LIC qs)        ', dLIC_mas_qs           , 'e', True, width=45 ) 
     1564prtFlux ( 'dmass (LIC wat)       ', dLIC_mas_wat          , 'f', True, width=45 ) 
     1565prtFlux ( 'dmass (LIC runlic0)   ', dLIC_mas_runlic0      , 'e', True, width=45 ) 
     1566prtFlux ( 'dmass (LIC total)     ', dLIC_mas_wat          , 'e', True, width=45 ) 
     1567prtFlux ( 'LIC ATM_flx_wemp_lic  ', ATM_flx_wemp_lic      , 'f', True, width=45 ) 
     1568prtFlux ( 'LIC LIC_flx_fqfonte   ', LIC_flx_fqfonte       , 'f', True, width=45 ) 
     1569prtFlux ( 'LIC LIC_flx_calving   ', LIC_flx_calving       , 'f', True, width=45 ) 
     1570prtFlux ( 'LIC LIC_flx_runofflic ', LIC_flx_runlic        , 'f', True, width=45 ) 
     1571prtFlux ( 'LIC fqfonte + calving ', LIC_flx_calving+LIC_flx_fqfonte , 'f', True, width=45 ) 
     1572prtFlux ( 'LIC fluxes 1 ( wemp_lic   - fqcalving - fqfonte)) ', LIC_flx_budget1              , 'f', True, width=45 ) 
     1573prtFlux ( 'LIC fluxes 2 (-wbilo_lic - fqcalving - fqfonte)   ', LIC_flx_budget2              , 'f', True, width=45 ) 
     1574prtFlux ( 'LIC fluxes 3 (-wbilo_lic - runofflic*frac_lic)    ', LIC_flx_budget3              , 'f', True, width=45 ) 
     1575prtFlux ( 'LIC fluxes 3 ( wemp_lic  - runofflic*frac_lic)    ', LIC_flx_budget4              , 'f', True, width=45 ) 
     1576prtFlux ( 'LIC error 1                                       ', LIC_flx_budget1-dLIC_mas_wat , 'e', True, width=45 ) 
     1577prtFlux ( 'LIC error 2                                       ', LIC_flx_budget2-dLIC_mas_wat , 'e', True, width=45 ) 
     1578prtFlux ( 'LIC error 3                                       ', LIC_flx_budget3-dLIC_mas_wat , 'e', True, width=45 ) 
    14561579echo ( 'LIC error (wevap - precip*frac_lic  - fqcalving - fqfonte)    = {:12.4e} (rel) '.format ( (LIC_flx_budget1-dLIC_mas_wat)/dLIC_mas_wat) ) 
    14571580echo ( 'LIC error (-wbilo_lic - fqcalving - fqfonte)                  = {:12.4e} (rel) '.format ( (LIC_flx_budget2-dLIC_mas_wat)/dLIC_mas_wat) ) 
     
    14681591SRF_flx_emp      = SRF_flux_int ( SRF_emp      ) 
    14691592 
    1470 RUN_flx_torouting  =  RUN_flx_runoff  + RUN_flx_drainage 
    1471 RUN_flx_fromrouting = RUN_flx_coastal + RUN_flx_river 
    1472  
    1473 SRF_flx_all = SRF_flx_rain + SRF_flx_snowf - SRF_flx_evap - RUN_flx_runoff - RUN_flx_drainage 
     1593RUN_flx_torouting   = SRF_flux_int  ( RUN_runoff       + RUN_drainage) 
     1594RUN_flx_fromrouting = ONE_flux_int  ( RUN_coastalflow + RUN_riverflow ) 
     1595 
     1596SRF_flx_all =  SRF_flux_int  ( SRF_rain + SRF_snowf - SRF_evap - RUN_runoff - RUN_drainage ) 
    14741597 
    14751598prtFlux ('rain         ', SRF_flx_rain       , 'f' ) 
  • TOOLS/WATER_BUDGET/CPL_waterbudget.py

    r6508 r6647  
    1212## 
    1313## 
    14 ## SVN information 
     14# SVN information 
    1515#  $Author$ 
    1616#  $Date$ 
     
    1919#  $HeadURL$ 
    2020 
    21  
     21# SVN Information 
     22SVN = { 
     23    'Author'  : "$Author$", 
     24    'Date'    : "$Date$", 
     25    'Revision': "$Revision$", 
     26    'Id'      : "$Id$", 
     27    'HeadURL' : "$HeadUrl:  $" 
     28    } 
    2229### 
    2330## Import system modules 
     
    2734from pathlib import Path 
    2835 
     36### 
     37## Import system modules 
     38import sys, os, shutil#, subprocess, platform 
     39import configparser, re 
     40 
     41## Import needed scientific modules 
     42import numpy as np, xarray as xr 
     43 
    2944# Check python version 
    3045if sys.version_info < (3, 8, 0) : 
     
    3247    raise Exception ( "Minimum Python version is 3.8" ) 
    3348 
    34 ## Import local module 
     49## Import local modules 
    3550import WaterUtils as wu 
     51import libIGCM_sys 
     52import nemo, lmdz 
     53 
     54from WaterUtils import VarInt, Rho, Ra, Grav, ICE_rho_ice, ICE_rho_sno, OCE_rho_liq, ATM_rho, SRF_rho, RUN_rho, ICE_rho_pnd, YearLength 
    3655 
    3756## Creates parser for reading .ini input file 
    38 config = configparser.ConfigParser (interpolation=configparser.ExtendedInterpolation() ) 
     57## ------------------------------------------- 
     58config = configparser.ConfigParser ( interpolation=configparser.ExtendedInterpolation() ) 
    3959config.optionxform = str # To keep capitals 
    4060 
    4161## Experiment parameters 
    42 ATM=None ; ATM_HIS='latlon' ; SRF_HIS='latlon' ; ORCA=None ; NEMO=None ; OCE_relax=False ; OCE_icb=False ; Coupled=False ; Routing=None ;  TarRestartPeriod_beg=None ; TarRestartPeriod_end=None ; Comment=None ; Period=None ; Title=None 
     62## --------------------- 
     63ATM=None ; ATM_HIS='latlon' ; SRF_HIS='latlon' ; RUN_HIS='latlon' ; ORCA=None ; NEMO=None ; OCE_relax=False 
     64OCE_icb=False ; Coupled=False ; Routing=None ; TestInterp=None 
     65TarRestartPeriod_beg=None ; TarRestartPeriod_end=None ; Comment=None ; Period=None ; Title=None 
     66YearBegin=None ; YearEnd=None ; DateBegin=None ; DateEnd=None 
    4367 
    4468## 
    45 ARCHIVE=None ; STORAGE=None ; SCRATCHDIR=None ; R_IN=None ; rebuild=None 
    46 TmpDir=None ; RunDir=None ; FileOut=None ; dir_ATM_his=None ; dir_SRF_his=None ; dir_OCE_his=None ; dir_ICE_his=None ; FileCommon=None 
    47 file_ATM_his=None ; file_SRF_his=None ; file_RUN_his=None ; file_OCE_his=None ;  file_ICE_his=None ; file_OCE_sca=None 
    48 tar_restart_beg=None ; tar_restart_end=None ; file_ATM_beg=None ; file_ATM_end=None ; file_DYN_beg=None ; file_DYN_end=None ; file_SRF_beg=None ; file_SRF_end=None 
    49 file_RUN_beg=None ; file_RUN_end=None ; file_RUN_end=None ; file_OCE_beg=None ; file_ICE_beg=None ; file_OCE_beg=None ; file_OCE_end=None ; file_OCE_srf=None ; file_OCE_sca=None ; file_ICE_beg=None ; file_OCE_end=None ; file_ICE_end=None 
    50  
    51 # Read command line arguments 
     69ARCHIVE=None ; STORAGE=None ; SCRATCHDIR=None ; R_IN=None ; rebuild=None ; TmpDir=None 
     70FileDir=None ; FileOut=None 
     71dir_ATM_his=None ; dir_SRF_his=None ; dir_OCE_his=None ; dir_ICE_his=None 
     72FileCommon=None ; file_ATM_his=None ; file_SRF_his=None ; file_RUN_his=None 
     73file_OCE_his=None ;  file_ICE_his=None ; file_OCE_sca=None ; file_OCE_srf=None 
     74tar_restart_beg=None ; tar_restart_end=None ; file_ATM_beg=None ; file_ATM_end=None ; file_DYN_beg=None 
     75file_DYN_end=None ; file_SRF_beg=None ; file_SRF_end=None 
     76file_RUN_beg=None ; file_RUN_end=None ; file_RUN_end=None ; file_OCE_beg=None 
     77file_ICE_beg=None ; file_OCE_beg=None 
     78file_OCE_end=None ; file_ICE_beg=None ; file_OCE_end=None ; file_ICE_end=None 
     79tar_restart_beg_ATM=None ; tar_restart_beg_DYN=None ; tar_restart_beg_SRF=None 
     80tar_restart_beg_RUN=None ; tar_restart_beg_OCE=None ; tar_restart_beg_ICE=None 
     81tar_restart_end_ATM=None ; tar_restart_end_DYN=None ; tar_restart_end_SRF=None 
     82tar_restart_end_RUN=None ; tar_restart_end_OCE=None ; tar_restart_end_ICE=None 
     83ContinueOnError=False ; ErrorCount=0 ; SortIco = False 
     84 
     85## 
     86## Precision of history file reading 
     87## --------------------------------- 
     88# Default is float (full precision). Degrade the precision by using np.float32 
     89# Restart file are always read at the full precision 
     90readPrec=float 
     91 
     92## Read command line arguments 
     93## --------------------------- 
    5294print ( "Name of Python script:", sys.argv[0] ) 
    5395IniFile = sys.argv[1] 
    54 # Text existence of IniFile 
     96 
     97# Test existence of IniFile 
    5598if not os.path.exists (IniFile ) : 
    5699    raise FileExistsError ( f"File not found : {IniFile = }" ) 
     
    63106FullIniFile = 'full_' + IniFile 
    64107 
     108## Reading config.card if possible 
     109## ------------------------------- 
     110ConfigCard = None 
     111 
     112if 'Experiment' in config.keys ()  : ## Read Experiment on Config file if possible 
     113    if 'ConfigCard' in config['Experiment'].keys () : 
     114        ConfigCard = config['Experiment']['ConfigCard'] 
     115        print ( f'{ConfigCard=}' ) 
     116 
     117if ConfigCard : ## Read config card if it exists 
     118    # Text existence of ConfigCard 
     119    if os.path.exists ( ConfigCard ) : 
     120        print ( f'Reading Config Card : {ConfigCard}' ) 
     121        ## Creates parser for reading .ini input file 
     122        MyReader = configparser.ConfigParser (interpolation=configparser.ExtendedInterpolation() ) 
     123        MyReader.optionxform = str # To keep capitals 
     124         
     125        MyReader.read (ConfigCard) 
     126 
     127        for VarName in ['JobName', 'ExperimentName', 'SpaceName', 'LongName', 'ModelName', 'TagName'] : 
     128            if VarName in MyReader['UserChoices'].keys() : 
     129                locals()[VarName] = MyReader['UserChoices'][VarName] 
     130                exec  ( f'{VarName} = wu.setBool ({VarName})' ) 
     131                exec  ( f'{VarName} = wu.setNum  ({VarName})' ) 
     132                exec  ( f'{VarName} = wu.setNone ({VarName})' ) 
     133                exec  ( f'wu.{VarName} = {VarName}' ) 
     134                print ( f'    {VarName:21} set to : {locals()[VarName]:}' ) 
     135                 
     136        for VarName in ['PackFrequency'] : 
     137            if VarName in MyReader['Post'].keys() : 
     138                locals()[VarName] = MyReader['Post'][VarName] 
     139                exec  ( f'{VarName} = wu.setBool ({VarName})' ) 
     140                exec  ( f'{VarName} = wu.setNum  ({VarName})' ) 
     141                exec  ( f'{VarName} = wu.setNone ({VarName})' ) 
     142                exec  ( f'wu.{VarName} = {VarName}' ) 
     143                print ( f'    {VarName:21} set to : {locals()[VarName]:}' ) 
     144    else : 
     145        raise FileExistsError ( f"File not found : {ConfigCard = }" ) 
     146 
     147     
    65148## Reading config file 
    66 for Section in ['Experiment', 'libIGCM', 'Files', 'Physics' ] : 
     149## ------------------- 
     150for Section in ['Config', 'Experiment', 'libIGCM', 'Files', 'Physics' ] : 
    67151   if Section in config.keys () :  
    68         print ( f'Reading [{Section}]' ) 
     152        print ( f'\nReading [{Section}]' ) 
    69153        for VarName in config[Section].keys() : 
    70154            locals()[VarName] = config[Section][VarName] 
    71             exec ( f'{VarName} = wu.setBool ({VarName})' ) 
    72             exec ( f'{VarName} = wu.setNum  ({VarName})' ) 
    73             exec ( f'{VarName} = wu.setNone ({VarName})' ) 
    74             exec ( f'wu.{VarName} = {VarName}' ) 
    75             print ( '{:25} set to : {:}'.format (VarName, locals()[VarName]) ) 
     155            exec  ( f'{VarName} = wu.setBool ({VarName})' ) 
     156            exec  ( f'{VarName} = wu.setNum  ({VarName})' ) 
     157            exec  ( f'{VarName} = wu.setNone ({VarName})' ) 
     158            exec  ( f'wu.{VarName} = {VarName}' ) 
     159            print ( f'    {VarName:21} set to : {locals()[VarName]}' ) 
    76160            #exec ( f'del {VarName}' ) 
    77161 
    78 #-- Some physical constants 
    79 if wu.unDefined ( 'Ra' )           : Ra          = 6366197.7236758135 #-- Earth Radius (m) 
    80 if wu.unDefined ( 'Grav' )         : Grav        = 9.81               #-- Gravity (m^2/s 
    81 if wu.unDefined ( 'ICE_rho_ice' )  : ICE_rho_ice = 917.0              #-- Ice volumic mass (kg/m3) in LIM3 
    82 if wu.unDefined ( 'ICE_rho_sno')   : ICE_rho_sno = 330.0              #-- Snow volumic mass (kg/m3) in LIM3 
    83 if wu.unDefined ( 'OCE_rho_liq' )  : OCE_rho_liq = 1026.0             #-- Ocean water volumic mass (kg/m3) in NEMO 
    84 if wu.unDefined ( 'ATM_rho' )      : ATM_rho     = 1000.0             #-- Water volumic mass in atmosphere (kg/m^3) 
    85 if wu.unDefined ( 'SRF_rho' )      : SRF_rho     = 1000.0             #-- Water volumic mass in surface reservoir (kg/m^3) 
    86 if wu.unDefined ( 'RUN_rho' )      : RUN_rho     = 1000.0             #-- Water volumic mass of rivers (kg/m^3) 
    87 if wu.unDefined ( 'ICE_rho_pnd' )  : ICE_rho_pnd = 1000.              #-- Water volumic mass in ice ponds (kg/m^3) 
    88 if wu.unDefined ( 'YearLength' )   : YearLength  = 365.25 * 24. * 60. * 60. #-- Year length (s) - Use only to compute drif in approximate unit  
    89  
    90 # Set libIGCM and machine dependant values 
    91 if not 'Files' in config.keys() : config['Files'] = {} 
    92  
    93 config['Physics'] = { 'Ra':Ra, 'Grav':Grav, 'ICE_rho_ice':ICE_rho_ice, 'ICE_rho_sno':ICE_rho_sno, 'OCE_rho_liq':OCE_rho_liq, 'ATM_rho':ATM_rho, 'SRF_rho':SRF_rho, 'RUN_rho':RUN_rho} 
     162print ( f'\nConfig file readed : {IniFile} ' ) 
     163 
     164## 
     165## Reading prec 
     166if wu.unDefined ( 'readPrec' )  : 
     167    readPrec = np.float64 
     168else : 
     169    if readPrec in ["float", "float64", "r8", "double", "<class 'float'>"         ] : readPrec = float 
     170    if readPrec in [         "float32", "r4", "single", "<class 'numpy.float32'>" ] : readPrec = np.float32 
     171    if readPrec in [         "float16", "r2", "half"  , "<class 'numpy.float16'>" ] : readPrec = np.float16 
     172     
     173## Some physical constants 
     174## ======================= 
     175if wu.unDefined ( 'Ra' )           : Ra          = wu.Ra           #-- Earth Radius (m) 
     176if wu.unDefined ( 'Grav' )         : Grav        = wu.Grav         #-- Gravity (m^2/s 
     177if wu.unDefined ( 'ICE_rho_ice' )  : ICE_rho_ice = wu.ICE_rho_ice  #-- Ice volumic mass (kg/m3) in LIM3 
     178if wu.unDefined ( 'ICE_rho_sno')   : ICE_rho_sno = wu.ICE_rho_sno  #-- Snow volumic mass (kg/m3) in LIM3 
     179if wu.unDefined ( 'OCE_rho_liq' )  : OCE_rho_liq = wu.OCE_rho_liq  #-- Ocean water volumic mass (kg/m3) in NEMO 
     180if wu.unDefined ( 'ATM_rho' )      : ATM_rho     = wu.ATM_rho      #-- Water volumic mass in atmosphere (kg/m^3) 
     181if wu.unDefined ( 'SRF_rho' )      : SRF_rho     = wu.SRF_rho      #-- Water volumic mass in surface reservoir (kg/m^3) 
     182if wu.unDefined ( 'RUN_rho' )      : RUN_rho     = wu.RUN_rho      #-- Water volumic mass of rivers (kg/m^3) 
     183if wu.unDefined ( 'ICE_rho_pnd' )  : ICE_rho_pnd = wu.ICE_rho_pnd  #-- Water volumic mass in ice ponds (kg/m^3) 
     184if wu.unDefined ( 'YearLength' )   : YearLength  = wu.YearLength   #-- Year length (s) 
     185 
     186## Set libIGCM and machine dependant values 
     187## ---------------------------------------- 
     188if not 'Files' in config.keys () : config['Files'] = {} 
     189 
     190config['Physics'] = { 'Ra':str(Ra), 'Grav':str(Grav), 'ICE_rho_ice':str(ICE_rho_ice), 'ICE_rho_sno':str(ICE_rho_sno), 
     191                      'OCE_rho_liq':str(OCE_rho_liq), 'ATM_rho':str(ATM_rho), 'SRF_rho':str(SRF_rho), 'RUN_rho':str(RUN_rho)} 
     192 
     193config['Config'] = { 'ContinueOnError':str(ContinueOnError), 'SortIco':str(SortIco), 'TestInterp':str(TestInterp), 'readPrec':str(readPrec) } 
    94194 
    95195## -------------------------- 
     
    97197LMDZ = ( 'LMD' in wu.ATM ) 
    98198 
    99 with open ('SetLibIGCM.py') as f: exec ( f.read() ) 
     199mm = libIGCM_sys.config ( TagName=TagName, SpaceName=SpaceName, ExperimentName=ExperimentName, JobName=JobName, User=User, Group=Group, 
     200             ARCHIVE=None, SCRATCHDIR=None, STORAGE=None, R_IN=None, R_OUT=None, R_FIG=None, rebuild=None, TmpDir=None,  
     201             R_SAVE=None, R_FIGR=None, R_BUFR=None, R_BUF_KSH=None, REBUILD_DIR=None, POST_DIR=None ) 
     202globals().update(mm) 
     203 
    100204config['Files']['TmpDir'] = TmpDir 
    101  
    102 if libIGCM : 
    103     config['libIGCM'] = {'ARCHIVE':ARCHIVE, 'STORAGE':STORAGE, 'SCRATCHDIR':SCRATCHDIR, 'R_IN':R_IN, 'rebuild':rebuild } 
    104  
    105 # Import specific module 
    106 import nemo, lmdz 
    107 ## Now import needed scientific modules 
    108 import xarray as xr 
    109      
    110 # Output file with water budget diagnostics 
    111 if wu.unDefined ( 'FileOut' ) : FileOut = f'CPL_waterbudget_{JobName}_{YearBegin}_{YearEnd}.out' 
     205config['libIGCM'] = { 'ARCHIVE':ARCHIVE, 'STORAGE':STORAGE, 'TmpDir':TmpDir, 'R_IN':R_IN, 'rebuild':rebuild } 
     206     
     207## Defines begining and end of experiment 
     208## -------------------------------------- 
     209if wu.unDefined ( 'DateBegin' ) : 
     210    DateBegin = f'{YearBegin}0101' 
     211    config['Experiment']['DateBegin'] = str(DateBegin) 
     212else : 
     213    YearBegin, MonthBegin, DayBegin = wu.SplitDate ( DateBegin ) 
     214    DateBegin = wu.FormatToGregorian (DateBegin) 
     215    config['Experiment']['YearBegin'] = str(YearBegin) 
     216 
     217if wu.unDefined ( 'DateEnd' )   : 
     218    DateEnd   = f'{YearEnd}1231' 
     219    config['Experiment']['DateEnd'] = str(DateEnd) 
     220else : 
     221    YearEnd, MonthEnd, DayEnd = wu.SplitDate ( DateEnd ) 
     222    DateEnd   = wu.FormatToGregorian (DateEnd) 
     223    config['Experiment']['DateEnd'] = str(DateEnd) 
     224 
     225if wu.unDefined ( 'PackFrequency' ) : 
     226    PackFrequency = YearEnd - YearBegin + 1 
     227    config['Experiment']['PackFrequency']   = f'{PackFrequency}' 
     228 
     229if type ( PackFrequency ) == str :  
     230    if 'Y' in PackFrequency : PackFrequency = PackFrequency.replace ( 'Y', '')  
     231    if 'M' in PackFrequency : PackFrequency = PackFrequency.replace ( 'M', '') 
     232    PackFrequency = int ( PackFrequency ) 
     233     
     234## Output file with water budget diagnostics 
     235## ----------------------------------------- 
     236if wu.unDefined ( 'FileOut' ) : 
     237    FileOut = f'CPL_waterbudget_{JobName}_{YearBegin}_{YearEnd}' 
     238    if ICO :  
     239        if ATM_HIS == 'latlon' : FileOut = f'{FileOut}_LATLON' 
     240        if ATM_HIS == 'ico'    : FileOut = f'{FileOut}_ICO' 
     241    if readPrec == np.float32  : FileOut = f'{FileOut}_float32' 
     242    FileOut = f'{FileOut}.out' 
     243 
    112244config['Files']['FileOut'] = FileOut 
    113245 
    114246f_out = open ( FileOut, mode = 'w' ) 
    115247     
    116 # Useful functions 
     248## Useful functions 
     249## ---------------- 
     250if readPrec == float : 
     251    def rprec (tab) : return tab 
     252else :  
     253    def rprec (tab) : return tab.astype(readPrec).astype(float) 
     254     
    117255def kg2Sv    (val, rho=ATM_rho) : 
    118256    '''From kg to Sverdrup''' 
     
    124262 
    125263def var2prt (var, small=False, rho=ATM_rho) : 
    126     if small :  return var , kg2Sv(var, rho=rho)*1000., kg2myear(var, rho=rho)*1000. 
     264    if small :  return var , kg2Sv(var, rho=rho)*1000., kg2myear(var, rho=rho)*1000 
    127265    else     :  return var , kg2Sv(var, rho=rho)      , kg2myear(var, rho=rho) 
    128266 
    129267def prtFlux (Desc, var, Form='F', small=False, rho=ATM_rho, width=15) : 
    130268    if small : 
    131         if Form in ['f', 'F'] : ff=" {:12.4e} kg | {:12.4f} mSv | {:12.4f} mm/year " 
    132         if Form in ['e', 'E'] : ff=" {:12.4e} kg | {:12.4e} mSv | {:12.4e} mm/year " 
     269        if Form in ['f', 'F'] : ff=" {:14.6e} kg | {:12.4f} mSv | {:12.4f} mm/year " 
     270        if Form in ['e', 'E'] : ff=" {:14.6e} kg | {:12.4e} mSv | {:12.4e} mm/year " 
    133271    else : 
    134         if Form in ['f', 'F'] : ff=" {:12.4e} kg | {:12.4f} Sv  | {:12.4f} m/year  " 
    135         if Form in ['e', 'E'] : ff=" {:12.4e} kg | {:12.4e} Sv  | {:12.4e} m/year  " 
    136     echo ( (' {:>{width}} = ' +ff).format (Desc, *var2prt(var, small, rho=rho), width=width ) ) 
     272        if Form in ['f', 'F'] : ff=" {:14.6e} kg | {:12.4f} Sv  | {:12.4f} m/year  " 
     273        if Form in ['e', 'E'] : ff=" {:14.6e} kg | {:12.4e} Sv  | {:12.4e} m/year  " 
     274    echo ( (' {:>{width}} = ' +ff).format (Desc, *var2prt(var, small=small, rho=rho), width=width ) ) 
    137275    return None 
    138276 
     
    144282    f_out.flush () 
    145283    return None 
    146      
     284 
     285echo ( f'{ContinueOnError = }' ) 
     286echo ( f'{SortIco         = }' ) 
     287echo ( f'{readPrec        = }' ) 
     288 
     289echo ( f'{JobName         = }' ) 
     290echo ( f'{ConfigCard      = }' ) 
     291echo ( f'{libIGCM         = }' )      
     292echo ( f'{User            = }' )        
     293echo ( f'{Group           = }' )        
     294echo ( f'{Freq            = }' )        
     295echo ( f'{YearBegin       = }' )      
     296echo ( f'{YearEnd         = }' )      
     297echo ( f'{DateBegin       = }' ) 
     298echo ( f'{DateEnd         = }' ) 
     299echo ( f'{PackFrequency   = }' )  
     300echo ( f'{ATM             = }' )        
     301echo ( f'{Routing         = }' )        
     302echo ( f'{ORCA            = }' )       
     303echo ( f'{NEMO            = }' )       
     304echo ( f'{Coupled         = }' )       
     305echo ( f'{ATM_HIS         = }' )       
     306echo ( f'{SRF_HIS         = }' )       
     307echo ( f'{RUN_HIS         = }' ) 
     308 
    147309## Set libIGCM directories 
     310## ----------------------- 
    148311if wu.unDefined ('R_OUT'      ) : R_OUT       = os.path.join ( ARCHIVE   , 'IGCM_OUT' ) 
    149312if wu.unDefined ('R_BUF'      ) : R_BUF       = os.path.join ( SCRATCHDIR, 'IGCM_OUT' ) 
     
    156319if wu.unDefined ('R_FIGR'     ) : R_FIGR      = os.path.join ( STORAGE, 'IGCM_OUT', L_EXP ) 
    157320 
    158 config['libIGCM'] = { 'R_OUT':R_OUT, 'R_BUF':R_BUF, 'L_EXP':L_EXP, 'R_BUFR':R_BUFR, 'POST_DIR':POST_DIR, 'REBUILD_DIR':REBUILD_DIR, 'R_BUF_KSH':R_BUF_KSH, 'R_FIGR':R_FIGR } 
    159  
    160 # Set directory to extract filesa 
    161 if RunDir == None : RunDir = os.path.join ( TmpDir, f'WATER_{JobName}_{YearBegin}_{YearEnd}' ) 
    162 config['Files']['RunDir'] = RunDir 
    163  
    164 if not os.path.isdir ( RunDir ) : os.makedirs ( RunDir ) 
    165  
    166 # Set directories to rebuild ocean and ice restart files 
    167 RunDirOCE = os.path.join ( RunDir, 'OCE' ) 
    168 RunDirICE = os.path.join ( RunDir, 'ICE' ) 
    169 #RunDirATM = os.path.join ( RunDir, 'ATM' ) 
    170 #RunDirSRF = os.path.join ( RunDir, 'SRF' ) 
    171 #RunDirRUN = os.path.join ( RunDir, 'RUN' ) 
    172 #RunDirDYN = os.path.join ( RunDir, 'DYN' ) 
    173 if not os.path.exists ( RunDirOCE ) : os.mkdir ( RunDirOCE ) 
    174 if not os.path.exists ( RunDirICE ) : os.mkdir ( RunDirICE ) 
     321config['libIGCM'].update ( { 'R_OUT':R_OUT, 'R_BUF':R_BUF, 'L_EXP':L_EXP, 'R_BUFR':R_BUFR, 'POST_DIR':POST_DIR, 
     322                      'REBUILD_DIR':REBUILD_DIR, 'R_BUF_KSH':R_BUF_KSH, 'R_FIGR':R_FIGR, 'rebuild':rebuild } ) 
     323 
     324## Set directory to extract files 
     325## ------------------------------ 
     326if wu.unDefined ( 'FileDir' ) : FileDir = os.path.join ( TmpDir, f'WATER_{JobName}' ) 
     327config['Files']['FileDir'] = FileDir 
     328 
     329if not os.path.isdir ( FileDir ) : os.makedirs ( FileDir ) 
     330 
     331##- Set directories to rebuild ocean and ice restart files 
     332if wu.unDefined ( 'FileDirOCE' ) : FileDirOCE = os.path.join ( FileDir, 'OCE' ) 
     333if wu.unDefined ( 'FileDirICE' ) : FileDirICE = os.path.join ( FileDir, 'ICE' ) 
     334if not os.path.exists ( FileDirOCE ) : os.mkdir ( FileDirOCE ) 
     335if not os.path.exists ( FileDirICE ) : os.mkdir ( FileDirICE ) 
     336 
     337echo (' ') 
     338echo ( f'JobName     : {JobName}'    ) 
     339echo ( f'Comment     : {Comment}'    ) 
     340echo ( f'TmpDir      : {TmpDir}'     ) 
     341echo ( f'FileDir     : {FileDir}'    ) 
     342echo ( f'FileDirOCE  : {FileDirOCE}' ) 
     343echo ( f'FileDirICE  : {FileDirICE}' ) 
     344 
     345echo ( f'\nDealing with {L_EXP}'  ) 
    175346 
    176347echo (' ') 
     
    178349echo ( f'Comment   : {Comment}'   ) 
    179350echo ( f'TmpDir    : {TmpDir}'    ) 
    180 echo ( f'RunDirOCE : {RunDirOCE}' ) 
    181 echo ( f'RunDirICE : {RunDirICE}' ) 
    182351 
    183352echo ( f'\nDealing with {L_EXP}'  ) 
    184353 
    185 #-- Model output directories 
     354## Creates model output directory names 
     355## ------------------------------------ 
    186356if Freq == "MO" : FreqDir =  os.path.join ('Output' , 'MO' ) 
    187357if Freq == "SE" : FreqDir =  os.path.join ('Analyse', 'SE' ) 
     
    205375echo ( f'{dir_SRF_his}' ) 
    206376 
    207 #-- Creates files names 
    208 if Period == None : 
    209     if Freq == 'MO' : Period = f'{YearBegin}0101_{YearEnd}1231_1M' 
    210     if Freq == 'SE' : Period = f'SE_{YearBegin}0101_{YearEnd}1231_1M' 
     377##-- Creates files names 
     378if wu.unDefined ( 'Period' ) : 
     379    if Freq == 'MO' : Period = f'{DateBegin}_{DateEnd}_1M' 
     380    if Freq == 'SE' : Period = f'SE_{DateBegin}_{DateEnd}_1M' 
    211381    config['Files']['Period'] = Period 
    212 if FileCommon == None : 
     382 
     383config['Files']['DateBegin'] = DateBegin 
     384config['Files']['DateBegin'] = DateEnd 
     385 
     386echo ( f'Period   : {Period}' ) 
     387 
     388if wu.unDefined ( 'FileCommon' ) : 
    213389    FileCommon = f'{JobName}_{Period}' 
    214390    config['Files']['FileCommon'] = FileCommon 
    215391 
    216 if Title == None : 
    217     Title = f'{JobName} : {Freq} : {YearBegin}-01-01 - {YearEnd}-12-31' 
     392if wu.unDefined ( 'Title' ) : 
     393    Title = f'{JobName} : {Freq} : {DateBegin} - {DateEnd}' 
    218394    config['Files']['Title'] = Title 
    219  
    220395echo ('\nOpen history files' ) 
    221 if file_ATM_his == None :  
    222     file_ATM_his = os.path.join (  dir_ATM_his, f'{FileCommon}_histmth.nc' ) 
     396if wu.unDefined ( 'file_ATM_his' ) : 
     397    if ATM_HIS == 'latlon' : 
     398        file_ATM_his = os.path.join ( dir_ATM_his, f'{FileCommon}_histmth.nc' ) 
     399    if ATM_HIS == 'ico' : 
     400        file_ATM_his = os.path.join ( dir_ATM_his, f'{FileCommon}_histmth_ico.nc' ) 
    223401    config['Files']['file_ATM_his'] = file_ATM_his 
    224 if file_SRF_his == None : 
    225     file_SRF_his = os.path.join (  dir_SRF_his, f'{FileCommon}_sechiba_history.nc' ) 
     402if wu.unDefined ( 'file_SRF_his' ) : 
     403    if ATM_HIS == 'latlon' : 
     404        file_SRF_his = os.path.join ( dir_SRF_his, f'{FileCommon}_sechiba_history.nc' ) 
     405    if ATM_HIS == 'ico' : 
     406        file_SRF_his = os.path.join ( dir_SRF_his, f'{FileCommon}_sechiba_history_ico.nc' ) 
    226407    config['Files']['file_SRF_his'] = file_SRF_his 
    227 #if Routing == 'SECHIBA'  : 
    228 #     file_RUN_his = os.path.join (  dir_SRF_his, f'{FileCommon}_sechiba_history.nc' ) 
     408 
    229409if Routing == 'SIMPLE' : 
    230     if file_RUN_his == None :  
    231         file_RUN_his = os.path.join (  dir_SRF_his, f'{FileCommon}_sechiba_history.nc' ) 
     410    if file_RUN_his == None : 
     411        if ATM_HIS == 'latlon' : 
     412            file_RUN_his = os.path.join ( dir_SRF_his, f'{FileCommon}_sechiba_history.nc' ) 
     413        if ATM_HIS == 'ico' : 
     414            file_RUN_his = os.path.join ( dir_SRF_his, f'{FileCommon}_sechiba_history_ico.nc' ) 
    232415        config['Files']['file_RUN_his'] = file_RUN_his 
    233 if file_OCE_his == None : 
    234     file_OCE_his = os.path.join (  dir_OCE_his, f'{FileCommon}_grid_T.nc' ) 
    235     config['Files']['file_OCE_his'] = file_OCE_his 
    236 if file_OCE_sca == None : 
    237     file_OCE_sca = os.path.join (  dir_OCE_his, f'{FileCommon}_scalar.nc' ) 
    238     config['Files']['file_OCE_sca'] = file_OCE_sca 
    239 if file_ICE_his == None : 
    240     file_ICE_his = os.path.join (  dir_ICE_his, f'{FileCommon}_icemod.nc' ) 
    241     config['Files']['file_ICE_his'] = file_ICE_his 
    242 if file_OCE_srf == None : 
    243     file_OCE_srf = os.path.join (  dir_OCE_his, f'{FileCommon}_grid_T.nc' ) 
    244     config['Files']['file_OCE_srf'] = file_OCE_srf 
    245  
    246 d_ATM_his = xr.open_dataset ( file_ATM_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
    247 d_OCE_his = xr.open_dataset ( file_OCE_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
    248 d_OCE_sca = xr.open_dataset ( file_OCE_sca, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
    249 d_ICE_his = xr.open_dataset ( file_ICE_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
    250 if NEMO == '3.6' :d_ICE_his = d_ICE_his.rename ( {'y_grid_T':'y', 'x_grid_T':'x'} ) 
    251 d_SRF_his = xr.open_dataset ( file_SRF_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
    252 d_OCE_srf = xr.open_dataset ( file_OCE_srf, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
    253 if Routing == 'SECHIBA' : d_RUN_his = d_SRF_his 
    254 if Routing == 'SIMPLE'  : d_RUN_his = xr.open_dataset ( file_RUN_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
    255  
    256      
     416 
    257417echo ( f'{file_ATM_his = }' ) 
    258418echo ( f'{file_SRF_his = }' ) 
    259419if Routing == 'SIMPLE' : echo ( f'{file_RUN_his = }' ) 
     420         
     421d_ATM_his = xr.open_dataset ( file_ATM_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
     422d_SRF_his = xr.open_dataset ( file_SRF_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
     423if Routing == 'SECHIBA' : d_RUN_his = d_SRF_his 
     424if Routing == 'SIMPLE'  : d_RUN_his = xr.open_dataset ( file_RUN_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
     425     
     426if wu.unDefined ('file_OCE_his' ) : 
     427    file_OCE_his = os.path.join ( dir_OCE_his, f'{FileCommon}_grid_T.nc' ) 
     428    file_OCE_his = file_OCE_his 
     429if wu.unDefined ('file_OCE_sca' ) :     
     430    file_OCE_sca = os.path.join ( dir_OCE_his, f'{FileCommon}_scalar.nc' ) 
     431    config['Files']['file_OCE_sca'] = file_OCE_sca 
     432if wu.unDefined ('file_OCE_srf' ) :     
     433    file_OCE_srf = os.path.join ( dir_OCE_his, f'{FileCommon}_sbc.nc' ) 
     434    config['Files']['file_OCE_srf'] = file_OCE_srf 
     435if wu.unDefined ( 'file_ICE_hi' ) :  
     436    file_ICE_his = os.path.join ( dir_ICE_his, f'{FileCommon}_icemod.nc' ) 
     437    config['Files']['file_ICE_his'] = file_ICE_his 
     438 
     439d_OCE_his = xr.open_dataset ( file_OCE_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
     440d_OCE_sca = xr.open_dataset ( file_OCE_sca, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
     441#d_OCE_srf = xr.open_dataset ( file_OCE_srf, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
     442d_ICE_his = xr.open_dataset ( file_ICE_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze() 
     443if NEMO == '3.6' :d_ICE_his = d_ICE_his.rename ( {'y_grid_T':'y', 'x_grid_T':'x'} ) 
     444 
    260445echo ( f'{file_OCE_his = }' ) 
    261446echo ( f'{file_ICE_his = }' ) 
     
    264449 
    265450## Compute run length 
     451## ------------------ 
    266452dtime = ( d_ATM_his.time_counter_bounds.max() - d_ATM_his.time_counter_bounds.min() ) 
    267453echo ('\nRun length : {:8.2f} days'.format ( (dtime/np.timedelta64(1, "D")).values ) ) 
     
    278464NbYear = dtime_sec / YearLength 
    279465 
    280 #-- Open restart files 
    281 YearRes = YearBegin - 1        # Year of the restart of beginning of simulation 
    282 YearPre = YearBegin - PackFrequency  # Year to find the tarfile of the restart of beginning of simulation 
    283  
    284 config['Files']['YearPre'] = f'{YearBegin}' 
    285  
    286 echo (f'Restart dates - Start : {YearRes}-12-31  /  End : {YearEnd}-12-31 ') 
    287  
    288 if TarRestartPeriod_beg == None :  
    289     echo (f'Restart dates - Start : {YearRes}-12-31  /  End : {YearEnd}-12-31 ') 
    290     TarRestartPeriod_beg = f'{YearPre}0101_{YearRes}1231' 
    291     config['Files']['TarRestartPeriod_beg'] = TarRestartPeriod_beg 
    292  
    293 if TarRestartPeriod_end == None :  
    294     YearPre = YearBegin - PackFrequency  # Year to find the tarfile of the restart of beginning of simulation 
    295     echo (f'Restart dates - Start : {YearRes}-12-31  /  End : {YearEnd}-12-31 ') 
    296     TarRestartPeriod_end = f'{YearBegin}0101_{YearEnd}1231' 
    297     config['Files']['TarRestartPeriod_end'] = TarRestartPeriod_end 
    298  
    299 if tar_restart_beg == None : 
    300     tar_restart_beg = os.path.join ( R_SAVE, 'RESTART', f'{JobName}_{TarRestartPeriod_beg}_restart.tar' ) 
    301     config['Files']['tar_restart_beg'] = tar_restart_beg 
    302 if tar_restart_end == None : 
    303     tar_restart_end = os.path.join ( R_SAVE, 'RESTART', f'{JobName}_{TarRestartPeriod_end}_restart.tar' ) 
    304     config['Files']['tar_restart_end'] = tar_restart_end 
    305  
    306 echo ( f'{tar_restart_beg}' ) 
    307 echo ( f'{tar_restart_end}' ) 
    308  
    309 if file_ATM_beg == None :  
    310     file_ATM_beg = f'{RunDir}/ATM_{JobName}_{YearRes}1231_restartphy.nc' 
    311     config['Files']['file_ATM_beg'] = file_ATM_beg 
    312 if file_ATM_end == None : 
    313     file_ATM_end = f'{RunDir}/ATM_{JobName}_{YearEnd}1231_restartphy.nc' 
    314     config['Files']['file_ATM_end'] = file_ATM_end 
    315  
    316 if file_DYN_beg == None : 
    317     if LMDZ : file_DYN_beg = f'{RunDir}/ATM_{JobName}_{YearRes}1231_restart.nc' 
    318     if ICO  : file_DYN_beg = f'{RunDir}/ICO_{JobName}_{YearRes}1231_restart.nc' 
    319     config['Files']['file_DYN_beg'] = file_DYN_beg 
    320      
    321 if file_DYN_end == None :  
    322     if LMDZ : file_DYN_end = f'{RunDir}/ATM_{JobName}_{YearEnd}1231_restart.nc' 
    323     if ICO  : file_DYN_end = f'{RunDir}/ICO_{JobName}_{YearEnd}1231_restart.nc' 
    324     config['Files']['file_DYN_end'] = file_DYN_end 
    325      
    326 if file_SRF_beg == None : 
    327     file_SRF_beg = f'{RunDir}/SRF_{JobName}_{YearRes}1231_sechiba_rest.nc' 
    328     config['Files']['file_SRF_beg'] = file_SRF_beg 
    329 if file_SRF_end == None : 
    330     file_SRF_end = f'{RunDir}/SRF_{JobName}_{YearEnd}1231_sechiba_rest.nc' 
    331     config['Files']['file_SRF_end'] = file_SRF_end 
    332      
    333 if file_OCE_beg == None :  
    334     file_OCE_beg = f'{RunDir}/OCE_{JobName}_{YearRes}1231_restart.nc' 
    335     config['Files']['file_OCE_beg'] = file_OCE_beg 
    336 if file_OCE_end == None : 
    337     file_OCE_end = f'{RunDir}/OCE_{JobName}_{YearEnd}1231_restart.nc' 
    338     config['Files']['file_OCE_end'] = file_OCE_end 
    339 if file_ICE_beg == None : 
    340     file_ICE_beg = f'{RunDir}/ICE_{JobName}_{YearRes}1231_restart_icemod.nc' 
    341     config['Files']['file_ICE_beg'] = file_ICE_beg 
    342 if file_ICE_end == None :  
    343     file_ICE_end = f'{RunDir}/ICE_{JobName}_{YearEnd}1231_restart_icemod.nc' 
    344     config['Files']['file_ICE_end'] = file_ICE_end 
    345  
    346 liste_beg = [file_ATM_beg, file_DYN_beg, file_SRF_beg] 
    347 liste_end = [file_ATM_end, file_DYN_end, file_SRF_end] 
    348  
    349 if Routing == 'SIMPLE' : 
    350     if file_RUN_beg == None :  
    351         file_RUN_beg = f'{RunDir}/SRF_{JobName}_{YearRes}1231_routing_restart.nc' 
    352         config['Files']['file_RUN_beg'] = file_RUN_beg 
    353     if file_RUN_end == None :  
    354         file_RUN_end = f'{RunDir}/SRF_{JobName}_{YearEnd}1231_routing_restart.nc' 
    355         config['Files']['file_RUN_end'] = file_RUN_end 
    356          
    357     liste_beg.append ( file_RUN_beg ) 
    358     liste_end.append ( file_RUN_end ) 
    359     echo ( f'{file_RUN_beg = }' ) 
    360     echo ( f'{file_RUN_end = }' ) 
    361  
    362 echo ( f'{file_ATM_beg = }' ) 
    363 echo ( f'{file_ATM_end = }' ) 
    364 echo ( f'{file_DYN_beg = }' ) 
    365 echo ( f'{file_DYN_end = }' ) 
    366 echo ( f'{file_SRF_beg = }' ) 
    367 echo ( f'{file_SRF_end = }' ) 
    368 echo ( f'{file_RUN_beg = }' ) 
    369 echo ( f'{file_RUN_end = }' ) 
    370 echo ( f'{file_OCE_beg = }' ) 
    371 echo ( f'{file_OCE_end = }' ) 
    372 echo ( f'{file_ICE_beg = }' ) 
    373 echo ( f'{file_ICE_end = }' ) 
    374  
    375 echo ('\nExtract restart files from tar : ATM, ICO and SRF') 
    376 for resFile in liste_beg + liste_end : 
    377     if os.path.exists ( os.path.join (RunDir, resFile) ) : 
    378         echo ( f'file found : {resFile = }' ) 
    379     else : 
    380         base_file = Path (file_name).stem # basename, and remove suffix 
    381         command =  f'cd {RunDir} ; tar xf {tar_restart_beg} {base_resFile}.nc' 
    382         echo ( command ) 
    383         ierr = os.system ( command ) 
    384         if ierr == 0 : echo ( f'tar done : {base_resFile}') 
    385         else         : raise Exception ( f'command failed : {command}' ) 
    386  
    387 echo ('\nOpening ATM SRF and ICO restart files') 
    388 d_ATM_beg = xr.open_dataset ( os.path.join (RunDir, file_ATM_beg), decode_times=False, decode_cf=True).squeeze() 
    389 d_ATM_end = xr.open_dataset ( os.path.join (RunDir, file_ATM_end), decode_times=False, decode_cf=True).squeeze() 
    390 d_SRF_beg = xr.open_dataset ( os.path.join (RunDir, file_SRF_beg), decode_times=False, decode_cf=True).squeeze() 
    391 d_SRF_end = xr.open_dataset ( os.path.join (RunDir, file_SRF_end), decode_times=False, decode_cf=True).squeeze() 
    392 d_DYN_beg = xr.open_dataset ( os.path.join (RunDir, file_DYN_beg), decode_times=False, decode_cf=True).squeeze() 
    393 d_DYN_end = xr.open_dataset ( os.path.join (RunDir, file_DYN_end), decode_times=False, decode_cf=True).squeeze() 
    394  
    395 echo ('\nExtract and rebuild OCE and ICE restarts') 
    396 def get_ndomain (zfile) : 
    397     #d_zfile = xr.open_dataset (zfile, decode_times=False).squeeze() 
    398     #ndomain_opa = d_zfile.attrs['DOMAIN_number_total'] 
    399     #d_zfile.close () 
    400     ndomain_opa = subprocess.getoutput ( f'ls {zfile}_*.nc | wc -l' ) #.format() 
    401     return int (ndomain_opa) 
    402  
    403 def extract_and_rebuild ( file_name=file_OCE_beg, tar_restart=tar_restart_end, RunDirComp=RunDirOCE ) : 
    404     '''Extract restart file from tar. Rebuild ocean files if needed''' 
    405     echo ( f'file to extract : {file_name} ' ) 
    406     if os.path.exists ( file_name ) : 
    407         echo ( f'-- File ready : {file_name}' ) 
    408     else :  
    409         echo ( f'-- Extracting {file_name}' ) 
    410         base_resFile = Path (file_name).stem # basename, and remove suffix 
    411         # Try to extract the rebuilded file 
    412         command =  f'cd {RunDirComp} ; tar xf {tar_restart} {base_resFile}.nc' 
    413         echo ( command ) 
    414         ierr = os.system ( command ) 
    415         if ierr == 0 : 
    416             echo ( f'tar done : {base_resFile}') 
    417             command = f'cd {RunDirComp} ; mv {base_resFile}.nc {RunDir}' 
    418             ierr = os.system ( command ) 
    419             if ierr == 0 : echo ( f'command done : {command}' ) 
    420             else         : raise Exception ( f'command failed : {command}' ) 
    421         else : 
    422             if not os.path.exists ( os.path.join (RunDir, f'{base_resFile}_0000.nc') ): 
    423                 command =  f'cd {RunDirComp} ; tar xf {tar_restart_end} {base_resFile}_*.nc' 
    424                 echo ( command ) 
    425                 ierr = os.system ( command ) 
    426                 if ierr == 0 : echo ( f'tar done : {file_OCE_beg}') 
    427                 else         : raise Exception ( f'command failed : {command}' ) 
    428                 echo ('extract ndomain' ) 
    429             ndomain_opa = get_ndomain ( os.path.join (RunDir, f'{base_resFile}') ) 
    430             command = f'cd {RunDirComp} ; {rebuild} {base_resFile} {ndomain_opa} ; mv {base_resFile}.nc {RunDir}' 
    431             echo ( command ) 
    432             ierr = os.system ( command ) 
    433             if ierr == 0 : echo ( f'Rebuild done : {base_resFile}.nc') 
    434             else         : raise Exception ( f'command failed : {command}' ) 
    435  
    436 extract_and_rebuild ( file_name=file_OCE_beg, tar_restart=tar_restart_beg, RunDirComp=RunDirOCE ) 
    437 extract_and_rebuild ( file_name=file_OCE_end, tar_restart=tar_restart_end, RunDirComp=RunDirOCE ) 
    438 extract_and_rebuild ( file_name=file_ICE_beg, tar_restart=tar_restart_beg, RunDirComp=RunDirICE ) 
    439 extract_and_rebuild ( file_name=file_ICE_end, tar_restart=tar_restart_end, RunDirComp=RunDirICE ) 
    440  
    441 echo ('Opening OCE and ICE restart files') 
    442 if NEMO == 3.6 :  
    443     d_OCE_beg = xr.open_dataset ( os.path.join (RunDir, file_OCE_beg), decode_times=False, decode_cf=True, drop_variables=['y', 'x']).squeeze() 
    444     d_OCE_end = xr.open_dataset ( os.path.join (RunDir, file_OCE_end), decode_times=False, decode_cf=True).squeeze() 
    445     d_ICE_beg = xr.open_dataset ( os.path.join (RunDir, file_ICE_beg), decode_times=False, decode_cf=True).squeeze() 
    446     d_ICE_end = xr.open_dataset ( os.path.join (RunDir, file_ICE_end), decode_times=False, decode_cf=True).squeeze() 
    447 if NEMO == 4.0 or NEMO == 4.2 :  
    448     d_OCE_beg = xr.open_dataset ( os.path.join (RunDir, file_OCE_beg), decode_times=False, decode_cf=True, drop_variables=['y', 'x']).squeeze() 
    449     d_OCE_end = xr.open_dataset ( os.path.join (RunDir, file_OCE_end), decode_times=False, decode_cf=True, drop_variables=['y', 'x']).squeeze() 
    450     d_ICE_beg = xr.open_dataset ( os.path.join (RunDir, file_ICE_beg), decode_times=False, decode_cf=True, drop_variables=['y', 'x']).squeeze() 
    451     d_ICE_end = xr.open_dataset ( os.path.join (RunDir, file_ICE_end), decode_times=False, decode_cf=True, drop_variables=['y', 'x']).squeeze() 
    452  
    453466## Write the full configuration 
    454467config_out = open (FullIniFile, 'w') 
     
    456469config_out.close () 
    457470 
    458 for var in d_SRF_beg.variables : 
    459     d_SRF_beg[var] = d_SRF_beg[var].where (  d_SRF_beg[var]<1.e20, 0.) 
    460     d_SRF_end[var] = d_SRF_end[var].where (  d_SRF_end[var]<1.e20, 0.) 
    461  
    462 if ICO : 
    463     d_RUN_beg = xr.open_dataset ( os.path.join (RunDir, file_RUN_beg), decode_times=False, decode_cf=True).squeeze() 
    464     d_RUN_end = xr.open_dataset ( os.path.join (RunDir, file_RUN_end), decode_times=False, decode_cf=True).squeeze() 
    465  
    466 def kg2Sv  (val, rho=OCE_rho_liq) : 
    467     '''From kg to Sverdrup''' 
    468     return val/dtime_sec*1.0e-6/rho 
    469  
    470 def kg2myear (val, rho=OCE_rho_liq) : 
    471     '''From kg to m/year''' 
    472     return val/OCE_aire_tot/rho/NbYear 
    473  
    474 def var2prt (var, small=False) : 
    475     if small :  return var , kg2Sv(var)*1000., kg2myear(var)*1000. 
    476     else     :  return var , kg2Sv(var)      , kg2myear(var) 
    477  
    478 def prtFlux (Desc, var, Form='F', small=False) : 
    479     if small : 
    480         if Form in ['f', 'F'] : ff=" {:12.4e} kg | {:12.4f} mSv | {:12.4f} mm/year " 
    481         if Form in ['e', 'E'] : ff=" {:12.4e} kg | {:12.4e} mSv | {:12.4e} mm/year " 
    482     else : 
    483         if Form in ['f', 'F'] : ff=" {:12.4e} kg | {:12.4f} Sv  | {:12.4f} m/year  " 
    484         if Form in ['e', 'E'] : ff=" {:12.4e} kg | {:12.4e} Sv  | {:12.4e} m/year  " 
    485     echo ( (' {:>15} = ' +ff).format (Desc, *var2prt(var, small) ) ) 
    486     return None 
    487  
    488  
    489  
    490471# ATM grid with cell surfaces 
     472if LMDZ : 
     473    echo ('ATM grid with cell surfaces : LMDZ') 
     474    ATM_lat       = lmdz.geo2point (   rprec (d_ATM_his ['lat'])+0*rprec (d_ATM_his ['lon']), dim1D='cell' ) 
     475    ATM_lon       = lmdz.geo2point ( 0*rprec (d_ATM_his ['lat'])+  rprec (d_ATM_his ['lon']), dim1D='cell' ) 
     476    ATM_aire      = lmdz.geo2point ( rprec (d_ATM_his ['aire'] )    [0], cumulPoles=True, dim1D='cell' ) 
     477    ATM_fter      = lmdz.geo2point ( rprec (d_ATM_his ['fract_ter'][0]), dim1D='cell' ) 
     478    ATM_foce      = lmdz.geo2point ( rprec (d_ATM_his ['fract_oce'][0]), dim1D='cell' ) 
     479    ATM_fsic      = lmdz.geo2point ( rprec (d_ATM_his ['fract_sic'][0]), dim1D='cell' ) 
     480    ATM_flic      = lmdz.geo2point ( rprec (d_ATM_his ['fract_lic'][0]), dim1D='cell' ) 
     481    SRF_lat       = lmdz.geo2point (   rprec (d_SRF_his ['lat'])+0*rprec (d_SRF_his ['lon']), dim1D='cell' ) 
     482    SRF_lon       = lmdz.geo2point ( 0*rprec (d_SRF_his ['lat'])+  rprec (d_SRF_his ['lon']), dim1D='cell' ) 
     483    SRF_aire      = lmdz.geo2point ( rprec (d_SRF_his ['Areas']) * rprec (d_SRF_his ['Contfrac']), dim1D='cell', cumulPoles=True ) 
     484    SRF_areas     = lmdz.geo2point ( rprec (d_SRF_his ['Areas'])  ,  dim1D='cell', cumulPoles=True ) 
     485    SRF_contfrac  = lmdz.geo2point ( rprec (d_SRF_his ['Contfrac']), dim1D='cell' ) 
    491486if ICO : 
    492487    if ATM_HIS == 'latlon' : 
    493         jpja, jpia = d_ATM_his['aire'][0].shape    
    494         file_ATM_aire = os.path.join ( R_IN, 'ATM', 'GRID', f'aire_{ATM}_to_{jpia}x{jpja}.nc' ) 
    495         config['Files']['file_ATM_aire'] = file_ATM_aire 
    496         echo ( f'Aire sur grille reguliere : {file_ATM_aire = }' ) 
    497         d_ATM_aire = xr.open_dataset ( file_ATM_aire, decode_times=False ).squeeze() 
    498         ATM_aire = lmdz.geo2point ( d_ATM_aire ['aire'].squeeze(), cumulPoles=True ) 
    499         ATM_fter = lmdz.geo2point ( d_ATM_his ['fract_ter'][0] ) 
    500         ATM_foce = lmdz.geo2point ( d_ATM_his ['fract_oce'][0] ) 
    501         ATM_fsic = lmdz.geo2point ( d_ATM_his ['fract_sic'][0] ) 
    502         ATM_flic = lmdz.geo2point ( d_ATM_his ['fract_lic'][0] ) 
    503         SRF_aire = lmdz.geo2point ( d_SRF_his ['Areas'] * d_SRF_his ['Contfrac'] ) 
    504         #SRF_aire = ATM_aire * lmdz.geo2point (d_SRF_his ['Contfrac'] ) 
    505         #SRF_aire = ATM_aire * ATM_fter 
     488        echo ( 'ATM areas and fractions on latlon grid' ) 
     489        if 'lat_dom_out' in d_ATM_his.variables : 
     490            ATM_lat  = lmdz.geo2point (   rprec (d_ATM_his ['lat_dom_out'])+0*rprec (d_ATM_his ['lon_dom_out']), dim1D='cell' ) 
     491            ATM_lon  = lmdz.geo2point ( 0*rprec (d_ATM_his ['lat_dom_out'])+  rprec (d_ATM_his ['lon_dom_out']), dim1D='cell' ) 
     492        else : 
     493            ATM_lat  = lmdz.geo2point (   rprec (d_ATM_his ['lat'])+0*rprec (d_ATM_his ['lon']), dim1D='cell' ) 
     494            ATM_lon  = lmdz.geo2point ( 0*rprec (d_ATM_his ['lat'])+  rprec (d_ATM_his ['lon']), dim1D='cell' ) 
     495        ATM_aire = lmdz.geo2point ( rprec (d_ATM_his ['aire'][0]).squeeze(), cumulPoles=True, dim1D='cell' ) 
     496        ATM_fter = lmdz.geo2point ( rprec (d_ATM_his ['fract_ter'][0]), dim1D='cell' ) 
     497        ATM_foce = lmdz.geo2point ( rprec (d_ATM_his ['fract_oce'][0]), dim1D='cell' ) 
     498        ATM_fsic = lmdz.geo2point ( rprec (d_ATM_his ['fract_sic'][0]), dim1D='cell' ) 
     499        ATM_flic = lmdz.geo2point ( rprec (d_ATM_his ['fract_lic'][0]), dim1D='cell' ) 
     500 
    506501    if ATM_HIS == 'ico' : 
    507         echo ( f'Aire sur grille icosaedre : {file_ATM_aire = }' ) 
    508          
    509 if LMDZ : 
    510     ATM_aire = lmdz.geo2point ( d_ATM_his ['aire'][0], cumulPoles=True ) 
    511     ATM_fter = lmdz.geo2point ( d_ATM_his ['fract_ter'][0] ) 
    512     ATM_foce = lmdz.geo2point ( d_ATM_his ['fract_oce'][0] ) 
    513     ATM_fsic = lmdz.geo2point ( d_ATM_his ['fract_sic'][0] ) 
    514     ATM_flic = lmdz.geo2point ( d_ATM_his ['fract_lic'][0] ) 
    515     #SRF_aire = lmdz.geo2point ( d_SRF_his['Areas'] * d_SRF_his['Contfrac'] ) 
    516     SRF_aire = ATM_aire * lmdz.geo2point ( d_SRF_his['Contfrac'] ) 
    517      
     502        echo ( 'ATM areas and fractions on ICO grid' ) 
     503        ATM_aire =  rprec (d_ATM_his ['aire']     [0]).squeeze() 
     504        ATM_lat  =  rprec (d_ATM_his ['lat']         ) 
     505        ATM_lon  =  rprec (d_ATM_his ['lon']         ) 
     506        ATM_fter =  rprec (d_ATM_his ['fract_ter'][0]) 
     507        ATM_foce =  rprec (d_ATM_his ['fract_oce'][0]) 
     508        ATM_fsic =  rprec (d_ATM_his ['fract_sic'][0]) 
     509        ATM_flic =  rprec (d_ATM_his ['fract_lic'][0]) 
     510 
     511    if SRF_HIS == 'latlon' : 
     512        echo ( 'SRF areas and fractions on latlon grid' ) 
     513        if 'lat_domain_landpoints_out' in d_SRF_his  :  
     514            SRF_lat  = lmdz.geo2point (   rprec (d_SRF_his ['lat_domain_landpoints_out'])+0*rprec (d_SRF_his ['lon_domain_landpoints_out']), dim1D='cell' ) 
     515            SRF_lon  = lmdz.geo2point ( 0*rprec (d_SRF_his ['lat_domain_landpoints_out'])+  rprec (d_SRF_his ['lon_domain_landpoints_out']), dim1D='cell' ) 
     516        else :  
     517            if 'lat_domain_landpoints_out' in d_SRF_his : 
     518                SRF_lat  = lmdz.geo2point (   rprec (d_SRF_his ['lat_dom_out'])+0*rprec (d_SRF_his ['lon_dom_out']), dim1D='cell' ) 
     519                SRF_lon  = lmdz.geo2point ( 0*rprec (d_SRF_his ['lat_dom_out'])+  rprec (d_SRF_his ['lon_dom_out']), dim1D='cell' ) 
     520            else : 
     521                SRF_lat  = lmdz.geo2point (   rprec (d_SRF_his ['lat'])+0*rprec (d_SRF_his ['lon']), dim1D='cell' ) 
     522                SRF_lon  = lmdz.geo2point ( 0*rprec (d_SRF_his ['lat'])+  rprec (d_SRF_his ['lon']), dim1D='cell' ) 
     523                 
     524        SRF_areas     = lmdz.geo2point ( rprec (d_SRF_his ['Areas']   )   , dim1D='cell', cumulPoles=True ) 
     525        SRF_areafrac  = lmdz.geo2point ( rprec (d_SRF_his ['AreaFrac'])   , dim1D='cell', cumulPoles=True ) 
     526        SRF_contfrac  = lmdz.geo2point ( rprec (d_SRF_his ['Contfrac'])   , dim1D='cell', cumulPoles=True ) 
     527        SRF_aire = SRF_areafrac 
     528  
     529    if SRF_HIS == 'ico' : 
     530        echo ( 'SRF areas and fractions on latlon grid' ) 
     531        SRF_lat       =  rprec (d_SRF_his ['lat']     ) 
     532        SRF_lon       =  rprec (d_SRF_his ['lon']     ) 
     533        SRF_areas     =  rprec (d_SRF_his ['Areas']   )  
     534        SRF_contfrac  =  rprec (d_SRF_his ['Contfrac']) 
     535        SRF_aire      =  SRF_areas * SRF_contfrac 
    518536ATM_fsea      = ATM_foce + ATM_fsic 
    519537ATM_flnd      = ATM_fter + ATM_flic 
     
    525543ATM_aire_fsea = ATM_aire * ATM_fsea 
    526544 
    527 SRF_aire = SRF_aire.where ( SRF_aire < 1E15, 0.) 
    528  
    529 if ICO : 
    530     # Area on icosahedron grid 
    531     file_DYN_aire = os.path.join ( R_IN, 'ATM', 'GRID', ATM+'_grid.nc' ) 
    532     d_DYN_aire = xr.open_dataset ( file_DYN_aire, decode_times=False).squeeze() 
    533     d_DYN_aire = d_DYN_aire.rename ( {'cell':'cell_mesh'} ) 
    534     DYN_aire   = d_DYN_aire['aire'] 
    535  
    536     DYN_fsea = d_DYN_aire ['fract_oce'] + d_DYN_aire ['fract_sic'] 
    537     DYN_flnd = 1.0 - DYN_fsea 
    538      
    539 if LMDZ : 
    540     # Area on lon/lat grid 
    541     DYN_aire = ATM_aire 
    542     DYN_fsea = ATM_fsea 
    543     DYN_flnd = ATM_flnd 
    544     DYN_fter = d_ATM_beg['FTER'] 
    545     DYN_flic = d_ATM_beg['FTER'] 
    546  
    547 def ATM_stock_int (stock) : 
    548     '''Integrate (* surface) stock on atmosphere grid''' 
    549     ATM_stock_int  = wu.Psum ( (stock * DYN_aire).to_masked_array().ravel() )  
    550     return ATM_stock_int 
     545#SRF_aire = SRF_aire.where ( SRF_aire < 1E15, 0.) 
     546 
     547# if ICO : 
     548#     if wu.unDefined ('file_DYN_aire') : file_DYN_aire = os.path.join ( R_IN, 'ATM', 'GRID', ATM+'_grid.nc' ) 
     549#     config['Files']['file_DYN_aire'] = file_DYN_aire 
     550 
     551# if ICO : 
     552#     # Area on icosahedron grid 
     553#     d_DYN_aire = xr.open_dataset ( file_DYN_aire, decode_times=False ).squeeze() 
     554            
     555#     DYN_lat = d_DYN_aire['lat'] 
     556#     DYN_lon = d_DYN_aire['lon'] 
     557 
     558#     DYN_aire = d_DYN_aire['aire'] 
     559#     DYN_fsea = d_DYN_aire['fract_oce'] + d_DYN_aire['fract_sic'] 
     560#     DYN_flnd = 1.0 - DYN_fsea 
     561#     DYN_fter = d_ATM_beg['FTER'] 
     562#     DYN_flic = d_ATM_beg['FLIC'] 
     563#     DYN_aire_fter = DYN_aire * DYN_fter 
     564     
     565# if LMDZ : 
     566#     # Area on lon/lat grid 
     567#     DYN_aire = ATM_aire 
     568#     DYN_fsea = ATM_fsea 
     569#     DYN_flnd = ATM_flnd 
     570#     DYN_fter = rprec (d_ATM_beg['FTER']) 
     571#     DYN_flic = rprec (d_ATM_beg['FLIC']) 
     572#     DYN_aire_fter = DYN_aire * DYN_fter 
     573 
     574# Functions computing integrals and sum 
     575# def ATM_stock_int (stock) : 
     576#     '''Integrate (* surface) stock on atmosphere grid''' 
     577#     ATM_stock_int  = wu.Psum ( (stock * DYN_aire).to_masked_array().ravel() )  
     578#     return ATM_stock_int 
    551579 
    552580def ATM_flux_int (flux) : 
     
    555583    return ATM_flux_int 
    556584 
    557 def SRF_stock_int (stock) : 
    558     '''Integrate (* surface) stock on land grid''' 
    559     ATM_stock_int  = wu.Ksum (  ( (stock * DYN_aire_fter).to_masked_array().ravel()) ) 
    560     return ATM_stock_int 
     585# def SRF_stock_int (stock) : 
     586#     '''Integrate (* surface) stock on land grid''' 
     587#     ATM_stock_int  = wu.Ksum (  ( (stock * DYN_aire_fter).to_masked_array().ravel()) ) 
     588#     return ATM_stock_int 
    561589 
    562590def SRF_flux_int (flux) : 
     
    565593    return SRF_flux_int 
    566594 
    567 def OCE_stock_int (stock) : 
    568     '''Integrate stock on ocean grid''' 
    569     OCE_stock_int = np.sum (  np.sort ( (stock * OCE_aire ).to_masked_array().ravel()) ) 
    570     return OCE_stock_int 
     595def LIC_flux_int (flux) : 
     596    '''Integrate (* time * surface) flux on land ice grid''' 
     597    LIC_flux_int  = wu.Psum ( (flux * dtime_per_sec * ATM_aire_flic).to_masked_array().ravel() ) 
     598    return LIC_flux_int 
     599 
     600# def OCE_stock_int (stock) : 
     601#     '''Integrate stock on ocean grid''' 
     602#     OCE_stock_int = np.sum (  np.sort ( (stock * OCE_aire ).to_masked_array().ravel()) ) 
     603#     return OCE_stock_int 
    571604 
    572605def ONE_stock_int (stock) : 
     
    584617    OCE_flux_int = np.sum (  np.sort ( (flux * dtime_per_sec).to_masked_array().ravel()) ) 
    585618    return OCE_flux_int 
    586      
    587 #if LMDZ : 
    588 #    d_ATM_beg = d_ATM_beg.assign ( coords={'lon':d_ATM_beg.lon*180./np.pi} ) 
    589619 
    590620# Get mask and surfaces 
     
    607637 
    608638echo ( '\n====================================================================================' ) 
    609 echo ( '-- NEMO change in stores (for the records)' ) 
    610 #-- Note that the total number of days of the run should be diagnosed rather than assumed 
    611 #-- Here the result is in Sv 
    612 # 
    613 #-- Change in ocean volume in freshwater equivalent 
    614  
    615 OCE_ssh_beg = d_OCE_beg['sshn'] 
    616 OCE_ssh_end = d_OCE_end['sshn'] 
    617 OCE_sum_ssh_beg = OCE_stock_int ( OCE_ssh_beg ) 
    618 OCE_sum_ssh_end = OCE_stock_int ( OCE_ssh_end ) 
    619  
    620 OCE_mas_wat_beg = OCE_sum_ssh_beg * OCE_rho_liq 
    621 OCE_mas_wat_end = OCE_sum_ssh_end * OCE_rho_liq 
    622  
    623 echo ( 'OCE_sum_ssh_beg = {:12.6e} m^3 | OCE_sum_ssh_end = {:12.6e} m^3'.format (OCE_sum_ssh_beg, OCE_sum_ssh_end) ) 
    624 dOCE_vol_liq = ( OCE_sum_ssh_end - OCE_sum_ssh_beg ) 
    625 dOCE_mas_liq = dOCE_vol_liq * OCE_rho_liq 
    626 dOCE_mas_wat = dOCE_mas_liq 
    627  
    628 echo ( 'dOCE vol    = {:12.3e} m^3'.format (dOCE_vol_liq) ) 
    629 echo ( 'dOCE ssh    = {:12.3e} m  '.format (dOCE_vol_liq/OCE_aire_tot) ) 
    630 echo ( 'dOCE mass   = {:12.3e} kg '.format (dOCE_mas_liq) ) 
    631 echo ( 'dOCE mass   = {:12.3e} Sv '.format (dOCE_mas_liq/dtime_sec*1E-6/OCE_rho_liq) ) 
    632  
    633 ## Glace et neige 
     639echo ( f'-- ATM Fluxes  -- {Title} ' ) 
     640 
     641if ATM_HIS == 'latlon' : 
     642    echo ( ' latlon case' ) 
     643    ATM_wbilo_oce   = lmdz.geo2point ( rprec (d_ATM_his ['wbilo_oce']), dim1D='cell' ) 
     644    ATM_wbilo_sic   = lmdz.geo2point ( rprec (d_ATM_his ['wbilo_sic']), dim1D='cell' ) 
     645    ATM_wbilo_ter   = lmdz.geo2point ( rprec (d_ATM_his ['wbilo_ter']), dim1D='cell' ) 
     646    ATM_wbilo_lic   = lmdz.geo2point ( rprec (d_ATM_his ['wbilo_lic']), dim1D='cell' ) 
     647    ATM_runofflic   = lmdz.geo2point ( rprec (d_ATM_his ['runofflic']), dim1D='cell' ) 
     648    ATM_fqcalving   = lmdz.geo2point ( rprec (d_ATM_his ['fqcalving']), dim1D='cell' ) 
     649    ATM_fqfonte     = lmdz.geo2point ( rprec (d_ATM_his ['fqfonte']  ), dim1D='cell' ) 
     650    ATM_precip      = lmdz.geo2point ( rprec (d_ATM_his ['precip']   ), dim1D='cell' ) 
     651    ATM_snowf       = lmdz.geo2point ( rprec (d_ATM_his ['snow']     ), dim1D='cell' ) 
     652    ATM_evap        = lmdz.geo2point ( rprec (d_ATM_his ['evap']     ), dim1D='cell' ) 
     653    ATM_wevap_ter   = lmdz.geo2point ( rprec (d_ATM_his ['wevap_ter']), dim1D='cell' ) 
     654    ATM_wevap_oce   = lmdz.geo2point ( rprec (d_ATM_his ['wevap_oce']), dim1D='cell' ) 
     655    ATM_wevap_lic   = lmdz.geo2point ( rprec (d_ATM_his ['wevap_lic']), dim1D='cell' ) 
     656    ATM_wevap_sic   = lmdz.geo2point ( rprec (d_ATM_his ['wevap_sic']), dim1D='cell' ) 
     657    ATM_wrain_ter   = lmdz.geo2point ( rprec (d_ATM_his ['wrain_ter']), dim1D='cell' ) 
     658    ATM_wrain_oce   = lmdz.geo2point ( rprec (d_ATM_his ['wrain_oce']), dim1D='cell' ) 
     659    ATM_wrain_lic   = lmdz.geo2point ( rprec (d_ATM_his ['wrain_lic']), dim1D='cell' ) 
     660    ATM_wrain_sic   = lmdz.geo2point ( rprec (d_ATM_his ['wrain_sic']), dim1D='cell' ) 
     661    ATM_wsnow_ter   = lmdz.geo2point ( rprec (d_ATM_his ['wsnow_ter']), dim1D='cell' ) 
     662    ATM_wsnow_oce   = lmdz.geo2point ( rprec (d_ATM_his ['wsnow_oce']), dim1D='cell' ) 
     663    ATM_wsnow_lic   = lmdz.geo2point ( rprec (d_ATM_his ['wsnow_lic']), dim1D='cell' ) 
     664    ATM_wsnow_sic   = lmdz.geo2point ( rprec (d_ATM_his ['wsnow_sic']), dim1D='cell' ) 
     665    ATM_runofflic   = lmdz.geo2point ( rprec (d_ATM_his ['runofflic']), dim1D='cell' ) 
     666    echo ( f'End of LATLON case') 
     667     
     668if ATM_HIS == 'ico' : 
     669    echo (' ico case') 
     670    ATM_wbilo_oce   = rprec (d_ATM_his ['wbilo_oce']) 
     671    ATM_wbilo_sic   = rprec (d_ATM_his ['wbilo_sic']) 
     672    ATM_wbilo_ter   = rprec (d_ATM_his ['wbilo_ter']) 
     673    ATM_wbilo_lic   = rprec (d_ATM_his ['wbilo_lic']) 
     674    ATM_runofflic   = rprec (d_ATM_his ['runofflic']) 
     675    ATM_fqcalving   = rprec (d_ATM_his ['fqcalving']) 
     676    ATM_fqfonte     = rprec (d_ATM_his ['fqfonte']  ) 
     677    ATM_precip      = rprec (d_ATM_his ['precip']   ) 
     678    ATM_snowf       = rprec (d_ATM_his ['snow']     ) 
     679    ATM_evap        = rprec (d_ATM_his ['evap']     ) 
     680    ATM_wevap_ter   = rprec (d_ATM_his ['wevap_ter']) 
     681    ATM_wevap_oce   = rprec (d_ATM_his ['wevap_oce']) 
     682    ATM_wevap_lic   = rprec (d_ATM_his ['wevap_lic']) 
     683    ATM_wevap_sic   = rprec (d_ATM_his ['wevap_sic']) 
     684    ATM_runofflic   = rprec (d_ATM_his ['runofflic']) 
     685    ATM_wevap_ter   = rprec (d_ATM_his ['wevap_ter']) 
     686    ATM_wevap_oce   = rprec (d_ATM_his ['wevap_oce']) 
     687    ATM_wevap_lic   = rprec (d_ATM_his ['wevap_lic']) 
     688    ATM_wevap_sic   = rprec (d_ATM_his ['wevap_sic']) 
     689    ATM_wrain_ter   = rprec (d_ATM_his ['wrain_ter']) 
     690    ATM_wrain_oce   = rprec (d_ATM_his ['wrain_oce']) 
     691    ATM_wrain_lic   = rprec (d_ATM_his ['wrain_lic']) 
     692    ATM_wrain_sic   = rprec (d_ATM_his ['wrain_sic']) 
     693    ATM_wsnow_ter   = rprec (d_ATM_his ['wsnow_ter']) 
     694    ATM_wsnow_oce   = rprec (d_ATM_his ['wsnow_oce']) 
     695    ATM_wsnow_lic   = rprec (d_ATM_his ['wsnow_lic']) 
     696    ATM_wsnow_sic   = rprec (d_ATM_his ['wsnow_sic']) 
     697    echo ( f'End of ico case ') 
     698 
     699 
     700     
     701echo ( 'ATM wprecip_oce' ) 
     702ATM_wprecip_oce = ATM_wrain_oce + ATM_wsnow_oce 
     703ATM_wprecip_ter = ATM_wrain_ter + ATM_wsnow_ter 
     704ATM_wprecip_sic = ATM_wrain_sic + ATM_wsnow_sic 
     705ATM_wprecip_lic = ATM_wrain_lic + ATM_wsnow_lic 
     706 
     707ATM_wbilo       = ATM_wbilo_oce   + ATM_wbilo_sic   + ATM_wbilo_ter   + ATM_wbilo_lic 
     708ATM_wevap       = ATM_wevap_oce   + ATM_wevap_sic   + ATM_wevap_ter   + ATM_wevap_lic 
     709ATM_wprecip     = ATM_wprecip_oce + ATM_wprecip_sic + ATM_wprecip_ter + ATM_wprecip_lic 
     710ATM_wsnow       = ATM_wsnow_oce   + ATM_wsnow_sic   + ATM_wsnow_ter   + ATM_wsnow_lic 
     711ATM_wrain       = ATM_wrain_oce   + ATM_wrain_sic   + ATM_wrain_ter   + ATM_wrain_lic 
     712ATM_wemp        = ATM_wevap - ATM_wprecip 
     713ATM_emp         = ATM_evap  - ATM_precip 
     714 
     715ATM_wprecip_sea = ATM_wprecip_oce + ATM_wprecip_sic 
     716ATM_wsnow_sea   = ATM_wsnow_oce   + ATM_wsnow_sic 
     717ATM_wrain_sea   = ATM_wrain_oce   + ATM_wrain_sic 
     718ATM_wbilo_sea   = ATM_wbilo_oce   + ATM_wbilo_sic 
     719ATM_wevap_sea   = ATM_wevap_sic   + ATM_wevap_oce 
     720 
     721ATM_wemp_ter    = ATM_wevap_ter - ATM_wprecip_ter 
     722ATM_wemp_oce    = ATM_wevap_oce - ATM_wprecip_oce 
     723ATM_wemp_sic    = ATM_wevap_sic - ATM_wprecip_sic 
     724ATM_wemp_lic    = ATM_wevap_lic - ATM_wprecip_lic 
     725ATM_wemp_sea    = ATM_wevap_sic - ATM_wprecip_oce 
     726 
     727if RUN_HIS == 'latlon' : 
     728    echo ( f'RUN costalflow Grille LATLON' ) 
     729    if TestInterp : 
     730        echo ( f'RUN runoff TestInterp' ) 
     731        RUN_runoff      = lmdz.geo2point ( rprec (d_RUN_his ['runoff_contfrac_interp']  )   , dim1D='cell' ) 
     732        RUN_drainage    = lmdz.geo2point ( rprec (d_RUN_his ['drainage_contfrac_interp'])   , dim1D='cell' ) 
     733    else :  
     734        echo ( f'RUN runoff' ) 
     735        RUN_runoff      = lmdz.geo2point ( rprec (d_RUN_his ['runoff']         ), dim1D='cell' ) 
     736        RUN_drainage    = lmdz.geo2point ( rprec (d_RUN_his ['drainage']       ), dim1D='cell' ) 
     737         
     738    RUN_coastalflow     = lmdz.geo2point ( rprec (d_RUN_his ['coastalflow']    ), dim1D='cell' )  
     739    RUN_riverflow       = lmdz.geo2point ( rprec (d_RUN_his ['riverflow']      ), dim1D='cell' ) 
     740    RUN_riversret       = lmdz.geo2point ( rprec (d_RUN_his ['riversret']      ), dim1D='cell' ) 
     741    RUN_coastalflow_cpl = lmdz.geo2point ( rprec (d_RUN_his ['coastalflow_cpl']), dim1D='cell' )  
     742    RUN_riverflow_cpl   = lmdz.geo2point ( rprec (d_RUN_his ['riverflow_cpl']  ), dim1D='cell' ) 
     743 
     744if RUN_HIS == 'ico' : 
     745    echo ( f'RUN costalflow Grille ICO' ) 
     746    RUN_coastalflow =  rprec (d_RUN_his ['coastalflow']) 
     747    RUN_riverflow   =  rprec (d_RUN_his ['riverflow']  ) 
     748    RUN_runoff      =  rprec (d_RUN_his ['runoff']     ) 
     749    RUN_drainage    =  rprec (d_RUN_his ['drainage']   ) 
     750    RUN_riversret   =  rprec (d_RUN_his ['riversret']  ) 
     751     
     752    RUN_coastalflow_cpl = rprec (d_RUN_his ['coastalflow_cpl']) 
     753    RUN_riverflow_cpl   = rprec (d_RUN_his ['riverflow_cpl']  ) 
     754 
     755## Correcting units of SECHIBA variables 
     756def mmd2SI ( Var ) : 
     757    '''Change unit from mm/d or m^3/s to kg/s if needed''' 
     758    if 'units' in VarT.attrs :  
     759        if VarT.attrs['units'] in ['m^3/s', 'm3/s', 'm3.s-1',] : 
     760            VarT.values = VarT.values  * ATM_rho                 ;  VarT.attrs['units'] = 'kg/s' 
     761        if VarT.attrs['units'] == 'mm/d' : 
     762            VarT.values = VarT.values  * ATM_rho * (1e-3/86400.) ;  VarT.attrs['units'] = 'kg/s' 
     763        if VarT.attrs['units'] in ['m^3', 'm3', ] : 
     764            VarT.values = VarT.values  * ATM_rho                 ;  VarT.attrs['units'] = 'kg' 
     765             
     766for var in [ 'runoff', 'drainage', 'riversret', 'coastalflow', 'riverflow', 'coastalflow_cpl', 'riverflow_cpl' ] : 
     767    VarT = locals()['RUN_' + var] 
     768    mmd2SI (VarT) 
     769 
     770#for var in ['evap', 'snowf', 'subli', 'transpir', 'rain', 'emp' ] : 
     771#    VarT = locals()['SRF_' + var] 
     772#    mmd2SI (VarT) 
     773echo ( f'RUN input' ) 
     774RUN_input  = RUN_runoff      + RUN_drainage 
     775RUN_output = RUN_coastalflow + RUN_riverflow 
     776 
     777echo ( f'ATM flw_wbilo' ) 
     778ATM_flx_wbilo       = ATM_flux_int ( ATM_wbilo      ) 
     779ATM_flx_wevap       = ATM_flux_int ( ATM_wevap      ) 
     780ATM_flx_wprecip     = ATM_flux_int ( ATM_wprecip    ) 
     781ATM_flx_wsnow       = ATM_flux_int ( ATM_wsnow      ) 
     782ATM_flx_wrain       = ATM_flux_int ( ATM_wrain      ) 
     783ATM_flx_wemp        = ATM_flux_int ( ATM_wemp       ) 
     784 
     785ATM_flx_wbilo_lic   = ATM_flux_int ( ATM_wbilo_lic  ) 
     786ATM_flx_wbilo_oce   = ATM_flux_int ( ATM_wbilo_oce  ) 
     787ATM_flx_wbilo_sea   = ATM_flux_int ( ATM_wbilo_sea  ) 
     788ATM_flx_wbilo_sic   = ATM_flux_int ( ATM_wbilo_sic  ) 
     789ATM_flx_wbilo_ter   = ATM_flux_int ( ATM_wbilo_ter  ) 
     790ATM_flx_calving     = ATM_flux_int ( ATM_fqcalving  ) 
     791ATM_flx_fqfonte     = ATM_flux_int ( ATM_fqfonte    ) 
     792 
     793LIC_flx_calving     = LIC_flux_int ( ATM_fqcalving  ) 
     794LIC_flx_fqfonte     = LIC_flux_int ( ATM_fqfonte    ) 
     795 
     796ATM_flx_precip      = ATM_flux_int ( ATM_precip     ) 
     797ATM_flx_snowf       = ATM_flux_int ( ATM_snowf      ) 
     798ATM_flx_evap        = ATM_flux_int ( ATM_evap       ) 
     799ATM_flx_runlic      = ATM_flux_int ( ATM_runofflic  ) 
     800 
     801LIC_flx_precip      = LIC_flux_int ( ATM_precip     ) 
     802LIC_flx_snowf       = LIC_flux_int ( ATM_snowf      ) 
     803LIC_flx_evap        = LIC_flux_int ( ATM_evap       ) 
     804LIC_flx_runlic      = LIC_flux_int ( ATM_runofflic  ) 
     805 
     806ATM_flx_wrain_ter   = ATM_flux_int ( ATM_wrain_ter ) 
     807ATM_flx_wrain_oce   = ATM_flux_int ( ATM_wrain_oce ) 
     808ATM_flx_wrain_lic   = ATM_flux_int ( ATM_wrain_lic ) 
     809ATM_flx_wrain_sic   = ATM_flux_int ( ATM_wrain_sic ) 
     810ATM_flx_wrain_sea   = ATM_flux_int ( ATM_wrain_sea ) 
     811 
     812ATM_flx_wsnow_ter   = ATM_flux_int ( ATM_wsnow_ter ) 
     813ATM_flx_wsnow_oce   = ATM_flux_int ( ATM_wsnow_oce ) 
     814ATM_flx_wsnow_lic   = ATM_flux_int ( ATM_wsnow_lic ) 
     815ATM_flx_wsnow_sic   = ATM_flux_int ( ATM_wsnow_sic ) 
     816ATM_flx_wsnow_sea   = ATM_flux_int ( ATM_wsnow_sea ) 
     817 
     818ATM_flx_wevap_ter   = ATM_flux_int ( ATM_wevap_ter ) 
     819ATM_flx_wevap_oce   = ATM_flux_int ( ATM_wevap_oce ) 
     820ATM_flx_wevap_lic   = ATM_flux_int ( ATM_wevap_lic ) 
     821ATM_flx_wevap_sic   = ATM_flux_int ( ATM_wevap_sic ) 
     822ATM_flx_wevap_sea   = ATM_flux_int ( ATM_wevap_sea ) 
     823ATM_flx_wprecip_lic = ATM_flux_int ( ATM_wprecip_lic ) 
     824ATM_flx_wprecip_oce = ATM_flux_int ( ATM_wprecip_oce ) 
     825ATM_flx_wprecip_sic = ATM_flux_int ( ATM_wprecip_sic ) 
     826ATM_flx_wprecip_ter = ATM_flux_int ( ATM_wprecip_ter ) 
     827ATM_flx_wprecip_sea = ATM_flux_int ( ATM_wprecip_sea ) 
     828ATM_flx_wemp_lic    = ATM_flux_int ( ATM_wemp_lic ) 
     829ATM_flx_wemp_oce    = ATM_flux_int ( ATM_wemp_oce ) 
     830ATM_flx_wemp_sic    = ATM_flux_int ( ATM_wemp_sic ) 
     831ATM_flx_wemp_ter    = ATM_flux_int ( ATM_wemp_ter ) 
     832ATM_flx_wemp_sea    = ATM_flux_int ( ATM_wemp_sea ) 
     833 
     834ATM_flx_emp          = ATM_flux_int ( ATM_emp ) 
     835 
     836RUN_flx_coastal     = ONE_flux_int ( RUN_coastalflow) 
     837RUN_flx_river       = ONE_flux_int ( RUN_riverflow  ) 
     838RUN_flx_coastal_cpl = ONE_flux_int ( RUN_coastalflow_cpl) 
     839RUN_flx_river_cpl   = ONE_flux_int ( RUN_riverflow_cpl  ) 
     840RUN_flx_drainage    = SRF_flux_int ( RUN_drainage   ) 
     841RUN_flx_riversret   = SRF_flux_int ( RUN_riversret  ) 
     842RUN_flx_runoff      = SRF_flux_int ( RUN_runoff     ) 
     843RUN_flx_input       = SRF_flux_int ( RUN_input      ) 
     844RUN_flx_output      = ONE_flux_int ( RUN_output     ) 
     845 
     846RUN_flx_bil    = ONE_flux_int ( RUN_input       - RUN_output) 
     847RUN_flx_rivcoa = ONE_flux_int ( RUN_coastalflow + RUN_riverflow) 
     848 
     849prtFlux ('wbilo_oce            ', ATM_flx_wbilo_oce     , 'f' )           
     850prtFlux ('wbilo_sic            ', ATM_flx_wbilo_sic     , 'f' )           
     851prtFlux ('wbilo_sic+oce        ', ATM_flx_wbilo_sea     , 'f' )           
     852prtFlux ('wbilo_ter            ', ATM_flx_wbilo_ter     , 'f' )           
     853prtFlux ('wbilo_lic            ', ATM_flx_wbilo_lic     , 'f' )           
     854prtFlux ('Sum wbilo_*          ', ATM_flx_wbilo         , 'f', True)   
     855prtFlux ('E-P                  ', ATM_flx_emp           , 'f', True)   
     856prtFlux ('calving              ', ATM_flx_calving       , 'f' )  
     857prtFlux ('fqfonte              ', ATM_flx_fqfonte       , 'f' )        
     858prtFlux ('precip               ', ATM_flx_precip        , 'f' )        
     859prtFlux ('snowf                ', ATM_flx_snowf         , 'f' )         
     860prtFlux ('evap                 ', ATM_flx_evap          , 'f' ) 
     861prtFlux ('runoff lic           ', ATM_flx_runlic        , 'f' ) 
     862 
     863prtFlux ('ATM_flx_wevap*       ', ATM_flx_wevap         , 'f' ) 
     864prtFlux ('ATM_flx_wrain*       ', ATM_flx_wrain         , 'f' ) 
     865prtFlux ('ATM_flx_wsnow*       ', ATM_flx_wsnow         , 'f' ) 
     866prtFlux ('ATM_flx_wprecip*     ', ATM_flx_wprecip       , 'f' ) 
     867prtFlux ('ATM_flx_wemp*        ', ATM_flx_wemp          , 'f', True ) 
     868 
     869prtFlux ('ERROR evap           ', ATM_flx_wevap   - ATM_flx_evap  , 'e', True ) 
     870prtFlux ('ERROR precip         ', ATM_flx_wprecip - ATM_flx_precip, 'e', True ) 
     871prtFlux ('ERROR snow           ', ATM_flx_wsnow   - ATM_flx_snowf , 'e', True ) 
     872prtFlux ('ERROR emp            ', ATM_flx_wemp    - ATM_flx_emp   , 'e', True ) 
     873 
     874 
     875echo ( '\n====================================================================================' ) 
     876echo ( f'-- RUNOFF Fluxes  -- {Title} ' ) 
     877prtFlux ('coastalflow   ', RUN_flx_coastal    , 'f' )  
     878prtFlux ('riverflow     ', RUN_flx_river      , 'f' )         
     879prtFlux ('coastal_cpl   ', RUN_flx_coastal_cpl, 'f' )   
     880prtFlux ('riverf_cpl    ', RUN_flx_river_cpl  , 'f' )     
     881prtFlux ('river+coastal ', RUN_flx_rivcoa     , 'f' )    
     882prtFlux ('drainage      ', RUN_flx_drainage   , 'f' )    
     883prtFlux ('riversret     ', RUN_flx_riversret  , 'f' )    
     884prtFlux ('runoff        ', RUN_flx_runoff     , 'f' )    
     885prtFlux ('river in      ', RUN_flx_input      , 'f' )    
     886prtFlux ('river out     ', RUN_flx_output     , 'f' )    
     887prtFlux ('river bil     ', RUN_flx_bil        , 'f' )  
     888     
     889echo ( '\n====================================================================================' ) 
     890echo ( f'-- OCE Fluxes  -- {Title} ' ) 
     891 
     892# Read variable and computes integral over space and time 
     893OCE_empmr      = rprec (d_OCE_his['wfo']     )    ; OCE_mas_empmr    = OCE_flux_int ( OCE_empmr    ) 
     894OCE_wfob       = rprec (d_OCE_his['wfob']    )    ; OCE_mas_wfob     = OCE_flux_int ( OCE_wfob     ) 
     895OCE_emp_oce    = rprec (d_OCE_his['emp_oce'] )    ; OCE_mas_emp_oce  = OCE_flux_int ( OCE_emp_oce  ) 
     896OCE_emp_ice    = rprec (d_OCE_his['emp_ice'] )    ; OCE_mas_emp_ice  = OCE_flux_int ( OCE_emp_ice  ) 
     897OCE_iceshelf   = rprec (d_OCE_his['iceshelf'])    ; OCE_mas_iceshelf = OCE_flux_int ( OCE_iceshelf ) 
     898OCE_calving    = rprec (d_OCE_his['calving'] )    ; OCE_mas_calving  = OCE_flux_int ( OCE_calving  ) 
     899OCE_iceberg    = rprec (d_OCE_his['iceberg'] )    ; OCE_mas_iceberg  = OCE_flux_int ( OCE_iceberg  ) 
     900OCE_friver     = rprec (d_OCE_his['friver']  )    ; OCE_mas_friver   = OCE_flux_int ( OCE_friver   ) 
     901OCE_runoffs    = rprec (d_OCE_his['runoffs'] )    ; OCE_mas_runoffs  = OCE_flux_int ( OCE_runoffs  ) 
     902if NEMO == 4.0 or NEMO == 4.2 : 
     903    OCE_wfxice     = rprec (d_OCE_his['vfxice']) ; OCE_mas_wfxice   = OCE_flux_int ( OCE_wfxice ) 
     904    OCE_wfxsnw     = rprec (d_OCE_his['vfxsnw']) ; OCE_mas_wfxsnw   = OCE_flux_int ( OCE_wfxsnw ) 
     905    OCE_wfxsub     = rprec (d_OCE_his['vfxsub']) ; OCE_mas_wfxsub   = OCE_flux_int ( OCE_wfxsub ) 
    634906if NEMO == 3.6 : 
    635     ICE_ice_beg = d_ICE_beg['v_i_htc1']+d_ICE_beg['v_i_htc2']+d_ICE_beg['v_i_htc3']+d_ICE_beg['v_i_htc4']+d_ICE_beg['v_i_htc5'] 
    636     ICE_ice_end = d_ICE_end['v_i_htc1']+d_ICE_end['v_i_htc2']+d_ICE_end['v_i_htc3']+d_ICE_end['v_i_htc4']+d_ICE_end['v_i_htc5'] 
    637  
    638     ICE_sno_beg = d_ICE_beg['v_s_htc1']+d_ICE_beg['v_s_htc2']+d_ICE_beg['v_s_htc3']+d_ICE_beg['v_s_htc4']+d_ICE_beg['v_s_htc5'] 
    639     ICE_sno_end = d_ICE_end['v_s_htc1']+d_ICE_end['v_s_htc2']+d_ICE_end['v_s_htc3']+d_ICE_end['v_s_htc4']+d_ICE_end['v_s_htc5'] 
    640      
    641     ICE_pnd_beg = 0.0 ; ICE_pnd_end = 0.0 
    642     ICE_fzl_beg = 0.0 ; ICE_fzl_end = 0.0 
    643  
    644     ICE_mas_wat_beg = OCE_stock_int ( (ICE_ice_beg*ICE_rho_ice + ICE_sno_beg*ICE_rho_sno) ) 
    645     ICE_mas_wat_end = OCE_stock_int ( (ICE_ice_end*ICE_rho_ice + ICE_sno_end*ICE_rho_sno) ) 
    646      
     907    OCE_wfxice     = rprec (d_OCE_his['vfxice'])/86400.*ICE_rho_ice ; OCE_mas_wfxice   = OCE_flux_int ( OCE_wfxice ) 
     908    OCE_wfxsnw     = rprec (d_OCE_his['vfxsnw'])/86400.*ICE_rho_sno ; OCE_mas_wfxsnw   = OCE_flux_int ( OCE_wfxsnw ) 
     909    OCE_wfxsub     = rprec (d_OCE_his['vfxsub'])/86400.*ICE_rho_sno ; OCE_mas_wfxsub   = OCE_flux_int ( OCE_wfxsub ) 
     910# Additional checks 
     911OCE_evap_oce   = rprec (d_OCE_his['evap_ao_cea']) ; OCE_mas_evap_oce   = OCE_flux_int ( OCE_evap_oce ) 
     912ICE_evap_ice   = rprec (d_OCE_his['subl_ai_cea']) ; ICE_mas_evap_ice   = OCE_flux_int ( ICE_evap_ice ) 
     913OCE_snow_oce   = rprec (d_OCE_his['snow_ao_cea']) ; OCE_mas_snow_oce   = OCE_flux_int ( OCE_snow_oce ) 
     914OCE_snow_ice   = rprec (d_OCE_his['snow_ai_cea']) ; OCE_mas_snow_ice   = OCE_flux_int ( OCE_snow_ice ) 
     915OCE_rain       = rprec (d_OCE_his['rain']       ) ; OCE_mas_rain       = OCE_flux_int ( OCE_rain     ) 
     916ICE_wfxsub_err = rprec (d_ICE_his['vfxsub_err'] ) ; ICE_mas_wfxsub_err = OCE_flux_int ( ICE_wfxsub_err ) 
    647917if NEMO == 4.0 or NEMO == 4.2 : 
    648     ICE_ice_beg = d_ICE_beg ['v_i']  ; ICE_ice_end = d_ICE_end ['v_i'] 
    649     ICE_sno_beg = d_ICE_beg ['v_s']  ; ICE_sno_end = d_ICE_end ['v_s'] 
    650     ICE_pnd_beg = d_ICE_beg ['v_ip'] ; ICE_pnd_end = d_ICE_end ['v_ip'] 
    651     ICE_fzl_beg = d_ICE_beg ['v_il'] ; ICE_fzl_end = d_ICE_end ['v_il'] 
    652      
    653     ICE_mas_wat_beg = OCE_stock_int ( d_ICE_beg['snwice_mass'] ) 
    654     ICE_mas_wat_end = OCE_stock_int ( d_ICE_end['snwice_mass'] ) 
    655      
    656      
    657 ICE_vol_ice_beg = OCE_stock_int ( ICE_ice_beg ) 
    658 ICE_vol_ice_end = OCE_stock_int ( ICE_ice_end ) 
    659  
    660 ICE_vol_sno_beg = OCE_stock_int ( ICE_sno_beg ) 
    661 ICE_vol_sno_end = OCE_stock_int ( ICE_sno_end ) 
    662  
    663 ICE_vol_pnd_beg = OCE_stock_int ( ICE_pnd_beg ) 
    664 ICE_vol_pnd_end = OCE_stock_int ( ICE_pnd_end ) 
    665  
    666 ICE_vol_fzl_beg = OCE_stock_int ( ICE_fzl_beg ) 
    667 ICE_vol_fzl_end = OCE_stock_int ( ICE_fzl_end ) 
    668  
    669 #-- Converting to freswater volume 
    670 dICE_vol_ice = ICE_vol_ice_end - ICE_vol_ice_beg 
    671 dICE_mas_ice = dICE_vol_ice * ICE_rho_ice 
    672  
    673 dICE_vol_sno = ICE_vol_sno_end - ICE_vol_sno_beg 
    674 dICE_mas_sno = dICE_vol_sno * ICE_rho_sno 
    675  
    676 dICE_vol_pnd = ICE_vol_pnd_end - ICE_vol_pnd_beg 
    677 dICE_mas_pnd = dICE_vol_pnd * ICE_rho_pnd 
    678  
    679 dICE_vol_fzl= ICE_vol_fzl_end - ICE_vol_fzl_beg 
    680 dICE_mas_fzl = dICE_vol_fzl * ICE_rho_pnd 
    681  
     918    ICE_wfxpnd     = rprec (d_ICE_his['vfxpnd']    ) ; ICE_mas_wfxpnd     = OCE_flux_int ( ICE_wfxpnd     ) 
     919    ICE_wfxsnw_sub = rprec (d_ICE_his['vfxsnw_sub']) ; ICE_mas_wfxsnw_sub = OCE_flux_int ( ICE_wfxsnw_sub ) 
     920    ICE_wfxsnw_pre = rprec (d_ICE_his['vfxsnw_pre']) ; ICE_mas_wfxsnw_pre = OCE_flux_int ( ICE_wfxsnw_pre ) 
    682921if NEMO == 3.6 : 
    683     dICE_mas_wat = dICE_mas_ice + dICE_mas_sno 
    684     dSEA_mas_wat = dOCE_mas_wat + dICE_mas_ice + dICE_mas_sno 
    685  
    686 if NEMO == 4.0 or NEMO == 4.2 : 
    687     dICE_mas_wat = ICE_mas_wat_end - ICE_mas_wat_beg 
    688     dSEA_mas_wat = dOCE_mas_wat + dICE_mas_wat 
    689  
    690 echo ( f'ICE_vol_ice_beg = {ICE_vol_ice_beg:12.6e} m^3 | ICE_vol_ice_end = {ICE_vol_ice_end:12.6e} m^3' ) 
    691 echo ( f'ICE_vol_sno_beg = {ICE_vol_sno_beg:12.6e} m^3 | ICE_vol_sno_end = {ICE_vol_sno_end:12.6e} m^3' ) 
    692 echo ( f'ICE_vol_pnd_beg = {ICE_vol_pnd_beg:12.6e} m^3 | ICE_vol_pnd_end = {ICE_vol_pnd_end:12.6e} m^3' ) 
    693 echo ( f'ICE_vol_fzl_beg = {ICE_vol_fzl_beg:12.6e} m^3 | ICE_vol_fzl_end = {ICE_vol_fzl_end:12.6e} m^3' ) 
    694  
    695 echo ( f'dICE_vol_ice   = {dICE_vol_ice:12.3e} m^3' ) 
    696 echo ( f'dICE_vol_sno   = {dICE_vol_sno:12.3e} m^3' ) 
    697 echo ( f'dICE_vol_pnd   = {dICE_vol_pnd:12.3e} m^3' ) 
    698 echo ( f'dICE_mas_ice   = {dICE_mas_ice:12.3e} m^3' ) 
    699 echo ( f'dICE_mas_sno   = {dICE_mas_sno:12.3e} m^3' )   
    700 echo ( f'dICE_mas_pnd   = {dICE_mas_pnd:12.3e} m^3' )   
    701 echo ( f'dICE_mas_fzl   = {dICE_mas_fzl:12.3e} m^3' )   
    702 echo ( f'dICE_mas_wat   = {dICE_mas_wat:12.3e} m^3' )  
    703  
    704  
    705 SEA_mas_wat_beg = OCE_mas_wat_beg + ICE_mas_wat_beg 
    706 SEA_mas_wat_end = OCE_mas_wat_end + ICE_mas_wat_end 
    707  
    708 echo ( '\n------------------------------------------------------------') 
    709 echo ( 'Variation du contenu en eau ocean + glace ' ) 
    710 echo ( 'dMass (ocean)   = {:12.6e} kg '.format(dSEA_mas_wat) ) 
    711 echo ( 'dVol  (ocean)   = {:12.3e} Sv '.format(dSEA_mas_wat/dtime_sec*1E-6/OCE_rho_liq) ) 
    712 echo ( 'dVol  (ocean)   = {:12.3e} m  '.format(dSEA_mas_wat*1E-3/OCE_aire_tot) ) 
    713  
    714  
    715 echo ( '\n------------------------------------------------------------------------------------' ) 
    716 echo ( '-- ATM changes in stores ' ) 
    717  
    718 #-- Change in precipitable water from the atmosphere daily and monthly files 
    719 #-- Compute sum weighted by gridcell area (kg/m2) then convert to Sv 
    720  
    721 # ATM vertical grid 
    722 ATM_Ahyb = d_ATM_his['Ahyb'].squeeze() 
    723 ATM_Bhyb = d_ATM_his['Bhyb'].squeeze() 
    724 klevp1 = ATM_Ahyb.shape[0] 
    725  
    726 # Surface pressure 
    727 if ICO :  
    728     DYN_ps_beg = d_DYN_beg['ps'] 
    729     DYN_ps_end = d_DYN_end['ps'] 
    730      
    731 if LMDZ :  
    732     DYN_ps_beg =  lmdz.geo2point ( d_DYN_beg['ps'].isel(rlonv=slice(0,-1)) ) 
    733     DYN_ps_end =  lmdz.geo2point ( d_DYN_end['ps'].isel(rlonv=slice(0,-1)) ) 
    734      
    735 # 3D Pressure 
    736 DYN_p_beg = ATM_Ahyb + ATM_Bhyb * DYN_ps_beg 
    737 DYN_p_end = ATM_Ahyb + ATM_Bhyb * DYN_ps_end 
    738  
    739 # Layer thickness 
    740 DYN_sigma_beg = DYN_p_beg[0:-1]*0. 
    741 DYN_sigma_end = DYN_p_end[0:-1]*0.  
    742  
    743 for k in np.arange (klevp1-1) : 
    744     DYN_sigma_beg[k,:] = (DYN_p_beg[k,:] - DYN_p_beg[k+1,:]) / Grav 
    745     DYN_sigma_end[k,:] = (DYN_p_end[k,:] - DYN_p_end[k+1,:]) / Grav 
    746  
    747 DYN_sigma_beg = DYN_sigma_beg.rename ( {'klevp1':'sigs'} ) 
    748 DYN_sigma_end = DYN_sigma_end.rename ( {'klevp1':'sigs'} ) 
    749  
    750 ##-- Vertical and horizontal integral, and sum of liquid, solid and vapor water phases 
    751 if LMDZ : 
    752     try :  
    753         DYN_wat_beg = lmdz.geo3point ( (d_DYN_beg['H2Ov'] + d_DYN_beg['H2Ol'] + d_DYN_beg['H2Oi']).isel(rlonv=slice(0,-1) ) ) 
    754         DYN_wat_end = lmdz.geo3point ( (d_DYN_end['H2Ov'] + d_DYN_end['H2Ol'] + d_DYN_end['H2Oi']).isel(rlonv=slice(0,-1) ) ) 
    755     except : 
    756         DYN_wat_beg = lmdz.geo3point ( (d_DYN_beg['H2O_g'] + d_DYN_beg['H2O_l'] + d_DYN_beg['H2O_s']).isel(rlonv=slice(0,-1) ) ) 
    757         DYN_wat_end = lmdz.geo3point ( (d_DYN_end['H2O_g'] + d_DYN_end['H2O_l'] + d_DYN_end['H2O_s']).isel(rlonv=slice(0,-1) ) ) 
    758 if ICO : 
    759     try : 
    760         DYN_wat_beg = (d_DYN_beg['H2O_g'] + d_DYN_beg['H2O_l'] + d_DYN_beg['H2O_s']).rename ( {'lev':'sigs'} ) 
    761         DYN_wat_end = (d_DYN_end['H2O_g'] + d_DYN_end['H2O_l'] + d_DYN_end['H2O_s']).rename ( {'lev':'sigs'} ) 
    762     except :  
    763         DYN_wat_beg = (d_DYN_beg['q'].isel(nq=0) + d_DYN_beg['q'].isel(nq=1) + d_DYN_beg['q'].isel(nq=2) ).rename ( {'lev':'sigs'} ) 
    764         DYN_wat_end = (d_DYN_end['q'].isel(nq=0) + d_DYN_end['q'].isel(nq=1) + d_DYN_end['q'].isel(nq=2) ).rename ( {'lev':'sigs'} ) 
    765      
    766 DYN_mas_wat_beg = ATM_stock_int (DYN_sigma_beg * DYN_wat_beg) 
    767 DYN_mas_wat_end = ATM_stock_int (DYN_sigma_end * DYN_wat_end) 
    768  
    769 dDYN_mas_wat = DYN_mas_wat_end - DYN_mas_wat_beg 
    770  
    771 echo ( '\nVariation du contenu en eau atmosphere (dynamique) ' ) 
    772 echo ( 'DYN_mas_beg = {:12.6e} kg | DYN_mas_end = {:12.6e} kg'.format (DYN_mas_wat_beg, DYN_mas_wat_end) ) 
    773 echo ( 'dMass (atm)   = {:12.3e} kg '.format (dDYN_mas_wat) ) 
    774 echo ( 'dMass (atm)   = {:12.3e} Sv '.format (dDYN_mas_wat/dtime_sec*1.e-6/ATM_rho) ) 
    775 echo ( 'dMass (atm)   = {:12.3e} m  '.format (dDYN_mas_wat/ATM_aire_sea_tot/ATM_rho) ) 
    776  
    777 ATM_sno_beg = d_ATM_beg['SNOW01']*d_ATM_beg['FTER']+d_ATM_beg['SNOW02']*d_ATM_beg['FLIC']+d_ATM_beg['SNOW03']*d_ATM_beg['FOCE']+d_ATM_beg['SNOW04']*d_ATM_beg['FSIC'] 
    778 ATM_sno_end = d_ATM_end['SNOW01']*d_ATM_end['FTER']+d_ATM_end['SNOW02']*d_ATM_end['FLIC']+d_ATM_end['SNOW03']*d_ATM_end['FOCE']+d_ATM_end['SNOW04']*d_ATM_end['FSIC'] 
    779  
    780 ATM_qs_beg  = d_ATM_beg['QS01']*d_ATM_beg['FTER']+d_ATM_beg['QS02']*d_ATM_beg['FLIC']+d_ATM_beg['QS03']*d_ATM_beg['FOCE']+d_ATM_beg['QS04']*d_ATM_beg['FSIC'] 
    781 ATM_qs_end  = d_ATM_end['QS01']*d_ATM_end['FTER']+d_ATM_end['QS02']*d_ATM_end['FLIC']+d_ATM_end['QS03']*d_ATM_end['FOCE']+d_ATM_end['QS04']*d_ATM_end['FSIC'] 
    782  
    783 ATM_qsol_beg = d_ATM_beg['QSOL'] 
    784 ATM_qsol_end = d_ATM_end['QSOL'] 
    785  
    786 ATM_qs01_beg  = d_ATM_beg['QS01'] * d_ATM_beg['FTER'] 
    787 ATM_qs01_end  = d_ATM_end['QS01'] * d_ATM_end['FTER'] 
    788 ATM_qs02_beg  = d_ATM_beg['QS02'] * d_ATM_beg['FLIC'] 
    789 ATM_qs02_end  = d_ATM_end['QS02'] * d_ATM_end['FLIC'] 
    790 ATM_qs03_beg  = d_ATM_beg['QS03'] * d_ATM_beg['FOCE'] 
    791 ATM_qs03_end  = d_ATM_end['QS03'] * d_ATM_end['FOCE'] 
    792 ATM_qs04_beg  = d_ATM_beg['QS04'] * d_ATM_beg['FSIC'] 
    793 ATM_qs04_end  = d_ATM_end['QS04'] * d_ATM_end['FSIC']   
    794  
    795 if ICO : 
    796    ATM_sno_beg   = ATM_sno_beg .rename ( {'points_physiques':'cell_mesh'} ) 
    797    ATM_sno_end   = ATM_sno_end .rename ( {'points_physiques':'cell_mesh'} ) 
    798    ATM_qs_beg    = ATM_qs_beg  .rename ( {'points_physiques':'cell_mesh'} ) 
    799    ATM_qs_end    = ATM_qs_end  .rename ( {'points_physiques':'cell_mesh'} ) 
    800    ATM_qsol_beg  = ATM_qsol_beg.rename ( {'points_physiques':'cell_mesh'} ) 
    801    ATM_qsol_end  = ATM_qsol_end.rename ( {'points_physiques':'cell_mesh'} ) 
    802    ATM_qs01_beg  = ATM_qs01_beg.rename ( {'points_physiques':'cell_mesh'} ) 
    803    ATM_qs01_end  = ATM_qs01_end.rename ( {'points_physiques':'cell_mesh'} ) 
    804    ATM_qs02_beg  = ATM_qs02_beg.rename ( {'points_physiques':'cell_mesh'} ) 
    805    ATM_qs02_end  = ATM_qs02_end.rename ( {'points_physiques':'cell_mesh'} ) 
    806    ATM_qs03_beg  = ATM_qs03_beg.rename ( {'points_physiques':'cell_mesh'} ) 
    807    ATM_qs03_end  = ATM_qs03_end.rename ( {'points_physiques':'cell_mesh'} ) 
    808    ATM_qs04_beg  = ATM_qs04_beg.rename ( {'points_physiques':'cell_mesh'} ) 
    809    ATM_qs04_end  = ATM_qs04_end.rename ( {'points_physiques':'cell_mesh'} )  
    810  
    811 echo ('Computing atmosphere integrals') 
    812 ATM_mas_sno_beg   = ATM_stock_int ( ATM_sno_beg  ) 
    813 ATM_mas_sno_end   = ATM_stock_int ( ATM_sno_end  ) 
    814 ATM_mas_qs_beg    = ATM_stock_int ( ATM_qs_beg   ) 
    815 ATM_mas_qs_end    = ATM_stock_int ( ATM_qs_end   ) 
    816 ATM_mas_qsol_beg  = ATM_stock_int ( ATM_qsol_beg ) 
    817 ATM_mas_qsol_end  = ATM_stock_int ( ATM_qsol_end ) 
    818 ATM_mas_qs01_beg  = ATM_stock_int ( ATM_qs01_beg ) 
    819 ATM_mas_qs01_end  = ATM_stock_int ( ATM_qs01_end ) 
    820 ATM_mas_qs02_beg  = ATM_stock_int ( ATM_qs02_beg ) 
    821 ATM_mas_qs02_end  = ATM_stock_int ( ATM_qs02_end ) 
    822 ATM_mas_qs03_beg  = ATM_stock_int ( ATM_qs03_beg ) 
    823 ATM_mas_qs03_end  = ATM_stock_int ( ATM_qs03_end ) 
    824 ATM_mas_qs04_beg  = ATM_stock_int ( ATM_qs04_beg ) 
    825 ATM_mas_qs04_end  = ATM_stock_int ( ATM_qs04_end ) 
    826  
    827 dATM_mas_sno  = ATM_mas_sno_end  - ATM_mas_sno_beg 
    828 dATM_mas_qs   = ATM_mas_qs_end   - ATM_mas_qs_beg 
    829 dATM_mas_qsol = ATM_mas_qsol_end - ATM_mas_qsol_beg 
    830  
    831 dATM_mas_qs01 = ATM_mas_qs01_end - ATM_mas_qs01_beg 
    832 dATM_mas_qs02 = ATM_mas_qs02_end - ATM_mas_qs02_beg 
    833 dATM_mas_qs03 = ATM_mas_qs03_end - ATM_mas_qs03_beg 
    834 dATM_mas_qs04 = ATM_mas_qs04_end - ATM_mas_qs04_beg 
    835  
    836 echo ( '\nVariation du contenu en neige atmosphere (calottes)' ) 
    837 echo ( 'ATM_mas_sno_beg  = {:12.6e} kg | ATM_mas_sno_end  = {:12.6e} kg'.format (ATM_mas_sno_beg, ATM_mas_sno_end) ) 
    838 echo ( 'dMass (neige atm) = {:12.3e} kg '.format (dATM_mas_sno ) ) 
    839 echo ( 'dMass (neige atm) = {:12.3e} Sv '.format (dATM_mas_sno/dtime_sec*1e-6/ICE_rho_ice) ) 
    840 echo ( 'dMass (neige atm) = {:12.3e} m  '.format (dATM_mas_sno/ATM_aire_sea_tot/ATM_rho) ) 
    841  
    842 echo ( '\nVariation du contenu humidite du sol' ) 
    843 echo ( 'ATM_mas_qs_beg  = {:12.6e} kg | ATM_mas_qs_end  = {:12.6e} kg'.format (ATM_mas_qs_beg, ATM_mas_qs_end) ) 
    844 echo ( 'dMass (neige atm) = {:12.3e} kg '.format (dATM_mas_qs ) ) 
    845 echo ( 'dMass (neige atm) = {:12.3e} Sv '.format (dATM_mas_qs/dtime_sec*1e-6/ATM_rho) ) 
    846 echo ( 'dMass (neige atm) = {:12.3e} m  '.format (dATM_mas_qs/ATM_aire_sea_tot/ATM_rho) ) 
    847  
    848 echo ( '\nVariation du contenu en eau+neige atmosphere ' ) 
    849 echo ( 'dMass (eau + neige atm) = {:12.3e} kg '.format (  dDYN_mas_wat + dATM_mas_sno) ) 
    850 echo ( 'dMass (eau + neige atm) = {:12.3e} Sv '.format ( (dDYN_mas_wat + dATM_mas_sno)/dtime_sec*1E-6/ATM_rho) ) 
    851 echo ( 'dMass (eau + neige atm) = {:12.3e} m  '.format ( (dDYN_mas_wat + dATM_mas_sno)/ATM_aire_sea_tot/ATM_rho) ) 
    852  
    853 echo ( '\n------------------------------------------------------------------------------------' ) 
    854 echo ( '-- SRF changes ' ) 
    855  
    856 if Routing == 'SIMPLE' : 
    857     RUN_mas_wat_beg = ONE_stock_int ( d_RUN_beg ['fast_reservoir'] +  d_RUN_beg ['slow_reservoir'] +  d_RUN_beg ['stream_reservoir']) 
    858     RUN_mas_wat_end = ONE_stock_int ( d_RUN_end ['fast_reservoir'] +  d_RUN_end ['slow_reservoir'] +  d_RUN_end ['stream_reservoir']) 
    859  
    860 if Routing == 'SECHIBA' :  
    861     RUN_mas_wat_beg = ONE_stock_int ( d_SRF_beg['fastres']  + d_SRF_beg['slowres'] + d_SRF_beg['streamres'] \ 
    862                                     + d_SRF_beg['floodres'] + d_SRF_beg['lakeres'] + d_SRF_beg['pondres'] ) 
    863     RUN_mas_wat_end = ONE_stock_int ( d_SRF_end['fastres']  + d_SRF_end['slowres'] + d_SRF_end['streamres'] \ 
    864                                     + d_SRF_end['floodres'] + d_SRF_end['lakeres'] + d_SRF_end['pondres'] ) 
    865  
    866 dRUN_mas_wat = RUN_mas_wat_end - RUN_mas_wat_beg 
    867      
    868 echo ( '\nWater content in routing ' ) 
    869 echo ( 'RUN_mas_wat_beg = {:12.6e} kg | RUN_mas_wat_end = {:12.6e} kg '.format (RUN_mas_wat_end, RUN_mas_wat_end) ) 
    870 echo ( 'dMass (routing)  = {:12.3e} kg '.format(dRUN_mas_wat) ) 
    871 echo ( 'dMass (routing)  = {:12.3e} Sv '.format(dRUN_mas_wat/dtime_sec*1E-9) ) 
    872 echo ( 'dMass (routing)  = {:12.3e} m  '.format(dRUN_mas_wat/OCE_aire_tot*1E-3) ) 
    873  
    874 print ('Reading SRF restart') 
    875 tot_watveg_beg  = d_SRF_beg['tot_watveg_beg']  ; tot_watveg_beg  = tot_watveg_beg .where (tot_watveg_beg < 1E10, 0.) 
    876 tot_watsoil_beg = d_SRF_beg['tot_watsoil_beg'] ; tot_watsoil_beg = tot_watsoil_beg.where (tot_watsoil_beg< 1E10, 0.) 
    877 snow_beg        = d_SRF_beg['snow_beg']        ; snow_beg        = snow_beg       .where (snow_beg       < 1E10, 0.) 
    878  
    879 tot_watveg_end  = d_SRF_end['tot_watveg_beg']  ; tot_watveg_end  = tot_watveg_end .where (tot_watveg_end < 1E10, 0.) 
    880 tot_watsoil_end = d_SRF_end['tot_watsoil_beg'] ; tot_watsoil_end = tot_watsoil_end.where (tot_watsoil_end< 1E10, 0.) 
    881 snow_end        = d_SRF_end['snow_beg']        ; snow_end        = snow_end       .where (snow_end       < 1E10, 0.) 
    882  
    883 if LMDZ : 
    884     tot_watveg_beg  = lmdz.geo2point (tot_watveg_beg) 
    885     tot_watsoil_beg = lmdz.geo2point (tot_watsoil_beg) 
    886     snow_beg        = lmdz.geo2point (snow_beg) 
    887     tot_watveg_end  = lmdz.geo2point (tot_watveg_end) 
    888     tot_watsoil_end = lmdz.geo2point (tot_watsoil_end) 
    889     snow_end        = lmdz.geo2point (snow_end) 
    890  
    891 SRF_wat_beg = tot_watveg_beg + tot_watsoil_beg + snow_beg 
    892 SRF_wat_end = tot_watveg_end + tot_watsoil_end + snow_end 
    893  
    894 #SRF_mas_wat_beg = d_SRF_beg['tot_watveg_beg']+d_SRF_beg['tot_watsoil_beg'] + d_SRF_beg['snow_beg'] 
    895 #SRF_mas_wat_end = d_SRF_end['tot_watveg_beg']+d_SRF_end['tot_watsoil_beg'] + d_SRF_end['snow_beg'] 
    896  
    897 #if LMDZ : 
    898 #    tot_watveg_beg  = tot_watveg_beg .rename ( {'y':'points_phyiques'} ) 
    899 #    tot_watsoil_beg = tot_watsoil_beg.rename ( {'y':'points_phyiques'} ) 
    900 #    snow_beg        = snow_beg       .rename ( {'y':'points_phyiques'} ) 
    901 #    tot_watveg_end  = tot_watveg_end .rename ( {'y':'points_phyiques'} ) 
    902 #    tot_watsoil_end = tot_watsoil_end.rename ( {'y':'points_phyiques'} ) 
    903 #    snow_end        = snow_end       .rename ( {'y':'points_phyiques'} ) 
    904 #    SRF_wat_beg     = SRF_wat_beg    .rename ( {'y':'points_phyiques'} ) 
    905 #    SRF_wat_end     = SRF_wat_end    .rename ( {'y':'points_phyiques'} ) 
    906 if ICO : 
    907     tot_watveg_beg  = tot_watveg_beg .rename ( {'y':'cell_mesh'} ) 
    908     tot_watsoil_beg = tot_watsoil_beg.rename ( {'y':'cell_mesh'} ) 
    909     snow_beg        = snow_beg       .rename ( {'y':'cell_mesh'} ) 
    910     tot_watveg_end  = tot_watveg_end .rename ( {'y':'cell_mesh'} ) 
    911     tot_watsoil_end = tot_watsoil_end.rename ( {'y':'cell_mesh'} ) 
    912     snow_end        = snow_end       .rename ( {'y':'cell_mesh'} ) 
    913     SRF_wat_beg     = SRF_wat_beg    .rename ( {'y':'cell_mesh'} ) 
    914     SRF_wat_end     = SRF_wat_end    .rename ( {'y':'cell_mesh'} )   
    915  
    916 print ('Computing integrals') 
    917  
    918 print ( ' 1/6', end='' ) ; sys.stdout.flush () 
    919 SRF_mas_watveg_beg   = ATM_stock_int ( tot_watveg_beg  ) 
    920 print ( ' 2/6', end='' ) ; sys.stdout.flush () 
    921 SRF_mas_watsoil_beg  = ATM_stock_int ( tot_watsoil_beg ) 
    922 print ( ' 3/6', end='' ) ; sys.stdout.flush () 
    923 SRF_mas_snow_beg     = ATM_stock_int ( snow_beg        ) 
    924 print ( ' 4/6', end='' ) ; sys.stdout.flush () 
    925 SRF_mas_watveg_end   = ATM_stock_int ( tot_watveg_end  ) 
    926 print ( ' 5/6', end='' ) ; sys.stdout.flush () 
    927 SRF_mas_watsoil_end  = ATM_stock_int ( tot_watsoil_end ) 
    928 print ( ' 6/6', end='' ) ; sys.stdout.flush () 
    929 SRF_mas_snow_end     = ATM_stock_int ( snow_end        ) 
    930 print (' -- ') ; sys.stdout.flush () 
    931  
    932 dSRF_mas_watveg   = SRF_mas_watveg_end   - SRF_mas_watveg_beg 
    933 dSRF_mas_watsoil  = SRF_mas_watsoil_end  - SRF_mas_watsoil_beg 
    934 dSRF_mas_snow     = SRF_mas_snow_end     - SRF_mas_snow_beg 
    935  
    936 echo ('\nLes differents reservoirs') 
    937 echo ( f'SRF_mas_watveg_beg   = {SRF_mas_watveg_beg :12.6e} kg | SRF_mas_watveg_end   = {SRF_mas_watveg_end :12.6e} kg ' ) 
    938 echo ( f'SRF_mas_watsoil_beg  = {SRF_mas_watsoil_beg:12.6e} kg | SRF_mas_watsoil_end  = {SRF_mas_watsoil_end:12.6e} kg ' ) 
    939 echo ( f'SRF_mas_snow_beg     = {SRF_mas_snow_beg   :12.6e} kg | SRF_mas_snow_end     = {SRF_mas_snow_end   :12.6e} kg ' ) 
    940  
    941 echo ( 'dMass (watveg)  = {:12.3e} kg | {:12.2e} Sv | {:12.2e} m '.format (dSRF_mas_watveg , dSRF_mas_watveg /dtime_sec*1E-9, dSRF_mas_watveg /OCE_aire_tot*1E-3) ) 
    942 echo ( 'dMass (watsoil) = {:12.3e} kg | {:12.2e} Sv | {:12.2e} m '.format (dSRF_mas_watsoil, dSRF_mas_watsoil/dtime_sec*1E-9, dSRF_mas_watsoil/OCE_aire_tot*1E-3) ) 
    943 echo ( 'dMass (sno)     = {:12.3e} kg | {:12.2e} Sv | {:12.2e} m '.format (dSRF_mas_snow   , dSRF_mas_snow   /dtime_sec*1E-9, dSRF_mas_snow   /OCE_aire_tot*1E-3  ) ) 
    944  
    945 SRF_mas_wat_beg = SRF_mas_watveg_beg + SRF_mas_watsoil_beg + SRF_mas_snow_beg  
    946 SRF_mas_wat_end = SRF_mas_watveg_end + SRF_mas_watsoil_end + SRF_mas_snow_end 
    947 dSRF_mas_wat = SRF_mas_wat_end - SRF_mas_wat_beg 
    948  
    949 echo ( '\nWater content in surface ' ) 
    950 echo ( 'SRF_mas_wat_beg  = {:12.6e} kg | SRF_mas_wat_end  = {:12.6e} kg '.format (SRF_mas_wat_beg, SRF_mas_wat_end) ) 
    951 echo ( 'dMass (water srf) = {:12.3e} kg '.format (dSRF_mas_wat) ) 
    952 echo ( 'dMass (water srf) = {:12.3e} Sv '.format (dSRF_mas_wat/dtime_sec*1E-6/ATM_rho) ) 
    953 echo ( 'dMass (water srf) = {:12.3e} m  '.format (dSRF_mas_wat/ATM_aire_sea_tot/ATM_rho) ) 
    954  
    955 echo ( '\nWater content in  ATM + SRF + RUN ' ) 
    956 echo ( 'mas_wat_beg = {:12.6e} kg | mas_wat_end = {:12.6e} kg '. 
    957            format (DYN_mas_wat_beg + ATM_mas_sno_beg + RUN_mas_wat_beg + SRF_mas_wat_beg, 
    958                    DYN_mas_wat_end + ATM_mas_sno_end + RUN_mas_wat_end + SRF_mas_wat_end) ) 
    959 echo ( 'dMass (water atm+srf+run) = {:12.6e} kg '.format ( dDYN_mas_wat + dATM_mas_sno + dRUN_mas_wat + dSRF_mas_wat) ) 
    960 echo ( 'dMass (water atm+srf+run) = {:12.3e} Sv '.format ((dDYN_mas_wat + dATM_mas_sno + dRUN_mas_wat + dSRF_mas_wat)/dtime_sec*1E-6/ATM_rho) ) 
    961 echo ( 'dMass (water atm+srf+run) = {:12.3e} m  '.format ((dDYN_mas_wat + dATM_mas_sno + dRUN_mas_wat + dSRF_mas_wat)/ATM_aire_sea_tot/ATM_rho) ) 
    962  
    963 echo ( '\n------------------------------------------------------------------------------------' ) 
    964 echo ( '-- Change in all components' ) 
    965 echo ( 'mas_wat_beg = {:12.6e} kg | mas_wat_end = {:12.6e} kg'. 
    966            format (SEA_mas_wat_beg + DYN_mas_wat_beg + ATM_mas_sno_beg + RUN_mas_wat_beg + SRF_mas_wat_beg, 
    967                    SEA_mas_wat_end + DYN_mas_wat_end + ATM_mas_sno_end + RUN_mas_wat_end + SRF_mas_wat_end) ) 
    968 echo ( 'dMass (water CPL)         = {:12.3e} kg '.format ( dSEA_mas_wat + dDYN_mas_wat + dATM_mas_sno + dRUN_mas_wat + dSRF_mas_wat) ) 
    969 echo ( 'dMass (water CPL)         = {:12.3e} Sv '.format ((dSEA_mas_wat + dDYN_mas_wat + dATM_mas_sno + dRUN_mas_wat + dSRF_mas_wat)/dtime_sec*1E-9) ) 
    970 echo ( 'dMass (water CPL)         = {:12.3e} m  '.format ((dSEA_mas_wat + dDYN_mas_wat + dATM_mas_sno + dRUN_mas_wat + dSRF_mas_wat)/OCE_aire_tot*1E-3) ) 
    971  
    972  
     922    ICE_wfxpnd = 0.0 ; ICE_mas_wfxpnd = 0.0 
     923    ICE_wfxsnw_sub = rprec (d_ICE_his['vfxsub'])/86400.*ICE_rho_sno  ; ICE_mas_wfxsnw_sub = OCE_flux_int ( ICE_wfxsnw_sub ) 
     924    ICE_wfxsnw_pre = rprec (d_ICE_his['vfxspr'])/86400.*ICE_rho_sno  ; ICE_mas_wfxsnw_pre = OCE_flux_int ( ICE_wfxsnw_pre     ) 
     925 
     926OCE_wfcorr    = rprec (d_OCE_his['wfcorr']) ; OCE_mas_wfcorr  = OCE_flux_int ( OCE_wfcorr ) 
     927if OCE_relax  : 
     928    # ssr and fwb are included in emp=>empmr but not in emp_oce (outputed by sea-ice) 
     929    OCE_vflx_fwb = rprec (d_OCE_his['vflx_fwb']) ; OCE_mas_vflx_fwb   = OCE_flux_int ( OCE_vflx_fwb ) 
     930    OCE_vflx_ssr = rprec (d_OCE_his['vflx_ssr']) ; OCE_mas_vflx_ssr   = OCE_flux_int ( OCE_vflx_ssr ) 
     931else :  
     932    OCE_fwb = 0.0 ; OCE_mas_fwb = 0.0 
     933    OCE_ssr = 0.0 ; OCE_mas_ssr = 0.0 
     934if OCE_icb : 
     935    OCE_berg_icb    = rprec (d_OCE_his['berg_floating_melt']) ; OCE_mas_berg_icb = OCE_flux_int ( OCE_berg_icb    ) 
     936    OCE_calving_icb = rprec (d_OCE_his['calving_icb']       ) ; OCE_mas_calv_icb = OCE_flux_int ( OCE_calving_icb ) 
     937else : 
     938    OCE_berg_icb = 0. ; OCE_mas_berg_icb = 0. 
     939    OCE_calv_icb = 0. ; OCE_mas_calv_icb = 0. 
     940 
     941OCE_mas_emp = OCE_mas_emp_oce - OCE_mas_wfxice  - OCE_mas_wfxsnw  - ICE_mas_wfxpnd - ICE_mas_wfxsub_err 
     942OCE_mas_all = OCE_mas_emp_oce + OCE_mas_emp_ice - OCE_mas_runoffs - OCE_mas_iceshelf 
     943 
     944prtFlux ('OCE+ICE budget ', OCE_mas_all       , 'e', True) 
     945prtFlux ('  EMPMR        ', OCE_mas_empmr     , 'e', True) 
     946prtFlux ('  WFOB         ', OCE_mas_wfob      , 'e', True) 
     947prtFlux ('  EMP_OCE      ', OCE_mas_emp_oce   , 'e', True) 
     948prtFlux ('  EMP_ICE      ', OCE_mas_emp_ice   , 'e', True) 
     949prtFlux ('  EMP          ', OCE_mas_emp       , 'e', True) 
     950prtFlux ('  ICEBERG      ', OCE_mas_iceberg   , 'e',     ) 
     951prtFlux ('  ICESHELF     ', OCE_mas_iceshelf  , 'e', True) 
     952prtFlux ('  CALVING      ', OCE_mas_calving   , 'e', True) 
     953prtFlux ('  FRIVER       ', OCE_mas_friver    , 'e',     )   
     954prtFlux ('  RUNOFFS      ', OCE_mas_runoffs   , 'e', True) 
     955prtFlux ('  WFXICE       ', OCE_mas_wfxice    , 'e', True) 
     956prtFlux ('  WFXSNW       ', OCE_mas_wfxsnw    , 'e', True) 
     957prtFlux ('  WFXSUB       ', OCE_mas_wfxsub    , 'e', True) 
     958prtFlux ('  WFXPND       ', ICE_mas_wfxpnd    , 'e', True) 
     959prtFlux ('  WFXSNW_SUB   ', ICE_mas_wfxsnw_sub, 'e', True) 
     960prtFlux ('  WFXSNW_PRE   ', ICE_mas_wfxsnw_pre, 'e', True) 
     961prtFlux ('  WFXSUB_ERR   ', ICE_mas_wfxsub_err, 'e', True) 
     962prtFlux ('  EVAP_OCE     ', OCE_mas_evap_oce  , 'e'      ) 
     963prtFlux ('  EVAP_ICE     ', ICE_mas_evap_ice  , 'e', True) 
     964prtFlux ('  SNOW_OCE     ', OCE_mas_snow_oce  , 'e', True) 
     965prtFlux ('  SNOW_ICE     ', OCE_mas_snow_ice  , 'e', True) 
     966prtFlux ('  RAIN         ', OCE_mas_rain      , 'e'      ) 
     967prtFlux ('  FWB          ', OCE_mas_fwb       , 'e', True) 
     968prtFlux ('  SSR          ', OCE_mas_ssr       , 'e', True) 
     969prtFlux ('  WFCORR       ', OCE_mas_wfcorr    , 'e', True) 
     970prtFlux ('  BERG_ICB     ', OCE_mas_berg_icb  , 'e', True) 
     971prtFlux ('  CALV_ICB     ', OCE_mas_calv_icb  , 'e', True) 
     972 
     973 
     974echo (' ') 
     975 
     976prtFlux ( 'wbilo sea  ', ATM_flux_int (ATM_wbilo_sea), 'e',   ) 
     977prtFlux ( 'costalflow ', ONE_flux_int (RUN_coastalflow), 'e',   ) 
     978prtFlux ( 'riverflow  ', RUN_flx_river  , 'e',   ) 
     979prtFlux ( 'costalflow ', RUN_flx_coastal, 'e',   ) 
     980prtFlux ( 'runoff     ', RUN_flx_river+RUN_flx_coastal, 'e',   ) 
     981 
     982ATM_to_OCE   =  ATM_flux_int (ATM_wbilo_sea) - RUN_flx_river - RUN_flx_coastal - ATM_flx_calving 
     983#OCE_from_ATM = -OCE_mas_emp_oce - OCE_mas_emp_ice + OCE_mas_runoffs + OCE_mas_iceberg + OCE_mas_calving + OCE_mas_iceshelf 
     984OCE_from_ATM = OCE_mas_all 
     985 
     986prtFlux ( 'ATM_to_OCE  ', ATM_to_OCE  , 'e', True ) 
     987prtFlux ( 'OCE_from_ATM', OCE_from_ATM, 'e', True ) 
  • TOOLS/WATER_BUDGET/OCE_waterbudget.py

    r6620 r6647  
    3939import nemo, lmdz 
    4040 
     41from WaterUtils import VarInt, Rho, Ra, Grav, ICE_rho_ice, ICE_rho_sno, OCE_rho_liq, ATM_rho, SRF_rho, RUN_rho, ICE_rho_pnd, YearLength 
     42 
    4143## Creates parser for reading .ini input file 
    4244## ------------------------------------------- 
     
    4749## --------------------- 
    4850ATM=None ; ATM_HIS='latlon' ; SRF_HIS='latlon' ; RUN_HIS='latlon' ; ORCA=None ; NEMO=None ; OCE_relax=False 
    49 OCE_icb=False ; Coupled=False ; Routing=None 
     51OCE_icb=False ; Coupled=False ; Routing=None ; TestInterp=None 
    5052TarRestartPeriod_beg=None ; TarRestartPeriod_end=None ; Comment=None ; Period=None ; Title=None 
     53YearBegin=None ; YearEnd=None ; DateBegin=None ; DateEnd=None 
    5154 
    5255## 
     
    6669tar_restart_end_RUN=None ; tar_restart_end_OCE=None ; tar_restart_end_ICE=None 
    6770ContinueOnError=False ; ErrorCount=0 ; SortIco = False 
     71 
     72## 
     73## Precision of history file reading 
     74## --------------------------------- 
     75# Default is float (full precision). Degrade the precision by using np.float32 
     76# Restart file are always read at the full precision 
     77readPrec=float 
    6878 
    6979## Read command line arguments 
     
    137147 
    138148print ( f'\nConfig file readed : {IniFile} ' ) 
    139              
     149 
     150## 
     151## Reading prec 
     152if wu.unDefined ( 'readPrec' )  : 
     153    readPrec = np.float64 
     154else : 
     155    if readPrec in ["float", "float64", "r8", "double", "<class 'float'>"         ] : readPrec = float 
     156    if readPrec in [         "float32", "r4", "single", "<class 'numpy.float32'>" ] : readPrec = np.float32 
     157    if readPrec in [         "float16", "r2", "half"  , "<class 'numpy.float16'>" ] : readPrec = np.float16 
     158               
    140159## Some physical constants 
    141160## ======================= 
     
    155174if not 'Files' in config.keys () : config['Files'] = {} 
    156175 
    157 config['Physics'] = { 'Ra':Ra, 'Grav':Grav, 'ICE_rho_ice':ICE_rho_ice, 'ICE_rho_sno':ICE_rho_sno, 
    158                       'OCE_rho_liq':OCE_rho_liq, 'ATM_rho':ATM_rho, 'SRF_rho':SRF_rho, 'RUN_rho':RUN_rho} 
    159  
    160 config['Config'] = { 'ContinueOnError':ContinueOnError, 'SortIco':SortIco } 
     176config['Physics'] = { 'Ra':str(Ra), 'Grav':str(Grav), 'ICE_rho_ice':str(ICE_rho_ice), 'ICE_rho_sno':str(ICE_rho_sno), 
     177                      'OCE_rho_liq':str(OCE_rho_liq), 'ATM_rho':str(ATM_rho), 'SRF_rho':str(SRF_rho), 'RUN_rho':str(RUN_rho)} 
     178 
     179config['Config'] = { 'ContinueOnError':ContinueOnError, 'SortIco':SortIco, 'TestInterp':str(TestInterp), 'readPrec':str(readPrec) } 
    161180 
    162181## -------------------------- 
     
    178197    config['Experiment']['DateBegin'] = DateBegin 
    179198else : 
    180     YearBegin, MonthBegin, DayBegin = wu.DateSplit ( DateBegin ) 
     199    YearBegin, MonthBegin, DayBegin = wu.SplitDate ( DateBegin ) 
    181200    DateBegin = wu.FormatToGregorian ( DateBegin) 
    182     config['Experiment']['YearBegin'] = YearBegin 
     201    config['Experiment']['YearBegin'] = str(YearBegin) 
    183202 
    184203if wu.unDefined ( 'DateEnd' )   : 
    185204    DateEnd   = f'{YearEnd}1231' 
    186     config['Experiment']['DateEnd']   = DateEnd 
     205    config['Experiment']['DateEnd']   = str(DateEnd) 
    187206else : 
    188     YearEnd, MonthEnd, DayEnd = wu.DateSplit ( DateEnd ) 
     207    YearEnd, MonthEnd, DayEnd = wu.SplitDate ( DateEnd ) 
    189208    DateEnd   = wu.FormatToGregorian ( DateEnd) 
     209    config['Experiment']['DateEnd']   = str(DateEnd) 
    190210 
    191211if wu.unDefined ( 'PackFrequency' ) : 
     
    204224## Output file with water budget diagnostics 
    205225## ----------------------------------------- 
    206 if wu.unDefined ( 'FileOut' ) : FileOut = f'ATM_waterbudget_{JobName}_{DateBegin}_{DateEnd}.out' 
    207 config['Files']['FileOut'] = FileOut 
     226if wu.unDefined ( 'FileOut' ) : 
     227    FileOut = f'OCE_waterbudget_{JobName}_{YearBegin}_{YearEnd}' 
     228    if readPrec == np.float32 : FileOut = f'{FileOut}_float32' 
     229    FileOut = f'{FileOut}.out' 
     230 
     231    config['Files']['FileOut'] = FileOut 
    208232 
    209233f_out = open ( FileOut, mode = 'w' ) 
     
    211235## Useful functions 
    212236## ---------------- 
    213 def kg2Sv  (val, rho=OCE_rho_liq) : 
     237 
     238# Degrades precision  
     239if readPrec == float : 
     240    def rprec (tab) : return tab 
     241else :  
     242    def rprec (tab) : return tab.astype(readPrec).astype(float) 
     243         
     244def kg2Sv  (val, rho=ATM_rho) : 
    214245    '''From kg to Sverdrup''' 
    215246    return val/dtime_sec*1.0e-6/rho 
    216247 
    217 def kg2myear (val, rho=OCE_rho_liq) : 
     248def kg2myear (val, rho=ATM_rho) : 
    218249    '''From kg to m/year''' 
    219250    return val/OCE_aire_tot/rho/NbYear 
    220251 
    221 def var2prt (var, small=False, rho=OCE_rho_liq) : 
     252def var2prt (var, small=False, rho=ATM_rho) : 
    222253    if small :  return var , kg2Sv(var, rho=rho)*1000., kg2myear(var, rho=rho)*1000. 
    223254    else     :  return var , kg2Sv(var, rho=rho)      , kg2myear(var, rho=rho) 
    224255 
    225 def prtFlux (Desc, var, Form='F', small=False, rho=OCE_rho_liq, width=15) : 
     256def prtFlux (Desc, var, Form='F', small=False, rho=ATM_rho, width=15) : 
    226257    if small : 
    227258        if Form in ['f', 'F'] : ff=" {:14.6e} kg | {:12.4f} mSv | {:12.4f} mm/year " 
     
    330361if NEMO == 3.6 :d_ICE_his = d_ICE_his.rename ( {'y_grid_T':'y', 'x_grid_T':'x'} ) 
    331362 
    332 echo ( file_OCE_his ) 
    333 echo ( file_OCE_sca ) 
    334 echo ( file_ICE_his ) 
     363echo ( f'{file_OCE_his = }' ) 
     364echo ( f'{file_OCE_sca = }' ) 
     365echo ( f'{file_ICE_his = }' ) 
    335366 
    336367## Compute run length 
     
    666697 
    667698# Read variable and computes integral over space and time 
    668 OCE_empmr      = d_OCE_his['wfo']         ; OCE_mas_empmr    = OCE_flux_int ( OCE_empmr    ) 
    669 OCE_wfob       = d_OCE_his['wfob']        ; OCE_mas_wfob     = OCE_flux_int ( OCE_wfob     ) 
    670 OCE_emp_oce    = d_OCE_his['emp_oce']     ; OCE_mas_emp_oce  = OCE_flux_int ( OCE_emp_oce  ) 
    671 OCE_emp_ice    = d_OCE_his['emp_ice']     ; OCE_mas_emp_ice  = OCE_flux_int ( OCE_emp_ice  ) 
    672 OCE_iceshelf   = d_OCE_his['iceshelf']    ; OCE_mas_iceshelf = OCE_flux_int ( OCE_iceshelf ) 
    673 OCE_calving    = d_OCE_his['calving']     ; OCE_mas_calving  = OCE_flux_int ( OCE_calving  ) 
    674 OCE_iceberg    = d_OCE_his['iceberg']     ; OCE_mas_iceberg  = OCE_flux_int ( OCE_iceberg  ) 
    675 OCE_friver     = d_OCE_his['friver']      ; OCE_mas_friver   = OCE_flux_int ( OCE_friver   ) 
    676 OCE_runoffs    = d_OCE_his['runoffs']     ; OCE_mas_runoffs  = OCE_flux_int ( OCE_runoffs  ) 
     699OCE_empmr      = rprec (d_OCE_his['wfo']     )    ; OCE_mas_empmr    = OCE_flux_int ( OCE_empmr    ) 
     700OCE_wfob       = rprec (d_OCE_his['wfob']    )    ; OCE_mas_wfob     = OCE_flux_int ( OCE_wfob     ) 
     701OCE_emp_oce    = rprec (d_OCE_his['emp_oce'] )    ; OCE_mas_emp_oce  = OCE_flux_int ( OCE_emp_oce  ) 
     702OCE_emp_ice    = rprec (d_OCE_his['emp_ice'] )    ; OCE_mas_emp_ice  = OCE_flux_int ( OCE_emp_ice  ) 
     703OCE_iceshelf   = rprec (d_OCE_his['iceshelf'])    ; OCE_mas_iceshelf = OCE_flux_int ( OCE_iceshelf ) 
     704OCE_calving    = rprec (d_OCE_his['calving'] )    ; OCE_mas_calving  = OCE_flux_int ( OCE_calving  ) 
     705OCE_iceberg    = rprec (d_OCE_his['iceberg'] )    ; OCE_mas_iceberg  = OCE_flux_int ( OCE_iceberg  ) 
     706OCE_friver     = rprec (d_OCE_his['friver']  )    ; OCE_mas_friver   = OCE_flux_int ( OCE_friver   ) 
     707OCE_runoffs    = rprec (d_OCE_his['runoffs'] )    ; OCE_mas_runoffs  = OCE_flux_int ( OCE_runoffs  ) 
    677708if NEMO == 4.0 or NEMO == 4.2 : 
    678     OCE_wfxice     = d_OCE_his['vfxice'] ; OCE_mas_wfxice   = OCE_flux_int ( OCE_wfxice ) 
    679     OCE_wfxsnw     = d_OCE_his['vfxsnw'] ; OCE_mas_wfxsnw   = OCE_flux_int ( OCE_wfxsnw ) 
    680     OCE_wfxsub     = d_OCE_his['vfxsub'] ; OCE_mas_wfxsub   = OCE_flux_int ( OCE_wfxsub ) 
     709    OCE_wfxice     = rprec (d_OCE_his['vfxice']) ; OCE_mas_wfxice   = OCE_flux_int ( OCE_wfxice ) 
     710    OCE_wfxsnw     = rprec (d_OCE_his['vfxsnw']) ; OCE_mas_wfxsnw   = OCE_flux_int ( OCE_wfxsnw ) 
     711    OCE_wfxsub     = rprec (d_OCE_his['vfxsub']) ; OCE_mas_wfxsub   = OCE_flux_int ( OCE_wfxsub ) 
    681712if NEMO == 3.6 : 
    682     OCE_wfxice     = d_OCE_his['vfxice']/86400.*ICE_rho_ice ; OCE_mas_wfxice   = OCE_flux_int ( OCE_wfxice ) 
    683     OCE_wfxsnw     = d_OCE_his['vfxsnw']/86400.*ICE_rho_sno ; OCE_mas_wfxsnw   = OCE_flux_int ( OCE_wfxsnw ) 
    684     OCE_wfxsub     = d_OCE_his['vfxsub']/86400.*ICE_rho_sno ; OCE_mas_wfxsub   = OCE_flux_int ( OCE_wfxsub ) 
     713    OCE_wfxice     = rprec (d_OCE_his['vfxice'])/86400.*ICE_rho_ice ; OCE_mas_wfxice   = OCE_flux_int ( OCE_wfxice ) 
     714    OCE_wfxsnw     = rprec (d_OCE_his['vfxsnw'])/86400.*ICE_rho_sno ; OCE_mas_wfxsnw   = OCE_flux_int ( OCE_wfxsnw ) 
     715    OCE_wfxsub     = rprec (d_OCE_his['vfxsub'])/86400.*ICE_rho_sno ; OCE_mas_wfxsub   = OCE_flux_int ( OCE_wfxsub ) 
    685716# Additional checks 
    686 OCE_evap_oce   = d_OCE_his['evap_ao_cea'] ; OCE_mas_evap_oce   = OCE_flux_int ( OCE_evap_oce ) 
    687 ICE_evap_ice   = d_OCE_his['subl_ai_cea'] ; ICE_mas_evap_ice   = OCE_flux_int ( ICE_evap_ice ) 
    688 OCE_snow_oce   = d_OCE_his['snow_ao_cea'] ; OCE_mas_snow_oce   = OCE_flux_int ( OCE_snow_oce ) 
    689 OCE_snow_ice   = d_OCE_his['snow_ai_cea'] ; OCE_mas_snow_ice   = OCE_flux_int ( OCE_snow_ice ) 
    690 OCE_rain       = d_OCE_his['rain']        ; OCE_mas_rain       = OCE_flux_int ( OCE_rain     ) 
    691 ICE_wfxsub_err = d_ICE_his['vfxsub_err'] ; ICE_mas_wfxsub_err = OCE_flux_int ( ICE_wfxsub_err ) 
     717OCE_evap_oce   = rprec (d_OCE_his['evap_ao_cea']) ; OCE_mas_evap_oce   = OCE_flux_int ( OCE_evap_oce ) 
     718ICE_evap_ice   = rprec (d_OCE_his['subl_ai_cea']) ; ICE_mas_evap_ice   = OCE_flux_int ( ICE_evap_ice ) 
     719OCE_snow_oce   = rprec (d_OCE_his['snow_ao_cea']) ; OCE_mas_snow_oce   = OCE_flux_int ( OCE_snow_oce ) 
     720OCE_snow_ice   = rprec (d_OCE_his['snow_ai_cea']) ; OCE_mas_snow_ice   = OCE_flux_int ( OCE_snow_ice ) 
     721OCE_rain       = rprec (d_OCE_his['rain']       ) ; OCE_mas_rain       = OCE_flux_int ( OCE_rain     ) 
     722ICE_wfxsub_err = rprec (d_ICE_his['vfxsub_err'] ) ; ICE_mas_wfxsub_err = OCE_flux_int ( ICE_wfxsub_err ) 
    692723if NEMO == 4.0 or NEMO == 4.2 : 
    693     ICE_wfxpnd     = d_ICE_his['vfxpnd']    ; ICE_mas_wfxpnd     = OCE_flux_int ( ICE_wfxpnd     ) 
    694     ICE_wfxsnw_sub = d_ICE_his['vfxsnw_sub'] ; ICE_mas_wfxsnw_sub = OCE_flux_int ( ICE_wfxsnw_sub ) 
    695     ICE_wfxsnw_pre = d_ICE_his['vfxsnw_pre'] ; ICE_mas_wfxsnw_pre = OCE_flux_int ( ICE_wfxsnw_pre ) 
     724    ICE_wfxpnd     = rprec (d_ICE_his['vfxpnd']    ) ; ICE_mas_wfxpnd     = OCE_flux_int ( ICE_wfxpnd     ) 
     725    ICE_wfxsnw_sub = rprec (d_ICE_his['vfxsnw_sub']) ; ICE_mas_wfxsnw_sub = OCE_flux_int ( ICE_wfxsnw_sub ) 
     726    ICE_wfxsnw_pre = rprec (d_ICE_his['vfxsnw_pre']) ; ICE_mas_wfxsnw_pre = OCE_flux_int ( ICE_wfxsnw_pre ) 
    696727if NEMO == 3.6 : 
    697728    ICE_wfxpnd = 0.0 ; ICE_mas_wfxpnd = 0.0 
    698     ICE_wfxsnw_sub = d_ICE_his['vfxsub']/86400.*ICE_rho_sno  ; ICE_mas_wfxsnw_sub = OCE_flux_int ( ICE_wfxsnw_sub ) 
    699     ICE_wfxsnw_pre = d_ICE_his['vfxspr']/86400.*ICE_rho_sno  ; ICE_mas_wfxsnw_pre = OCE_flux_int ( ICE_wfxsnw_pre     ) 
    700  
    701 OCE_wfcorr    = d_OCE_his['wfcorr'] ; OCE_mas_wfcorr  = OCE_flux_int ( OCE_wfcorr ) 
     729    ICE_wfxsnw_sub = rprec (d_ICE_his['vfxsub'])/86400.*ICE_rho_sno  ; ICE_mas_wfxsnw_sub = OCE_flux_int ( ICE_wfxsnw_sub ) 
     730    ICE_wfxsnw_pre = rprec (d_ICE_his['vfxspr'])/86400.*ICE_rho_sno  ; ICE_mas_wfxsnw_pre = OCE_flux_int ( ICE_wfxsnw_pre     ) 
     731 
     732OCE_wfcorr    = rprec (d_OCE_his['wfcorr']) ; OCE_mas_wfcorr  = OCE_flux_int ( OCE_wfcorr ) 
    702733if OCE_relax  : 
    703734    # ssr and fwb are included in emp=>empmr but not in emp_oce (outputed by sea-ice) 
    704     OCE_vflx_fwb = d_OCE_his['vflx_fwb'] ; OCE_mas_vflx_fwb   = OCE_flux_int ( OCE_vflx_fwb ) 
    705     OCE_vflx_ssr = d_OCE_his['vflx_ssr'] ; OCE_mas_vflx_ssr   = OCE_flux_int ( OCE_vflx_ssr ) 
     735    OCE_vflx_fwb = rprec (d_OCE_his['vflx_fwb']) ; OCE_mas_vflx_fwb   = OCE_flux_int ( OCE_vflx_fwb ) 
     736    OCE_vflx_ssr = rprec (d_OCE_his['vflx_ssr']) ; OCE_mas_vflx_ssr   = OCE_flux_int ( OCE_vflx_ssr ) 
    706737else :  
    707738    OCE_fwb = 0.0 ; OCE_mas_fwb = 0.0 
    708739    OCE_ssr = 0.0 ; OCE_mas_ssr = 0.0 
    709740if OCE_icb : 
    710     OCE_berg_icb    = d_OCE_his['berg_floating_melt'] ; OCE_mas_berg_icb = OCE_flux_int ( OCE_berg_icb    ) 
    711     OCE_calving_icb = d_OCE_his['calving_icb']        ; OCE_mas_calv_icb = OCE_flux_int ( OCE_calving_icb ) 
     741    OCE_berg_icb    = rprec (d_OCE_his['berg_floating_melt']) ; OCE_mas_berg_icb = OCE_flux_int ( OCE_berg_icb    ) 
     742    OCE_calving_icb = rprec (d_OCE_his['calving_icb']       ) ; OCE_mas_calv_icb = OCE_flux_int ( OCE_calving_icb ) 
    712743else : 
    713744    OCE_berg_icb = 0. ; OCE_mas_berg_icb = 0. 
     
    715746 
    716747OCE_mas_emp = OCE_mas_emp_oce - OCE_mas_wfxice - OCE_mas_wfxsnw - ICE_mas_wfxpnd - ICE_mas_wfxsub_err 
    717  
    718 OCE_mas_all = OCE_mas_emp_oce +OCE_mas_emp_ice - OCE_mas_runoffs - OCE_mas_iceshelf 
     748OCE_mas_all = OCE_mas_emp_oce + OCE_mas_emp_ice - OCE_mas_runoffs - OCE_mas_iceshelf 
    719749 
    720750echo ('\n-- Fields:' )  
     
    748778prtFlux ('  CALV_ICB     ', OCE_mas_calv_icb  , 'e', True) 
    749779 
     780echo (' ') 
     781if Coupled : 
     782    prtFlux ( 'Bilan ocean :', -OCE_mas_emp_oce - OCE_mas_emp_ice + OCE_mas_runoffs + OCE_mas_iceshelf, 'e', True ) 
     783else : 
     784    prtFlux ( 'Bilan ocean :', -OCE_mas_emp_oce - OCE_mas_emp_ice + OCE_mas_runoffs + OCE_mas_iceberg + OCE_mas_calving + OCE_mas_iceshelf, 'e', True ) 
     785 
     786 
    750787echo     ('\n===>  Comparing ===>' )  
    751788echo     ('  WFX OCE                     = -empmr + iceshelf                                            = {:12.5e} (kg) '.format ( -OCE_mas_empmr + OCE_mas_iceshelf) ) 
     
    770807echo ('                        = (dSEA_mas_wat + emp_oce + emp_ice - runoffs - iceshelf)*/abs(dSEA_mas_wat)      = {:12.1e} (-)  '.format ( (dSEA_mas_wat + OCE_mas_emp_oce + OCE_mas_emp_ice - OCE_mas_runoffs - OCE_mas_iceshelf)/abs(dSEA_mas_wat) ) ) 
    771808 
    772 prtFlux ('   Leak OCE             ', ( dOCE_mas_wat + OCE_mas_empmr - OCE_mas_iceshelf) , 'e' ) 
    773 prtFlux ('   Leak ICE+SNW+PND     ', ( dICE_mas_wat + OCE_mas_emp_ice + OCE_mas_wfxice + OCE_mas_wfxsnw + ICE_mas_wfxpnd + ICE_mas_wfxsub_err ) , 'e' ) 
    774 prtFlux ('   Leak OCE+ICE+SNW+PND ',  ( dSEA_mas_wat + OCE_mas_emp_oce +OCE_mas_emp_ice - OCE_mas_runoffs - OCE_mas_iceshelf ) , 'e' ) 
     809prtFlux ('   Leak OCE             ', ( dOCE_mas_wat + OCE_mas_empmr - OCE_mas_iceshelf) , 'e', True ) 
     810prtFlux ('   Leak ICE+SNW+PND     ', ( dICE_mas_wat + OCE_mas_emp_ice + OCE_mas_wfxice + OCE_mas_wfxsnw + ICE_mas_wfxpnd + ICE_mas_wfxsub_err ) , 'e', True ) 
     811prtFlux ('   Leak OCE+ICE+SNW+PND ',  ( dSEA_mas_wat + OCE_mas_emp_oce +OCE_mas_emp_ice - OCE_mas_runoffs - OCE_mas_iceshelf ) , 'e', True ) 
    775812 
    776813 
  • TOOLS/WATER_BUDGET/WaterUtils.py

    r6620 r6647  
    7070def unDefined (char) : 
    7171    '''True if a variable is not defined, or set to None''' 
    72     if char in locals () : 
    73         if locals()[char] == None : unDefined = True 
     72    if char in globals () : 
     73        if globals()[char] == None : 
     74                unDefined = True 
    7475        else            : unDefined = False 
    7576    else                : unDefined = True 
     
    7980    '''True if a variable is defined and not equal to None''' 
    8081    if char in globals () : 
    81         if globals()[char] == None : Defined = False 
     82        if globals()[char] == None : 
     83                Defined = False 
    8284        else            : Defined = True 
    8385    else                : Defined = False 
  • TOOLS/WATER_BUDGET/lmdz.py

    r6519 r6647  
    2828__Date__     = "$Date$" 
    2929__Revision__ = "$Revision$" 
    30 __Id__       = "$Id: lmdz.py 6508 2023-06-13 10:58:38Z omamce $" 
     30__Id__       = "$Id: $" 
    3131__HeadURL    = "$HeadURL$" 
    3232 
     
    3636except ImportError : pass 
    3737 
    38 #try    : import numba 
    39 #except ImportError : pass 
     38try    : import numba 
     39except ImportError : pass 
    4040 
    4141rpi = np.pi ; rad = np.deg2rad (1.0) ; dar = np.rad2deg (1.0) 
    4242 
    4343 
    44 def __math__ (tab) : 
     44def __mmath__ (tab) : 
    4545    ''' 
    4646    Determines the type of tab : i.e. numpy or xarray 
     
    7171     
    7272    ''' 
    73     math = __math__ (tab) 
     73    math = __mmath__ (tab) 
    7474    if tab.shape[-1] == 1 : extend = tab 
    7575 
     
    9999    return extend 
    100100 
    101 def interp1d (x, xp, yp, zdim='presnivs', verbose=False, method='linear') : 
     101def interp1d (x, xp, yp, zdim='presnivs', units=None, verbose=False, method='linear') : 
    102102    ''' 
    103103    One-dimensionnal interpolation of a multi-dimensionnal field 
     
    118118 
    119119       \!/ xp should be decreasing values along zdim axis \!/ 
    120     '''     
     120    ''' 
    121121    # Get the number of dimension with dim==zdim 
    122122    axis = list(xp.dims).index(zdim) 
     
    128128    # Define the result array 
    129129    in_shape       = np.array (xp.shape) 
    130     if verbose : print ( 'in_shape    : ', in_shape  ) 
     130    if verbose : print ( f'{in_shape=}' ) 
    131131    ou_shape       = np.array (in_shape) 
    132     if verbose : print ( 'ou_shape    : ', ou_shape  ) 
     132    if verbose : print ( f'{ou_shape=}' ) 
    133133    ou_shape[axis] = nk_ou 
    134134     
    135135    in_dims        = list (yp.dims) 
    136     if verbose : print ( 'in_dims     : ', in_dims    ) 
     136    if verbose : print ( f'{in_dims=}' ) 
    137137    ou_dims        = in_dims 
    138     if verbose : print ( 'ou_dims     : ', ou_dims    ) 
     138   
    139139    pdim           = x.dims[0] 
    140140    ou_dims[axis]  = pdim 
    141141 
    142142    new_coords = [] 
    143     for coord in yp.dims : 
    144         if coord == zdim : new_coords.append (x.coords[pdim].values) 
    145         else             : new_coords.append (yp.coords[coord].values) 
     143    for i, dim in enumerate (yp.dims) : 
     144        if dim == zdim : 
     145            ou_dims[i] = x.dims[0] 
     146            if units != None : yp[dim].attrs['units'] = units 
     147            new_coords.append (x             .values) 
     148        else : 
     149            new_coords.append (yp.coords[dim].values) 
    146150    
    147     if verbose : print ( 'new_coords  : ', new_coords ) 
     151    if verbose : 
     152        print ( f'{ou_dims   =}'     ) 
     153        print ( f'{new_coords=}' ) 
    148154         
    149155    ou_tab = xr.DataArray (np.empty (ou_shape), dims=ou_dims, coords=new_coords) 
     
    159165 
    160166    # Optimized (pre-compiled) interpolation loop 
    161     #@numba.jit(nopython=True) 
    162     def __interp (nk_ou, x, xp, yp, result) : 
     167    #@numba.jit (nopython=True) 
     168    def __interp (nk_ou, x, xp, yp) : 
    163169        # Interpolate 
    164         for k in np.arange (nk_ou) : 
    165             # Find index of the just above level 
    166             idk1 = np.minimum ( (x[k]-xp), 0.).argmax (dim=zdim) 
    167             idk2 = idk1 - 1 
    168             idk2 = np.maximum (idk2, 0) 
    169              
    170             x1   = xp[{zdim:idk1}] 
    171             x2   = xp[{zdim:idk2}] 
    172              
    173             dx1  = x[k] - x1 
    174             dx2  = x2   - x[k] 
    175             dx   = x2   - x1 
    176             dx1  = dx1/dx ; dx2 = dx2/dx 
    177              
    178             y1   = yp[{zdim:idk1}] 
    179             y2   = yp[{zdim:idk2}] 
    180              
    181             if 'linear'  in method :  
    182                 result = (dx1*y2 + dx2*y1) 
    183             if 'log'     in method : 
    184                 if yp_min > 0. :  
    185                     result = np.power(y2, dx1) * np.power(y1, dx2) 
    186                 if yp_max < 0. : 
    187                     result = -np.power(-y2, dx1) * np.power(-y1, dx2) 
    188             if 'nearest' in method : 
    189                 result = xr.where ( dx2>=dx1, y1, y2) 
     170        # Find index of the just above level 
     171        idk1 = np.minimum ( (x-xp), 0.).argmax (dim=zdim) 
     172        idk2 = idk1 - 1 
     173        idk2 = np.maximum (idk2, 0) 
     174         
     175        x1   = xp[{zdim:idk1}] 
     176        x2   = xp[{zdim:idk2}] 
     177         
     178        dx1  = x  - x1 
     179        dx2  = x2 - x 
     180        dx   = x2 - x1 
     181        dx1  = dx1/dx ; dx2 = dx2/dx 
     182         
     183        y1   = yp[{zdim:idk1}] 
     184        y2   = yp[{zdim:idk2}] 
     185         
     186        #print ( f'{k=} {idk1=} {idk2=} {x1=} {x2=} {dx=1} {dx2=} {y1=} {y2}' ) 
     187         
     188        if 'linear'  in method :  
     189            result = (dx1*y2 + dx2*y1) 
     190        if 'log'     in method : 
     191            if yp_min > 0. :  
     192                result = np.power(y2, dx1) * np.power(y1, dx2) 
     193            if yp_max < 0. : 
     194                result = -np.power(-y2, dx1) * np.power(-y1, dx2) 
     195        if 'nearest' in method : 
     196            result = xr.where ( dx2>=dx1, y1, y2) 
    190197                 
    191             return result 
    192  
    193         result = __interp  (nk_ou, x, xp, yp, result) 
    194              
     198        return result 
     199 
     200    for k in np.arange (nk_ou) : 
     201        result = __interp  (nk_ou, x[{pdim:k}], xp, yp) 
     202            
    195203        # Put result in the final array 
    196204        ou_tab [{pdim:k}] = result 
     
    198206    return ou_tab.squeeze() 
    199207 
     208def fixed_lon (lon, center_lon=0.0) : 
     209    ''' 
     210    Returns corrected longitudes for nicer plots 
     211 
     212    lon        : longitudes of the grid. At least 1D. 
     213    center_lon : center longitude. Default=0. 
     214 
     215    Designed by Phil Pelson. See https://gist.github.com/pelson/79cf31ef324774c97ae7 
     216    ''' 
     217    mmath = __mmath__ (lon) 
     218     
     219    fixed_lon = lon.copy () 
     220 
     221    fixed_lon = mmath.where (fixed_lon > center_lon+180., fixed_lon-360.0, fixed_lon) 
     222    fixed_lon = mmath.where (fixed_lon < center_lon-180., fixed_lon+360.0, fixed_lon) 
     223     
     224    start = np.argmax (np.abs (np.diff (fixed_lon, axis=-1)) > 180., axis=-1) 
     225    fixed_lon [start+1:] += 360. 
     226 
     227    return fixed_lon 
     228 
    200229def nord2sud (p2D) : 
    201230    ''' 
     
    210239    From 1D (restart type) to 2D 
    211240    ''' 
    212     math = __math__ (p1D) 
     241    math = __mmath__ (p1D) 
    213242 
    214243    # Get the dimensions 
     
    244273    return p2D 
    245274 
    246 def geo2point ( p2D, cumulPoles=False, dim1D='cell', debug=False ) :  
     275def geo2point ( p2D, cumulPoles=False, dim1D='points_physiques' ) :  
    247276    ''' 
    248277    From 2D (lat, lon) to 1D (points_phyiques) 
    249278    ''' 
    250     math = __math__ (p2D) 
     279    math = __mmath__ (p2D) 
    251280    # 
    252281    # Get the dimension 
     
    260289 
    261290    jpn = jpi*(jpj-2) + 2 
    262  
    263     if debug : 
    264         print ( f'{jpi=} {jpj=} {jpn=} {jpt=}' ) 
    265291 
    266292    if jpt == -1 : 
     
    281307    if math == xr : 
    282308        p1D       = xr.DataArray (p1D) 
    283         for attr in p2D.attrs : 
     309        for attr in p2D.attrs :  
    284310            p1D.attrs[attr] = p2D.attrs[attr] 
    285311        p1D       = p1D.rename ( {p1D.dims[0]:p2D.dims[0], p1D.dims[-1]:dim1D} ) 
     
    291317    return p1D 
    292318 
    293 def geo3point ( p3D, cumulPoles=False, dim1D='cell' ) :  
     319def geo3point ( p3D, cumulPoles=False, dim1D='points_physiques' ) :  
    294320    ''' 
    295321    From 3D (lev, lat, lon) to 2D (lev, points_phyiques) 
    296322    ''' 
    297     math = __math__ (p3D) 
     323    math = __mmath__ (p3D) 
    298324    # 
    299325    # Get the dimensions 
  • TOOLS/WATER_BUDGET/nemo.py

    r6519 r6647  
    2222Periodicity and other stuff 
    2323 
     24- Lots of tests for xarray object 
     25- Not much testerd for numpy objects 
     26 
    2427olivier.marti@lsce.ipsl.fr 
    25 ''' 
    2628 
    2729## SVN information 
     
    2931__Date__     = "$Date$" 
    3032__Revision__ = "$Revision$" 
    31 __Id__       = "$Id: nemo.py 6265 2022-11-02 12:45:56Z omamce $" 
     33__Id__       = "$Id: $" 
    3234__HeadURL    = "$HeadURL$" 
     35''' 
    3336 
    3437import numpy as np 
     
    3639except ImportError : pass 
    3740 
    38 try    : import f90nml 
    39 except : pass 
    40  
    41 try : from sklearn.impute import SimpleImputer 
    42 except : pass 
    43  
    44 try    : import numba 
    45 except : pass 
     41#try    : import f90nml 
     42#except : pass 
     43 
     44#try : from sklearn.impute import SimpleImputer 
     45#except : pass 
    4646 
    4747rpi = np.pi ; rad = np.deg2rad (1.0) ; dar = np.rad2deg (1.0) 
     
    6161repsi  = np.finfo (1.0).eps 
    6262 
    63 xList = [ 'x', 'X', 'lon'   , 'longitude' ] 
    64 yList = [ 'y', 'Y', 'lat'   , 'latitude'  ] 
    65 zList = [ 'z', 'Z', 'depth' , ] 
    66 tList = [ 't', 'T', 'time'  , ] 
     63## Default names of dimensions 
     64dim_names = {'x':'xx', 'y':'yy', 'z':'olevel', 't':None} 
     65 
     66## All possibles name of dimensions in Nemo files 
     67xName = [ 'x', 'X', 'X1', 'xx', 'XX', 'x_grid_T', 'x_grid_U', 'x_grid_V', 'x_grid_F', 'x_grid_W', 'lon', 'nav_lon', 'longitude', 'X1', 'x_c', 'x_f', ] 
     68yName = [ 'y', 'Y', 'Y1', 'yy', 'YY', 'y_grid_T', 'y_grid_U', 'y_grid_V', 'y_grid_F', 'y_grid_W', 'lat', 'nav_lat', 'latitude' , 'Y1', 'y_c', 'y_f', ] 
     69zName = [ 'z', 'Z', 'Z1', 'zz', 'ZZ', 'depth', 'tdepth', 'udepth', 'vdepth', 'wdepth', 'fdepth', 'deptht', 'depthu', 'depthv', 'depthw', 'depthf', 'olevel', 'z_c', 'z_f', ] 
     70tName = [ 't', 'T', 'tt', 'TT', 'time', 'time_counter', 'time_centered', ] 
     71 
     72## All possibles name of units of dimensions in Nemo files 
     73xUnit = [ 'degrees_east', ] 
     74yUnit = [ 'degrees_north', ] 
     75zUnit = [ 'm', 'meter', ] 
     76tUnit = [ 'second', 'minute', 'hour', 'day', 'month', 'year', ] 
     77 
     78## All possibles size of dimensions in Orca files 
     79xLength = [ 180, 182, 360, 362 ] 
     80yLength = [ 148, 149, 331, 332 ] 
     81zLength = [31, 75] 
    6782 
    6883## =========================================================================== 
    6984def __mmath__ (tab, default=None) : 
     85    ''' 
     86    Determines the type of tab : xarray or numpy object ? 
     87    ''' 
    7088    mmath = default 
    7189    try    : 
    7290        if type (tab) == xr.core.dataarray.DataArray : mmath = xr 
    73     except : 
    74         pass 
     91    except : pass 
    7592 
    7693    try    : 
    7794        if type (tab) == np.ndarray : mmath = np 
    78     except : 
    79         pass 
     95    except : pass 
    8096             
    8197    return mmath 
    82  
    8398 
    8499def __guessNperio__ (jpj, jpi, nperio=None, out='nperio') : 
     
    99114    ''' 
    100115    Tries to guess the value of nperio (periodicity parameter. See NEMO documentation for details) 
    101      
     116 
    102117    Inputs 
    103118    jpj    : number of latitudes 
     
    105120    nperio : periodicity parameter 
    106121    ''' 
     122    print ( jpi, jpj) 
    107123    if nperio == None : 
    108124        ## Values for NEMO version < 4.2 
    109         if jpj ==  149 and jpi ==  182 : 
     125        if (jpj ==  149 and jpi == 182) or (jpj == None and jpi == 182) or (jpj == 149 or jpi == None) : 
    110126            config = 'ORCA2.3' 
    111127            nperio = 4   # ORCA2. We choose legacy orca2. 
    112128            Iperio = 1 ; Jperio = 0 ; NFold = 1 ; NFtype = 'T' 
    113         if jpj ==  332 and jpi ==  362 : # eORCA1. 
     129        if (jpj == 332 and jpi == 362) or (jpj == None and jpi == 362) or (jpj ==  332 and jpi == None) : # eORCA1. 
    114130            config = 'eORCA1.2' 
    115131            nperio = 6   
     
    125141             
    126142        ## Values for NEMO version >= 4.2. No more halo points 
    127         if jpj == 148 and jpi ==  180 : 
     143        if (jpj == 148 and jpi == 180) or (jpj == None and jpi == 180) or (jpj == 148 and jpi == None) : 
    128144            config = 'ORCA2.4' 
    129145            nperio = 4.2 # ORCA2. We choose legacy orca2. 
    130146            Iperio = 1 ; Jperio = 0 ; NFold = 1 ; NFtype = 'F' 
    131         if jpj == 331  and jpi ==  360 : # eORCA1. 
     147        if (jpj == 331 and jpi == 360) or (jpj == None and jpi == 360) or (jpj == 331 and jpi == None) : # eORCA1. 
    132148            config = 'eORCA1.4' 
    133149            nperio = 6.2 
     
    142158        else : 
    143159            if nperio in nperio_valid_range : 
    144                 print ('nperio set as {:} (deduced from jpj={:d} jpi={:d})'.format (nperio, jpj, jpi)) 
     160                print ( f'nperio set as {nperio} (deduced from {jpj=} and {jpi=})' ) 
    145161            else :  
    146                 raise ValueError ('nperio set as {:} (deduced from jpi={:d}) : nemo.py is not ready for this value'.format (nperio, jpi)) 
     162                raise ValueError ( f'nperio set as {nperio} (deduced from {jpi=} and {jpj=}) : nemo.py is not ready for this value' ) 
    147163 
    148164    if out == 'nperio' : return nperio 
     
    162178    Credits : who is the original author ? 
    163179    ''' 
     180     
    164181    gP = None 
    165182    mmath = __mmath__ (ptab) 
     
    178195            raise Exception ('in nemo module : cd_type not found, and cannot by guessed') 
    179196        else : 
    180             print ('Grid set as', gP, 'deduced from dims ', ptab.dims) 
     197            print ( f'Grid set as {gP} deduced from dims {ptab.dims}' ) 
    181198            return gP 
    182199    else : 
    183200         raise Exception  ('in nemo module : cd_type not found, input is not an xarray data') 
    184201 
     202def get_shape ( ptab ) : 
     203    ''' 
     204    Get shape of ptab :  
     205    shape main contain X, Y, Z or T 
     206    Y is missing for a latitudinal slice 
     207    X is missing for on longitudinal slice 
     208    etc ... 
     209    ''' 
     210     
     211    get_shape = '' 
     212    ix, ax = __findAxis__ (ptab, 'x') 
     213    jy, ay = __findAxis__ (ptab, 'y') 
     214    kz, az = __findAxis__ (ptab, 'z') 
     215    lt, at = __findAxis__ (ptab, 't') 
     216    if ax : get_shape = 'X' 
     217    if ay : get_shape = 'Y' + get_shape 
     218    if az : get_shape = 'Z' + get_shape 
     219    if at : get_shape = 'T' + get_shape 
     220    return get_shape 
     221      
    185222def lbc_diag (nperio) : 
    186223    lperio = nperio ; aperio = False 
     
    190227        lperio = 6 ; aperio = True 
    191228         
    192     return lperio, aperio  
     229    return lperio, aperio 
    193230 
    194231def __findAxis__ (tab, axis='z') : 
    195232    ''' 
    196     Find number and name of the requested axis 
     233    Find order and name of the requested axis 
    197234    ''' 
    198235    mmath = __mmath__ (tab) 
    199236    ix = None ; ax = None 
    200237 
    201     if axis in xList : 
    202         axList = [ 'x', 'X', 
    203                    'lon', 'nav_lon', 'nav_lon_T', 'nav_lon_U', 'nav_lon_V', 'nav_lon_F', 'nav_lon_W', 
    204                    'x_grid_T', 'x_grid_U', 'x_grid_V', 'x_grid_F', 'x_grid_W', 
    205                    'glam', 'glamt', 'glamu', 'glamv', 'glamf', 'glamw' ] 
    206         unList = [ 'degrees_east' ] 
    207     if axis in yList : 
    208         axList = [ 'y', 'Y', 'lat', 
    209                    'nav_lat', 'nav_lat_T', 'nav_lat_U', 'nav_lat_V', 'nav_lat_F', 'nav_lat_W', 
    210                    'y_grid_T', 'y_grid_U', 'y_grid_V', 'y_grid_F', 'y_grid_W', 
    211                    'gphi', 'gphi', 'gphiu', 'gphiv', 'gphif', 'gphiw'] 
    212         unList = [ 'degrees_north' ] 
    213     if axis in zList : 
    214         axList = [ 'z', 'Z', 
    215                    'depth', 'deptht', 'depthu', 'depthv', 'depthf', 'depthw', 
    216                    'olevel' ] 
    217         unList = [ 'm', 'meter' ] 
    218     if axis in tList : 
    219         axList = [ 't', 'T', 'time', 'time_counter' ] 
    220         unList = [ 'second', 'minute', 'hour', 'day', 'month' ] 
     238    if axis in xName : axName = xName ; unList = xUnit ; Length = xLength 
     239    if axis in yName : axName = yName ; unList = yUnit ; Length = yLength 
     240    if axis in zName : axName = zName ; unList = zUnit ; Length = zLength 
     241    if axis in tName : axName = tName ; unList = tUnit ; Length = None 
    221242     
    222243    if mmath == xr : 
    223         for Name in axList : 
     244        for Name in axName : 
    224245            try    : 
    225246                ix = tab.dims.index (Name) 
     
    231252                for name in unList : 
    232253                    if name in tab.coords[dim].attrs['units'] : 
    233                         ix = i 
    234                         ax = dim 
     254                        ix = i ; ax = dim 
    235255    else : 
    236         if axis in xList : ix=-1 
    237         if axis in yList : 
    238             if len(tab.shape) >= 2 : ix=-2 
    239         if axis in zList : 
    240             if len(tab.shape) >= 3 : ix=-3 
    241         if axis in tList : 
    242             if len(tab.shape) >=3  : ix=-3 
    243             if len(tab.shape) >=4  : ix=-4 
     256        #if axis in xName : ix=-1 
     257        #if axis in yName : 
     258        #    if len(tab.shape) >= 2 : ix=-2 
     259        #if axis in zName : 
     260        #    if len(tab.shape) >= 3 : ix=-3 
     261        #if axis in tName : 
     262        #    if len(tab.shape) >=3  : ix=-3 
     263        #    if len(tab.shape) >=4  : ix=-4 
     264 
     265        l_shape = tab.shape 
     266        for nn in np.arange ( len(l_shape)) : 
     267            if l_shape[nn] in Length : ix = nn 
    244268        
    245269    return ix, ax 
    246270 
    247 #@numba.jit(forceobj=True) 
     271def findAxis ( tab, axis= 'z' ) : 
     272  ix, xx = __findAxis__ (tab, axis) 
     273  return xx 
     274 
    248275def fixed_lon (lon, center_lon=0.0) : 
    249276    ''' 
     
    277304    return fixed_lon 
    278305 
    279 #@numba.jit(forceobj=True) 
     306def bounds_clolon ( bounds_lon, lon, rad=False, deg=True) : 
     307    '''Choose closest to lon0 longitude, adding or substacting 360° if needed''' 
     308 
     309    if rad : lon_range = 2.0*np.pi 
     310    if deg : lon_range = 360.0 
     311    bounds_clolon = bounds_lon.copy () 
     312 
     313    bounds_clolon = xr.where ( bounds_clolon < lon-lon_range/2., bounds_clolon+lon_range, bounds_clolon ) 
     314    bounds_clolon = xr.where ( bounds_clolon > lon+lon_range/2., bounds_clolon-lon_range, bounds_clolon ) 
     315 
     316    return bounds_clolon 
     317 
     318def UnifyDims ( dd, udims=dim_names, verbose=False ) : 
     319    ''' 
     320    Rename dimensions to unify them between NEMO versions 
     321    ''' 
     322     
     323    if udims['x'] : 
     324        for xx in xName : 
     325            if xx in dd.dims and xx != udims['x'] : 
     326                if verbose : print ( f"{xx} renamed to {udims['x']}" ) 
     327                dd = dd.rename ( {xx:udims['x']}) 
     328    if udims['y'] : 
     329        for yy in yName : 
     330            if yy in dd.dims and yy != udims['y']  : 
     331                if verbose : print ( f"{yy} renamed to {udims['y']}" ) 
     332                dd = dd.rename ( {yy:udims['y']} ) 
     333    if udims['z'] : 
     334        for zz in zName : 
     335            if zz in dd.dims and zz != udims['z'] : 
     336                if verbose : print ( f"{zz} renamed to {udims['z']}" ) 
     337                dd = dd.rename ( {zz:udims['z']} ) 
     338    if udims['t'] : 
     339        for tt in tName  : 
     340            if tt in dd.dims and tt != udims['t'] : 
     341                if verbose : print ( f"{tt} renamed to {udims['t']}" ) 
     342                dd = dd.rename ( {tt:udims['t']} ) 
     343 
     344    return dd 
     345 
    280346def fill_empty (ztab, sval=np.nan, transpose=False) : 
    281347    ''' 
     
    283349 
    284350    Useful when NEMO has run with no wet points options :  
    285     some parts of the domain, with no ocean points, has no 
    286     lon/lat values 
    287     ''' 
     351    some parts of the domain, with no ocean points, have no 
     352    values 
     353    ''' 
     354    from sklearn.impute import SimpleImputer 
    288355    mmath = __mmath__ (ztab) 
    289356 
     
    302369    return ptab 
    303370 
    304 #@numba.jit(forceobj=True) 
    305371def fill_lonlat (lon, lat, sval=-1) : 
    306372    ''' 
     
    308374 
    309375    Useful when NEMO has run with no wet points options :  
    310     some parts of the domain, with no ocean points, as no 
     376    some parts of the domain, with no ocean points, have no 
    311377    lon/lat values 
    312378    ''' 
     379    from sklearn.impute import SimpleImputer 
    313380    mmath = __mmath__ (lon) 
    314381 
     
    328395    return plon, plat 
    329396 
    330 #@numba.jit(forceobj=True) 
     397def fill_bounds_lonlat (bounds_lon, bounds_lat, sval=-1) : 
     398    ''' 
     399    Fill longitude/latitude bounds values 
     400 
     401    Useful when NEMO has run with no wet points options :  
     402    some parts of the domain, with no ocean points, as no 
     403    lon/lat values 
     404    ''' 
     405    mmath = __mmath__ (bounds_lon) 
     406 
     407    p_bounds_lon = np.empty ( bounds_lon.shape ) 
     408    p_bounds_lat = np.empty ( bounds_lat.shape ) 
     409 
     410    imp = SimpleImputer (missing_values=sval, strategy='mean') 
     411     
     412    for n in np.arange (4) :  
     413        imp.fit (bounds_lon[:,:,n]) 
     414        p_bounds_lon[:,:,n] = imp.transform (bounds_lon[:,:,n]) 
     415        imp.fit (bounds_lat[:,:,n].T) 
     416        p_bounds_lat[:,:,n] = imp.transform (bounds_lat[:,:,n].T).T 
     417         
     418    if mmath == xr : 
     419        p_bounds_lon = xr.DataArray (bounds_lon, dims=bounds_lon.dims, coords=bounds_lon.coords) 
     420        p_bounds_lat = xr.DataArray (bounds_lat, dims=bounds_lat.dims, coords=bounds_lat.coords) 
     421        p_bounds_lon.attrs = bounds_lat.attrs ; p_bounds_lat.attrs = bounds_lat.attrs 
     422         
     423    return p_bounds_lon, p_bounds_lat 
     424 
    331425def jeq (lat) : 
    332426    ''' 
     
    337431    mmath = __mmath__ (lat) 
    338432    ix, ax = __findAxis__ (lat, 'x') 
    339     iy, ay = __findAxis__ (lat, 'y') 
     433    jy, ay = __findAxis__ (lat, 'y') 
    340434 
    341435    if mmath == xr : 
    342         jeq = int ( np.mean ( np.argmin (np.abs (np.float64 (lat)), axis=iy) ) ) 
     436        jeq = int ( np.mean ( np.argmin (np.abs (np.float64 (lat)), axis=jy) ) ) 
    343437    else :  
    344438        jeq = np.argmin (np.abs (np.float64 (lat[...,:, 0]))) 
    345439    return jeq 
    346440 
    347 #@numba.jit(forceobj=True) 
    348441def lon1D (lon, lat=None) : 
    349442    ''' 
     
    354447    ''' 
    355448    mmath = __mmath__ (lon) 
    356     if np.max (lat) != None : 
     449    jpj, jpi  = lon.shape [-2:] 
     450    if np.max (lat) : 
    357451        je    = jeq (lat) 
    358         lon1D = lon.copy() [..., je, :] 
     452        #lon1D = lon.copy() [..., je, :] 
     453        lon0 = lon [..., je, 0].copy() 
     454        dlon = lon [..., je, 1].copy() - lon [..., je, 0].copy() 
     455        lon1D = np.linspace ( start=lon0, stop=lon0+360.+2*dlon, num=jpi ) 
    359456    else : 
    360         jpj, jpi = lon.shape [-2:] 
    361         lon1D    = lon.copy() [..., jpj//3, :] 
    362  
    363     start = np.argmax (np.abs (np.diff (lon1D, axis=-1)) > 180.0, axis=-1) 
    364     lon1D [..., start+1:] += 360 
     457        lon0 = lon [..., jpj//3, 0].copy() 
     458        dlon = lon [..., jpj//3, 1].copy() - lon [..., jpj//3, 0].copy() 
     459        lon1D = np.linspace ( start=lon0, stop=lon0+360.+2*dlon, num=jpi ) 
     460 
     461    #start = np.argmax (np.abs (np.diff (lon1D, axis=-1)) > 180.0, axis=-1) 
     462    #lon1D [..., start+1:] += 360 
    365463 
    366464    if mmath == xr : 
     465        lon1D = xr.DataArray( lon1D, dims=('lon',), coords=(lon1D,)) 
    367466        lon1D.attrs = lon.attrs 
    368         lon1D = lon1D.assign_coords ( {'x':lon1D} ) 
     467        lon1D.attrs['units']         = 'degrees_east' 
     468        lon1D.attrs['standard_name'] = 'longitude' 
     469        lon1D.attrs['long_name :']   = 'Longitude' 
    369470         
    370471    return lon1D 
    371472 
    372 #@numba.jit(forceobj=True) 
    373473def latreg (lat, diff=0.1) : 
    374474    ''' 
     
    381481    if diff == None : 
    382482        dy   = np.float64 (np.mean (np.abs (lat - np.roll (lat,shift=1,axis=-2, roll_coords=False)))) 
     483        print ( f'{dy=}' ) 
    383484        diff = dy/100. 
    384      
     485 
    385486    je     = jeq (lat) 
    386487    jreg   = np.where (lat[...,je:,:].max(axis=-1) - lat[...,je:,:].min(axis=-1)< diff)[-1][-1] + je 
     
    390491    return jreg, latreg 
    391492 
    392 #@numba.jit(forceobj=True) 
    393493def lat1D (lat) : 
    394494    ''' 
     
    403503    je     = jeq (lat) 
    404504    lat_eq = np.float64 (lat[...,je,:].mean(axis=-1)) 
    405        
     505      
    406506    jreg, lat_reg = latreg (lat) 
    407507    lat_ave = np.mean (lat, axis=-1) 
    408508 
     509    #print ( f'{dy=} {jpj=} {je=} {lat_eq=} {jreg=} ' ) 
     510     
    409511    if (np.abs (lat_eq) < dy/100.) : # T, U or W grid 
    410         dys    = (90.-lat_reg) / (jpj-jreg-1)*0.5 
    411         yrange = 90.-dys-lat_reg 
     512        if jpj-1 > jreg : dys = (90.-lat_reg) / (jpj-jreg-1)*0.5 
     513        else            : dys = (90.-lat_reg) / 2.0 
     514        yrange = (90.-dys-lat_reg) 
    412515    else                           :  # V or F grid 
    413         yrange = 90.    -lat_reg 
    414          
    415     lat1D = mmath.where (lat_ave<lat_reg, lat_ave, lat_reg + yrange * (np.arange(jpj)-jreg)/(jpj-jreg-1))    
    416          
     516        yrange = 90.-lat_reg 
     517 
     518    if jpj-1 > jreg : 
     519        lat1D = mmath.where (lat_ave<lat_reg, lat_ave, lat_reg + yrange * (np.arange(jpj)-jreg)/(jpj-jreg-1) ) 
     520    else : 
     521        lat1D = lat_ave 
     522    lat1D[-1] = 90.0 
     523 
    417524    if mmath == xr : 
     525        lat1D = xr.DataArray( lat1D.values, dims=('lat',), coords=(lat1D,)) 
    418526        lat1D.attrs = lat.attrs 
    419         lat1D = lat1D.assign_coords ( {'y':lat1D} ) 
    420  
     527        lat1D.attrs ['units']         = 'degrees_north' 
     528        lat1D.attrs ['standard_name'] = 'latitude' 
     529        lat1D.attrs ['long_name :']   = 'Latitude' 
     530         
    421531    return lat1D 
    422532 
    423 #@numba.jit(forceobj=True) 
    424533def latlon1D (lat, lon) : 
    425534    ''' 
     
    430539    return lat1D (lat),  lon1D (lon, lat) 
    431540 
    432 #@numba.jit(forceobj=True) 
    433541def mask_lonlat (ptab, x0, x1, y0, y1, lon, lat, sval=np.nan) : 
    434542    mmath = __mmath__ (ptab) 
     
    445553    return tab 
    446554 
    447 #@numba.jit(forceobj=True)       
    448555def extend (tab, Lon=False, jplus=25, jpi=None, nperio=4) : 
    449556    ''' 
    450557    Returns extended field eastward to have better plots, and box average crossing the boundary 
    451558    Works only for xarray and numpy data (?) 
     559 
     560    Useful for vertical sections in OCE and ATM. 
    452561 
    453562    tab : field to extend. 
     
    539648    See NEMO documentation for further details 
    540649    ''' 
    541     jpj, jpi = ptab.shape[-2:] 
     650    jpi = None ; jpj = None 
     651    ix, ax = __findAxis__ (ptab, 'x') 
     652    jy, ay = __findAxis__ (ptab, 'y') 
     653    if ax : jpi = ptab.shape[ix] 
     654    if ay : jpj = ptab.shape[jy] 
     655         
    542656    if nperio == None : nperio = __guessNperio__ (jpj, jpi, nperio) 
    543657     
    544658    if nperio not in nperio_valid_range : 
    545         raise Exception ('nperio=', nperio, ' is not in the valid range', nperio_valid_range) 
     659        raise Exception ( f'{nperio=} is not in the valid range {nperio_valid_range}' ) 
    546660 
    547661    return jpj, jpi, nperio 
    548662         
    549 #@numba.jit(forceobj=True) 
    550663def lbc (ptab, nperio=None, cd_type='T', psgn=1.0, nemo_4U_bug=False) : 
    551664    ''' 
     
    559672    ''' 
    560673    jpj, jpi, nperio = lbc_init (ptab, nperio) 
     674    ix, ax = __findAxis__ (ptab, 'x') 
     675    jy, ay = __findAxis__ (ptab, 'y') 
    561676    psgn   = ptab.dtype.type (psgn) 
    562677    mmath = __mmath__ (ptab) 
     
    565680    else           : ztab = ptab.copy () 
    566681         
    567     # 
    568     #> East-West boundary conditions 
    569     # ------------------------------ 
    570     if nperio in [1, 4, 6] : 
     682    if ax :  
     683        # 
     684        #> East-West boundary conditions 
     685        # ------------------------------ 
     686        if nperio in [1, 4, 6] : 
    571687        # ... cyclic 
    572         ztab [..., :,  0] = ztab [..., :, -2] 
    573         ztab [..., :, -1] = ztab [..., :,  1] 
    574     # 
    575     #> North-South boundary conditions 
    576     # -------------------------------- 
    577     if nperio in [3, 4] :  # North fold T-point pivot 
    578         if cd_type in [ 'T', 'W' ] : # T-, W-point 
    579             ztab [..., -1, 1:       ] = psgn * ztab [..., -3, -1:0:-1      ] 
    580             ztab [..., -1, 0        ] = psgn * ztab [..., -3, 2            ] 
    581             ztab [..., -2, jpi//2:  ] = psgn * ztab [..., -2, jpi//2:0:-1  ] 
     688            ztab [...,  0] = ztab [..., -2] 
     689            ztab [..., -1] = ztab [...,  1] 
     690 
     691        if ay :  
     692            # 
     693            #> North-South boundary conditions 
     694            # -------------------------------- 
     695            if nperio in [3, 4] :  # North fold T-point pivot 
     696                if cd_type in [ 'T', 'W' ] : # T-, W-point 
     697                    ztab [..., -1, 1:       ] = psgn * ztab [..., -3, -1:0:-1      ] 
     698                    ztab [..., -1, 0        ] = psgn * ztab [..., -3, 2            ] 
     699                    ztab [..., -2, jpi//2:  ] = psgn * ztab [..., -2, jpi//2:0:-1  ] 
     700                     
     701                if cd_type == 'U' : 
     702                    ztab [..., -1, 0:-1     ] = psgn * ztab [..., -3, -1:0:-1      ]        
     703                    ztab [..., -1,  0       ] = psgn * ztab [..., -3,  1           ] 
     704                    ztab [..., -1, -1       ] = psgn * ztab [..., -3, -2           ] 
     705                     
     706                    if nemo_4U_bug : 
     707                        ztab [..., -2, jpi//2+1:-1] = psgn * ztab [..., -2, jpi//2-2:0:-1] 
     708                        ztab [..., -2, jpi//2-1   ] = psgn * ztab [..., -2, jpi//2       ] 
     709                    else : 
     710                        ztab [..., -2, jpi//2-1:-1] = psgn * ztab [..., -2, jpi//2:0:-1] 
     711                         
     712                if cd_type == 'V' :  
     713                    ztab [..., -2, 1:       ] = psgn * ztab [..., -3, jpi-1:0:-1   ] 
     714                    ztab [..., -1, 1:       ] = psgn * ztab [..., -4, -1:0:-1      ]    
     715                    ztab [..., -1, 0        ] = psgn * ztab [..., -4, 2            ] 
     716                     
     717                if cd_type == 'F' : 
     718                    ztab [..., -2, 0:-1     ] = psgn * ztab [..., -3, -1:0:-1      ] 
     719                    ztab [..., -1, 0:-1     ] = psgn * ztab [..., -4, -1:0:-1      ] 
     720                    ztab [..., -1,  0       ] = psgn * ztab [..., -4,  1           ] 
     721                    ztab [..., -1, -1       ] = psgn * ztab [..., -4, -2           ] 
    582722                 
    583         if cd_type == 'U' : 
    584             ztab [..., -1, 0:-1     ] = psgn * ztab [..., -3, -1:0:-1      ]        
    585             ztab [..., -1,  0       ] = psgn * ztab [..., -3,  1           ] 
    586             ztab [..., -1, -1       ] = psgn * ztab [..., -3, -2           ] 
     723            if nperio in [4.2] :  # North fold T-point pivot 
     724                if cd_type in [ 'T', 'W' ] : # T-, W-point 
     725                    ztab [..., -1, jpi//2:  ] = psgn * ztab [..., -1, jpi//2:0:-1  ] 
     726                     
     727                if cd_type == 'U' : 
     728                    ztab [..., -1, jpi//2-1:-1] = psgn * ztab [..., -1, jpi//2:0:-1] 
     729                     
     730                if cd_type == 'V' :  
     731                    ztab [..., -1, 1:       ] = psgn * ztab [..., -2, jpi-1:0:-1   ] 
     732                     
     733                if cd_type == 'F' : 
     734                    ztab [..., -1, 0:-1     ] = psgn * ztab [..., -2, -1:0:-1      ] 
    587735                 
    588             if nemo_4U_bug : 
    589                 ztab [..., -2, jpi//2+1:-1] = psgn * ztab [..., -2, jpi//2-2:0:-1] 
    590                 ztab [..., -2, jpi//2-1   ] = psgn * ztab [..., -2, jpi//2       ] 
    591             else : 
    592                 ztab [..., -2, jpi//2-1:-1] = psgn * ztab [..., -2, jpi//2:0:-1] 
    593                  
    594         if cd_type == 'V' :  
    595             ztab [..., -2, 1:       ] = psgn * ztab [..., -3, jpi-1:0:-1   ] 
    596             ztab [..., -1, 1:       ] = psgn * ztab [..., -4, -1:0:-1      ]    
    597             ztab [..., -1, 0        ] = psgn * ztab [..., -4, 2            ] 
    598                  
    599         if cd_type == 'F' : 
    600             ztab [..., -2, 0:-1     ] = psgn * ztab [..., -3, -1:0:-1      ] 
    601             ztab [..., -1, 0:-1     ] = psgn * ztab [..., -4, -1:0:-1      ] 
    602             ztab [..., -1,  0       ] = psgn * ztab [..., -4,  1           ] 
    603             ztab [..., -1, -1       ] = psgn * ztab [..., -4, -2           ] 
    604  
    605     if nperio in [4.2] :  # North fold T-point pivot 
    606         if cd_type in [ 'T', 'W' ] : # T-, W-point 
    607             ztab [..., -1, jpi//2:  ] = psgn * ztab [..., -1, jpi//2:0:-1  ] 
    608                  
    609         if cd_type == 'U' : 
    610             ztab [..., -1, jpi//2-1:-1] = psgn * ztab [..., -1, jpi//2:0:-1] 
    611                  
    612         if cd_type == 'V' :  
    613             ztab [..., -1, 1:       ] = psgn * ztab [..., -2, jpi-1:0:-1   ] 
    614                  
    615         if cd_type == 'F' : 
    616             ztab [..., -1, 0:-1     ] = psgn * ztab [..., -2, -1:0:-1      ] 
    617  
    618     if nperio in [5, 6] :            #  North fold F-point pivot   
    619         if cd_type in ['T', 'W']  : 
    620             ztab [..., -1, 0:       ] = psgn * ztab [..., -2, -1::-1       ] 
    621                  
    622         if cd_type == 'U' : 
    623             ztab [..., -1, 0:-1     ] = psgn * ztab [..., -2, -2::-1       ]        
    624             ztab [..., -1, -1       ] = psgn * ztab [..., -2, 0            ] # Bug ? 
    625                  
    626         if cd_type == 'V' : 
    627             ztab [..., -1, 0:       ] = psgn * ztab [..., -3, -1::-1       ] 
    628             ztab [..., -2, jpi//2:  ] = psgn * ztab [..., -2, jpi//2-1::-1 ] 
    629                  
    630         if cd_type == 'F' : 
    631             ztab [..., -1, 0:-1     ] = psgn * ztab [..., -3, -2::-1       ] 
    632             ztab [..., -1, -1       ] = psgn * ztab [..., -3, 0            ] 
    633             ztab [..., -2, jpi//2:-1] = psgn * ztab [..., -2, jpi//2-2::-1 ] 
    634  
    635     # 
    636     #> East-West boundary conditions 
    637     # ------------------------------ 
    638     if nperio in [1, 4, 6] : 
    639         # ... cyclic 
    640         ztab [..., :,  0] = ztab [..., :, -2] 
    641         ztab [..., :, -1] = ztab [..., :,  1] 
     736            if nperio in [5, 6] :            #  North fold F-point pivot   
     737                if cd_type in ['T', 'W']  : 
     738                    ztab [..., -1, 0:       ] = psgn * ztab [..., -2, -1::-1       ] 
     739                     
     740                if cd_type == 'U' : 
     741                    ztab [..., -1, 0:-1     ] = psgn * ztab [..., -2, -2::-1       ]        
     742                    ztab [..., -1, -1       ] = psgn * ztab [..., -2, 0            ] # Bug ? 
     743                     
     744                if cd_type == 'V' : 
     745                    ztab [..., -1, 0:       ] = psgn * ztab [..., -3, -1::-1       ] 
     746                    ztab [..., -2, jpi//2:  ] = psgn * ztab [..., -2, jpi//2-1::-1 ] 
     747                     
     748                if cd_type == 'F' : 
     749                    ztab [..., -1, 0:-1     ] = psgn * ztab [..., -3, -2::-1       ] 
     750                    ztab [..., -1, -1       ] = psgn * ztab [..., -3, 0            ] 
     751                    ztab [..., -2, jpi//2:-1] = psgn * ztab [..., -2, jpi//2-2::-1 ] 
     752                     
     753            # 
     754            #> East-West boundary conditions 
     755            # ------------------------------ 
     756            if nperio in [1, 4, 6] : 
     757                # ... cyclic 
     758                ztab [...,  0] = ztab [..., -2] 
     759                ztab [..., -1] = ztab [...,  1] 
    642760 
    643761    if mmath == xr : 
    644         ztab = xr.DataArray ( ztab, dims=ptab.dims, coords=ptab.coords) 
     762        ztab = xr.DataArray ( ztab, dims=ptab.dims, coords=ptab.coords ) 
    645763        ztab.attrs = ptab.attrs 
    646764         
    647765    return ztab 
    648766 
    649 #@numba.jit(forceobj=True) 
    650767def lbc_mask (ptab, nperio=None, cd_type='T', sval=np.nan) : 
    651768    # 
     
    659776    ''' 
    660777    jpj, jpi, nperio = lbc_init (ptab, nperio) 
     778    ix, ax = __findAxis__ (ptab, 'x') 
     779    jy, ay = __findAxis__ (ptab, 'y') 
    661780    ztab = ptab.copy () 
    662781 
    663     # 
    664     #> East-West boundary conditions 
    665     # ------------------------------ 
    666     if nperio in [1, 4, 6] : 
     782    if ax :  
     783        # 
     784        #> East-West boundary conditions 
     785        # ------------------------------ 
     786        if nperio in [1, 4, 6] : 
    667787        # ... cyclic 
    668         ztab [..., :,  0] = sval 
    669         ztab [..., :, -1] = sval 
    670  
    671     # 
    672     #> South (in which nperio cases ?) 
    673     # -------------------------------- 
    674     if nperio in [1, 3, 4, 5, 6] : 
    675         ztab [..., 0, :] = sval 
    676          
    677     # 
    678     #> North-South boundary conditions 
    679     # -------------------------------- 
    680     if nperio in [3, 4] :  # North fold T-point pivot 
    681         if cd_type in [ 'T', 'W' ] : # T-, W-point 
    682             ztab [..., -1,  :         ] = sval 
    683             ztab [..., -2, :jpi//2  ] = sval 
     788            ztab [...,  0] = sval 
     789            ztab [..., -1] = sval 
     790 
     791        if ay :  
     792            # 
     793            #> South (in which nperio cases ?) 
     794            # -------------------------------- 
     795            if nperio in [1, 3, 4, 5, 6] : 
     796                ztab [..., 0, :] = sval 
     797         
     798            # 
     799            #> North-South boundary conditions 
     800            # -------------------------------- 
     801            if nperio in [3, 4] :  # North fold T-point pivot 
     802                if cd_type in [ 'T', 'W' ] : # T-, W-point 
     803                    ztab [..., -1,  :         ] = sval 
     804                    ztab [..., -2, :jpi//2  ] = sval 
    684805                 
    685         if cd_type == 'U' : 
    686             ztab [..., -1,  :         ] = sval   
    687             ztab [..., -2, jpi//2+1:  ] = sval 
     806                if cd_type == 'U' : 
     807                    ztab [..., -1,  :         ] = sval   
     808                    ztab [..., -2, jpi//2+1:  ] = sval 
    688809                 
    689         if cd_type == 'V' : 
    690             ztab [..., -2, :       ] = sval 
    691             ztab [..., -1, :       ] = sval    
    692                  
    693         if cd_type == 'F' : 
    694             ztab [..., -2, :       ] = sval 
    695             ztab [..., -1, :       ] = sval 
    696  
    697     if nperio in [4.2] :  # North fold T-point pivot 
    698         if cd_type in [ 'T', 'W' ] : # T-, W-point 
    699             ztab [..., -1, jpi//2  :  ] = sval 
    700                  
    701         if cd_type == 'U' : 
    702             ztab [..., -1, jpi//2-1:-1] = sval 
    703                  
    704         if cd_type == 'V' :  
    705             ztab [..., -1, 1:       ] = sval 
    706                  
    707         if cd_type == 'F' : 
    708             ztab [..., -1, 0:-1     ] = sval 
    709      
    710     if nperio in [5, 6] :            #  North fold F-point pivot 
    711         if cd_type in ['T', 'W']  : 
    712             ztab [..., -1, 0:       ] = sval 
    713                  
    714         if cd_type == 'U' : 
    715             ztab [..., -1, 0:-1     ] = sval        
    716             ztab [..., -1, -1       ] = sval 
    717               
    718         if cd_type == 'V' : 
    719             ztab [..., -1, 0:       ] = sval 
    720             ztab [..., -2, jpi//2:  ] = sval 
    721                               
    722         if cd_type == 'F' : 
    723             ztab [..., -1, 0:-1       ] = sval 
    724             ztab [..., -1, -1         ] = sval 
    725             ztab [..., -2, jpi//2+1:-1] = sval 
     810                if cd_type == 'V' : 
     811                    ztab [..., -2, :       ] = sval 
     812                    ztab [..., -1, :       ] = sval    
     813 
     814                if cd_type == 'F' : 
     815                    ztab [..., -2, :       ] = sval 
     816                    ztab [..., -1, :       ] = sval 
     817 
     818            if nperio in [4.2] :  # North fold T-point pivot 
     819                if cd_type in [ 'T', 'W' ] : # T-, W-point 
     820                    ztab [..., -1, jpi//2  :  ] = sval 
     821 
     822                if cd_type == 'U' : 
     823                    ztab [..., -1, jpi//2-1:-1] = sval 
     824 
     825                if cd_type == 'V' :  
     826                    ztab [..., -1, 1:       ] = sval 
     827 
     828                if cd_type == 'F' : 
     829                    ztab [..., -1, 0:-1     ] = sval 
     830 
     831            if nperio in [5, 6] :            #  North fold F-point pivot 
     832                if cd_type in ['T', 'W']  : 
     833                    ztab [..., -1, 0:       ] = sval 
     834 
     835                if cd_type == 'U' : 
     836                    ztab [..., -1, 0:-1     ] = sval        
     837                    ztab [..., -1, -1       ] = sval 
     838 
     839                if cd_type == 'V' : 
     840                    ztab [..., -1, 0:       ] = sval 
     841                    ztab [..., -2, jpi//2:  ] = sval 
     842 
     843                if cd_type == 'F' : 
     844                    ztab [..., -1, 0:-1       ] = sval 
     845                    ztab [..., -1, -1         ] = sval 
     846                    ztab [..., -2, jpi//2+1:-1] = sval 
    726847 
    727848    return ztab 
    728849 
    729 #@numba.jit(forceobj=True) 
    730850def lbc_plot (ptab, nperio=None, cd_type='T', psgn=1.0, sval=np.nan) : 
    731851    ''' 
     
    738858    See NEMO documentation for further details 
    739859    ''' 
    740  
    741860    jpj, jpi, nperio = lbc_init (ptab, nperio) 
     861    ix, ax = __findAxis__ (ptab, 'x') 
     862    jy, ay = __findAxis__ (ptab, 'y') 
    742863    psgn   = ptab.dtype.type (psgn) 
    743864    ztab   = ptab.copy () 
    744     # 
    745     #> East-West boundary conditions 
    746     # ------------------------------ 
    747     if nperio in [1, 4, 6] : 
    748         # ... cyclic 
    749         ztab [..., :,  0] = ztab [..., :, -2] 
    750         ztab [..., :, -1] = ztab [..., :,  1] 
    751  
    752     #> Masks south 
    753     # ------------ 
    754     if nperio in [4, 6] : ztab [..., 0, : ] = sval 
    755          
    756     # 
    757     #> North-South boundary conditions 
    758     # -------------------------------- 
    759     if nperio in [3, 4] :  # North fold T-point pivot 
    760         if cd_type in [ 'T', 'W' ] : # T-, W-point 
    761             ztab [..., -1,  :      ] = sval 
    762             #ztab [..., -2, jpi//2: ] = sval 
    763             ztab [..., -2, :jpi//2 ] = sval # Give better plots than above 
    764         if cd_type == 'U' : 
    765             ztab [..., -1, : ] = sval 
    766  
    767         if cd_type == 'V' :  
    768             ztab [..., -2, : ] = sval 
    769             ztab [..., -1, : ] = sval 
    770              
    771         if cd_type == 'F' : 
    772             ztab [..., -2, : ] = sval 
    773             ztab [..., -1, : ] = sval 
    774  
    775     if nperio in [4.2] :  # North fold T-point pivot 
    776         if cd_type in [ 'T', 'W' ] : # T-, W-point 
    777             ztab [..., -1, jpi//2:  ] = sval 
    778                  
    779         if cd_type == 'U' : 
    780             ztab [..., -1, jpi//2-1:-1] = sval 
    781                  
    782         if cd_type == 'V' :  
    783             ztab [..., -1, 1:       ] = sval 
    784                  
    785         if cd_type == 'F' : 
    786             ztab [..., -1, 0:-1     ] = sval 
    787        
    788     if nperio in [5, 6] :            #  North fold F-point pivot   
    789         if cd_type in ['T', 'W']  : 
    790             ztab [..., -1, : ] = sval 
    791                  
    792         if cd_type == 'U' : 
    793             ztab [..., -1, : ] = sval       
    794               
    795         if cd_type == 'V' : 
    796             ztab [..., -1, :        ] = sval 
    797             ztab [..., -2, jpi//2:  ] = sval 
    798                               
    799         if cd_type == 'F' : 
    800             ztab [..., -1, :          ] = sval 
    801             ztab [..., -2, jpi//2+1:-1] = sval 
     865 
     866    if ax :  
     867        # 
     868        #> East-West boundary conditions 
     869        # ------------------------------ 
     870        if nperio in [1, 4, 6] : 
     871            # ... cyclic 
     872            ztab [..., :,  0] = ztab [..., :, -2] 
     873            ztab [..., :, -1] = ztab [..., :,  1] 
     874 
     875        if ay :  
     876            #> Masks south 
     877            # ------------ 
     878            if nperio in [4, 6] : ztab [..., 0, : ] = sval 
     879 
     880            # 
     881            #> North-South boundary conditions 
     882            # -------------------------------- 
     883            if nperio in [3, 4] :  # North fold T-point pivot 
     884                if cd_type in [ 'T', 'W' ] : # T-, W-point 
     885                    ztab [..., -1,  :      ] = sval 
     886                    #ztab [..., -2, jpi//2: ] = sval 
     887                    ztab [..., -2, :jpi//2 ] = sval # Give better plots than above 
     888                if cd_type == 'U' : 
     889                    ztab [..., -1, : ] = sval 
     890 
     891                if cd_type == 'V' :  
     892                    ztab [..., -2, : ] = sval 
     893                    ztab [..., -1, : ] = sval 
     894 
     895                if cd_type == 'F' : 
     896                    ztab [..., -2, : ] = sval 
     897                    ztab [..., -1, : ] = sval 
     898 
     899            if nperio in [4.2] :  # North fold T-point pivot 
     900                if cd_type in [ 'T', 'W' ] : # T-, W-point 
     901                    ztab [..., -1, jpi//2:  ] = sval 
     902 
     903                if cd_type == 'U' : 
     904                    ztab [..., -1, jpi//2-1:-1] = sval 
     905 
     906                if cd_type == 'V' :  
     907                    ztab [..., -1, 1:       ] = sval 
     908 
     909                if cd_type == 'F' : 
     910                    ztab [..., -1, 0:-1     ] = sval 
     911 
     912            if nperio in [5, 6] :            #  North fold F-point pivot   
     913                if cd_type in ['T', 'W']  : 
     914                    ztab [..., -1, : ] = sval 
     915 
     916                if cd_type == 'U' : 
     917                    ztab [..., -1, : ] = sval       
     918 
     919                if cd_type == 'V' : 
     920                    ztab [..., -1, :        ] = sval 
     921                    ztab [..., -2, jpi//2:  ] = sval 
     922 
     923                if cd_type == 'F' : 
     924                    ztab [..., -1, :          ] = sval 
     925                    ztab [..., -2, jpi//2+1:-1] = sval 
    802926 
    803927    return ztab 
    804928 
    805 #@numba.jit(forceobj=True) 
    806929def lbc_add (ptab, nperio=None, cd_type=None, psgn=1, sval=None) : 
    807930    ''' 
    808     Handle NEMO domain changes between NEMO 4.0 to NEMO 4.2 
     931    Handles NEMO domain changes between NEMO 4.0 to NEMO 4.2 
    809932      Peridodicity halo has been removed 
    810933    This routine adds the halos if needed 
     
    818941    mmath = __mmath__ (ptab)  
    819942    jpj, jpi, nperio = lbc_init (ptab, nperio) 
     943    lshape = get_shape (ptab) 
     944    ix, ax = __findAxis__ (ptab, 'x') 
     945    jy, ay = __findAxis__ (ptab, 'y') 
    820946 
    821947    t_shape = np.array (ptab.shape) 
     
    823949    if nperio == 4.2 or nperio == 6.2 : 
    824950       
    825         ext_shape = t_shape 
    826         ext_shape[-1] = ext_shape[-1] + 2 
    827         ext_shape[-2] = ext_shape[-2] + 1 
     951        ext_shape = t_shape.copy() 
     952        if 'X' in lshape : ext_shape[ix] = ext_shape[ix] + 2 
     953        if 'Y' in lshape : ext_shape[jy] = ext_shape[jy] + 1 
    828954 
    829955        if mmath == xr : 
    830             ptab_ext = xr.DataArray (np.zeros (ext_shape), dims=ptab.dims)  
    831             ptab_ext.values[..., :-1, 1:-1] = ptab.values.copy () 
     956            ptab_ext = xr.DataArray (np.zeros (ext_shape), dims=ptab.dims) 
     957            if 'X' in lshape and 'Y' in lshape : 
     958                ptab_ext.values[..., :-1, 1:-1] = ptab.values.copy () 
     959            else : 
     960                if 'X' in lshape     : ptab_ext.values[...,      1:-1] = ptab.values.copy () 
     961                if 'Y' in lshape     : ptab_ext.values[..., :-1      ] = ptab.values.copy () 
    832962        else           : 
    833963            ptab_ext =               np.zeros (ext_shape) 
    834             ptab_ext[..., :-1, 1:-1] = ptab.copy () 
    835              
    836         #if sval != None :  ptab_ext[..., 0, :] = sval 
    837          
     964            if 'X' in lshape and 'Y' in lshape : ptab_ext       [..., :-1, 1:-1] = ptab.copy () 
     965            else : 
     966                if 'X' in lshape     : ptab_ext       [...,      1:-1] = ptab.copy () 
     967                if 'Y' in lshape     : ptab_ext       [..., :-1      ] = ptab.copy ()             
     968 
    838969        if nperio == 4.2 : ptab_ext = lbc (ptab_ext, nperio=4, cd_type=cd_type, psgn=psgn) 
    839970        if nperio == 6.2 : ptab_ext = lbc (ptab_ext, nperio=6, cd_type=cd_type, psgn=psgn) 
    840               
     971         
    841972        if mmath == xr : 
    842973            ptab_ext.attrs = ptab.attrs 
     974            kz, az = __findAxis__ (ptab, 'z') 
     975            it, at = __findAxis__ (ptab, 't') 
     976            if az : ptab_ext = ptab_ext.assign_coords ( {az:ptab.coords[az]} ) 
     977            if at : ptab_ext = ptab_ext.assign_coords ( {at:ptab.coords[at]} ) 
    843978 
    844979    else : ptab_ext = lbc (ptab, nperio=nperio, cd_type=cd_type, psgn=psgn) 
     
    848983def lbc_del (ptab, nperio=None, cd_type='T', psgn=1) : 
    849984    ''' 
    850     Handle NEMO domain changes between NEMO 4.0 to NEMO 4.2 
     985    Handles NEMO domain changes between NEMO 4.0 to NEMO 4.2 
    851986      Periodicity halo has been removed 
    852987    This routine removes the halos if needed 
     
    858993    See NEMO documentation for further details 
    859994    ''' 
    860  
    861995    jpj, jpi, nperio = lbc_init (ptab, nperio) 
     996    lshape = get_shape (ptab) 
     997    ix, ax = __findAxis__ (ptab, 'x') 
     998    jy, ay = __findAxis__ (ptab, 'y') 
    862999 
    8631000    if nperio == 4.2 or nperio == 6.2 : 
    864         return lbc (ptab[..., :-1, 1:-1], nperio=nperio, cd_type=cd_type, psgn=psgn) 
     1001        if ax or ay :  
     1002            if ax and ay :  
     1003                return lbc (ptab[..., :-1, 1:-1], nperio=nperio, cd_type=cd_type, psgn=psgn) 
     1004            else :  
     1005                if ax : 
     1006                    return lbc (ptab[...,      1:-1], nperio=nperio, cd_type=cd_type, psgn=psgn) 
     1007                if ay : 
     1008                    return lbc (ptab[..., -1], nperio=nperio, cd_type=cd_type, psgn=psgn) 
     1009        else : 
     1010            return ptab 
    8651011    else : 
    8661012        return ptab 
    8671013 
    868 #@numba.jit(forceobj=True) 
    8691014def lbc_index (jj, ii, jpj, jpi, nperio=None, cd_type='T') : 
    8701015    ''' 
     
    9511096    return jy, ix 
    9521097     
    953 #def geo2en (pxx, pyy, pzz, glam, gphi) :  
     1098def findJI (lat_data, lon_data, lat_grid, lon_grid, mask=1.0, verbose=False, out=None) : 
     1099    ''' 
     1100    Description: seeks J,I indices of the grid point which is the closest of a given point  
     1101    Usage: go FindJI  <data latitude> <data longitude> <grid latitudes> <grid longitudes> [mask] 
     1102    <longitude fields> <latitude field> are 2D fields on J/I (Y/X) dimensions 
     1103    mask : if given, seek only non masked grid points (i.e with mask=1) 
     1104     
     1105    Example : findIJ (40, -20, nav_lat, nav_lon, mask=1.0) 
     1106 
     1107    Note : all longitudes and latitudes in degrees 
     1108         
     1109    Note : may work with 1D lon/lat (?) 
     1110    ''' 
     1111    # Get grid dimensions 
     1112    if len (lon_grid.shape) == 2 : (jpj, jpi) = lon_grid.shape 
     1113    else                         : jpj = len(lat_grid) ; jpi=len(lon_grid) 
     1114 
     1115    mmath = __mmath__ (lat_grid) 
     1116         
     1117    # Compute distance from the point to all grid points (in radian) 
     1118    arg      = np.sin (rad*lat_data) * np.sin (rad*lat_grid) \ 
     1119             + np.cos (rad*lat_data) * np.cos (rad*lat_grid) * np.cos(rad*(lon_data-lon_grid)) 
     1120    distance = np.arccos (arg) + 4.0*rpi*(1.0-mask) # Send masked points to 'infinite'  
     1121 
     1122    # Truncates to alleviate some precision problem with some grids 
     1123    prec = int (1E7) 
     1124    distance = (distance*prec).astype(int) / prec 
     1125 
     1126    # Compute minimum of distance, and index of minimum 
     1127    # 
     1128    distance_min = distance.min    () 
     1129    jimin        = int (distance.argmin ()) 
     1130     
     1131    # Compute 2D indices  
     1132    jmin = jimin // jpi ; imin = jimin - jmin*jpi 
     1133     
     1134    # Result 
     1135    if verbose : 
     1136        # Compute distance achieved 
     1137        mindist = distance [jmin, imin] 
     1138         
     1139        # Compute azimuth 
     1140        dlon = lon_data-lon_grid[jmin,imin] 
     1141        arg  = np.sin (rad*dlon) /  (np.cos(rad*lat_data)*np.tan(rad*lat_grid[jmin,imin]) - np.sin(rad*lat_data)*np.cos(rad*dlon)) 
     1142        azimuth = dar*np.arctan (arg) 
     1143        print ( f'I={imin:d} J={jmin:d} - Data:{lat_data:5.1f}°N {lon_data:5.1f}°E - Grid:{lat_grid[jmin,imin]:4.1f}°N '   \ 
     1144            +   f'{lon_grid[jmin,imin]:4.1f}°E - Dist: {ra*distance[jmin,imin]:6.1f}km {dar*distance[jmin,imin]:5.2f}° ' \ 
     1145            +   f'- Azimuth: {rad*azimuth:3.2f}rad - {azimuth:5.1f}°' ) 
     1146 
     1147    if   out=='dict'                               : return {'x':imin, 'y':jmin} 
     1148    elif out=='array' or out=='numpy'  or out=='np': return np.array ( [jmin, imin] ) 
     1149    elif out=='xarray' or out=='xr'                : return xr.DataArray ( [jmin, imin] ) 
     1150    elif out=='list'                               : return [jmin, imin] 
     1151    elif out=='tuple'                              : return jmin, imin 
     1152    else                                           : return jmin, imin 
     1153 
     1154def geo2en (pxx, pyy, pzz, glam, gphi) :  
    9541155    ''' 
    9551156    Change vector from geocentric to east/north 
     
    9701171    return pte, ptn 
    9711172 
    972 #def en2geo (pte, ptn, glam, gphi) : 
     1173def en2geo (pte, ptn, glam, gphi) : 
    9731174    ''' 
    9741175    Change vector from east/north to geocentric 
     
    9901191    return pxx, pyy, pzz 
    9911192 
    992 #def findJI (lat_data, lon_data, lat_grid, lon_grid, mask=1.0, verbose=False) : 
    993     ''' 
    994     Description: seeks J,I indices of the grid point which is the closest of a given point  
    995     Usage: go FindJI  <data latitude> <data longitude> <grid latitudes> <grid longitudes> [mask] 
    996     <longitude fields> <latitude field> are 2D fields on J/I (Y/X) dimensions 
    997     mask : if given, seek only non masked grid points (i.e with mask=1) 
    998      
    999     Example : findIJ (40, -20, nav_lat, nav_lon, mask=1.0) 
    1000  
    1001     Note : all longitudes and latitudes in degrees 
    1002          
    1003     Note : may work with 1D lon/lat (?) 
    1004     ''' 
    1005     # Get grid dimensions 
    1006     if len (lon_grid.shape) == 2 : (jpj, jpi) = lon_grid.shape 
    1007     else                         : jpj = len(lat_grid) ; jpi=len(lon_grid) 
    1008  
    1009     mmath = __mmath__ (lat_grid) 
    1010          
    1011     # Compute distance from the point to all grid points (in radian) 
    1012     arg      = np.sin (rad*lat_data) * np.sin (rad*lat_grid) \ 
    1013              + np.cos (rad*lat_data) * np.cos (rad*lat_grid) * np.cos(rad*(lon_data-lon_grid)) 
    1014     distance = np.arccos (arg) + 4.0*rpi*(1.0-mask) # Send masked points to 'infinite'  
    1015  
    1016     # Truncates to alleviate some precision problem with some grids 
    1017     prec = int (1E7) 
    1018     distance = (distance*prec).astype(int) / prec 
    1019  
    1020     # Compute minimum of distance, and index of minimum 
    1021     # 
    1022     distance_min = distance.min    () 
    1023     jimin        = int (distance.argmin ()) 
    1024      
    1025     # Compute 2D indices  
    1026     jmin = jimin // jpi ; imin = jimin - jmin*jpi 
    1027  
    1028     # Compute distance achieved 
    1029     mindist = distance[jmin, imin] 
    1030      
    1031     # Compute azimuth 
    1032     dlon = lon_data-lon_grid[jmin,imin] 
    1033     arg  = np.sin (rad*dlon) /  (np.cos(rad*lat_data)*np.tan(rad*lat_grid[jmin,imin]) - np.sin(rad*lat_data)*np.cos(rad*dlon)) 
    1034     azimuth = dar*np.arctan (arg) 
    1035      
    1036     # Result 
    1037     if verbose :  
    1038         print ('I={:d} J={:d} - Data:{:5.1f}°N {:5.1f}°E - Grid:{:4.1f}°N {:4.1f}°E - Dist: {:6.1f}km {:5.2f}° - Azimuth: {:3.2f}rad - {:5.1f}°' 
    1039             .format (imin, jmin, lat_data, lon_data, lat_grid[jmin,imin], lon_grid[jmin,imin], ra*distance[jmin,imin], dar*distance[jmin,imin], rad*azimuth, azimuth)) 
    1040  
    1041     return jmin, imin 
    1042  
    1043 #def clo_lon (lon, lon0) : 
     1193 
     1194def clo_lon (lon, lon0=0., rad=False, deg=True) : 
    10441195    '''Choose closest to lon0 longitude, adding or substacting 360° if needed''' 
    10451196    mmath = __mmath__ (lon, np) 
    1046          
     1197    if rad : lon_range = 2.*np.pi 
     1198    if deg : lon_range = 360. 
    10471199    clo_lon = lon 
    1048     clo_lon = mmath.where (clo_lon > lon0 + 180., clo_lon-360., clo_lon) 
    1049     clo_lon = mmath.where (clo_lon < lon0 - 180., clo_lon+360., clo_lon) 
    1050     clo_lon = mmath.where (clo_lon > lon0 + 180., clo_lon-360., clo_lon) 
    1051     clo_lon = mmath.where (clo_lon < lon0 - 180., clo_lon+360., clo_lon) 
     1200    clo_lon = mmath.where (clo_lon > lon0 + lon_range*0.5, clo_lon-lon_range, clo_lon) 
     1201    clo_lon = mmath.where (clo_lon < lon0 - lon_range*0.5, clo_lon+lon_range, clo_lon) 
     1202    clo_lon = mmath.where (clo_lon > lon0 + lon_range*0.5, clo_lon-lon_range, clo_lon) 
     1203    clo_lon = mmath.where (clo_lon < lon0 - lon_range*0.5, clo_lon+lon_range, clo_lon) 
    10521204    if clo_lon.shape == () : clo_lon = clo_lon.item () 
     1205    if mmath == xr : 
     1206        try :  
     1207            for attr in lon.attrs : clo_lon.attrs[attr] = lon.attrs[attr] 
     1208        except : 
     1209            pass 
    10531210    return clo_lon 
    10541211 
    1055 #def angle_full (glamt, gphit, glamu, gphiu, glamv, gphiv, glamf, gphif, nperio=None) : 
     1212 
     1213def index2depth (pk, gdept_0) : 
     1214    ''' 
     1215    From index (real, continuous), get depth 
     1216    ''' 
     1217    jpk = gdept_0.shape[0] 
     1218    kk = xr.DataArray(pk) 
     1219    k  = np.maximum (0, np.minimum (jpk-1, kk    )) 
     1220    k0 = np.floor (k).astype (int) 
     1221    k1 = np.maximum (0, np.minimum (jpk-1,  k0+1)) 
     1222    zz = k - k0 
     1223    gz = (1.0-zz)*gdept_0[k0]+ zz*gdept_0[k1] 
     1224    return gz.values 
     1225 
     1226def depth2index (pz, gdept_0) : 
     1227    ''' 
     1228    From depth, get index (real, continuous) 
     1229    ''' 
     1230    jpk  = gdept_0.shape[0] 
     1231    if type (pz) == xr.core.dataarray.DataArray : 
     1232        zz   = xr.DataArray (pz.values, dims=('zz',)) 
     1233    elif type (pz) == np.ndarray : 
     1234        zz   = xr.DataArray (pz.ravel(), dims=('zz',)) 
     1235    else : 
     1236        zz   = xr.DataArray (np.array([pz]).ravel(), dims=('zz',)) 
     1237    zz   = np.minimum (gdept_0[-1], np.maximum (0, zz)) 
     1238     
     1239    idk1 = np.minimum ( (gdept_0-zz), 0.).argmax (axis=0).astype(int) 
     1240    idk1 = np.maximum (0, np.minimum (jpk-1,  idk1  )) 
     1241    idk2 = np.maximum (0, np.minimum (jpk-1,  idk1-1)) 
     1242     
     1243    ff = (zz - gdept_0[idk2])/(gdept_0[idk1]-gdept_0[idk2]) 
     1244    idk = ff*idk1 + (1.0-ff)*idk2 
     1245    idk = xr.where ( np.isnan(idk), idk1, idk) 
     1246    return idk.values 
     1247 
     1248def index2depth_panels (pk, gdept_0, depth0, fact) : 
     1249    ''' 
     1250    From  index (real, continuous), get depth, with bottom part compressed 
     1251    ''' 
     1252    jpk = gdept_0.shape[0] 
     1253    kk = xr.DataArray (pk) 
     1254    k  = np.maximum (0, np.minimum (jpk-1, kk    )) 
     1255    k0 = np.floor (k).astype (int) 
     1256    k1 = np.maximum (0, np.minimum (jpk-1,  k0+1)) 
     1257    zz = k - k0 
     1258    gz = (1.0-zz)*gdept_0[k0]+ zz*gdept_0[k1] 
     1259    gz = xr.where ( gz<depth0, gz, depth0 + (gz-depth0)*fact) 
     1260    return gz.values 
     1261 
     1262def depth2index_panels (pz, gdept_0, depth0, fact) : 
     1263    ''' 
     1264    From  index (real, continuous), get depth, with bottom part compressed 
     1265    ''' 
     1266    jpk = gdept_0.shape[0] 
     1267    if type (pz) == xr.core.dataarray.DataArray : 
     1268        zz   = xr.DataArray (pz.values , dims=('zz',)) 
     1269    elif type (pz) == np.ndarray : 
     1270        zz   = xr.DataArray (pz.ravel(), dims=('zz',)) 
     1271    else :  
     1272        zz   = xr.DataArray (np.array([pz]).ravel(), dims=('zz',)) 
     1273    zz         = np.minimum (gdept_0[-1], np.maximum (0, zz)) 
     1274    gdept_comp = xr.where ( gdept_0>depth0, (gdept_0-depth0)*fact+depth0, gdept_0) 
     1275    zz_comp    = xr.where ( zz     >depth0, (zz     -depth0)*fact+depth0, zz     ) 
     1276    zz_comp    = np.minimum (gdept_comp[-1], np.maximum (0, zz_comp)) 
     1277 
     1278    idk1 = np.minimum ( (gdept_0-zz_comp), 0.).argmax (axis=0).astype(int) 
     1279    idk1 = np.maximum (0, np.minimum (jpk-1,  idk1  )) 
     1280    idk2 = np.maximum (0, np.minimum (jpk-1,  idk1-1)) 
     1281      
     1282    ff = (zz_comp - gdept_0[idk2])/(gdept_0[idk1]-gdept_0[idk2]) 
     1283    idk = ff*idk1 + (1.0-ff)*idk2 
     1284    idk = xr.where ( np.isnan(idk), idk1, idk) 
     1285    return idk.values 
     1286 
     1287def depth2comp (pz, depth0, fact ) : 
     1288    ''' 
     1289    Form depth, get compressed depth, with bottom part compressed 
     1290    ''' 
     1291    #print ('start depth2comp') 
     1292    if type (pz) == xr.core.dataarray.DataArray : 
     1293        zz   = pz.values 
     1294    elif type(pz) == list : 
     1295        zz = np.array (pz) 
     1296    else :  
     1297        zz   = pz 
     1298    gz = np.where ( zz>depth0, (zz-depth0)*fact+depth0, zz) 
     1299    #print ( f'depth2comp : {gz=}' ) 
     1300    if type (pz) in [int, float] : return gz.item() 
     1301    else : return gz 
     1302    #print ('end depth2comp') 
     1303 
     1304def comp2depth (pz, depth0, fact ) : 
     1305    ''' 
     1306    Form compressed depth, get depth, with bottom part compressed 
     1307    ''' 
     1308    if type (pz) == xr.core.dataarray.DataArray : 
     1309        zz   = pz.values 
     1310    elif type(pz) == list : 
     1311        zz = np.array (pz) 
     1312    else :  
     1313        zz   = pz 
     1314    gz = np.where ( zz>depth0, (zz-depth0)/fact+depth0, zz) 
     1315    if type (pz) in [int, float] : return gz.item() 
     1316    else : return gz 
     1317 
     1318def index2lon (pi, lon1D) : 
     1319    ''' 
     1320    From index (real, continuous), get longitude 
     1321    ''' 
     1322    jpi = lon1D.shape[0] 
     1323    ii = xr.DataArray (pi) 
     1324    i =  np.maximum (0, np.minimum (jpi-1, ii    )) 
     1325    i0 = np.floor (i).astype (int) 
     1326    i1 = np.maximum (0, np.minimum (jpi-1,  i0+1)) 
     1327    xx = i - i0 
     1328    gx = (1.0-xx)*lon1D[i0]+ xx*lon1D[i1] 
     1329    return gx.values 
     1330 
     1331def lon2index (px, lon1D) : 
     1332    ''' 
     1333    From longitude, get index (real, continuous) 
     1334    ''' 
     1335    jpi  = lon1D.shape[0] 
     1336    if type (px) == xr.core.dataarray.DataArray : 
     1337        xx   = xr.DataArray (px.values , dims=('xx',)) 
     1338    elif type (px) == np.ndarray : 
     1339        xx   = xr.DataArray (px.ravel(), dims=('xx',)) 
     1340    else :  
     1341        xx   = xr.DataArray (np.array([px]).ravel(), dims=('xx',)) 
     1342    xx   = xr.where ( xx>lon1D.max(), xx-360.0, xx) 
     1343    xx   = xr.where ( xx<lon1D.min(), xx+360.0, xx) 
     1344    xx   = np.minimum (lon1D.max(), np.maximum(xx, lon1D.min() )) 
     1345    idi1 = np.minimum ( (lon1D-xx), 0.).argmax (axis=0).astype(int) 
     1346    idi1 = np.maximum (0, np.minimum (jpi-1,  idi1  )) 
     1347    idi2 = np.maximum (0, np.minimum (jpi-1,  idi1-1)) 
     1348     
     1349    ff = (xx - lon1D[idi2])/(lon1D[idi1]-lon1D[idi2]) 
     1350    idi = ff*idi1 + (1.0-ff)*idi2 
     1351    idi = xr.where ( np.isnan(idi), idi1, idi) 
     1352    return idi.values 
     1353 
     1354def index2lat (pj, lat1D) : 
     1355    ''' 
     1356    From index (real, continuous), get latitude 
     1357    ''' 
     1358    jpj = lat1D.shape[0] 
     1359    jj  = xr.DataArray (pj) 
     1360    j   = np.maximum (0, np.minimum (jpj-1, jj    )) 
     1361    j0  = np.floor (j).astype (int) 
     1362    j1  = np.maximum (0, np.minimum (jpj-1,  j0+1)) 
     1363    yy  = j - j0 
     1364    gy  = (1.0-yy)*lat1D[j0]+ yy*lat1D[j1] 
     1365    return gy.values 
     1366 
     1367def lat2index (py, lat1D) : 
     1368    ''' 
     1369    From latitude, get index (real, continuous) 
     1370    ''' 
     1371    jpj = lat1D.shape[0] 
     1372    if type (py) == xr.core.dataarray.DataArray : 
     1373        yy   = xr.DataArray (py.values , dims=('yy',)) 
     1374    elif type (py) == np.ndarray : 
     1375        yy   = xr.DataArray (py.ravel(), dims=('yy',)) 
     1376    else :  
     1377        yy   = xr.DataArray (np.array([py]).ravel(), dims=('yy',)) 
     1378    yy   = np.minimum (lat1D.max(), np.minimum(yy, lat1D.max() )) 
     1379    idj1 = np.minimum ( (lat1D-yy), 0.).argmax (axis=0).astype(int) 
     1380    idj1 = np.maximum (0, np.minimum (jpj-1,  idj1  )) 
     1381    idj2 = np.maximum (0, np.minimum (jpj-1,  idj1-1)) 
     1382     
     1383    ff = (yy - lat1D[idj2])/(lat1D[idj1]-lat1D[idj2]) 
     1384    idj = ff*idj1 + (1.0-ff)*idj2 
     1385    idj = xr.where ( np.isnan(idj), idj1, idj) 
     1386    return idj.values 
     1387 
     1388def angle_full (glamt, gphit, glamu, gphiu, glamv, gphiv, glamf, gphif, nperio=None) : 
    10561389    '''Compute sinus and cosinus of model line direction with respect to east''' 
    10571390    mmath = __mmath__ (glamt) 
     
    12341567    v_n = + u_i * gsin + v_j * gcos 
    12351568     
    1236     u_e = lbc (u_e, nperio=nperio, cd_type=cd_type, psgn= 1.0) 
    1237     v_n = lbc (v_n, nperio=nperio, cd_type=cd_type, psgn= 1.0) 
     1569    u_e = lbc (u_e, nperio=nperio, cd_type=cd_type, psgn=1.0) 
     1570    v_n = lbc (v_n, nperio=nperio, cd_type=cd_type, psgn=1.0) 
    12381571     
    12391572    return u_e, v_n 
    12401573 
    1241 def rot_uv2en ( uo, vo, gsint, gcost, nperio, zdim='deptht' ) : 
     1574def rot_uv2en ( uo, vo, gsint, gcost, nperio, zdim=None ) : 
    12421575    ''' 
    12431576    ** Purpose :   Rotate the Repere: Change vector componantes from 
     
    12471580    ''' 
    12481581    mmath = __mmath__ (uo) 
    1249  
     1582     
    12501583    ut = U2T (uo, nperio=nperio, psgn=-1.0, zdim=zdim) 
    12511584    vt = V2T (vo, nperio=nperio, psgn=-1.0, zdim=zdim) 
     
    12591592    return u_e, v_n 
    12601593 
    1261 def rot_uv2enF ( uo, vo, gsinf, gcosf, nperio, zdim='deptht' ) : 
     1594def rot_uv2enF ( uo, vo, gsinf, gcosf, nperio, zdim=None ) : 
    12621595    ''' 
    12631596    ** Purpose : Rotate the Repere: Change vector componantes from 
     
    12791612    return u_e, v_n 
    12801613 
    1281 #@numba.jit(forceobj=True) 
    1282 def U2T (utab, nperio=None, psgn=-1.0, zdim='deptht', action='ave') : 
     1614def U2T (utab, nperio=None, psgn=-1.0, zdim=None, action='ave') : 
    12831615    '''Interpolate an array from U grid to T grid i-mean)''' 
    12841616    mmath = __mmath__ (utab) 
     
    12871619    utab_0 = lbc_add (utab_0, nperio=nperio, cd_type='U', psgn=psgn) 
    12881620    ix, ax = __findAxis__ (utab_0, 'x') 
    1289     iz, az = __findAxis__ (utab_0, 'z') 
    1290     if action == 'ave'  : ttab = 0.5 *      (utab_0 + np.roll (utab_0, axis=ix, shift=1)) 
    1291     if action == 'min'  : ttab = np.minimum (utab_0 , np.roll (utab_0, axis=ix, shift=1)) 
    1292     if action == 'max'  : ttab = np.maximum (utab_0 , np.roll (utab_0, axis=ix, shift=1)) 
    1293     if action == 'mult' : ttab =             utab_0 * np.roll (utab_0, axis=ix, shift=1) 
    1294     ttab = lbc_del (ttab, nperio=nperio, cd_type='T', psgn=psgn) 
    1295      
     1621    kz, az = __findAxis__ (utab_0, 'z') 
     1622 
     1623    if ax :  
     1624        if action == 'ave' : ttab = 0.5 *      (utab_0 + np.roll (utab_0, axis=ix, shift=1)) 
     1625        if action == 'min' : ttab = np.minimum (utab_0 , np.roll (utab_0, axis=ix, shift=1)) 
     1626        if action == 'max' : ttab = np.maximum (utab_0 , np.roll (utab_0, axis=ix, shift=1)) 
     1627        if action == 'mult': ttab =             utab_0 * np.roll (utab_0, axis=ix, shift=1) 
     1628        ttab = lbc_del (ttab  , nperio=nperio, cd_type='T', psgn=psgn) 
     1629    else :  
     1630        ttab = lbc_del (utab_0, nperio=nperio, cd_type='T', psgn=psgn) 
     1631         
    12961632    if mmath == xr : 
    1297         if ax != None : 
     1633        if ax : 
    12981634            ttab = ttab.assign_coords({ax:np.arange (ttab.shape[ix])+1.}) 
    1299         if zdim != None and iz != None  and az != 'olevel' :  
    1300             ttab = ttab.rename( {az:zdim})  
     1635        if zdim and az : 
     1636            if az != zdim : ttab = ttab.rename( {az:zdim})  
    13011637    return ttab 
    13021638 
    1303 #@numba.jit(forceobj=True) 
    1304 def V2T (vtab, nperio=None, psgn=-1.0, zdim='deptht', action='ave') : 
     1639def V2T (vtab, nperio=None, psgn=-1.0, zdim=None, action='ave') : 
    13051640    '''Interpolate an array from V grid to T grid (j-mean)''' 
    13061641    mmath = __mmath__ (vtab) 
     
    13081643    vtab_0 = mmath.where ( np.isnan(vtab), 0., vtab) 
    13091644    vtab_0 = lbc_add (vtab_0, nperio=nperio, cd_type='V', psgn=psgn) 
    1310     iy, ay = __findAxis__ (vtab_0, 'y') 
    1311     iz, az = __findAxis__ (vtab_0, 'z') 
    1312     if action == 'ave'  : ttab = 0.5 *      (vtab_0 + np.roll (vtab_0, axis=iy, shift=1)) 
    1313     if action == 'min'  : ttab = np.minimum (vtab_0 , np.roll (vtab_0, axis=iy, shift=1)) 
    1314     if action == 'max'  : ttab = np.maximum (vtab_0 , np.roll (vtab_0, axis=iy, shift=1)) 
    1315     if action == 'mult' : ttab =             vtab_0 * np.roll (vtab_0, axis=iy, shift=1) 
    1316     ttab = lbc_del (ttab, nperio=nperio, cd_type='T', psgn=psgn) 
     1645    jy, ay = __findAxis__ (vtab_0, 'y') 
     1646    kz, az = __findAxis__ (vtab_0, 'z') 
     1647    if ay :  
     1648        if action == 'ave'  : ttab = 0.5 *      (vtab_0 + np.roll (vtab_0, axis=jy, shift=1)) 
     1649        if action == 'min'  : ttab = np.minimum (vtab_0 , np.roll (vtab_0, axis=jy, shift=1)) 
     1650        if action == 'max'  : ttab = np.maximum (vtab_0 , np.roll (vtab_0, axis=jy, shift=1)) 
     1651        if action == 'mult' : ttab =             vtab_0 * np.roll (vtab_0, axis=jy, shift=1) 
     1652        ttab = lbc_del (ttab  , nperio=nperio, cd_type='T', psgn=psgn) 
     1653    else : 
     1654        ttab = lbc_del (vtab_0, nperio=nperio, cd_type='T', psgn=psgn) 
     1655         
    13171656    if mmath == xr : 
    1318         if ay !=None :  
    1319             ttab = ttab.assign_coords({ay:np.arange(ttab.shape[iy])+1.}) 
    1320         if zdim != None and iz != None  and az != 'olevel' : 
    1321             ttab = ttab.rename( {az:zdim})  
     1657        if ay : 
     1658            ttab = ttab.assign_coords({ay:np.arange(ttab.shape[jy])+1.}) 
     1659        if zdim and az : 
     1660            if az != zdim : ttab = ttab.rename( {az:zdim})  
    13221661    return ttab 
    13231662 
    1324 #@numba.jit(forceobj=True) 
    1325 def F2T (ftab, nperio=None, psgn=1.0, zdim='depthf', action='ave') : 
     1663def F2T (ftab, nperio=None, psgn=1.0, zdim=None, action='ave') : 
    13261664    '''Interpolate an array from F grid to T grid (i- and j- means)''' 
    13271665    mmath = __mmath__ (ftab) 
    13281666    ftab_0 = mmath.where ( np.isnan(ftab), 0., ftab) 
    13291667    ftab_0 = lbc_add (ftab_0 , nperio=nperio, cd_type='F', psgn=psgn) 
    1330     ttab = V2T(F2V(ftab_0, nperio=nperio, psgn=psgn, zdim=zdim, action=action), nperio=nperio, psgn=psgn, zdim=zdim, action=action) 
     1668    ttab = V2T (F2V (ftab_0, nperio=nperio, psgn=psgn, zdim=zdim, action=action), nperio=nperio, psgn=psgn, zdim=zdim, action=action) 
    13311669    return lbc_del (ttab, nperio=nperio, cd_type='T', psgn=psgn) 
    13321670 
    1333 #@numba.jit(forceobj=True) 
    1334 def T2U (ttab, nperio=None, psgn=1.0, zdim='depthu', action='ave') : 
     1671def T2U (ttab, nperio=None, psgn=1.0, zdim=None, action='ave') : 
    13351672    '''Interpolate an array from T grid to U grid (i-mean)''' 
    13361673    mmath = __mmath__ (ttab) 
     
    13381675    ttab_0 = lbc_add (ttab_0 , nperio=nperio, cd_type='T', psgn=psgn) 
    13391676    ix, ax = __findAxis__ (ttab_0, 'x') 
    1340     iz, az = __findAxis__ (ttab_0, 'z') 
    1341     if action == 'ave'  : utab = 0.5 *      (ttab_0 + np.roll (ttab_0, axis=ix, shift=-1)) 
    1342     if action == 'min'  : utab = np.minimum (ttab_0 , np.roll (ttab_0, axis=ix, shift=-1)) 
    1343     if action == 'max'  : utab = np.maximum (ttab_0 , np.roll (ttab_0, axis=ix, shift=-1)) 
    1344     if action == 'mult' : utab =             ttab_0 * np.roll (ttab_0, axis=ix, shift=-1) 
    1345     utab = lbc_del (utab, nperio=nperio, cd_type='U', psgn=psgn) 
    1346  
     1677    kz, az = __findAxis__ (ttab_0, 'z') 
     1678    if ix :  
     1679        if action == 'ave'  : utab = 0.5 *      (ttab_0 + np.roll (ttab_0, axis=ix, shift=-1)) 
     1680        if action == 'min'  : utab = np.minimum (ttab_0 , np.roll (ttab_0, axis=ix, shift=-1)) 
     1681        if action == 'max'  : utab = np.maximum (ttab_0 , np.roll (ttab_0, axis=ix, shift=-1)) 
     1682        if action == 'mult' : utab =             ttab_0 * np.roll (ttab_0, axis=ix, shift=-1) 
     1683        utab = lbc_del (utab  , nperio=nperio, cd_type='U', psgn=psgn) 
     1684    else : 
     1685        utab = lbc_del (ttab_0, nperio=nperio, cd_type='U', psgn=psgn) 
     1686         
    13471687    if mmath == xr :     
    1348         if ax != None :  
     1688        if ax :  
    13491689            utab = ttab.assign_coords({ax:np.arange(utab.shape[ix])+1.}) 
    1350         if zdim != None  and iz != None  and az != 'olevel' : 
    1351             utab = utab.rename( {az:zdim})  
     1690        if zdim and az : 
     1691            if az != zdim : utab = utab.rename( {az:zdim})  
    13521692    return utab 
    13531693 
    1354 #@numba.jit(forceobj=True) 
    1355 def T2V (ttab, nperio=None, psgn=1.0, zdim='depthv', action='ave') : 
     1694def T2V (ttab, nperio=None, psgn=1.0, zdim=None, action='ave') : 
    13561695    '''Interpolate an array from T grid to V grid (j-mean)''' 
    13571696    mmath = __mmath__ (ttab) 
    13581697    ttab_0 = mmath.where ( np.isnan(ttab), 0., ttab) 
    13591698    ttab_0 = lbc_add (ttab_0 , nperio=nperio, cd_type='T', psgn=psgn) 
    1360     iy, ay = __findAxis__ (ttab_0, 'y') 
    1361     iz, az = __findAxis__ (ttab_0, 'z') 
    1362     if action == 'ave'  : vtab = 0.5 *      (ttab_0 + np.roll (ttab_0, axis=iy, shift=-1)) 
    1363     if action == 'min'  : vtab = np.minimum (ttab_0 , np.roll (ttab_0, axis=iy, shift=-1)) 
    1364     if action == 'max'  : vtab = np.maximum (ttab_0 , np.roll (ttab_0, axis=iy, shift=-1)) 
    1365     if action == 'mult' : vtab =             ttab_0 * np.roll (ttab_0, axis=iy, shift=-1) 
    1366  
    1367     vtab = lbc_del (vtab, nperio=nperio, cd_type='V', psgn=psgn) 
     1699    jy, ay = __findAxis__ (ttab_0, 'y') 
     1700    kz, az = __findAxis__ (ttab_0, 'z') 
     1701    if jy :  
     1702        if action == 'ave'  : vtab = 0.5 *      (ttab_0 + np.roll (ttab_0, axis=jy, shift=-1)) 
     1703        if action == 'min'  : vtab = np.minimum (ttab_0 , np.roll (ttab_0, axis=jy, shift=-1)) 
     1704        if action == 'max'  : vtab = np.maximum (ttab_0 , np.roll (ttab_0, axis=jy, shift=-1)) 
     1705        if action == 'mult' : vtab =             ttab_0 * np.roll (ttab_0, axis=jy, shift=-1) 
     1706        vtab = lbc_del (vtab  , nperio=nperio, cd_type='V', psgn=psgn) 
     1707    else : 
     1708        vtab = lbc_del (ttab_0, nperio=nperio, cd_type='V', psgn=psgn) 
     1709 
    13681710    if mmath == xr : 
    1369         if ay != None :  
    1370             vtab = vtab.assign_coords({ay:np.arange(vtab.shape[iy])+1.}) 
    1371         if zdim != None  and iz != None and az != 'olevel' : 
    1372             vtab = vtab.rename( {az:zdim})  
     1711        if ay :  
     1712            vtab = vtab.assign_coords({ay:np.arange(vtab.shape[jy])+1.}) 
     1713        if zdim and az : 
     1714            if az != zdim : vtab = vtab.rename( {az:zdim})  
    13731715    return vtab 
    13741716 
    1375 #@numba.jit(forceobj=True) 
    1376 def V2F (vtab, nperio=None, psgn=-1.0, zdim='depthf', action='ave') : 
     1717def V2F (vtab, nperio=None, psgn=-1.0, zdim=None, action='ave') : 
    13771718    '''Interpolate an array from V grid to F grid (i-mean)''' 
    13781719    mmath = __mmath__ (vtab) 
     
    13801721    vtab_0 = lbc_add (vtab_0 , nperio=nperio, cd_type='V', psgn=psgn) 
    13811722    ix, ax = __findAxis__ (vtab_0, 'x') 
    1382     iz, az = __findAxis__ (vtab_0, 'z') 
    1383     if action == 'ave'  : 0.5 *      (vtab_0 + np.roll (vtab_0, axis=ix, shift=-1)) 
    1384     if action == 'min'  : np.minimum (vtab_0 , np.roll (vtab_0, axis=ix, shift=-1)) 
    1385     if action == 'max'  : np.maximum (vtab_0 , np.roll (vtab_0, axis=ix, shift=-1)) 
    1386     if action == 'mult' :             vtab_0 * np.roll (vtab_0, axis=ix, shift=-1) 
    1387     ftab = lbc_del (ftab, nperio=nperio, cd_type='F', psgn=psgn) 
    1388      
     1723    kz, az = __findAxis__ (vtab_0, 'z') 
     1724    if ix :  
     1725        if action == 'ave'  : 0.5 *      (vtab_0 + np.roll (vtab_0, axis=ix, shift=-1)) 
     1726        if action == 'min'  : np.minimum (vtab_0 , np.roll (vtab_0, axis=ix, shift=-1)) 
     1727        if action == 'max'  : np.maximum (vtab_0 , np.roll (vtab_0, axis=ix, shift=-1)) 
     1728        if action == 'mult' :             vtab_0 * np.roll (vtab_0, axis=ix, shift=-1) 
     1729        ftab = lbc_del (ftab  , nperio=nperio, cd_type='F', psgn=psgn) 
     1730    else : 
     1731         ftab = lbc_del (vtab_0, nperio=nperio, cd_type='F', psgn=psgn) 
     1732    
    13891733    if mmath == xr : 
    1390         if ax != None :  
     1734        if ax :  
    13911735            ftab = ftab.assign_coords({ax:np.arange(ftab.shape[ix])+1.}) 
    1392         if zdim != None and iz != None and az != 'olevel' : 
    1393             ftab = ftab.rename( {az:zdim})  
     1736        if zdim and az : 
     1737            if az != zdim : ftab = ftab.rename( {az:zdim})  
    13941738    return lbc_del (ftab, nperio=nperio, cd_type='F', psgn=psgn) 
    13951739 
    1396 #@numba.jit(forceobj=True) 
    1397 def U2F (utab, nperio=None, psgn=-1.0, zdim='depthf', action='ave') : 
     1740def U2F (utab, nperio=None, psgn=-1.0, zdim=None, action='ave') : 
    13981741    '''Interpolate an array from U grid to F grid i-mean)''' 
    13991742    mmath = __mmath__ (utab) 
    14001743    utab_0 = mmath.where ( np.isnan(utab), 0., utab) 
    14011744    utab_0 = lbc_add (utab_0 , nperio=nperio, cd_type='U', psgn=psgn) 
    1402     iy, ay = __findAxis__ (utab_0, 'y') 
    1403     iz, az = __findAxis__ (utab_0, 'z') 
    1404     if action == 'ave'  :    ftab = 0.5 *      (utab_0 + np.roll (utab_0, axis=iy, shift=-1)) 
    1405     if action == 'min'  :    ftab = np.minimum (utab_0 , np.roll (utab_0, axis=iy, shift=-1)) 
    1406     if action == 'max'  :    ftab = np.maximum (utab_0 , np.roll (utab_0, axis=iy, shift=-1)) 
    1407     if action == 'mult' :    ftab =             utab_0 * np.roll (utab_0, axis=iy, shift=-1) 
    1408     ftab = lbc_del (ftab, nperio=nperio, cd_type='F', psgn=psgn) 
    1409  
     1745    jy, ay = __findAxis__ (utab_0, 'y') 
     1746    kz, az = __findAxis__ (utab_0, 'z') 
     1747    if jy :  
     1748        if action == 'ave'  :    ftab = 0.5 *      (utab_0 + np.roll (utab_0, axis=jy, shift=-1)) 
     1749        if action == 'min'  :    ftab = np.minimum (utab_0 , np.roll (utab_0, axis=jy, shift=-1)) 
     1750        if action == 'max'  :    ftab = np.maximum (utab_0 , np.roll (utab_0, axis=jy, shift=-1)) 
     1751        if action == 'mult' :    ftab =             utab_0 * np.roll (utab_0, axis=jy, shift=-1) 
     1752        ftab = lbc_del (ftab  , nperio=nperio, cd_type='F', psgn=psgn) 
     1753    else : 
     1754        ftab = lbc_del (utab_0, nperio=nperio, cd_type='F', psgn=psgn) 
     1755   
    14101756    if mmath == xr : 
    1411         if ay != None :  
    1412             ftab = ftab.assign_coords({'y':np.arange(ftab.shape[iy])+1.}) 
    1413         if zdim != None and iz != None and az != 'olevel' : 
    1414             ftab = ftab.rename( {az:zdim})  
     1757        if ay :  
     1758            ftab = ftab.assign_coords({'y':np.arange(ftab.shape[jy])+1.}) 
     1759        if zdim and az : 
     1760            if az != zdim : ftab = ftab.rename( {az:zdim})  
    14151761    return ftab 
    14161762 
    1417 #@numba.jit(forceobj=True) 
    1418 def F2T (ftab, nperio=None, psgn=1.0, zdim='deptht', action='ave') : 
     1763def F2T (ftab, nperio=None, psgn=1.0, zdim=None, action='ave') : 
    14191764    '''Interpolate an array on F grid to T grid (i- and j- means)''' 
    14201765    mmath = __mmath__ (ftab) 
     
    14241769    return lbc_del (ttab, nperio=nperio, cd_type='T', psgn=psgn) 
    14251770 
    1426 #@numba.jit(forceobj=True) 
    1427 def T2F (ttab, nperio=None, psgn=1.0, zdim='deptht', action='mean') : 
     1771def T2F (ttab, nperio=None, psgn=1.0, zdim=None, action='mean') : 
    14281772    '''Interpolate an array on T grid to F grid (i- and j- means)''' 
    14291773    mmath = __mmath__ (ttab) 
    14301774    ttab_0 = mmath.where ( np.isnan(ttab), 0., ttab) 
    14311775    ttab_0 = lbc_add (ttab_0 , nperio=nperio, cd_type='T', psgn=psgn) 
    1432     ftab = T2U(U2F(ttab, nperio=nperio, psgn=psgn, zdim=zdim, action=action), nperio=nperio, psgn=psgn, zdim=zdim, action=action) 
     1776    ftab = T2U (U2F (ttab, nperio=nperio, psgn=psgn, zdim=zdim, action=action), nperio=nperio, psgn=psgn, zdim=zdim, action=action) 
    14331777     
    14341778    return lbc_del (ftab, nperio=nperio, cd_type='F', psgn=psgn) 
    14351779 
    1436 #@numba.jit(forceobj=True) 
    1437 def F2U (ftab, nperio=None, psgn=1.0, zdim='depthu', action='ave') : 
     1780def F2U (ftab, nperio=None, psgn=1.0, zdim=None, action='ave') : 
    14381781    '''Interpolate an array on F grid to FUgrid (i-mean)''' 
    14391782    mmath = __mmath__ (ftab) 
    14401783    ftab_0 = mmath.where ( np.isnan(ftab), 0., ftab) 
    14411784    ftab_0 = lbc_add (ftab_0 , nperio=nperio, cd_type='F', psgn=psgn) 
    1442     iy, ay = __findAxis__ (ftab_0, 'y') 
    1443     iz, az = __findAxis__ (ftab_0, 'z') 
    1444     if action == 'ave'  : utab = 0.5 *      (ftab_0 + np.roll (ftab_0, axis=iy, shift=-1)) 
    1445     if action == 'min'  : utab = np.minimum (ftab_0 , np.roll (ftab_0, axis=iy, shift=-1)) 
    1446     if action == 'max'  : utab = np.maximum (ftab_0 , np.roll (ftab_0, axis=iy, shift=-1)) 
    1447     if action == 'mult' : utab =             ftab_0 * np.roll (ftab_0, axis=iy, shift=-1) 
    1448  
    1449     utab = lbc_del (utab, nperio=nperio, cd_type='U', psgn=psgn) 
    1450      
     1785    jy, ay = __findAxis__ (ftab_0, 'y') 
     1786    kz, az = __findAxis__ (ftab_0, 'z') 
     1787    if jy :  
     1788        if action == 'ave'  : utab = 0.5 *      (ftab_0 + np.roll (ftab_0, axis=jy, shift=-1)) 
     1789        if action == 'min'  : utab = np.minimum (ftab_0 , np.roll (ftab_0, axis=jy, shift=-1)) 
     1790        if action == 'max'  : utab = np.maximum (ftab_0 , np.roll (ftab_0, axis=jy, shift=-1)) 
     1791        if action == 'mult' : utab =             ftab_0 * np.roll (ftab_0, axis=jy, shift=-1) 
     1792        utab = lbc_del (utab  , nperio=nperio, cd_type='U', psgn=psgn) 
     1793    else : 
     1794        utab = lbc_del (ftab_0, nperio=nperio, cd_type='U', psgn=psgn) 
     1795 
    14511796    if mmath == xr : 
    1452         utab = utab.assign_coords({ay:np.arange(ftab.shape[iy])+1.}) 
    1453         if zdim != None and iz != None and az != 'olevel' : 
    1454             utab = utab.rename( {az:zdim})  
     1797        utab = utab.assign_coords({ay:np.arange(ftab.shape[jy])+1.}) 
     1798        if zdim and zz : 
     1799            if az != zdim : utab = utab.rename( {az:zdim})  
    14551800    return utab 
    14561801 
    1457 #@numba.jit(forceobj=True) 
    1458 def F2V (ftab, nperio=None, psgn=1.0, zdim='depthv', action='ave') : 
     1802def F2V (ftab, nperio=None, psgn=1.0, zdim=None, action='ave') : 
    14591803    '''Interpolate an array from F grid to V grid (i-mean)''' 
    14601804    mmath = __mmath__ (ftab) 
     
    14621806    ftab_0 = lbc_add (ftab_0 , nperio=nperio, cd_type='F', psgn=psgn) 
    14631807    ix, ax = __findAxis__ (ftab_0, 'x') 
    1464     iz, az = __findAxis__ (ftab_0, 'z') 
    1465     if action == 'ave'  : vtab = 0.5 *      (ftab_0 + np.roll (ftab_0, axis=ix, shift=-1)) 
    1466     if action == 'min'  : vtab = np.minimum (ftab_0 , np.roll (ftab_0, axis=ix, shift=-1)) 
    1467     if action == 'max'  : vtab = np.maximum (ftab_0 , np.roll (ftab_0, axis=ix, shift=-1)) 
    1468     if action == 'mult' : vtab =             ftab_0 * np.roll (ftab_0, axis=ix, shift=-1) 
    1469  
    1470     vtab = lbc_del (vtab, nperio=nperio, cd_type='V', psgn=psgn) 
     1808    kz, az = __findAxis__ (ftab_0, 'z') 
     1809    if ix :  
     1810        if action == 'ave'  : vtab = 0.5 *      (ftab_0 + np.roll (ftab_0, axis=ix, shift=-1)) 
     1811        if action == 'min'  : vtab = np.minimum (ftab_0 , np.roll (ftab_0, axis=ix, shift=-1)) 
     1812        if action == 'max'  : vtab = np.maximum (ftab_0 , np.roll (ftab_0, axis=ix, shift=-1)) 
     1813        if action == 'mult' : vtab =             ftab_0 * np.roll (ftab_0, axis=ix, shift=-1) 
     1814        vtab = lbc_del (vtab  , nperio=nperio, cd_type='V', psgn=psgn) 
     1815    else :  
     1816        vtab = lbc_del (ftab_0, nperio=nperio, cd_type='V', psgn=psgn) 
     1817 
    14711818    if mmath == xr : 
    14721819        vtab = vtab.assign_coords({ax:np.arange(ftab.shape[ix])+1.}) 
    1473         if zdim != None and iz != None and az != 'olevel' : 
    1474             vtab = vtab.rename( {az:zdim})  
     1820        if zdim and az : 
     1821            if az != zdim : vtab = vtab.rename( {az:zdim})  
    14751822    return vtab 
    14761823 
    1477 #@numba.jit(forceobj=True) 
    1478 def W2T (wtab, zcoord=None, zdim='deptht', sval=np.nan) : 
     1824def W2T (wtab, zcoord=None, zdim=None, sval=np.nan) : 
    14791825    ''' 
    14801826    Interpolate an array on W grid to T grid (k-mean) 
     
    14841830    wtab_0 = mmath.where ( np.isnan(wtab), 0., wtab) 
    14851831 
    1486     iz, az = __findAxis__ (wtab_0, 'z') 
    1487         
    1488     ttab = 0.5 * ( wtab_0 + np.roll (wtab_0, axis=iz, shift=-1) ) 
    1489      
     1832    kz, az = __findAxis__ (wtab_0, 'z') 
     1833 
     1834    if kz :  
     1835        ttab = 0.5 * ( wtab_0 + np.roll (wtab_0, axis=kz, shift=-1) ) 
     1836    else : 
     1837        ttab = wtab_0 
     1838 
    14901839    if mmath == xr : 
    1491         ttab[{az:iz}] = sval 
    1492         if zdim != None and iz != None and az != 'olevel' : 
    1493             ttab = ttab.rename ( {az:zdim} ) 
    1494         try    : ttab = ttab.assign_coords ( {zdim:zcoord} ) 
    1495         except : pass 
     1840        ttab[{az:kz}] = sval 
     1841        if zdim and az : 
     1842            if az != zdim : ttab = ttab.rename ( {az:zdim} ) 
     1843        if zcoord is not None : 
     1844            ttab = ttab.assign_coords ( {zdim:zcoord} ) 
    14961845    else : 
    14971846        ttab[..., -1, :, :] = sval 
     
    14991848    return ttab 
    15001849 
    1501 #@numba.jit(forceobj=True) 
    1502 def T2W (ttab, zcoord=None, zdim='depthw', sval=np.nan, extrap_surf=False) : 
     1850def T2W (ttab, zcoord=None, zdim=None, sval=np.nan, extrap_surf=False) : 
    15031851    '''Interpolate an array from T grid to W grid (k-mean) 
    15041852    sval is the surface value 
     
    15071855    mmath = __mmath__ (ttab) 
    15081856    ttab_0 = mmath.where ( np.isnan(ttab), 0., ttab) 
    1509     iz, az = __findAxis__ (ttab_0, 'z') 
    1510     wtab = 0.5 * ( ttab_0 + np.roll (ttab_0, axis=iz, shift=1) ) 
     1857    kz, az = __findAxis__ (ttab_0, 'z') 
     1858    wtab = 0.5 * ( ttab_0 + np.roll (ttab_0, axis=kz, shift=1) ) 
    15111859 
    15121860    if mmath == xr : 
     
    15181866 
    15191867    if mmath == xr : 
    1520         if zdim != None and iz != None and az != 'olevel' : 
    1521                 wtab = wtab.rename ( {az:zdim}) 
    1522         if zcoord != None : wtab = wtab.assign_coords ( {zdim:zcoord}) 
    1523         else              : ztab = wtab.assign_coords ( {zdim:np.arange(ttab.shape[iz])+1.} ) 
     1868        if zdim and az : 
     1869            if az != zdim : wtab = wtab.rename ( {az:zdim}) 
     1870        if zcoord is not None : 
     1871            wtab = wtab.assign_coords ( {zdim:zcoord}) 
     1872        else : 
     1873            ztab = wtab.assign_coords ( {zdim:np.arange(ttab.shape[kz])+1.} ) 
    15241874    return wtab 
    15251875 
    1526 #@numba.jit(forceobj=True) 
    15271876def fill (ptab, nperio, cd_type='T', npass=1, sval=0.) : 
    15281877    ''' 
     
    15841933    return ztab 
    15851934 
    1586 #@numba.jit(forceobj=True) 
    15871935def correct_uv (u, v, lat) : 
    15881936    ''' 
    1589     Correct a Cartopy bug in Orthographic projection 
     1937    Correct a Cartopy bug in orthographic projection 
    15901938 
    15911939    See https://github.com/SciTools/cartopy/issues/1179 
     
    15931941    The correction is needed with cartopy <= 0.20 
    15941942    It seems that version 0.21 will correct the bug (https://github.com/SciTools/cartopy/pull/1926) 
     1943    Later note : the bug is still present in Cartopy 0.22 
    15951944 
    15961945    Inputs : 
    1597        u, v : eastward/nothward components 
     1946       u, v : eastward/northward components 
    15981947       lat  : latitude of the point (degrees north) 
    15991948 
     
    16081957    return uc, vc 
    16091958 
    1610 def msf (v_e1v_e3v, lat1d, depthw) : 
     1959def norm_uv (u, v) : 
     1960    ''' 
     1961    Return norm of a 2 components vector 
     1962    ''' 
     1963    return np.sqrt (u*u + v*v) 
     1964 
     1965def normalize_uv (u, v) : 
     1966    ''' 
     1967    Normalize 2 components vector 
     1968    ''' 
     1969    uv = norm_uv (u, v) 
     1970    return u/uv, v/uv 
     1971 
     1972def msf (vv, e1v_e3v, lat1d, depthw) : 
    16111973    ''' 
    16121974    Computes the meridonal stream function 
    16131975    First input is meridional_velocity*e1v*e3v 
    16141976    ''' 
    1615     @numba.jit(forceobj=True) 
    1616     def iin (tab, dim) : 
    1617         ''' 
    1618         Integrate from the bottom 
    1619         ''' 
    1620         result = tab * 0.0 
    1621         nlen = len(tab.coords[dim]) 
    1622         for jn in np.arange (nlen-2, 0, -1) : 
    1623             result [{dim:jn}] = result [{dim:jn+1}] - tab [{dim:jn}] 
    1624         result = result.where (result !=0, np.nan) 
    1625         return result 
    1626      
    1627     zomsf = iin ((v_e1v_e3v).sum (dim='x', keep_attrs=True)*1E-6, dim='depthv') 
    1628     zomsf = zomsf.assign_coords ( {'depthv':depthw.values, 'y':lat1d}) 
    1629     zomsf = zomsf.rename ( {'depthv':'depthw', 'y':'lat'}) 
     1977  
     1978    v_e1v_e3v = vv * e1v_e3v 
     1979    v_e1v_e3v.attrs = vv.attrs 
     1980     
     1981    ix, ax = __findAxis__ (v_e1v_e3v, 'x') 
     1982    kz, az = __findAxis__ (v_e1v_e3v, 'z') 
     1983    if az == 'olevel' : new_az = 'olevel' 
     1984    else              : new_az = 'depthw' 
     1985 
     1986    zomsf = -v_e1v_e3v.cumsum ( dim=az, keep_attrs=True).sum (dim=ax, keep_attrs=True)*1.E-6 
     1987    zomsf = zomsf - zomsf.isel ( { az:-1} ) 
     1988     
     1989    jy, ay = __findAxis__ (zomsf, 'y' ) 
     1990    zomsf = zomsf.assign_coords ( {az:depthw.values, ay:lat1d.values}) 
     1991     
     1992    zomsf = zomsf.rename ( {ay:'lat'}) 
     1993    if az != new_az : zomsf = zomsf.rename ( {az:new_az} ) 
     1994    zomsf.attrs['standard_name'] = 'Meridional stream function' 
    16301995    zomsf.attrs['long_name'] = 'Meridional stream function' 
    1631  
    16321996    zomsf.attrs['units'] = 'Sv' 
    1633     zomsf.depthw.attrs=depthw.attrs 
     1997    zomsf[new_az].attrs  = depthw.attrs 
    16341998    zomsf.lat.attrs=lat1d.attrs 
    16351999         
    16362000    return zomsf 
    16372001 
    1638 def bsf (u_e2u_e3u, mask, nperio=None, bsf0=None ) : 
     2002def bsf (uu, e2u_e3u, mask, nperio=None, bsf0=None ) : 
    16392003    ''' 
    16402004    Computes the barotropic stream function 
    16412005    First input is zonal_velocity*e2u*e3u 
    1642     bsf0 is the point with bsf=0 (ex: bsf0={'x':5, 'y':120} ) 
    1643     ''' 
    1644     @numba.jit(forceobj=True) 
    1645     def iin (tab, dim) : 
    1646         ''' 
    1647         Integrate from the south 
    1648         ''' 
    1649         result = tab * 0.0 
    1650         nlen = len(tab.coords[dim]) 
    1651         for jn in np.arange (3, nlen) : 
    1652             result [{dim:jn}] = result [{dim:jn-1}] + tab [{dim:jn}] 
    1653         return result 
    1654      
    1655     bsf = iin ((u_e2u_e3u).sum(dim='depthu', keep_attrs=True)*1E-6, dim='y') 
    1656     bsf.attrs = u_e2u_e3u.attrs 
    1657     if bsf0 != None : 
     2006    bsf0 is the point with bsf=0  
     2007    (ex: bsf0={'x':3, 'y':120} for orca2,  
     2008         bsf0={'x':5, 'y':300} for eeORCA1 
     2009    ''' 
     2010    u_e2u_e3u       = uu * e2u_e3u 
     2011    u_e2u_e3u.attrs = uu.attrs 
     2012 
     2013    iy, ay = __findAxis__ (u_e2u_e3u, 'y') 
     2014    kz, az = __findAxis__ (u_e2u_e3u, 'z') 
     2015     
     2016    bsf = -u_e2u_e3u.cumsum ( dim=ay, keep_attrs=True ) 
     2017    bsf = bsf.sum (dim=az, keep_attrs=True)*1.E-6 
     2018         
     2019    if bsf0 : 
    16582020        bsf = bsf - bsf.isel (bsf0) 
    16592021        
    16602022    bsf = bsf.where (mask !=0, np.nan) 
    1661     bsf.attrs['long_name'] = 'Barotropic stream function' 
    1662     bsf.attrs['units'] = 'Sv' 
     2023    for attr in uu.attrs : 
     2024        bsf.attrs[attr] = uu.attrs[attr] 
     2025    bsf.attrs['standard_name'] = 'barotropic_stream_function' 
     2026    bsf.attrs['long_name']     = 'Barotropic stream function' 
     2027    bsf.attrs['units']         = 'Sv' 
    16632028    bsf = lbc (bsf, nperio=nperio, cd_type='F') 
    16642029        
     
    16792044     
    16802045    ''' 
    1681  
    1682     if ref != None : 
     2046     
     2047    import f90nml 
     2048    if ref : 
    16832049        if isinstance (ref, str) : nml_ref = f90nml.read (ref) 
    16842050        if isinstance (ref, f90nml.namelist.Namelist) : nml_ref = ref 
    16852051         
    1686     if cfg != None : 
     2052    if cfg : 
    16872053        if isinstance (cfg, str) : nml_cfg = f90nml.read (cfg) 
    16882054        if isinstance (cfg, f90nml.namelist.Namelist) : nml_cfg = cfg 
     
    16932059    list_nml = [] ; list_comment = [] 
    16942060 
    1695     if ref != None : 
    1696         list_nml.append (nml_ref) ; list_comment.append ('ref') 
    1697     if cfg != None : 
    1698         list_nml.append (nml_cfg) ; list_comment.append ('cfg') 
     2061    if ref : list_nml.append (nml_ref) ; list_comment.append ('ref') 
     2062    if cfg : list_nml.append (nml_cfg) ; list_comment.append ('cfg') 
    16992063 
    17002064    for nml, comment in zip (list_nml, list_comment) : 
     
    17192083    if out == 'xr'   : return xr_namelist 
    17202084 
    1721  
    17222085def fill_closed_seas (imask, nperio=None,  cd_type='T') : 
    17232086    '''Fill closed seas with image processing library 
     
    17302093 
    17312094    return imask_filled 
     2095 
     2096''' 
     2097Sea water state function parameters from NEMO code 
     2098''' 
     2099rdeltaS = 32. ; r1_S0  = 0.875/35.16504 ; r1_T0  = 1./40. ; r1_Z0  = 1.e-4 
     2100 
     2101EOS000 =  8.0189615746e+02 ; EOS100 =  8.6672408165e+02 ; EOS200 = -1.7864682637e+03 ; EOS300 =  2.0375295546e+03 ; EOS400 = -1.2849161071e+03 ; EOS500 =  4.3227585684e+02 ; EOS600 = -6.0579916612e+01 
     2102EOS010 =  2.6010145068e+01 ; EOS110 = -6.5281885265e+01 ; EOS210 =  8.1770425108e+01 ; EOS310 = -5.6888046321e+01 ; EOS410 =  1.7681814114e+01 ; EOS510 = -1.9193502195 
     2103EOS020 = -3.7074170417e+01 ; EOS120 =  6.1548258127e+01 ; EOS220 = -6.0362551501e+01 ; EOS320 =  2.9130021253e+01 ; EOS420 = -5.4723692739     ; EOS030 =  2.1661789529e+01  
     2104EOS130 = -3.3449108469e+01 ; EOS230 =  1.9717078466e+01 ; EOS330 = -3.1742946532 
     2105EOS040 = -8.3627885467     ; EOS140 =  1.1311538584e+01 ; EOS240 = -5.3563304045 
     2106EOS050 =  5.4048723791e-01 ; EOS150 =  4.8169980163e-01 
     2107EOS060 = -1.9083568888e-01 
     2108EOS001 =  1.9681925209e+01 ; EOS101 = -4.2549998214e+01 ; EOS201 =  5.0774768218e+01 ; EOS301 = -3.0938076334e+01 ; EOS401 =   6.6051753097    ; EOS011 = -1.3336301113e+01 
     2109EOS111 = -4.4870114575     ; EOS211 =  5.0042598061     ; EOS311 = -6.5399043664e-01 ; EOS021 =  6.7080479603     ; EOS121 =   3.5063081279 
     2110EOS221 = -1.8795372996     ; EOS031 = -2.4649669534     ; EOS131 = -5.5077101279e-01 ; EOS041 =  5.5927935970e-01 
     2111EOS002 =  2.0660924175     ; EOS102 = -4.9527603989     ; EOS202 =  2.5019633244     ; EOS012 =  2.0564311499     ; EOS112 = -2.1311365518e-01 ; EOS022 = -1.2419983026 
     2112EOS003 = -2.3342758797e-02 ; EOS103 = -1.8507636718e-02 ; EOS013 =  3.7969820455e-01  
     2113 
     2114def rhop ( ptemp, psal ) : 
     2115    ''' 
     2116    Potential density referenced to surface 
     2117    Computation from NEMO code 
     2118    ''' 
     2119    zt  = ptemp * r1_T0                                  # Temperature (°C) 
     2120    zs  = np.sqrt ( np.abs( psal + rdeltaS ) * r1_S0 )   # Square root of salinity (PSS) 
     2121    # 
     2122    prhop = (((((EOS060*zt   \ 
     2123             + EOS150*zs     + EOS050)*zt   \ 
     2124             + (EOS240*zs    + EOS140)*zs + EOS040)*zt   \ 
     2125             + ((EOS330*zs   + EOS230)*zs + EOS130)*zs + EOS030)*zt   \ 
     2126             + (((EOS420*zs  + EOS320)*zs + EOS220)*zs + EOS120)*zs + EOS020)*zt   \ 
     2127             + ((((EOS510*zs + EOS410)*zs + EOS310)*zs + EOS210)*zs + EOS110)*zs + EOS010)*zt   \ 
     2128             + (((((EOS600*zs+ EOS500)*zs + EOS400)*zs + EOS300)*zs + EOS200)*zs + EOS100)*zs + EOS000 
     2129    # 
     2130    return prhop 
     2131 
     2132def rho ( pdep, ptemp, psal ) : 
     2133    ''' 
     2134    In situ density 
     2135    Computation from NEMO code 
     2136    ''' 
     2137    zh  = pdep  * r1_Z0                                  # Depth (m) 
     2138    zt  = ptemp * r1_T0                                  # Temperature (°C) 
     2139    zs  = np.sqrt ( np.abs( psal + rdeltaS ) * r1_S0 )   # Square root salinity (PSS) 
     2140    # 
     2141    zn3 = EOS013*zt + EOS103*zs+EOS003 
     2142    # 
     2143    zn2 = (EOS022*zt + EOS112*zs+EOS012)*zt + (EOS202*zs+EOS102)*zs+EOS002 
     2144    # 
     2145    zn1 = (((EOS041*zt   \ 
     2146         + EOS131*zs   + EOS031)*zt   \ 
     2147         + (EOS221*zs  + EOS121)*zs + EOS021)*zt   \ 
     2148        + ((EOS311*zs  + EOS211)*zs + EOS111)*zs + EOS011)*zt   \ 
     2149        + (((EOS401*zs + EOS301)*zs + EOS201)*zs + EOS101)*zs + EOS001 
     2150    # 
     2151    zn0 = (((((EOS060*zt   \ 
     2152             + EOS150*zs      + EOS050)*zt   \ 
     2153             + (EOS240*zs     + EOS140)*zs + EOS040)*zt   \ 
     2154             + ((EOS330*zs    + EOS230)*zs + EOS130)*zs + EOS030)*zt   \ 
     2155             + (((EOS420*zs   + EOS320)*zs + EOS220)*zs + EOS120)*zs + EOS020)*zt   \ 
     2156             + ((((EOS510*zs  + EOS410)*zs + EOS310)*zs + EOS210)*zs + EOS110)*zs + EOS010)*zt   \ 
     2157             + (((((EOS600*zs + EOS500)*zs + EOS400)*zs + EOS300)*zs + EOS200)*zs + EOS100)*zs + EOS000 
     2158    # 
     2159    prho  = ( ( zn3 * zh + zn2 ) * zh + zn1 ) * zh + zn0 
     2160    # 
     2161    return prho 
    17322162 
    17332163## =========================================================================== 
Note: See TracChangeset for help on using the changeset viewer.