source: TOOLS/WATER_BUDGET/CPL_waterbudget.py @ 6508

Last change on this file since 6508 was 6508, checked in by omamce, 11 months ago

WaterUtils?.pyVersion qui marche pour :
Water Budget
O.M.

Version qui marche pour :

  • Grille LMDZ et routage SECHIBA
  • Grille ICO avec sorties natives et routage SIMPLE : routage pas très précis.

Ne marche pas pour :

  • Grille LMDZ et routage SIMPLE : pb sur runoff
  • Grille ICO avec sorties interpolées :

# Erreurs relatives

### VALID-CM622-LR.01 - LMDZ : OK ? Sauf LIC

  • LIC : 1.e-2
  • SRF : 4.e-6
  • SRF/ATM : 2e-10
  • RUNOFF : 1.5e-4

### VALID-CM622-SIMPLE-ROUTING - LMDZ : Erreur RUNOFF, LIC

  • LIC : 1.6
  • SRF : 1e-6
  • SRF/ATM : 1.e-10
  • RUNOFF : -7

### TEST-CM72-SIMPLE-ROUTING.13 - ICO : Erreur SRF, RUNOFF, LIC

  • LIC : 150
  • SRF : 0.5
  • SRF/ATM : 4e-2
  • RUNOFF : 700

### CM71v420-LR-pd-02.ini - ICO interpolé : Erreur SRF, RUNOFF, LIC

  • LIC : 15
  • SRF : 0.7
  • SRF/ATM : -5.e-2
  • ROUTING : 3e3

### CM71v420-LR-pd-02.ini - ICO natif : Erreurs faibles RUNOFF, LIC

  • LIC : 0.3
  • SRF : 7.e-6
  • SRF/ATM : -6.e-9
  • ROUTING : 5.e-2
  • Property svn:keywords set to Date Revision HeadURL Author Id
File size: 47.0 KB
Line 
1#!/usr/bin/env python3
2###
3### Script to check water conservation in the IPSL coupled model
4###
5##  Warning, to install, configure, run, use any of included software or
6##  to read the associated documentation you'll need at least one (1)
7##  brain in a reasonably working order. Lack of this implement will
8##  void any warranties (either express or implied).  Authors assumes
9##  no responsability for errors, omissions, data loss, or any other
10##  consequences caused directly or indirectly by the usage of his
11##  software by incorrectly or partially configured personal
12##
13##
14## SVN information
15#  $Author$
16#  $Date$
17#  $Revision$
18#  $Id$
19#  $HeadURL$
20
21
22###
23## Import system modules
24import sys, os, shutil, subprocess, platform
25import numpy as np
26import configparser, re
27from pathlib import Path
28
29# Check python version
30if sys.version_info < (3, 8, 0) :
31    print ( f'Python version : {platform.python_version()}' ) 
32    raise Exception ( "Minimum Python version is 3.8" )
33
34## Import local module
35import WaterUtils as wu
36
37## Creates parser for reading .ini input file
38config = configparser.ConfigParser (interpolation=configparser.ExtendedInterpolation() )
39config.optionxform = str # To keep capitals
40
41## Experiment parameters
42ATM=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
43
44##
45ARCHIVE=None ; STORAGE=None ; SCRATCHDIR=None ; R_IN=None ; rebuild=None
46TmpDir=None ; RunDir=None ; FileOut=None ; dir_ATM_his=None ; dir_SRF_his=None ; dir_OCE_his=None ; dir_ICE_his=None ; FileCommon=None
47file_ATM_his=None ; file_SRF_his=None ; file_RUN_his=None ; file_OCE_his=None ;  file_ICE_his=None ; file_OCE_sca=None
48tar_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
49file_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
52print ( "Name of Python script:", sys.argv[0] )
53IniFile = sys.argv[1]
54# Text existence of IniFile
55if not os.path.exists (IniFile ) :
56    raise FileExistsError ( f"File not found : {IniFile = }" )
57
58if 'full' in IniFile : FullIniFile = IniFile
59else                 : FullIniFile = 'full_' + IniFile
60   
61print ("Input file : ", IniFile )
62config.read (IniFile)
63FullIniFile = 'full_' + IniFile
64
65## Reading config file
66for Section in ['Experiment', 'libIGCM', 'Files', 'Physics' ] :
67   if Section in config.keys () : 
68        print ( f'Reading [{Section}]' )
69        for VarName in config[Section].keys() :
70            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]) )
76            #exec ( f'del {VarName}' )
77
78#-- Some physical constants
79if wu.unDefined ( 'Ra' )           : Ra          = 6366197.7236758135 #-- Earth Radius (m)
80if wu.unDefined ( 'Grav' )         : Grav        = 9.81               #-- Gravity (m^2/s
81if wu.unDefined ( 'ICE_rho_ice' )  : ICE_rho_ice = 917.0              #-- Ice volumic mass (kg/m3) in LIM3
82if wu.unDefined ( 'ICE_rho_sno')   : ICE_rho_sno = 330.0              #-- Snow volumic mass (kg/m3) in LIM3
83if wu.unDefined ( 'OCE_rho_liq' )  : OCE_rho_liq = 1026.0             #-- Ocean water volumic mass (kg/m3) in NEMO
84if wu.unDefined ( 'ATM_rho' )      : ATM_rho     = 1000.0             #-- Water volumic mass in atmosphere (kg/m^3)
85if wu.unDefined ( 'SRF_rho' )      : SRF_rho     = 1000.0             #-- Water volumic mass in surface reservoir (kg/m^3)
86if wu.unDefined ( 'RUN_rho' )      : RUN_rho     = 1000.0             #-- Water volumic mass of rivers (kg/m^3)
87if wu.unDefined ( 'ICE_rho_pnd' )  : ICE_rho_pnd = 1000.              #-- Water volumic mass in ice ponds (kg/m^3)
88if 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
91if not 'Files' in config.keys() : config['Files'] = {}
92
93config['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}
94
95## --------------------------
96ICO  = ( 'ICO' in wu.ATM )
97LMDZ = ( 'LMD' in wu.ATM )
98
99with open ('SetLibIGCM.py') as f: exec ( f.read() )
100config['Files']['TmpDir'] = TmpDir
101
102if libIGCM :
103    config['libIGCM'] = {'ARCHIVE':ARCHIVE, 'STORAGE':STORAGE, 'SCRATCHDIR':SCRATCHDIR, 'R_IN':R_IN, 'rebuild':rebuild }
104
105# Import specific module
106import nemo, lmdz
107## Now import needed scientific modules
108import xarray as xr
109   
110# Output file with water budget diagnostics
111if wu.unDefined ( 'FileOut' ) : FileOut = f'CPL_waterbudget_{JobName}_{YearBegin}_{YearEnd}.out'
112config['Files']['FileOut'] = FileOut
113
114f_out = open ( FileOut, mode = 'w' )
115   
116# Useful functions
117def kg2Sv    (val, rho=ATM_rho) :
118    '''From kg to Sverdrup'''
119    return val/dtime_sec*1.0e-6/rho
120
121def kg2myear (val, rho=ATM_rho) :
122    '''From kg to m/year'''
123    return val/ATM_aire_sea_tot/rho/NbYear
124
125def var2prt (var, small=False, rho=ATM_rho) :
126    if small :  return var , kg2Sv(var, rho=rho)*1000., kg2myear(var, rho=rho)*1000.
127    else     :  return var , kg2Sv(var, rho=rho)      , kg2myear(var, rho=rho)
128
129def prtFlux (Desc, var, Form='F', small=False, rho=ATM_rho, width=15) :
130    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 "
133    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 ) )
137    return None
138
139def echo (string, end='\n') :
140    '''Function to print to stdout *and* output file'''
141    print ( str(string), end=end  )
142    sys.stdout.flush ()
143    f_out.write ( str(string) + end )
144    f_out.flush ()
145    return None
146   
147## Set libIGCM directories
148if wu.unDefined ('R_OUT'      ) : R_OUT       = os.path.join ( ARCHIVE   , 'IGCM_OUT' )
149if wu.unDefined ('R_BUF'      ) : R_BUF       = os.path.join ( SCRATCHDIR, 'IGCM_OUT' )
150if wu.unDefined ('L_EXP'      ) : L_EXP       = os.path.join (TagName, SpaceName, ExperimentName, JobName)
151if wu.unDefined ('R_SAVE'     ) : R_SAVE      = os.path.join ( R_OUT, L_EXP )
152if wu.unDefined ('R_BUFR'     ) : R_BUFR      = os.path.join ( R_BUF, L_EXP )
153if wu.unDefined ('POST_DIR'   ) : POST_DIR    = os.path.join ( R_BUFR, 'Out' )
154if wu.unDefined ('REBUILD_DIR') : REBUILD_DIR = os.path.join ( R_BUFR, 'REBUILD' )
155if wu.unDefined ('R_BUF_KSH'  ) : R_BUF_KSH   = os.path.join ( R_BUFR, 'Out' )
156if wu.unDefined ('R_FIGR'     ) : R_FIGR      = os.path.join ( STORAGE, 'IGCM_OUT', L_EXP )
157
158config['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
161if RunDir == None : RunDir = os.path.join ( TmpDir, f'WATER_{JobName}_{YearBegin}_{YearEnd}' )
162config['Files']['RunDir'] = RunDir
163
164if not os.path.isdir ( RunDir ) : os.makedirs ( RunDir )
165
166# Set directories to rebuild ocean and ice restart files
167RunDirOCE = os.path.join ( RunDir, 'OCE' )
168RunDirICE = 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' )
173if not os.path.exists ( RunDirOCE ) : os.mkdir ( RunDirOCE )
174if not os.path.exists ( RunDirICE ) : os.mkdir ( RunDirICE )
175
176echo (' ')
177echo ( f'JobName   : {JobName}'   )
178echo ( f'Comment   : {Comment}'   )
179echo ( f'TmpDir    : {TmpDir}'    )
180echo ( f'RunDirOCE : {RunDirOCE}' )
181echo ( f'RunDirICE : {RunDirICE}' )
182
183echo ( f'\nDealing with {L_EXP}'  )
184
185#-- Model output directories
186if Freq == "MO" : FreqDir =  os.path.join ('Output' , 'MO' )
187if Freq == "SE" : FreqDir =  os.path.join ('Analyse', 'SE' )
188if dir_ATM_his == None :
189    dir_ATM_his = os.path.join ( R_SAVE, "ATM", FreqDir )
190    config['Files']['dir_ATM_his'] = dir_ATM_his
191if dir_SRF_his == None : 
192    dir_SRF_his = os.path.join ( R_SAVE, "SRF", FreqDir )
193    config['Files']['dir_SRF_his'] = dir_SRF_his
194if dir_OCE_his == None :
195    dir_OCE_his = os.path.join ( R_SAVE, "OCE", FreqDir )
196    config['Files']['dir_OCE_his'] = dir_OCE_his
197if dir_ICE_his == None : 
198    dir_ICE_his = os.path.join ( R_SAVE, "ICE", FreqDir )
199    config['Files']['dir_ICE_his'] = dir_ICE_his
200
201echo ( f'The analysis relies on files from the following model output directories : ' )
202echo ( f'{dir_ATM_his}' )
203echo ( f'{dir_OCE_his}' )
204echo ( f'{dir_ICE_his}' )
205echo ( f'{dir_SRF_his}' )
206
207#-- Creates files names
208if 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'
211    config['Files']['Period'] = Period
212if FileCommon == None :
213    FileCommon = f'{JobName}_{Period}'
214    config['Files']['FileCommon'] = FileCommon
215
216if Title == None :
217    Title = f'{JobName} : {Freq} : {YearBegin}-01-01 - {YearEnd}-12-31'
218    config['Files']['Title'] = Title
219
220echo ('\nOpen history files' )
221if file_ATM_his == None : 
222    file_ATM_his = os.path.join (  dir_ATM_his, f'{FileCommon}_histmth.nc' )
223    config['Files']['file_ATM_his'] = file_ATM_his
224if file_SRF_his == None :
225    file_SRF_his = os.path.join (  dir_SRF_his, f'{FileCommon}_sechiba_history.nc' )
226    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' )
229if Routing == 'SIMPLE' :
230    if file_RUN_his == None : 
231        file_RUN_his = os.path.join (  dir_SRF_his, f'{FileCommon}_sechiba_history.nc' )
232        config['Files']['file_RUN_his'] = file_RUN_his
233if 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
236if 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
239if 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
242if 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
246d_ATM_his = xr.open_dataset ( file_ATM_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze()
247d_OCE_his = xr.open_dataset ( file_OCE_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze()
248d_OCE_sca = xr.open_dataset ( file_OCE_sca, use_cftime=True, decode_times=True, decode_cf=True ).squeeze()
249d_ICE_his = xr.open_dataset ( file_ICE_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze()
250if NEMO == '3.6' :d_ICE_his = d_ICE_his.rename ( {'y_grid_T':'y', 'x_grid_T':'x'} )
251d_SRF_his = xr.open_dataset ( file_SRF_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze()
252d_OCE_srf = xr.open_dataset ( file_OCE_srf, use_cftime=True, decode_times=True, decode_cf=True ).squeeze()
253if Routing == 'SECHIBA' : d_RUN_his = d_SRF_his
254if Routing == 'SIMPLE'  : d_RUN_his = xr.open_dataset ( file_RUN_his, use_cftime=True, decode_times=True, decode_cf=True ).squeeze()
255
256   
257echo ( f'{file_ATM_his = }' )
258echo ( f'{file_SRF_his = }' )
259if Routing == 'SIMPLE' : echo ( f'{file_RUN_his = }' )
260echo ( f'{file_OCE_his = }' )
261echo ( f'{file_ICE_his = }' )
262echo ( f'{file_OCE_sca = }' )
263echo ( f'{file_OCE_srf = }' )
264
265## Compute run length
266dtime = ( d_ATM_his.time_counter_bounds.max() - d_ATM_his.time_counter_bounds.min() )
267echo ('\nRun length : {:8.2f} days'.format ( (dtime/np.timedelta64(1, "D")).values ) )
268dtime_sec = (dtime/np.timedelta64(1, "s")).values.item() # Convert in seconds
269
270## Compute length of each period
271dtime_per = (d_ATM_his.time_counter_bounds[:,-1] -  d_ATM_his.time_counter_bounds[:,0] )
272echo ('\nPeriods lengths (days) : {:} days'.format ( (dtime_per/np.timedelta64(1, "D")).values ) )
273dtime_per_sec = (dtime_per/np.timedelta64(1, "s")).values # In seconds
274dtime_per_sec = xr.DataArray (dtime_per_sec, dims=["time_counter", ], coords=[d_ATM_his.time_counter,] )
275dtime_per_sec.attrs['unit'] = 's'
276
277# Number of years
278NbYear = dtime_sec / YearLength
279
280#-- Open restart files
281YearRes = YearBegin - 1        # Year of the restart of beginning of simulation
282YearPre = YearBegin - PackFrequency  # Year to find the tarfile of the restart of beginning of simulation
283
284config['Files']['YearPre'] = f'{YearBegin}'
285
286echo (f'Restart dates - Start : {YearRes}-12-31  /  End : {YearEnd}-12-31 ')
287
288if 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
293if 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
299if 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
302if 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
306echo ( f'{tar_restart_beg}' )
307echo ( f'{tar_restart_end}' )
308
309if 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
312if 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
316if 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   
321if 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   
326if 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
329if 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   
333if 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
336if 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
339if 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
342if 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
346liste_beg = [file_ATM_beg, file_DYN_beg, file_SRF_beg]
347liste_end = [file_ATM_end, file_DYN_end, file_SRF_end]
348
349if 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
362echo ( f'{file_ATM_beg = }' )
363echo ( f'{file_ATM_end = }' )
364echo ( f'{file_DYN_beg = }' )
365echo ( f'{file_DYN_end = }' )
366echo ( f'{file_SRF_beg = }' )
367echo ( f'{file_SRF_end = }' )
368echo ( f'{file_RUN_beg = }' )
369echo ( f'{file_RUN_end = }' )
370echo ( f'{file_OCE_beg = }' )
371echo ( f'{file_OCE_end = }' )
372echo ( f'{file_ICE_beg = }' )
373echo ( f'{file_ICE_end = }' )
374
375echo ('\nExtract restart files from tar : ATM, ICO and SRF')
376for 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
387echo ('\nOpening ATM SRF and ICO restart files')
388d_ATM_beg = xr.open_dataset ( os.path.join (RunDir, file_ATM_beg), decode_times=False, decode_cf=True).squeeze()
389d_ATM_end = xr.open_dataset ( os.path.join (RunDir, file_ATM_end), decode_times=False, decode_cf=True).squeeze()
390d_SRF_beg = xr.open_dataset ( os.path.join (RunDir, file_SRF_beg), decode_times=False, decode_cf=True).squeeze()
391d_SRF_end = xr.open_dataset ( os.path.join (RunDir, file_SRF_end), decode_times=False, decode_cf=True).squeeze()
392d_DYN_beg = xr.open_dataset ( os.path.join (RunDir, file_DYN_beg), decode_times=False, decode_cf=True).squeeze()
393d_DYN_end = xr.open_dataset ( os.path.join (RunDir, file_DYN_end), decode_times=False, decode_cf=True).squeeze()
394
395echo ('\nExtract and rebuild OCE and ICE restarts')
396def 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
403def 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
436extract_and_rebuild ( file_name=file_OCE_beg, tar_restart=tar_restart_beg, RunDirComp=RunDirOCE )
437extract_and_rebuild ( file_name=file_OCE_end, tar_restart=tar_restart_end, RunDirComp=RunDirOCE )
438extract_and_rebuild ( file_name=file_ICE_beg, tar_restart=tar_restart_beg, RunDirComp=RunDirICE )
439extract_and_rebuild ( file_name=file_ICE_end, tar_restart=tar_restart_end, RunDirComp=RunDirICE )
440
441echo ('Opening OCE and ICE restart files')
442if 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()
447if 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
453## Write the full configuration
454config_out = open (FullIniFile, 'w')
455config.write (config_out )
456config_out.close ()
457
458for 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
462if 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
466def kg2Sv  (val, rho=OCE_rho_liq) :
467    '''From kg to Sverdrup'''
468    return val/dtime_sec*1.0e-6/rho
469
470def kg2myear (val, rho=OCE_rho_liq) :
471    '''From kg to m/year'''
472    return val/OCE_aire_tot/rho/NbYear
473
474def var2prt (var, small=False) :
475    if small :  return var , kg2Sv(var)*1000., kg2myear(var)*1000.
476    else     :  return var , kg2Sv(var)      , kg2myear(var)
477
478def 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
490# ATM grid with cell surfaces
491if ICO :
492    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
506    if ATM_HIS == 'ico' :
507        echo ( f'Aire sur grille icosaedre : {file_ATM_aire = }' )
508       
509if 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   
518ATM_fsea      = ATM_foce + ATM_fsic
519ATM_flnd      = ATM_fter + ATM_flic
520ATM_aire_fter = ATM_aire * ATM_fter
521ATM_aire_flic = ATM_aire * ATM_flic
522ATM_aire_fsic = ATM_aire * ATM_fsic
523ATM_aire_foce = ATM_aire * ATM_foce
524ATM_aire_flnd = ATM_aire * ATM_flnd
525ATM_aire_fsea = ATM_aire * ATM_fsea
526
527SRF_aire = SRF_aire.where ( SRF_aire < 1E15, 0.)
528
529if 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   
539if 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
547def 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
551
552def ATM_flux_int (flux) :
553    '''Integrate (* time * surface) flux on atmosphere grid'''
554    ATM_flux_int  = wu.Psum ( (flux * dtime_per_sec * ATM_aire).to_masked_array().ravel() )
555    return ATM_flux_int
556
557def 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
561
562def SRF_flux_int (flux) :
563    '''Integrate (* time * surface) flux on land grid'''
564    SRF_flux_int  = wu.Psum (  (flux * dtime_per_sec * SRF_aire).to_masked_array().ravel() )
565    return SRF_flux_int
566
567def 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
571
572def ONE_stock_int (stock) :
573    '''Sum stock'''
574    ONE_stock_int = np.sum (  np.sort ( (stock ).to_masked_array().ravel()) )
575    return ONE_stock_int
576
577def OCE_flux_int (flux) :
578    '''Integrate flux on oce grid'''
579    OCE_flux_int = np.sum (  np.sort ( (flux * OCE_aire * dtime_per_sec).to_masked_array().ravel()) )
580    return OCE_flux_int
581
582def ONE_flux_int (flux) :
583    '''Integrate flux on oce grid'''
584    OCE_flux_int = np.sum (  np.sort ( (flux * dtime_per_sec).to_masked_array().ravel()) )
585    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} )
589
590# Get mask and surfaces
591sos = d_OCE_his ['sos'][0].squeeze()
592OCE_msk = nemo.lbc_mask ( xr.where ( sos>0, 1., 0.0 ), cd_type = 'T' )
593so = sos = d_OCE_his ['sos'][0].squeeze()
594OCE_msk3 = nemo.lbc_mask ( xr.where ( so>0., 1., 0. ), cd_type = 'T', sval = 0. )
595
596# lbc_mask removes the duplicate points (periodicity and north fold)
597OCE_aire = nemo.lbc_mask ( d_OCE_his ['area'] * OCE_msk, cd_type = 'T', sval = 0.0 )
598ICE_aire = OCE_aire
599
600ATM_aire_tot = ONE_stock_int (ATM_aire)
601SRF_aire_tot = ONE_stock_int (SRF_aire)
602OCE_aire_tot = ONE_stock_int (OCE_aire)
603ICE_aire_tot = ONE_stock_int (ICE_aire)
604
605ATM_aire_sea     = ATM_aire * ATM_fsea
606ATM_aire_sea_tot = ONE_stock_int ( ATM_aire_sea )
607
608echo ( '\n====================================================================================' )
609echo ( '-- 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
615OCE_ssh_beg = d_OCE_beg['sshn']
616OCE_ssh_end = d_OCE_end['sshn']
617OCE_sum_ssh_beg = OCE_stock_int ( OCE_ssh_beg )
618OCE_sum_ssh_end = OCE_stock_int ( OCE_ssh_end )
619
620OCE_mas_wat_beg = OCE_sum_ssh_beg * OCE_rho_liq
621OCE_mas_wat_end = OCE_sum_ssh_end * OCE_rho_liq
622
623echo ( '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) )
624dOCE_vol_liq = ( OCE_sum_ssh_end - OCE_sum_ssh_beg )
625dOCE_mas_liq = dOCE_vol_liq * OCE_rho_liq
626dOCE_mas_wat = dOCE_mas_liq
627
628echo ( 'dOCE vol    = {:12.3e} m^3'.format (dOCE_vol_liq) )
629echo ( 'dOCE ssh    = {:12.3e} m  '.format (dOCE_vol_liq/OCE_aire_tot) )
630echo ( 'dOCE mass   = {:12.3e} kg '.format (dOCE_mas_liq) )
631echo ( 'dOCE mass   = {:12.3e} Sv '.format (dOCE_mas_liq/dtime_sec*1E-6/OCE_rho_liq) )
632
633## Glace et neige
634if 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   
647if 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   
657ICE_vol_ice_beg = OCE_stock_int ( ICE_ice_beg )
658ICE_vol_ice_end = OCE_stock_int ( ICE_ice_end )
659
660ICE_vol_sno_beg = OCE_stock_int ( ICE_sno_beg )
661ICE_vol_sno_end = OCE_stock_int ( ICE_sno_end )
662
663ICE_vol_pnd_beg = OCE_stock_int ( ICE_pnd_beg )
664ICE_vol_pnd_end = OCE_stock_int ( ICE_pnd_end )
665
666ICE_vol_fzl_beg = OCE_stock_int ( ICE_fzl_beg )
667ICE_vol_fzl_end = OCE_stock_int ( ICE_fzl_end )
668
669#-- Converting to freswater volume
670dICE_vol_ice = ICE_vol_ice_end - ICE_vol_ice_beg
671dICE_mas_ice = dICE_vol_ice * ICE_rho_ice
672
673dICE_vol_sno = ICE_vol_sno_end - ICE_vol_sno_beg
674dICE_mas_sno = dICE_vol_sno * ICE_rho_sno
675
676dICE_vol_pnd = ICE_vol_pnd_end - ICE_vol_pnd_beg
677dICE_mas_pnd = dICE_vol_pnd * ICE_rho_pnd
678
679dICE_vol_fzl= ICE_vol_fzl_end - ICE_vol_fzl_beg
680dICE_mas_fzl = dICE_vol_fzl * ICE_rho_pnd
681
682if 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
686if 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
690echo ( 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' )
691echo ( 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' )
692echo ( 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' )
693echo ( 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
695echo ( f'dICE_vol_ice   = {dICE_vol_ice:12.3e} m^3' )
696echo ( f'dICE_vol_sno   = {dICE_vol_sno:12.3e} m^3' )
697echo ( f'dICE_vol_pnd   = {dICE_vol_pnd:12.3e} m^3' )
698echo ( f'dICE_mas_ice   = {dICE_mas_ice:12.3e} m^3' )
699echo ( f'dICE_mas_sno   = {dICE_mas_sno:12.3e} m^3' ) 
700echo ( f'dICE_mas_pnd   = {dICE_mas_pnd:12.3e} m^3' ) 
701echo ( f'dICE_mas_fzl   = {dICE_mas_fzl:12.3e} m^3' ) 
702echo ( f'dICE_mas_wat   = {dICE_mas_wat:12.3e} m^3' ) 
703
704
705SEA_mas_wat_beg = OCE_mas_wat_beg + ICE_mas_wat_beg
706SEA_mas_wat_end = OCE_mas_wat_end + ICE_mas_wat_end
707
708echo ( '\n------------------------------------------------------------')
709echo ( 'Variation du contenu en eau ocean + glace ' )
710echo ( 'dMass (ocean)   = {:12.6e} kg '.format(dSEA_mas_wat) )
711echo ( 'dVol  (ocean)   = {:12.3e} Sv '.format(dSEA_mas_wat/dtime_sec*1E-6/OCE_rho_liq) )
712echo ( 'dVol  (ocean)   = {:12.3e} m  '.format(dSEA_mas_wat*1E-3/OCE_aire_tot) )
713
714
715echo ( '\n------------------------------------------------------------------------------------' )
716echo ( '-- 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
722ATM_Ahyb = d_ATM_his['Ahyb'].squeeze()
723ATM_Bhyb = d_ATM_his['Bhyb'].squeeze()
724klevp1 = ATM_Ahyb.shape[0]
725
726# Surface pressure
727if ICO : 
728    DYN_ps_beg = d_DYN_beg['ps']
729    DYN_ps_end = d_DYN_end['ps']
730   
731if 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
736DYN_p_beg = ATM_Ahyb + ATM_Bhyb * DYN_ps_beg
737DYN_p_end = ATM_Ahyb + ATM_Bhyb * DYN_ps_end
738
739# Layer thickness
740DYN_sigma_beg = DYN_p_beg[0:-1]*0.
741DYN_sigma_end = DYN_p_end[0:-1]*0. 
742
743for 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
747DYN_sigma_beg = DYN_sigma_beg.rename ( {'klevp1':'sigs'} )
748DYN_sigma_end = DYN_sigma_end.rename ( {'klevp1':'sigs'} )
749
750##-- Vertical and horizontal integral, and sum of liquid, solid and vapor water phases
751if 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) ) )
758if 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   
766DYN_mas_wat_beg = ATM_stock_int (DYN_sigma_beg * DYN_wat_beg)
767DYN_mas_wat_end = ATM_stock_int (DYN_sigma_end * DYN_wat_end)
768
769dDYN_mas_wat = DYN_mas_wat_end - DYN_mas_wat_beg
770
771echo ( '\nVariation du contenu en eau atmosphere (dynamique) ' )
772echo ( 'DYN_mas_beg = {:12.6e} kg | DYN_mas_end = {:12.6e} kg'.format (DYN_mas_wat_beg, DYN_mas_wat_end) )
773echo ( 'dMass (atm)   = {:12.3e} kg '.format (dDYN_mas_wat) )
774echo ( 'dMass (atm)   = {:12.3e} Sv '.format (dDYN_mas_wat/dtime_sec*1.e-6/ATM_rho) )
775echo ( 'dMass (atm)   = {:12.3e} m  '.format (dDYN_mas_wat/ATM_aire_sea_tot/ATM_rho) )
776
777ATM_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']
778ATM_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
780ATM_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']
781ATM_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
783ATM_qsol_beg = d_ATM_beg['QSOL']
784ATM_qsol_end = d_ATM_end['QSOL']
785
786ATM_qs01_beg  = d_ATM_beg['QS01'] * d_ATM_beg['FTER']
787ATM_qs01_end  = d_ATM_end['QS01'] * d_ATM_end['FTER']
788ATM_qs02_beg  = d_ATM_beg['QS02'] * d_ATM_beg['FLIC']
789ATM_qs02_end  = d_ATM_end['QS02'] * d_ATM_end['FLIC']
790ATM_qs03_beg  = d_ATM_beg['QS03'] * d_ATM_beg['FOCE']
791ATM_qs03_end  = d_ATM_end['QS03'] * d_ATM_end['FOCE']
792ATM_qs04_beg  = d_ATM_beg['QS04'] * d_ATM_beg['FSIC']
793ATM_qs04_end  = d_ATM_end['QS04'] * d_ATM_end['FSIC'] 
794
795if 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
811echo ('Computing atmosphere integrals')
812ATM_mas_sno_beg   = ATM_stock_int ( ATM_sno_beg  )
813ATM_mas_sno_end   = ATM_stock_int ( ATM_sno_end  )
814ATM_mas_qs_beg    = ATM_stock_int ( ATM_qs_beg   )
815ATM_mas_qs_end    = ATM_stock_int ( ATM_qs_end   )
816ATM_mas_qsol_beg  = ATM_stock_int ( ATM_qsol_beg )
817ATM_mas_qsol_end  = ATM_stock_int ( ATM_qsol_end )
818ATM_mas_qs01_beg  = ATM_stock_int ( ATM_qs01_beg )
819ATM_mas_qs01_end  = ATM_stock_int ( ATM_qs01_end )
820ATM_mas_qs02_beg  = ATM_stock_int ( ATM_qs02_beg )
821ATM_mas_qs02_end  = ATM_stock_int ( ATM_qs02_end )
822ATM_mas_qs03_beg  = ATM_stock_int ( ATM_qs03_beg )
823ATM_mas_qs03_end  = ATM_stock_int ( ATM_qs03_end )
824ATM_mas_qs04_beg  = ATM_stock_int ( ATM_qs04_beg )
825ATM_mas_qs04_end  = ATM_stock_int ( ATM_qs04_end )
826
827dATM_mas_sno  = ATM_mas_sno_end  - ATM_mas_sno_beg
828dATM_mas_qs   = ATM_mas_qs_end   - ATM_mas_qs_beg
829dATM_mas_qsol = ATM_mas_qsol_end - ATM_mas_qsol_beg
830
831dATM_mas_qs01 = ATM_mas_qs01_end - ATM_mas_qs01_beg
832dATM_mas_qs02 = ATM_mas_qs02_end - ATM_mas_qs02_beg
833dATM_mas_qs03 = ATM_mas_qs03_end - ATM_mas_qs03_beg
834dATM_mas_qs04 = ATM_mas_qs04_end - ATM_mas_qs04_beg
835
836echo ( '\nVariation du contenu en neige atmosphere (calottes)' )
837echo ( 'ATM_mas_sno_beg  = {:12.6e} kg | ATM_mas_sno_end  = {:12.6e} kg'.format (ATM_mas_sno_beg, ATM_mas_sno_end) )
838echo ( 'dMass (neige atm) = {:12.3e} kg '.format (dATM_mas_sno ) )
839echo ( 'dMass (neige atm) = {:12.3e} Sv '.format (dATM_mas_sno/dtime_sec*1e-6/ICE_rho_ice) )
840echo ( 'dMass (neige atm) = {:12.3e} m  '.format (dATM_mas_sno/ATM_aire_sea_tot/ATM_rho) )
841
842echo ( '\nVariation du contenu humidite du sol' )
843echo ( 'ATM_mas_qs_beg  = {:12.6e} kg | ATM_mas_qs_end  = {:12.6e} kg'.format (ATM_mas_qs_beg, ATM_mas_qs_end) )
844echo ( 'dMass (neige atm) = {:12.3e} kg '.format (dATM_mas_qs ) )
845echo ( 'dMass (neige atm) = {:12.3e} Sv '.format (dATM_mas_qs/dtime_sec*1e-6/ATM_rho) )
846echo ( 'dMass (neige atm) = {:12.3e} m  '.format (dATM_mas_qs/ATM_aire_sea_tot/ATM_rho) )
847
848echo ( '\nVariation du contenu en eau+neige atmosphere ' )
849echo ( 'dMass (eau + neige atm) = {:12.3e} kg '.format (  dDYN_mas_wat + dATM_mas_sno) )
850echo ( 'dMass (eau + neige atm) = {:12.3e} Sv '.format ( (dDYN_mas_wat + dATM_mas_sno)/dtime_sec*1E-6/ATM_rho) )
851echo ( 'dMass (eau + neige atm) = {:12.3e} m  '.format ( (dDYN_mas_wat + dATM_mas_sno)/ATM_aire_sea_tot/ATM_rho) )
852
853echo ( '\n------------------------------------------------------------------------------------' )
854echo ( '-- SRF changes ' )
855
856if 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
860if 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
866dRUN_mas_wat = RUN_mas_wat_end - RUN_mas_wat_beg
867   
868echo ( '\nWater content in routing ' )
869echo ( 'RUN_mas_wat_beg = {:12.6e} kg | RUN_mas_wat_end = {:12.6e} kg '.format (RUN_mas_wat_end, RUN_mas_wat_end) )
870echo ( 'dMass (routing)  = {:12.3e} kg '.format(dRUN_mas_wat) )
871echo ( 'dMass (routing)  = {:12.3e} Sv '.format(dRUN_mas_wat/dtime_sec*1E-9) )
872echo ( 'dMass (routing)  = {:12.3e} m  '.format(dRUN_mas_wat/OCE_aire_tot*1E-3) )
873
874print ('Reading SRF restart')
875tot_watveg_beg  = d_SRF_beg['tot_watveg_beg']  ; tot_watveg_beg  = tot_watveg_beg .where (tot_watveg_beg < 1E10, 0.)
876tot_watsoil_beg = d_SRF_beg['tot_watsoil_beg'] ; tot_watsoil_beg = tot_watsoil_beg.where (tot_watsoil_beg< 1E10, 0.)
877snow_beg        = d_SRF_beg['snow_beg']        ; snow_beg        = snow_beg       .where (snow_beg       < 1E10, 0.)
878
879tot_watveg_end  = d_SRF_end['tot_watveg_beg']  ; tot_watveg_end  = tot_watveg_end .where (tot_watveg_end < 1E10, 0.)
880tot_watsoil_end = d_SRF_end['tot_watsoil_beg'] ; tot_watsoil_end = tot_watsoil_end.where (tot_watsoil_end< 1E10, 0.)
881snow_end        = d_SRF_end['snow_beg']        ; snow_end        = snow_end       .where (snow_end       < 1E10, 0.)
882
883if 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
891SRF_wat_beg = tot_watveg_beg + tot_watsoil_beg + snow_beg
892SRF_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'} )
906if 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
916print ('Computing integrals')
917
918print ( ' 1/6', end='' ) ; sys.stdout.flush ()
919SRF_mas_watveg_beg   = ATM_stock_int ( tot_watveg_beg  )
920print ( ' 2/6', end='' ) ; sys.stdout.flush ()
921SRF_mas_watsoil_beg  = ATM_stock_int ( tot_watsoil_beg )
922print ( ' 3/6', end='' ) ; sys.stdout.flush ()
923SRF_mas_snow_beg     = ATM_stock_int ( snow_beg        )
924print ( ' 4/6', end='' ) ; sys.stdout.flush ()
925SRF_mas_watveg_end   = ATM_stock_int ( tot_watveg_end  )
926print ( ' 5/6', end='' ) ; sys.stdout.flush ()
927SRF_mas_watsoil_end  = ATM_stock_int ( tot_watsoil_end )
928print ( ' 6/6', end='' ) ; sys.stdout.flush ()
929SRF_mas_snow_end     = ATM_stock_int ( snow_end        )
930print (' -- ') ; sys.stdout.flush ()
931
932dSRF_mas_watveg   = SRF_mas_watveg_end   - SRF_mas_watveg_beg
933dSRF_mas_watsoil  = SRF_mas_watsoil_end  - SRF_mas_watsoil_beg
934dSRF_mas_snow     = SRF_mas_snow_end     - SRF_mas_snow_beg
935
936echo ('\nLes differents reservoirs')
937echo ( f'SRF_mas_watveg_beg   = {SRF_mas_watveg_beg :12.6e} kg | SRF_mas_watveg_end   = {SRF_mas_watveg_end :12.6e} kg ' )
938echo ( f'SRF_mas_watsoil_beg  = {SRF_mas_watsoil_beg:12.6e} kg | SRF_mas_watsoil_end  = {SRF_mas_watsoil_end:12.6e} kg ' )
939echo ( f'SRF_mas_snow_beg     = {SRF_mas_snow_beg   :12.6e} kg | SRF_mas_snow_end     = {SRF_mas_snow_end   :12.6e} kg ' )
940
941echo ( '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) )
942echo ( '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) )
943echo ( '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
945SRF_mas_wat_beg = SRF_mas_watveg_beg + SRF_mas_watsoil_beg + SRF_mas_snow_beg
946SRF_mas_wat_end = SRF_mas_watveg_end + SRF_mas_watsoil_end + SRF_mas_snow_end
947dSRF_mas_wat = SRF_mas_wat_end - SRF_mas_wat_beg
948
949echo ( '\nWater content in surface ' )
950echo ( 'SRF_mas_wat_beg  = {:12.6e} kg | SRF_mas_wat_end  = {:12.6e} kg '.format (SRF_mas_wat_beg, SRF_mas_wat_end) )
951echo ( 'dMass (water srf) = {:12.3e} kg '.format (dSRF_mas_wat) )
952echo ( 'dMass (water srf) = {:12.3e} Sv '.format (dSRF_mas_wat/dtime_sec*1E-6/ATM_rho) )
953echo ( 'dMass (water srf) = {:12.3e} m  '.format (dSRF_mas_wat/ATM_aire_sea_tot/ATM_rho) )
954
955echo ( '\nWater content in  ATM + SRF + RUN ' )
956echo ( '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) )
959echo ( 'dMass (water atm+srf+run) = {:12.6e} kg '.format ( dDYN_mas_wat + dATM_mas_sno + dRUN_mas_wat + dSRF_mas_wat) )
960echo ( '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) )
961echo ( '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
963echo ( '\n------------------------------------------------------------------------------------' )
964echo ( '-- Change in all components' )
965echo ( '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) )
968echo ( 'dMass (water CPL)         = {:12.3e} kg '.format ( dSEA_mas_wat + dDYN_mas_wat + dATM_mas_sno + dRUN_mas_wat + dSRF_mas_wat) )
969echo ( '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) )
970echo ( '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
Note: See TracBrowser for help on using the repository browser.