# JvP 20210202: added import statements, MODULE_NAME module level logger
# JvP 20210720: added import of os
import logging
import sys
import os
from ......utils.check.errclass import CifRuntimeError
MODULE_NAME = __name__[__name__.index('TM5'):] if 'TM5' in __name__ else __name__
logger = logging.getLogger(MODULE_NAME)
[docs]
def pp_list( some_list, indent=0, items_per_line=8 ):
"""
PURPOSE
Pretty Print a list with names (i.e. strings) such as returned by the dir
function.
RETURNS
A string with the list items concatenated and inserted newlines.
ARGS
some_list = the list to print
KWARGS
indent = additional indent so that the list items line up nicely if
they are printed on multiple lines.
items_per_line = number of list items to print on a single line
ASSUMPTIONS
none
EXCEPTIONS
When this function encounters a problem that it cannot solve,
it will raise a RuntimeError. Pythons exeception handling will
provide a traceback, including files, calls and line numbers.
PYTHON VERSION
3.8.6
VERSION CHANGE HISTORY
1.0 15-04-2021 by J.C.A. van Peet.
Original code.
"""
return ("\n" + " " * indent).join( [ ', '.join(some_list[i:i + items_per_line])
for i in range(0, len(some_list), items_per_line) ] )
# end function pp_list
[docs]
def write_tm5_rc(self, config_file, runsubdir, mode, **kwargs):
"""
PURPOSE
There are two types of rc files for running TM5: 'tm5.rc' and
'tmvar-precon-run.rc'. The first is used in the jobs 'fwd', 'apos' and
'grd', the second in the jobs 'g2gc' and 'xc2x'. Some parameters in the
'tm5.rc' file vary from iteration to iteration, but most are constant.
These few parameters are changed using the keyword arguments to this
function. The same is true for the 'tmvar-precon-run.rc' files, but the set
of parameters is very different than that for the 'tm5.rc' files, so they
are written in their own function.
IN/OUT
self = TM5 model plugin, containing all TM5 settings.
config_file = filename to write the config settings to
mode = String with the mode of the TM5 run. Can be either 'fwd'
for a forward run or 'adj' for an adjoint run.
KWARGS
A lot, probably. To keep the function header clean, they are set in the
function body using kwargs.pop(...).
ASSUMPTIONS
none
EXCEPTIONS
When this function encounters a problem that it cannot solve,
it will raise a RuntimeError. Pythons exeception handling will
provide a traceback, including files, calls and line numbers.
PYTHON VERSION
3.8.6
VERSION CHANGE HISTORY
2.2 28-10-2021 by J.C.A. van Peet.
Updated determination of iter_nr.
2.1 22-10-2021 by J.C.A. van Peet.
Updated path to point departures file following changes by Antoine.
2.0 20-07-2021 by J.C.A. van Peet.
*) Added the mode argument to indicate forward (fwd) or adjoint (adj)
runs.
*) Added extraction of the iteration number from config_file.
*) Updated the setting of station.list.file
*) Updated write statements to include adj variables when they are
different than the fwd variables.
1.1 22-02-2021 by J.C.A. van Peet.
Added runsubdir as a parameter to this function. See the function
make_config below for more information.
1.0 03-02-2021 by J.C.A. van Peet.
Original code.
"""
# Set the name of this function
PROG_NAME = MODULE_NAME + ".write_tm5_rc"
# Local logger
logger = logging.getLogger(PROG_NAME)
logger.setLevel(logging.DEBUG)
# Keyword arguments
# bagger = kwargs.pop("bagger", "bagger")
# Debug messages
indent = 35
logger.debug("")
logger.debug("*" * 30)
logger.debug(PROG_NAME + " => DEBUG:")
logger.debug(
f" self = {self}" )
logger.debug(
f" dir(self) = {pp_list(dir(self), indent=indent)}" )
logger.debug(
f" self.attributes = {pp_list(self.attributes, indent=indent)}" )
logger.debug(
f" datei = {self.datei}" )
logger.debug(
f" datef = {self.datef}" )
logger.debug(
f" dir(self.chemistry) = {pp_list(dir(self.chemistry), indent=indent)}" )
logger.debug(
f" self.chemistry.attributes = {pp_list(self.chemistry.attributes, indent=indent)}" )
logger.debug(
f" dir(self.flux) = {pp_list(dir(self.flux), indent=indent)}" )
logger.debug(
f" self.flux.attributes = {pp_list(self.flux.attributes, indent=indent)}" )
logger.debug(
f" dir(self.meteo) = {pp_list(dir(self.meteo), indent=indent)}" )
logger.debug(
f" self.meteo.attributes = {pp_list(self.meteo.attributes, indent=indent)}" )
logger.debug(
f" dir(self.inicond) = {pp_list(dir(self.inicond), indent=indent)}" )
logger.debug(
f" self.inicond.attributes = {pp_list(self.inicond.attributes, indent=indent)}" )
logger.debug(
f" dir(self.chemistry.acspecies) = {pp_list(dir(self.chemistry.acspecies), indent=indent)}" )
logger.debug(
f" self.chemistry.dir_sink = {self.chemistry.dir_sink}" )
logger.debug(
f" self.chemistry.dir_tipp = {self.chemistry.dir_tipp}" )
logger.debug(
f" self.chemistry.dirchem_ref = {self.chemistry.dirchem_ref}" )
logger.debug(
f" self.chemistry.init_dir = {self.chemistry.init_dir}" )
logger.debug(
f" self.chemistry.workdir = {self.chemistry.workdir}" )
# JvP 20210414: added printing of tm5_meteo_dir
# JvP 20210503: After some changes by Antoine, use
# self.workdir+'/datavect/meteo/' instead of tm5_meteo_dir
logger.debug("")
# logger.debug(" tm5_meteo_dir = %s", self.tm5_meteo_dir )
logger.debug(
f" self.workdir+'/datavect/meteo/' = {self.workdir + '/datavect/meteo/'}" )
logger.debug("")
# logger.debug("")
# logger.debug("*"*30)
# logger.debug("JvP: Computer says no!")
# logger.debug("*"*30)
# logger.debug("")
# try:
# raise RuntimeError
# except RuntimeError as e:
# #logger.exception("OOPS!")
# logger.critical(e, exc_info=True)
# #raise # => Will display the traceback on screen a second time
# sys.exit() # => Just exit.
# end try
logger.debug("*" * 30)
logger.debug("")
# Check the domain definition (also done in compile.py).
# Only glb600x400 is currently supported in CIF.
#
if ( self.domain.tm5_label != 'glb600x400' ):
logger.critical("")
logger.critical("*" * 30)
logger.critical(
PROG_NAME + " => ERROR: self.domain.tm5_label must be 'glb600x400'!")
logger.critical(" self.domain.tm5_label = " + self.domain.tm5_label)
logger.critical(" Computer says no...")
logger.critical("*" * 30)
logger.critical("")
raise CifRuntimeError(
PROG_NAME + " => ERROR: self.domain.tm5_label must be 'glb600x400'!")
# end if
# >>> JvP 20211028
# Get the iteration number from the rc filename, since it is not stored
# somewhere easily accessible. According to Antoine (TM5-CIF telecon
# 27-10-2021) the iteration number is -1 for the apriori run (or first
# iteration), -2 for the aposterior run (or final iteration) and 2,3,...
# for the 'normal' iterations. This means that when you convert the
# iteration number to a string with '%04i'%iter_nr, the apriori iter_nr
# number will become '-001', the aposteriori iter_nr will become '-002',
# and the rest will become '0002', '0003' etc. If you combine the iter_nr
# with a prefix like 'fwd_', the strings become (in chronological order):
# 'fwd_-001', 'fwd_0002', 'fwd_0003', ..., 'fwd_-002'.
# Notes:
# *) Luckily, you only need the string representation of this number, so
# it is sufficient to extract the part after '[fwd|adj]_'.
# *) Similar code is used in make_obs.make_obs(...)
# Split config_file into path and filename components
config_path, config_base = os.path.split(config_file)
config_path_parts = config_path.split(sep='/')
# Check if config_path_parts[-2] starts with either 'fwd_' or 'adj_'.
if ( not config_path_parts[-2].startswith( ('fwd_', 'adj_') ) ):
logger.critical("")
logger.critical("*" * 30)
logger.critical(
PROG_NAME + " => ERROR: path component does not start with 'fwd_' or 'adj_'!")
logger.critical(" config_file = " + config_file )
logger.critical(" config_path = " + config_path )
logger.critical(" config_base = " + config_base )
logger.critical(f" config_path parts = {config_path_parts}" )
logger.critical(" Computer says no..." )
logger.critical("*" * 30)
logger.critical("")
raise CifRuntimeError
# end if
# Get the string representing the iteration number, and log a message.
iter_nr = config_path_parts[-2][4:]
logger.info(PROG_NAME + f" => iter_nr = {iter_nr}")
# <<< JvP 20211028
# Info message
logger.info(PROG_NAME + " => Writing TM5 config file to " + config_file)
# Write config file
# The values in this file are copied from the rc file from the forward run
# in the first iteration of 20200918-tm5_sf-18m_sat_only-with_bc-ERA5. To
# get all values without comment or white lines, use the following:
# grep -iEv '(^!|^$)' tm5.rc
# Some values (e.g. path names) have been updated using the keywords to
# this function.
# JvP 20210517: Updated the values in this file to match those from the
# rc-file from the forward run in the first iteration of
# 20210222-tm5_sf-18m_points_only-ERA5-spiv. TM5 will only try to use
# point observations, and use Spivakovski OH...
# JvP 20210720: Updated the adj values to match those in
# .../20210222-tm5_sf-18m_points_only-ERA5-spiv/tmvar/var4d/iter-0001/grd/tm5.rc
#
# Mode dependent variables:
if ( mode == 'fwd' ):
my_runmode = '1'
start_51_file = runsubdir + '/ini.nc'
mass_input_dir = 'bagger/rommel/zooi/mass_input_dir'
departures_point_file = 'bagger/rommel/zooi/point_departures.nc4'
elif ( mode == 'adj' ):
my_runmode = '2'
start_51_file = 'None'
# Note that the MASS directory is defined below as mass.output.subdir
# mass_input_dir = '../../fwd_'+iter_nr+'/'+config_path_parts[-1]+'/output/MASS' # ../fwd/output/MASS
# Use self.adj_refdir defined in run.py
# to be sure to use the last forward
mass_input_dir = f'{self.adj_refdir}/{config_path_parts[-1]}//output/MASS'
# ../fwd/output/MASS
# JvP 20211022: departure files are now written to the adjoint directory.
# departures_point_file = '../../fwd_'+iter_nr+'/'+config_path_parts[-1]+'/point_departures.nc4'
departures_point_file = '../../adj_' + iter_nr + '/' + \
config_path_parts[-1] + '/point_departures.nc4'
else:
logger.critical("")
logger.critical("*" * 30)
logger.critical(PROG_NAME + " => ERROR: unknown mode!")
logger.critical(" mode must be in ['fwd', 'adj']!")
logger.critical(" Computer says no...")
logger.critical("*" * 30)
logger.critical("")
raise CifRuntimeError(PROG_NAME + " => ERROR: unknown mode!")
# end if
with open(config_file, "w") as file_id:
print_kwds = {"file": file_id, "sep": ""}
print("region.maxref : 10", **print_kwds)
print("region.globe.xcyc : 1", **print_kwds)
print("region.globe.touch_np : 1", **print_kwds)
print("region.globe.touch_sp : 1", **print_kwds)
print("region.globe.xbeg : %4i" %
(self.domain.xmin), **print_kwds) # -180
print("region.globe.xend : %4i" %
(self.domain.xmax), **print_kwds) # 180
print("region.globe.ybeg : %4i" %
(self.domain.ymin), **print_kwds) # -90
print("region.globe.yend : %4i" %
(self.domain.ymax), **print_kwds) # 90
print("region.globe.im : 1", **print_kwds)
print("region.globe.jm : 1", **print_kwds)
print("region.globe.xref : 1", **print_kwds)
print("region.globe.yref : 1", **print_kwds)
print("region.globe.zref : 1", **print_kwds)
print("region.globe.tref : 1", **print_kwds)
print("region.globe.redgrid.nh.n : 0", **print_kwds)
print("region.globe.redgrid.nh.comb :", **print_kwds)
print("region.globe.redgrid.sh.n : 0", **print_kwds)
print("region.globe.redgrid.sh.comb :", **print_kwds)
print("region.glb100x100.xcyc : 1", **print_kwds)
print("region.glb100x100.touch_np : 1", **print_kwds)
print("region.glb100x100.touch_sp : 1", **print_kwds)
print("region.glb100x100.xbeg : -180", **print_kwds)
print("region.glb100x100.xend : 180", **print_kwds)
print("region.glb100x100.ybeg : -90", **print_kwds)
print("region.glb100x100.yend : 90", **print_kwds)
print("region.glb100x100.im : 360", **print_kwds)
print("region.glb100x100.jm : 180", **print_kwds)
print("region.glb100x100.xref : 1", **print_kwds)
print("region.glb100x100.yref : 1", **print_kwds)
print("region.glb100x100.zref : 1", **print_kwds)
print("region.glb100x100.tref : 1", **print_kwds)
print("region.glb100x100.redgrid.nh.n : 10", **print_kwds)
print("region.glb100x100.redgrid.nh.comb : 360 360 180 180 90 90 30 30 15 5", **print_kwds)
print("region.glb100x100.redgrid.sh.n : 10", **print_kwds)
print("region.glb100x100.redgrid.sh.comb : 360 360 180 180 90 90 30 30 15 5", **print_kwds)
# 6.0
print(
f"region.dx : {self.domain.dx:4.1f}", **print_kwds)
# 4.0
print(
f"region.dy : {self.domain.dy:4.1f}", **print_kwds)
print("region.dz : 1.0", **print_kwds)
# glb600x400
print(
f"regions : {self.domain.tm5_label}", **print_kwds)
print("region.glb600x400.parent : globe", **print_kwds)
# glb600x400
print(
f"my.region1 : {self.domain.tm5_label}", **print_kwds)
print("my.region2 :", **print_kwds)
print("my.region3 :", **print_kwds)
print("my.region1s : glb6x4", **print_kwds)
print("my.region2s :", **print_kwds)
print("my.region3s :", **print_kwds)
print("region.glb600x400.xcyc : 1", **print_kwds)
print("region.glb600x400.touch_np : 1", **print_kwds)
print("region.glb600x400.touch_sp : 1", **print_kwds)
print("region.glb600x400.xbeg : %4i" %
(self.domain.xmin), **print_kwds) # -180
print("region.glb600x400.xend : %4i" %
(self.domain.xmax), **print_kwds) # 180
print("region.glb600x400.ybeg : %4i" %
(self.domain.ymin), **print_kwds) # -90
print("region.glb600x400.yend : %4i" %
(self.domain.ymax), **print_kwds) # 90
print("region.glb600x400.im : %4i" %
(self.domain.nlon), **print_kwds) # 60
print("region.glb600x400.jm : %4i" %
(self.domain.nlat), **print_kwds) # 45
print("region.glb600x400.xref : 1", **print_kwds)
print("region.glb600x400.yref : 1", **print_kwds)
print("region.glb600x400.zref : 1", **print_kwds)
print("region.glb600x400.tref : 1", **print_kwds)
print("region.glb600x400.redgrid.nh.n : 4", **print_kwds)
print("region.glb600x400.redgrid.nh.comb : 60 20 10 5", **print_kwds)
print("region.glb600x400.redgrid.sh.n : 4", **print_kwds)
print("region.glb600x400.redgrid.sh.comb : 60 20 10 5", **print_kwds)
print("region.glbsfc : glb100x100", **print_kwds)
print("region.globe : globe", **print_kwds)
print("ppobs.nasim : 10800", **print_kwds)
# 1 for fwd, 2 for adj
print(f"my.runmode : {my_runmode}", **print_kwds)
print("runid : RUNID", **print_kwds)
print("jobstep.timerange.start : %s" % (
# 2018-01-01 00:00:00
self.datei.strftime('%Y-%m-%d %H:%M:%S')), **print_kwds)
print("jobstep.timerange.end : %s" % (
# 2019-07-01 00:00:00
self.datef.strftime('%Y-%m-%d %H:%M:%S')), **print_kwds)
print("timestep.read : 3600", **print_kwds)
print("ndyn : 3600", **print_kwds)
# /scratch/shared/jpt930/TM5-SF_4DVAR-a/20210222-tm5_sf-18m_points_only-ERA5-spiv/input
print(
f"input.dir : {self.workdir + '/model/input'}", **print_kwds)
print("istart : 51", **print_kwds)
# JvP 20210222: added runsubdir+ini.nc and continued updating variables.
# /scratch/shared/jpt930/TM5-SF_4DVAR-a/20210222-tm5_sf-18m_points_only-ERA5-spiv/input/iniconc.nc4
print(f"start.51.file : {start_51_file}", **print_kwds)
print("my.meteo_id : EA", **print_kwds)
print("meteo.convec.files : convec", **print_kwds)
print("my.meteo.unpacked : T", **print_kwds)
print("my.meteo.resol : coarsened ! coarsened to levels and regions", **print_kwds)
print("my.meteo.class : ea", **print_kwds)
print("my.meteo.format : tm5-nc ! NetCDF files", **print_kwds)
print("diffusion.files : T", **print_kwds)
# The DIFFCOEFF subdirectory is created in TM5s __init__.py. If you don't want that,
# try switching off diffusion.files above
# /scratch/shared/jpt930/TM5-SF_4DVAR-a/20210222-tm5_sf-18m_points_only-ERA5-spiv/DIFFCOEFF
print(
f"diffusion.dir : {self.workdir + '/DIFFCOEFF'}", **print_kwds)
print("my.ecclass_ecl : ea", **print_kwds)
print("my.meteo.nlev : 137", **print_kwds)
print("my.meteo.pfx : ec", **print_kwds)
print("my.mlevs : tropo25a", **print_kwds)
print("meteo.tinterp.* : interp1", **print_kwds)
print("meteo.tinterp.sfc.aver : aver1", **print_kwds)
print("meteo.tinterp.ml : interp3", **print_kwds)
print("meteo.tinterp.convec : aver3", **print_kwds)
print("meteo.tinterp.oro : const", **print_kwds)
print("meteo.tinterp.lsm : const", **print_kwds)
print("meteo.tinterp.srols : month", **print_kwds)
print("my.mext : /<yyyy>", **print_kwds)
print("my.msep : /", **print_kwds)
print("my.glb600x400.m : glb600x400", **print_kwds)
print("my.convec.filekey : filekey=convec", **print_kwds)
print("tmm.sourcekey.*.sfc.an : tm5-nc:mdir=ec/ea/an0tr1/sfc/glb100x100/<yyyy>;tres=_00p01;namesep=/", **print_kwds)
print("tmm.sourcekey.*.sfc.fc : tm5-nc:mdir=ec/ea/h06h18tr1/sfc/glb100x100/<yyyy>;tres=_00p01;namesep=/", **print_kwds)
print("tmm.sourcekey.glb600x400.ml : tm5-nc:mdir=ec/ea/h06h18tr3/tropo25a/glb600x400/<yyyy>;tres=_00p03;namesep=/", **print_kwds)
print("tmm.sourcekey.glb600x400.convec : tm5-nc:mdir=ec/ea/h06h18tr3/tropo25a/glb600x400/<yyyy>;tres=_00p03;namesep=/;filekey=convec", **print_kwds)
#
# JvP 20210517: update tmm.dir and my.meteo.source.dir
# /projects/0/tm5meteo/tm5-nc
print(
f"tmm.dir : {runsubdir + '/meteo/'}", **print_kwds)
# /projects/0/tm5meteo/tm5-nc
print(
f"my.meteo.source.dir : {runsubdir + '/meteo/'}", **print_kwds)
print("my.region1m : glb600x400", **print_kwds)
print("my.levs : tropo25a", **print_kwds)
print("emissions.source : PyShell", **print_kwds)
#
# JvP 20210517: @Antoine: TM5 requires the following two PyShell variables. The first should be set
# to the emission file specified in the yaml file in datavect/components/fluxes/parameters/CH4/"dir+file".
# The second should be set to the updated emission file of the previous iteration. How do I do that?
# JvP 20210609: Set both to sunsubdir+'emission.nc4'. See the following files:
# *) pycif/plugins/models/TM5/io/inputs/make_fluxes.py
# *) pycif/plugins/fluxes/tm5/write.py
# *) pycif/plugins/fluxes/tm5/read.py
# /scratch/shared/jpt930/TM5-SF_4DVAR-a/20210222-tm5_sf-18m_points_only-ERA5-spiv/input/emission.nc4
print(
f"PyShell.em.apri.filename : {runsubdir + '/emission.nc4'}", **print_kwds)
# ../../iter-0000/xc2x/emission.nc4
print(
f"PyShell.em.filename : {runsubdir + '/emission.nc4'}", **print_kwds)
#
print("emission.dailycycle : F", **print_kwds)
print("my.oh_id : SP", **print_kwds)
print("my.strat_id : EC", **print_kwds)
print("chemistry.ch4.Lrates : L_OH_tropo L_OH_strato L_Cl_strato L_O1D_strato", **print_kwds)
print("chemistry.ch4.lrate.dsec : 10800", **print_kwds)
print("chemistry.ch4.L_OH_tropo.domain : tropo", **print_kwds)
print("chemistry.ch4.L_OH_tropo.source : Spivakovsky", **print_kwds)
print("chemistry.ch4.L_OH_tropo.factor : 0.92", **print_kwds)
print("chemistry.ch4.L_OH_tropo.file : OH_troposphere-Spivakovsky-2000-ml60-glb100x100.hdf", **print_kwds)
# /home/jpt930/TM5-SF-data/TIPP/CH4/bc
print(
f"chemistry.ch4.L_OH_tropo.dir : {self.workdir + '/chemical_scheme/TIPP/CH4/bc'}", **print_kwds)
print("chemistry.ch4.L_OH_strato.domain : strato", **print_kwds)
print("chemistry.ch4.L_OH_strato.source : Bruehl_GG", **print_kwds)
print("chemistry.ch4.L_OH_strato.file : Bruehl_ECHAM_Lrate_CH4+OH.nc", **print_kwds)
# /home/jpt930/TM5-SF-data/SINKS
print(
f"chemistry.ch4.L_OH_strato.dir : {self.workdir + '/chemical_scheme/SINKS'}", **print_kwds)
print("chemistry.ch4.L_OH_strato.factor : 1.0", **print_kwds)
print("chemistry.ch4.L_Cl_strato.domain : strato", **print_kwds)
print("chemistry.ch4.L_Cl_strato.source : Bruehl_GG", **print_kwds)
print("chemistry.ch4.L_Cl_strato.file : Bruehl_ECHAM_Lrate_CH4+Cl.nc", **print_kwds)
# /home/jpt930/TM5-SF-data/SINKS
print(
f"chemistry.ch4.L_Cl_strato.dir : {self.workdir + '/chemical_scheme/SINKS'}", **print_kwds)
print("chemistry.ch4.L_Cl_strato.factor : 1.0", **print_kwds)
print("chemistry.ch4.L_O1D_strato.domain : strato", **print_kwds)
print("chemistry.ch4.L_O1D_strato.source : Bruehl_GG", **print_kwds)
print("chemistry.ch4.L_O1D_strato.file : Bruehl_ECHAM_Lrate_CH4+OD.nc", **print_kwds)
# /home/jpt930/TM5-SF-data/SINKS
print(
f"chemistry.ch4.L_O1D_strato.dir : {self.workdir + '/chemical_scheme/SINKS'}", **print_kwds)
print("chemistry.ch4.L_O1D_strato.factor : 1.0", **print_kwds)
print("chemistry.ch4.lrate.archive : F", **print_kwds)
print("proces.diffusion.eps_d : 0.0", **print_kwds)
print("convection.with_ev_slopes : F", **print_kwds)
print("proces.advection : T", **print_kwds)
print("proces.chemistry : T", **print_kwds)
print("proces.source : T", **print_kwds)
print("mask.apply : F", **print_kwds)
print("budget.global : T", **print_kwds)
print("budget.output : True", **print_kwds)
print("budget.output.subdir : budget", **print_kwds)
print("budget.store.from : <output.dir>", **print_kwds)
print("budget.store.files : budget.tar", **print_kwds)
print("budget.store.tarfilter : budget", **print_kwds)
print("output.dir : output", **print_kwds)
print("output.after.step : o", **print_kwds)
print("cfl.outputstep : 3600", **print_kwds)
print("model.output : F", **print_kwds)
print("output.point : T", **print_kwds)
print("output.point.verbose : T", **print_kwds)
print("station.repr_error : 5", **print_kwds)
print("output.point.errors : repr_error=5", **print_kwds)
print("output.point.sample.parent : F", **print_kwds)
# JvP 20210614: line below not yet used in TM5, waiting for the next crash...
# /scratch/shared/jpt930/TM5-SF_4DVAR-a/20210222-tm5_sf-18m_points_only-ERA5-spiv/input/point_input.nc4
print(
f"output.point.infile : {runsubdir + '/point_input.nc4'}", **print_kwds)
print("output.point.meteo : T", **print_kwds)
print("output.point.minerror : 0.5 ! ppm", **print_kwds)
print("output.point.timewindow : 0.5 ! hours", **print_kwds)
print("output.point.interpolation_method : linear", **print_kwds)
print("output.point.dryair.mixratio : F", **print_kwds)
print("station.ppobs.data.sel : 2", **print_kwds)
print("output.point.extrapol2surf : T", **print_kwds)
# JvP 20210723: added departures_point_file to line below
# ../dep/point_departures.nc4
print(
f"departures.point.file : {departures_point_file}", **print_kwds)
print("output.satellite : T", **print_kwds)
print("output.satellite.verbose : T", **print_kwds)
# JvP 20210614: path below not yet used in TM5, waiting for the next crash...
print(f"output.satellite.departure.dir : bagger/rommel/zooi/departure_dir",
**print_kwds) # ../dep/satellite
print("output.satellite.sample.parent : T", **print_kwds)
print("output.satellite.sample.time_window : 10800", **print_kwds)
print("output.satellite.interpolation_method : linear", **print_kwds)
print("output.satellite.errors : neighbors", **print_kwds)
print("output.satellite.meteo.CH4 : F", **print_kwds)
print("output.satellite.dryair.mixratio : F", **print_kwds)
print("station.output : T", **print_kwds)
print("station.extrapol2surf : T", **print_kwds)
print("station.output.subdir : STATION", **print_kwds)
#
# print("fts.list.file : /home/jpt930/TM5-SF-data_JvP/stationlist_FTS_TCCON-JvP-20200901.dat" , **print_kwds)
print(
f"fts.list.file : {self.TCCON_FTS_list}", **print_kwds)
#
print("fts.list.format : 1", **print_kwds)
print("fts.output : T", **print_kwds)
print("fts.output.subdir : FTS", **print_kwds)
print("output.tccon : F", **print_kwds)
print("validation.output : F", **print_kwds)
print("validation.output.subdir : VALIDATION", **print_kwds)
print("mixhdf.output : T", **print_kwds)
print("mixhdf.output.subdir : MIXHDF", **print_kwds)
print("output.mix : F", **print_kwds)
print("output.mix.tstep : 10800", **print_kwds)
print("output.mix.filename.prefix : mix_", **print_kwds)
print("mmix.output : T", **print_kwds)
print("mmix.output.subdir : MMIX", **print_kwds)
print("column.output : F", **print_kwds)
print("column.output.subdir : COLUMN", **print_kwds)
print("mass.output.subdir : MASS", **print_kwds)
# ../fwd/output/MASS
print(
f"mass.input.dir : {mass_input_dir}", **print_kwds)
print("save.output.subdir : save", **print_kwds)
print("timing.output.subdir : timing", **print_kwds)
print("adjoint.input.satellite : F", **print_kwds)
print("okdebug : F", **print_kwds)
print("optimize.emission : T", **print_kwds)
print(
f"var4d.optim_emis.type : {self.optim_emis_type}", **print_kwds)
#
# JvP 20210614: I'm not sure how to implement a single source. For now, just try setting
# categories to 1, category1 to total (name in the netCDF file, and keep tres on monthly
# print("emission.CH4.glb600x400.categories : 4" , **print_kwds)
# print("emission.CH4.glb600x400.category1 : wetlands" , **print_kwds)
# print("emission.CH4.glb600x400.category1.tres : monthly" , **print_kwds)
# print("emission.CH4.glb600x400.category2 : rice" , **print_kwds)
# print("emission.CH4.glb600x400.category2.tres : monthly" , **print_kwds)
# print("emission.CH4.glb600x400.category3 : biomass-burning" , **print_kwds)
# print("emission.CH4.glb600x400.category3.tres : monthly" , **print_kwds)
# print("emission.CH4.glb600x400.category4 : other" , **print_kwds)
# print("emission.CH4.glb600x400.category4.tres : monthly" , **print_kwds)
print("emission.CH4.glb600x400.categories : 1", **print_kwds)
print("emission.CH4.glb600x400.category1 : total", **print_kwds)
print("emission.CH4.glb600x400.category1.tres : monthly", **print_kwds)
#
# JvP 20210614: I'm not entirely sure that the station.list.file is actually being used.
# In the original rc file, there appears not to be a loop around this variable, so I'm
# not sure if the "...%{tracer}..." part will be replaced by something like CH4...
# JvP 20210706: Well, apparently the "...%{tracer}..." part is replaced by something
# (environment variable???), because tm5 crashes if it doesn't find this file. For now,
# I'll hardcode it here, but it should be moved to the yaml file...
# JvP 20210720: the file defined in station.list.file is now based on the actual locations
# of the observations and is generated in make_obs.py.
# print("station.list.file : /home/jpt930/TM5-SF-data/STATION//stationlist_%{tracer}_NOAA014_F3_v2.dat" , **print_kwds)
# print("station.list.file : %s" % '/bagger/rommel/zooi/meuk.dat' , **print_kwds)
# print("station.list.file : %s" % (self.input_dir+'/stationlist_CH4_NOAA014_F3_v2.dat',), **print_kwds)
print(
f"station.list.file : {runsubdir + '/stationlist_CH4.dat'}", **print_kwds)
#
print("station.list.format : 3", **print_kwds)
print("station.list.file2 : ", **print_kwds)
print("station.list.format2 : 3", **print_kwds)
#
# JvP 20210614: The current setup is for a surface only inversion, so the setting
# of the output.directory should not matter...
# print("output.satellite.output.directory : /scratch/shared/jpt930/TM5-SF_4DVAR-a/20210222-tm5_sf-18m_points_only-ERA5-spiv/input/satellites" , **print_kwds)
print(f"output.satellite.output.directory : /bagger/rommel/zooi/satellite_output_dir", **print_kwds)
print("output.satellite.split.period : m", **print_kwds)
# end with
# end write_tm5_rc
[docs]
def make_config(self, runsubdir, sdc, mode):
"""
PURPOSE
Write a configuration file for running TM5. This file will have the
name 'tm5.rc' and is therefore also called an rc-file. This function
is imported/called in native2inputs.py.
IN/OUT
self = TM5 model plugin, containing all TM5 settings.
runsubdir = The directory in which TM5 is run. Probably depends on iteration
number and date.
sdc = No idea. Is set in native2inputs as
ddi = min(datei, datef)
sdc = ddi.strftime("%Y%m%d%H")
so it is probably the formatted start date of the current
iteration.
mode = in native2inputs this is described as
"running mode: one of 'fwd', 'adj' and 'tl'". I'm not sure what
'tl' stands for.
KWARGS
none
ASSUMPTIONS
none
EXCEPTIONS
When this function encounters a problem that it cannot solve,
it will raise a RuntimeError. Pythons exeception handling will
provide a traceback, including files, calls and line numbers.
PYTHON VERSION
3.8.6
VERSION CHANGE HISTORY
2.0 20-07-2021 by J.C.A. van Peet.
Added selection of fwd and adj mode, and writing of corresponding
rc-files.
1.2 22-02-2021 by J.C.A. van Peet.
As Antoine pointed out, the initial condition file defined in the
yaml file (datavect.components.inicond.[dir|file]) is linked as
ini.nc in runsubdir (see make_inicond.py). So to access that file
from TM5, you only have to set runsubdir/ini.nc in the rc-file. But
runsubdir is not part of the TM5 object ('self') but passed as a
parameter to the current function. So you have to pass it explicitly
to the function write_tm5_rc, to be able to write it to rc file.
1.1 02-02-2021 by J.C.A. van Peet.
*) Added MODULE_NAME
*) Added import of the logging module
*) Updated PROG_NAME
*) Used new PROG_NAME as local logger name.
*) Moved writing of rc-file to separate function.
1.0 09-11-2020 by J.C.A. van Peet.
Original code.
"""
# Set the name of this function
PROG_NAME = MODULE_NAME + ".make_config"
# JvP 20210202: Local logger
logger = logging.getLogger(PROG_NAME)
logger.setLevel(logging.DEBUG)
# Debug messages
logger.debug("")
logger.debug("*" * 30)
logger.debug(PROG_NAME + " => DEBUG:")
logger.debug(" self = %s", self )
logger.debug(" runsubdir = %s", runsubdir)
logger.debug(" sdc = %s", sdc )
logger.debug(" mode = %s", mode )
logger.debug("*" * 30)
logger.debug("")
# Write the config file
config_file_name = f"{runsubdir}/tm5.rc"
logger.info(PROG_NAME + " => Writing TM5 config file to " + config_file_name)
# JvP 20210222: added runsubdir as a parameter to write_tm5_rc
# JvP 20210720: added mode as an argument to write_tm5_rc
write_tm5_rc(self, config_file_name, runsubdir, mode )
# end function make_config