Welcome to the MPAS-JEDI tutorial practice guide

This web page is intended to serve as a guide through the practice exercises of this tutorial. Exercises are split into seven main sections, each of which focuses on a particular aspect of using the MPAS-JEDI data assimilation system.

In case you would like to refer to any of the lecture slides from previous days, you can open the Tutorial Agenda in another window. The test dataset can be downloaded from Here.

You can proceed through the sections of this practical guide at your own pace. It is highly recommended to go through the exercises in order, since later exercises may require the output of earlier ones. Clicking the grey headers will expand each section or subsection.

0. Prerequisites and environment setup

The practical exercises in this tutorial have been tailored to work on the Derecho system. Derecho is an HPC cluster that provides most of the libraries needed by MPAS-JEDI and its pre- and post-processing tools through modules. In general, before compiling and running MPAS-JEDI on your own system, you will need to install spack-stack. However, this tutorial does not cover the installation of spack-stack, which was pre-installed on Derecho. MPAS-JEDI code build for this tutorial is based upon spack-stack-1.6.0.

Logging onto Derecho from your laptop or desktop by

$ ssh -X derecho.hpc.ucar.edu

then using your password and DUO two-factor authentication to get onto Derecho. Note that '-X' is necessary in order to use X11-forwarding for direct graphics display from Derecho. It is recommended to at least login onto Derecho with two terminals for different tasks.

First, copying the pre-prepared tutorial test dataset directory to your own scratch disk space:

$ cd /glade/derecho/scratch/$USER
$ cp -r /glade/derecho/scratch/liuz/mpasjedi_tutorial202410HOWARD ./mpas_jedi_tutorial
$ ls -l mpas_jedi_tutorial 
total 372 drwxr-xr-x 3 liuz ncar 16384 Aug 3 11:00 background drwxr-xr-x 3 liuz ncar 16384 Sep 23 2023 background_120km drwxr-xr-x 5 liuz ncar 16384 Aug 5 16:14 B_Matrix drwxr-xr-x 4 liuz ncar 16384 Sep 15 12:36 conus15km drwxr-xr-x 2 liuz ncar 147456 Aug 3 15:50 crtm_coeffs_v3 drwxr-xr-x 3 liuz ncar 16384 Aug 3 21:23 ensemble drwxr-xr-x 2 liuz ncar 49152 Aug 5 16:32 localization_pregenerated drwxr-xr-x 2 liuz ncar 16384 Sep 15 12:44 MPAS_JEDI_yamls_scripts drwxr-xr-x 2 liuz ncar 16384 Aug 3 14:44 MPAS_namelist_stream_physics_files drwxr-xr-x 2 liuz ncar 16384 Sep 23 2023 ncl_scripts drwxr-xr-x 3 liuz ncar 16384 Sep 23 2023 obs_bufr drwxr-xr-x 3 liuz ncar 16384 Aug 6 22:19 obs_ioda_pregenerated drwxr-xr-x 5 liuz ncar 16384 Aug 7 16:25 omboma_from2experiments -rwxr-xr-x 1 liuz ncar 393 Sep 15 15:26 setup_intel.sh

This copy will take some time as the size of the whole directory is ~15GB! You may pay special attention to the following directories:

On derecho, the default shell is bash.

Derecho uses the LMOD package to manage the software development. Running module list to see what modules are loaded by default right after you log in. It should print something similar to below:

$ module list

Currently Loaded Modules:
  1) ncarenv/23.09 (S)   3) intel/2023.2.1        5) cray-mpich/8.1.27   7) netcdf/4.9.2
  2) craype/2.7.23       4) ncarcompilers/1.0.0   6) hdf5/1.12.2

  Where:
   S:  Module is Sticky, requires --force to unload or purge

Post-processing and graphics exercises will need Python and NCAR Command Language (NCL). On Derecho, these are available in a Conda environment named 'npl'. The npl environment also provides NCL. We can load the conda module and activate the npl environment with the following commands:

$ module reset # this may or may not be needed
$ module load conda
$ conda activate npl
$ which ncl # check whether ncl exists

You will run all of the practical exercises in your own scratch space under /glade/derecho/scratch/$USER/mpas_jedi_tutorial.

Running jobs on Derecho requires the submission of a job script to a batch queueing system, which will allocate requested computing resources to your job when they become available. In general, it's best to avoid running any compute-intensive jobs on the login nodes, and the practical instructions to follow will guide you in the process of submitting jobs when necessary.

As a first introduction to running jobs on Derecho, there are several key commands worth noting:

Throughout this tutorial, you will submit your jobs to a special queue S6244386 with the 'premium' priority, using an account number UMMM0008. The special queue S6244386 can be used between 11:30am and 5:30pm each day. Out of this time slot, you can use the main queue by modifying the queue name in the job scripts. At various points in the practical exercises, we'll need to submit jobs to Derecho's queueing system using the qsub command, and after doing so, we may check on the status of the job with the qstat command, monitoring the log files produced by the job once we see that the job has begun to run. Most exercises will run with 64 cores of one single node though each of Derecho's nodes have 128 cores (235GB available memory). Note that 4DEnVar uses 3 nodes with the analyses at 3 times.

You're now ready to begin with the practical exercises of this tutorial!

1. Compiling/Testing MPAS-JEDI

In this section, the goal is to obtain, compile, and test the MPAS-JEDI code through cmake/ctest mechanism.

1.1 Git-Clone the mpas-bundle repository

In order to build MPAS-JEDI and its dependencies, it is recommended to access source code from mpas-bundle. We will use the 'release/3.0.1' branch from mpas-bundle-3.0.1:

$ cd /glade/derecho/scratch/$USER/mpas_jedi_tutorial
$ mkdir mpas_bundle_v3
$ cd mpas_bundle_v3
$ git clone -b release/3.0.1 https://github.com/JCSDA/mpas-bundle code

The git command will clone the mpas-bundle repository from github to a local directory 'code' , then make the 'release/3.0.1' branch as the active branch. The output to the terminal should look as following:

Cloning into 'code'...
remote: Enumerating objects: 461, done.
remote: Counting objects: 100% (82/82), done.
remote: Compressing objects: 100% (44/44), done.
remote: Total 461 (delta 44), reused 71 (delta 38), pack-reused 379
Receiving objects: 100% (461/461), 144.69 KiB | 1.64 MiB/s, done.
Resolving deltas: 100% (273/273), done.

Note that the mpas-bundle repository does not contain actual source code. Instead, the CMakeLists.txt file under code includes the github repositories's branch/tag information needed to build MPAS-JEDI. One important difference from previous mpas-bundle releases (1.0.0 and 2.0.0) is that 3.0.1-based bundle works together with the official 8.2.2-based MPAS-A model code from MPAS-v8.2.2. We now create a 'build' folder and load the spack-stack environment pre-built using the GNU compiler:

$ source ./code/env-setup/gnu-derecho.sh
$ module list

The output to the module list in the terminal should look like the following (102 modules!!!). These packages are from pre-installed spack-stack-1.6.0.

Currently Loaded Modules:
  1) ecflow/5.8.4                 35) base-env/1.0.0        69) json-schema-validator/2.1.0
  2) mysql/8.0.33                 36) boost/1.83.0          70) odc/1.4.6
  3) ncarenv/23.09           (S)  37) openblas/0.3.24       71) py-attrs/21.4.0
  4) gcc/12.2.0                   38) py-setuptools/63.4.3  72) py-pycparser/2.21
  5) stack-gcc/12.2.0             39) py-numpy/1.22.3       73) py-cffi/1.15.1
  6) craype/2.7.20                40) bufr/12.0.1           74) py-findlibs/0.0.2
  7) cray-mpich/8.1.25            41) ecbuild/3.7.2         75) py-eccodes/1.5.0
  8) libfabric/1.15.2.0           42) libpng/1.6.37         76) py-f90nml/1.4.3
  9) cray-pals/1.2.11             43) openjpeg/2.3.1        77) py-h5py/3.7.0
 10) stack-cray-mpich/8.1.25      44) eccodes/2.32.0        78) py-cftime/1.0.3.4
 11) tar/1.34                     45) eigen/3.4.0           79) py-netcdf4/1.5.8
 12) gettext/0.21.1               46) eckit/1.24.5          80) py-bottleneck/1.3.7
 13) libxcrypt/4.4.35             47) fftw/3.3.10           81) py-numexpr/2.8.4
 14) zlib/1.2.13                  48) fckit/0.11.0          82) py-et-xmlfile/1.0.1
 15) sqlite/3.43.2                49) fiat/1.2.0            83) py-openpyxl/3.1.2
 16) util-linux-uuid/2.38.1       50) ectrans/1.2.0         84) py-six/1.16.0
 17) python/3.10.13               51) qhull/2020.2          85) py-python-dateutil/2.8.2
 18) stack-python/3.10.13         52) atlas/0.35.1          86) py-pytz/2023.3
 19) nghttp2/1.57.0               53) git-lfs/3.3.0         87) py-pyxlsb/1.0.10
 20) curl/8.4.0                   54) gsibec/1.1.3          88) py-xlrd/2.0.1
 21) cmake/3.23.1                 55) gsl-lite/0.37.0       89) py-xlsxwriter/3.1.7
 22) git/2.41.0                   56) libjpeg/2.1.0         90) py-xlwt/1.3.0
 23) pkg-config/0.29.2            57) krb5/1.19.2           91) py-pandas/1.5.3
 24) hdf5/1.14.0                  58) libtirpc/1.3.3        92) py-pybind11/2.11.0
 25) snappy/1.1.10                59) hdf/4.2.15            93) py-pycodestyle/2.11.0
 26) zstd/1.5.2                   60) jedi-cmake/1.4.0      94) py-pyhdf/0.10.4
 27) c-blosc/1.21.5               61) libxt/1.1.5           95) libyaml/0.2.5
 28) netcdf-c/4.9.2               62) libxmu/1.1.4          96) py-pyyaml/6.0
 29) nccmp/1.9.0.1                63) libxpm/3.5.12         97) py-scipy/1.11.3
 30) netcdf-fortran/4.6.1         64) libxaw/1.0.13         98) py-packaging/23.1
 31) parallel-netcdf/1.12.2       65) udunits/2.2.28        99) py-xarray/2023.7.0
 32) parallelio/2.5.10            66) ncview/2.1.9         100) sp/2.5.0
 33) py-pip/23.1.2                67) netcdf-cxx4/4.3.1    101) jedi-base-env/1.0.0
 34) wget/1.20.3                  68) json/3.10.5          102) jedi-mpas-env/1.0.0

  Where:
   S:  Module is Sticky, requires --force to unload or purge

Now we are ready to 'fetch' actual source code from github repositories through cmake.

1.2 Compiling and testing MPAS-JEDI

MPAS-JEDI uses cmake to automatically fetch the code from various github repositories, listed in CMakeLists.txt under ~code. Now type the command below under the build directory:

$ git lfs install
$ mkdir build
$ cd build
$ cmake ../code

After it completes (may take 15-20 min depending on network connection), you will see the actual source code of various repositories (e.g., oops, vader, saber, ufo, ioda, crtm, mpas-jedi, and MPAS) is now under the code directory. Meanwhile, Makefile files to build executables are generated under the build directory. Now it is ready to compile MPAS-JEDI under 'build' using the standard make. However, it is NOT recommended to compile the code on the login node. Instead, better compiling code using a compute node with an interactive job by issuing the command below:

WARNING:This cmake step could take 15-20 min to complete. You may continue to read instructions while waiting.

$ qsub -A ummm0008 -N build-bundle -q S6244386 -l job_priority=premium -l walltime=03:00:00 -l select=1:ncpus=128:mem=235GB -I

This requests an interactive job to the 'S6244386' queue, with a job name 'build-bundle', 3 hours walltime of a compute node with 128 cores, the 'premium' priority and an account number 'UMMM0008'.

Note that the interactive job does not have the spack-stack environment loaded, you have to reload the spack-stack environment (under ~build), and then compiling code with the parallel make using 20 cores:

$ source ../code/env-setup/gnu-derecho.sh
$ make -j20

This could take ~25 min. Using more cores for build could speed up a bit, but will not help too much from our experience. Also note that the reason we do the cmake step (will clone various github repositories) on the login node instead of a compute node is that the derecho's compute nodes have a much slower internet connection.

WARNING:The compilation could take ~25 min to complete. You may continue to read instructions while waiting.

Once we reach 100% of the compilation, many executables will be generated under ~build/bin. mpas model and mpas-jedi DA related executables are:

$ ls bin/mpas*
bin/mpas_atmosphere                     bin/mpasjedi_enshofx.x                   bin/mpasjedi_rtpp.x
bin/mpas_atmosphere_build_tables        bin/mpasjedi_ens_mean_variance.x         bin/mpasjedi_saca.x
bin/mpas_init_atmosphere                bin/mpasjedi_error_covariance_toolbox.x  bin/mpasjedi_variational.x
bin/mpasjedi_convertstate.x             bin/mpasjedi_forecast.x                  bin/mpas_namelist_gen
bin/mpasjedi_converttostructuredgrid.x  bin/mpasjedi_gen_ens_pert_B.x            bin/mpas_parse_atmosphere
bin/mpasjedi_eda.x                      bin/mpasjedi_hofx3d.x                    bin/mpas_parse_init_atmosphere
bin/mpasjedi_enkf.x                     bin/mpasjedi_hofx.x                      bin/mpas_streams_gen

The last step is to ensure that the code was compiled properly by running the MPAS-JEDI ctests, with two lines of simple command:

$ export LD_LIBRARY_PATH=/glade/derecho/scratch/${USER}/mpas_jedi_tutorial/mpas_bundle_v3/build/lib:$LD_LIBRARY_PATH
$ cd mpas-jedi
$ ctest

At the moment the tests are running (take ~5 min to finish), it indicates if it passes or fails. At the end, a summary is provided with a percentage of the tests that passed, failed and the processing times.

The output to the terminal should look as following:

......
100% tests passed, 0 tests failed out of 59

Label Time Summary:
executable    =  18.76 sec*proc (13 tests)
mpasjedi      = 237.40 sec*proc (59 tests)
mpi           = 235.68 sec*proc (56 tests)
script        = 218.64 sec*proc (44 tests)

Total Test time (real) = 237.49 sec

WARNING:You could run ctest just under the 'build' directory, but that will run a total of 2159 ctest cases for all component packages (oops, vader, saber, ufo, ioda, crtm, mpas-jedi etc.) in mpas-bundle, which will take much longer time. Maybe something you can play with after this tutorial. You may use 'ctest -N, which will only list names of ctest cases, but not run them).

To determine if a test passes or fails, a comparison of the test log and reference file is done internally taking as reference a tolerance value. This tolerance is specified via YAML file. These files can be found under mpas-jedi/test/testoutput in the build folder:

3denvar_2stream_bumploc.ref       4denvar_ID.run                          ens_mean_variance.run.ref
3denvar_2stream_bumploc.run       4denvar_ID.run.ref                      forecast.ref
3denvar_2stream_bumploc.run.ref   4denvar_VarBC_nonpar.run                forecast.run
3denvar_amsua_allsky.ref          4denvar_VarBC_nonpar.run.ref            forecast.run.ref
3denvar_amsua_allsky.run          4denvar_VarBC.ref                       gen_ens_pert_B.ref
3denvar_amsua_allsky.run.ref      4denvar_VarBC.run                       gen_ens_pert_B.run
3denvar_amsua_bc.ref              4denvar_VarBC.run.ref                   gen_ens_pert_B.run.ref
3denvar_amsua_bc.run              4dfgat.ref                              hofx3d_nbam.ref
3denvar_amsua_bc.run.ref          4dfgat.run                              hofx3d_nbam.run
3denvar_bumploc.ref               4dfgat.run.ref                          hofx3d_nbam.run.ref
3denvar_bumploc.run               4dhybrid_bumpcov_bumploc.ref            hofx3d.ref
3denvar_bumploc.run.ref           4dhybrid_bumpcov_bumploc.run            hofx3d_ropp.ref
3denvar_dual_resolution.ref       4dhybrid_bumpcov_bumploc.run.ref        hofx3d_rttovcpp.ref
3denvar_dual_resolution.run       convertstate_bumpinterp.ref             hofx3d.run
3denvar_dual_resolution.run.ref   convertstate_bumpinterp.run             hofx3d.run.ref
3dfgat_pseudo.ref                 convertstate_bumpinterp.run.ref         hofx4d_pseudo.ref
3dfgat_pseudo.run                 convertstate_unsinterp.ref              hofx4d_pseudo.run
3dfgat_pseudo.run.ref             convertstate_unsinterp.run              hofx4d_pseudo.run.ref
3dfgat.ref                        convertstate_unsinterp.run.ref          hofx4d.ref
3dfgat.run                        converttostructuredgrid_latlon.ref      hofx4d.run
3dfgat.run.ref                    converttostructuredgrid_latlon.run      hofx4d.run.ref
3dhybrid_bumpcov_bumploc.ref      converttostructuredgrid_latlon.run.ref  letkf_3dloc.ref
3dhybrid_bumpcov_bumploc.run      dirac_bumpcov.ref                       letkf_3dloc.run
3dhybrid_bumpcov_bumploc.run.ref  dirac_bumpcov.run                       letkf_3dloc.run.ref
3dvar_bumpcov_nbam.ref            dirac_bumpcov.run.ref                   lgetkf_height_vloc.ref
3dvar_bumpcov_nbam.run            dirac_bumploc.ref                       lgetkf_height_vloc.run
3dvar_bumpcov_nbam.run.ref        dirac_bumploc.run                       lgetkf_height_vloc.run.ref
3dvar_bumpcov.ref                 dirac_bumploc.run.ref                   lgetkf.ref
3dvar_bumpcov_ropp.ref            dirac_noloc.ref                         lgetkf.run
3dvar_bumpcov_rttovcpp.ref        dirac_noloc.run                         lgetkf.run.ref
3dvar_bumpcov.run                 dirac_noloc.run.ref                     parameters_bumpcov.ref
3dvar_bumpcov.run.ref             dirac_spectral_1.ref                    parameters_bumpcov.run
3dvar.ref                         dirac_spectral_1.run                    parameters_bumpcov.run.ref
3dvar.run                         dirac_spectral_1.run.ref                parameters_bumploc.ref
3dvar.run.ref                     eda_3dhybrid.ref                        parameters_bumploc.run
4denvar_bumploc.ref               eda_3dhybrid.run                        parameters_bumploc.run.ref
4denvar_bumploc.run               eda_3dhybrid.run.ref                    rtpp.ref
4denvar_bumploc.run.ref           ens_mean_variance.ref                   rtpp.run
4denvar_ID.ref                    ens_mean_variance.run                   rtpp.run.ref

After running ctest, you can terminate your interactive job by simply typing 'exit' or by:

$ qstat -u $USER
$ qdel job-id-number

The qstat command will return your job ID in a form of 'job-id-number.desched*'. The qdel command will kill your interactive job by only supplying 'job-id-number'.

Note that the tutorial test cases are designed with single-precision MPAS model test dataset. Therefore, we pre-compiled mpas-bundle code with single-precision mode in

/glade/derecho/scratch/liuz/mpas_bundle_v3_public_gnuSP

Tutorial attendees should use this pre-build bundle for mpas-jedi practicals and should set an environment variable 'bundle_dir' for convenience in the subsequent practices.

$ export bundle_dir=/glade/derecho/scratch/liuz/mpas_bundle_v3_public_gnuSP

2. Running MPAS-JEDI's HofX application

In this session, we will be running an application called 𝐻(𝐱).

2.1 Create working directory and link files

Creating hofx directory in mpas_jedi_tutorial,

$ cd /glade/derecho/scratch/${USER}/mpas_jedi_tutorial
$ mkdir hofx
$ cd hofx

Set environment variable for the mpas-bundle directory,

$ export bundle_dir=/glade/derecho/scratch/liuz/mpas_bundle_v3_public_gnuSP

Now, we need to prepare input files to run hofx. The following commands are for linking files, such as, physics-related data and tables, MPAS graph, streams, and namelist files:

$ ln -fs ../MPAS_namelist_stream_physics_files/*TBL .
$ ln -fs ../MPAS_namelist_stream_physics_files/*DBL .
$ ln -fs ../MPAS_namelist_stream_physics_files/*DATA .
$ ln -fs ../MPAS_namelist_stream_physics_files/x1.10242.graph.info.part.64 .
$ ln -fs ../MPAS_namelist_stream_physics_files/namelist.atmosphere_240km .
$ ln -fs ../MPAS_namelist_stream_physics_files/streams.atmosphere_240km .
$ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.analysis .
$ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.background .
$ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.control .
$ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.ensemble .

Link yamls:

$ ln -fs ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/geovars.yaml .
$ ln -fs ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/keptvars.yaml .
$ ln -fs ${bundle_dir}/code/mpas-jedi/test/testinput/obsop_name_map.yaml .

Link MPAS 6-h forecast background file into template file and an MPAS invariant file for 2-stream I/O:

$ ln -fs ../MPAS_namelist_stream_physics_files/x1.10242.invariant.nc .
$ ln -fs ../background/2018041418/mpasout.2018-04-15_00.00.00.nc templateFields.10242.nc

Link the background and observation input files:

$ ln -fs ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./bg.2018-04-15_00.00.00.nc
$ ln -fs ../obs_ioda_pregenerated/2018041500/aircraft_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/gnssro_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/satwind_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/sfc_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/sondes_obs_2018041500.h5  .

2.2 Run HofX

Link hofx3d.yaml and run_hofx3d.csh to the working directory:

$ ln -sf ../MPAS_JEDI_yamls_scripts/hofx3d.yaml .
$ ln -sf ../MPAS_JEDI_yamls_scripts/run_hofx3d.csh .

Submit a PBS job to run hofx,

$ qsub run_hofx3d.csh 

According to the setting in hofx3d.yaml, the output files are obsout_hofx_*.h5. You may check the output file content using 'ncdump -h obsout_hofx_aircraft.h5'. you can also check hofx by running plot_diag.py.

The following steps are for set up python environment, copy graphics directory, and run plot_diag.py:

$ module reset
$ module load conda
$ conda activate npl
$ cp -r ${bundle_dir}/code/mpas-jedi/graphics .
$ cd graphics/standalone
$ python plot_diag.py

This will produce a number of figure files, display one of them

display distri_windEastward_hofx_aircraft_omb_allLevels.png

which will look like the figure below

To view more figures, it is more convenient to transfer them to your local computer via:

$ scp -r $USER@data-access.ucar.edu:/glade/derecho/scratch/$USER/mpas_jedi_tutorial/hofx/graphics/standalone .

3. Generating localization files and running 3D/4DEnVar with "conventional" obs

3.1 Generating BUMP localization files

In this practice, we will generate the BUMP localization files to be used for spatial localization of ensemble background error covariance. These files will be used in the following 3D/4DEnVar and hybrid-3DEnVar data assimilation practice.

After changing to our /glade/derecho/scratch/${USER}/mpas_jedi_tutorial directory, create the working directory.

$ cd /glade/derecho/scratch/$USER/mpas_jedi_tutorial
$ mkdir localization
$ cd localization

Set environment variable for the mpas-bundle directory,

$ export bundle_dir=/glade/derecho/scratch/liuz/mpas_bundle_v3_public_gnuSP

Link MPAS physics-related data and tables, MPAS graph, MPAS streams, MPAS namelist files.

$ ln -fs ../MPAS_namelist_stream_physics_files/*BL ./
$ ln -fs ../MPAS_namelist_stream_physics_files/*DATA ./
$ ln -fs ../MPAS_namelist_stream_physics_files/x1.10242.graph.info.part.64 ./
$ ln -fs ../MPAS_namelist_stream_physics_files/streams.atmosphere_240km ./
$ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.analysis ./
$ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.background ./
$ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.control ./
$ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.ensemble ./
$ ln -fs ../MPAS_namelist_stream_physics_files/namelist.atmosphere_240km ./

Link MPAS 2-stream files.

$ ln -fs ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./
$ ln -fs ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./templateFields.10242.nc
$ ln -fs ../MPAS_namelist_stream_physics_files/x1.10242.invariant.nc .

Link yaml files.

$ ln -fs ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/geovars.yaml  ./
$ ln -fs ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/keptvars.yaml  ./
$ ln -fs ../MPAS_JEDI_yamls_scripts/bumploc.yaml ./

Link and submit pbs job script.

$ ln -sf ../MPAS_JEDI_yamls_scripts/run_bumploc.csh ./
$ qsub run_bumploc.csh

User may check the PBS job status by running qstat -u $USER, or monitoring the log file jedi.log.

After finishing the PBS job, user can check the BUMP localization files generated. The "local" files are generated for each processor (64 processors in this practice).

$ ls bumploc_1200km6km_nicas_local_*.nc 
bumploc_1200km6km_nicas_local_000064-000001.nc bumploc_1200km6km_nicas_local_000064-000033.nc bumploc_1200km6km_nicas_local_000064-000002.nc bumploc_1200km6km_nicas_local_000064-000034.nc bumploc_1200km6km_nicas_local_000064-000003.nc bumploc_1200km6km_nicas_local_000064-000035.nc bumploc_1200km6km_nicas_local_000064-000004.nc bumploc_1200km6km_nicas_local_000064-000036.nc bumploc_1200km6km_nicas_local_000064-000005.nc bumploc_1200km6km_nicas_local_000064-000037.nc bumploc_1200km6km_nicas_local_000064-000006.nc bumploc_1200km6km_nicas_local_000064-000038.nc bumploc_1200km6km_nicas_local_000064-000007.nc bumploc_1200km6km_nicas_local_000064-000039.nc bumploc_1200km6km_nicas_local_000064-000008.nc bumploc_1200km6km_nicas_local_000064-000040.nc bumploc_1200km6km_nicas_local_000064-000009.nc bumploc_1200km6km_nicas_local_000064-000041.nc bumploc_1200km6km_nicas_local_000064-000010.nc bumploc_1200km6km_nicas_local_000064-000042.nc bumploc_1200km6km_nicas_local_000064-000011.nc bumploc_1200km6km_nicas_local_000064-000043.nc bumploc_1200km6km_nicas_local_000064-000012.nc bumploc_1200km6km_nicas_local_000064-000044.nc bumploc_1200km6km_nicas_local_000064-000013.nc bumploc_1200km6km_nicas_local_000064-000045.nc bumploc_1200km6km_nicas_local_000064-000014.nc bumploc_1200km6km_nicas_local_000064-000046.nc bumploc_1200km6km_nicas_local_000064-000015.nc bumploc_1200km6km_nicas_local_000064-000047.nc bumploc_1200km6km_nicas_local_000064-000016.nc bumploc_1200km6km_nicas_local_000064-000048.nc bumploc_1200km6km_nicas_local_000064-000017.nc bumploc_1200km6km_nicas_local_000064-000049.nc bumploc_1200km6km_nicas_local_000064-000018.nc bumploc_1200km6km_nicas_local_000064-000050.nc bumploc_1200km6km_nicas_local_000064-000019.nc bumploc_1200km6km_nicas_local_000064-000051.nc bumploc_1200km6km_nicas_local_000064-000020.nc bumploc_1200km6km_nicas_local_000064-000052.nc bumploc_1200km6km_nicas_local_000064-000021.nc bumploc_1200km6km_nicas_local_000064-000053.nc bumploc_1200km6km_nicas_local_000064-000022.nc bumploc_1200km6km_nicas_local_000064-000054.nc bumploc_1200km6km_nicas_local_000064-000023.nc bumploc_1200km6km_nicas_local_000064-000055.nc bumploc_1200km6km_nicas_local_000064-000024.nc bumploc_1200km6km_nicas_local_000064-000056.nc bumploc_1200km6km_nicas_local_000064-000025.nc bumploc_1200km6km_nicas_local_000064-000057.nc bumploc_1200km6km_nicas_local_000064-000026.nc bumploc_1200km6km_nicas_local_000064-000058.nc bumploc_1200km6km_nicas_local_000064-000027.nc bumploc_1200km6km_nicas_local_000064-000059.nc bumploc_1200km6km_nicas_local_000064-000028.nc bumploc_1200km6km_nicas_local_000064-000060.nc bumploc_1200km6km_nicas_local_000064-000029.nc bumploc_1200km6km_nicas_local_000064-000061.nc bumploc_1200km6km_nicas_local_000064-000030.nc bumploc_1200km6km_nicas_local_000064-000062.nc bumploc_1200km6km_nicas_local_000064-000031.nc bumploc_1200km6km_nicas_local_000064-000063.nc bumploc_1200km6km_nicas_local_000064-000032.nc bumploc_1200km6km_nicas_local_000064-000064.nc

For a Dirac function multiplied by a given localization function, user can make a plot with dirac_nicas.2018-04-15_00.00.00.nc .

Note that we need to load the python environment before executing the python script. If you have already loaded the spack-stack module, please reset the module environment to properly load the NCAR Python Library (NPL).

$ module reset
$ module load conda
$ conda activate npl

Copy the plotting script for Dirac output.

$ cp ../MPAS_JEDI_yamls_scripts/plot_bumploc.py ./
$ python plot_bumploc.py
$ display figure_bumploc.png

User may play with different localization lengths (e.g., change the horizontal one from 1200km to 600km) by changing the following YAML keys from bumploc.yaml, then re-submit the PBS job script.

[Note that dirac_nicas.2018-04-15_00.00.00.nc and figure_bumploc.png will be overwritten, so it is a good idea to rename the existing files to compare them to those from a new experiment with modified localization lengths.]

      ...
      io:
	files prefix: bumploc_1200km6km
      ...
      nicas:
        resolution: 8.0
        explicit length-scales: true
        horizontal length-scale:
          - groups: [common]
	    value: 1200.0e3
        vertical length-scale:
          - groups: [common]
	    value: 6.0e3
      ...

Make a plot for Dirac result (with plot_bumploc.py) to see how the localization looks like.

3.2 Running a 240 km 3DEnVar analysis

We are now ready to set up and run the first analysis test using 3DEnVar. For this 3DEnVar, we will use a 240 km background forecast and ensemble input at the same resolution.

Let's create a new working directory for this test:

$ cd /glade/derecho/scratch/${USER}/mpas_jedi_tutorial
$ mkdir 3denvar
$ cd 3denvar

Set environment variable for the mpas-bundle directory,

$ export bundle_dir=/glade/derecho/scratch/liuz/mpas_bundle_v3_public_gnuSP

We can then link the relevant MPAS stream, graph, namelist, and physics files:

$ ln -sf ../MPAS_namelist_stream_physics_files/*BL ./
$ ln -sf ../MPAS_namelist_stream_physics_files/*DATA ./
$ ln -sf ../MPAS_namelist_stream_physics_files/x1.10242.graph.info.part.64 ./
$ ln -sf ../MPAS_namelist_stream_physics_files/namelist.atmosphere_240km ./
$ ln -sf ../MPAS_namelist_stream_physics_files/streams.atmosphere_240km ./
$ ln -sf ../MPAS_namelist_stream_physics_files/stream_list*  ./

Next, we need to link in a few yaml files that define MPAS variables for JEDI:

$ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/geovars.yaml ./
$ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/keptvars.yaml ./
$ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/obsop_name_map.yaml ./

Next, we need to link MPAS 2-stream files corresponding to the 240 km mesh. For this experiment we need to link the following files:

$ ln -fs ../MPAS_namelist_stream_physics_files/x1.10242.invariant.nc .
$ ln -fs ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./templateFields.10242.nc

Next, we should link the background file mpasout.2018-04-15_00.00.00.nc into the working directory and make a copy of the background file as the analysis file to be overwritten.

$ ln -fs ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./bg.2018-04-15_00.00.00.nc
$ cp ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./an.2018-04-15_00.00.00.nc

Next, we need to link bump localization files.

$ ln -fs ../localization_pregenerated ./BUMP_files

Next, we need to link observation files into the working directory.

$ ln -fs ../obs_ioda_pregenerated/2018041500/aircraft_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/gnssro_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/satwind_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/sfc_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/sondes_obs_2018041500.h5  .

Next, we are ready to link the pre-prepared 3denvar.yaml file for 3DEnVar. 3denvar.yaml contains all of the settings we need for this 3DEnVar update.

$ ln -sf ../MPAS_JEDI_yamls_scripts/3denvar.yaml ./

We are finally ready to link a PBS job script and then submit it. Notice the job script runs the following executable mpasjedi_variational.x, which is used for all of our variational updates.

$ ln -fs ../MPAS_JEDI_yamls_scripts/run_3denvar.csh ./
$ qsub run_3denvar.csh

Once your job is submitted, you can check the status of the job using qstat -u ${USER}. When the job is complete, you can check the log file by using vi mpasjedi_3denvar.log.

Now that the analysis was successful, you may plot the cost function and gradient norm reduction.

$  module load conda
$  conda activate npl
$  cp ${bundle_dir}/code/mpas-jedi/graphics/standalone/plot_cost_grad.py .

Changing 'jedi.log' to 'mpasjedi_3denvar.log' in plot_cost_grad.py, then do

$  python plot_cost_grad.py

You can then view the figure using the following:

$ display costgrad.png
cost function and gradient norm reduction

You can also plot the analysis increment (i.e., an.*.nc - bg.*.nc) with the following.

$  cp ../MPAS_JEDI_yamls_scripts/plot_analysis_increment.py ./
$  python plot_analysis_increment.py
$  display figure_increment_uReconstructZonal_10.png
3DEnVar Inc

You will also see several so-called DA "feedback" files below:

obsout_da_aircraft.h5
obsout_da_gnssro.h5
obsout_da_satwind.h5
obsout_da_sfc.h5
obsout_da_sondes.h5

You can follow the same procedure as in section 2.2 to plot these 'feedback' files, e.g.,

$ module load conda
$ conda activate npl
$ cp -r ${bundle_dir}/code/mpas-jedi/graphics .
$ cd graphics/standalone
$ python plot_diag.py
This will produce a number of figure files, display one of them
display RMSofOMM_da_aircraft_airTemperature.png

which will look like the figure below

3.3 Running a dual-resolution 120-240 km 3DEnVar analysis

Now we know how to run a 3DEnVar analysis, let's prepare a second test which uses a higher resolution background of 120 km but a coarser ensemble of 240 km.

Let's create a new working directory to run our 120-240km 3DEnVar update:

$ cd /glade/derecho/scratch/${USER}/mpas_jedi_tutorial
$ mkdir 3denvar_120km240km
$ cd 3denvar_120km240km

Set environment variable for the mpas-bundle directory,

$ export bundle_dir=/glade/derecho/scratch/liuz/mpas_bundle_v3_public_gnuSP

We can then link the relevant MPAS stream, graph, namelist, and physics files. In addition to files for 240km mesh, we also need files for 120 km mesh.

$ ln -sf ../MPAS_namelist_stream_physics_files/*BL ./
$ ln -sf ../MPAS_namelist_stream_physics_files/*DATA ./
$ ln -sf ../MPAS_namelist_stream_physics_files/x1.10242.graph.info.part.64 ./
$ ln -sf ../MPAS_namelist_stream_physics_files/x1.40962.graph.info.part.64 ./
$ ln -sf ../MPAS_namelist_stream_physics_files/namelist.atmosphere_240km ./
$ ln -sf ../MPAS_namelist_stream_physics_files/namelist.atmosphere_120km ./
$ ln -sf ../MPAS_namelist_stream_physics_files/streams.atmosphere_240km ./
$ ln -sf ../MPAS_namelist_stream_physics_files/streams.atmosphere_120km ./
$ ln -sf ../MPAS_namelist_stream_physics_files/stream_list*  ./

Next, we need to link in a few yaml files again that define MPAS variables for JEDI:

$ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/geovars.yaml ./
$ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/keptvars.yaml ./
$ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/obsop_name_map.yaml ./

Next, we need to link MPAS 2-stream files corresponding to both 240 km and 120 km MPAS grids. We need both a static.nc file and templateFields.nc file. For this experiment we need to link the following files:

$ ln -fs ../MPAS_namelist_stream_physics_files/x1.10242.invariant.nc .
$ ln -fs ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./templateFields.10242.nc
$ ln -fs ../MPAS_namelist_stream_physics_files/x1.40962.invariant.nc .
$ ln -fs ../background_120km/2018041418/mpasout.2018-04-15_00.00.00.nc ./templateFields.40962.nc

Next, we should link 120 km background file into the working directory and make a copy of the background file as the analysis file to be overwritten.

$ ln -fs ../background_120km/2018041418/mpasout.2018-04-15_00.00.00.nc ./bg.2018-04-15_00.00.00.nc
$ cp ../background_120km/2018041418/mpasout.2018-04-15_00.00.00.nc ./an.2018-04-15_00.00.00.nc

Next, we need to link our bump localization files.

$ ln -fs ../localization_pregenerated ./BUMP_files

Next, we need to link observation files into the working directory.

$ ln -fs ../obs_ioda_pregenerated/2018041500/aircraft_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/gnssro_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/satwind_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/sfc_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/sondes_obs_2018041500.h5  .

Next, we are ready to copy the pre-prepared 3denvar_120km240km.yaml file for this dual-resolution 3DEnVar.

$ ln -sf ../MPAS_JEDI_yamls_scripts/3denvar_120km240km.yaml ./3denvar.yaml

We are finally ready to link a PBS job script and then submit the job.

$ ln -fs ../MPAS_JEDI_yamls_scripts/run_3denvar.csh ./
$ qsub run_3denvar.csh

Again, you can check the status of the job using qstat -u ${USER}. When the job is complete, you can check the log file by using vi mpasjedi_3denvar.log.

Again, you may plot cost function and gradient norm reduction as well as the analysis increment.

You need to change "x1.10242.invariant.nc" to "x1.40962.invariant.nc" within plot_analysis_increment.py in order to plot increment at the 120 km mesh.

3.4 Running a 240 km 4DEnVar analysis

Now we know how to run a 3DEnVar analysis, let's try 4DEnVar with 3 subwindows.

Let's create a new working directory to run 240km 4DEnVar:

$ cd /glade/derecho/scratch/${USER}/mpas_jedi_tutorial
$ mkdir 4denvar
$ cd 4denvar

Set environment variable for the mpas-bundle directory,

$ export bundle_dir=/glade/derecho/scratch/liuz/mpas_bundle_v3_public_gnuSP

We can then link MPAS stream, graph, namelist, and physics files just as we did for 3DEnVar.

$ ln -sf ../MPAS_namelist_stream_physics_files/*BL ./
$ ln -sf ../MPAS_namelist_stream_physics_files/*DATA ./
$ ln -sf ../MPAS_namelist_stream_physics_files/x1.10242.graph.info.part.64 ./
$ ln -sf ../MPAS_namelist_stream_physics_files/namelist.atmosphere_240km ./
$ ln -sf ../MPAS_namelist_stream_physics_files/streams.atmosphere_240km ./
$ ln -sf ../MPAS_namelist_stream_physics_files/stream_list*  ./

Next, we need to link a few yaml files again that define MPAS variables for JEDI:

$ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/geovars.yaml ./
$ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/keptvars.yaml ./
$ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/obsop_name_map.yaml ./

Next, we need to link MPAS 2-stream files corresponding to 240km mesh. For this experiment we need to link the following files:

$ ln -fs ../MPAS_namelist_stream_physics_files/x1.10242.invariant.nc .
$ ln -fs ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./templateFields.10242.nc

Next, we need to link 240km background files for each subwindow into the working directory and make a copy of each background file as the analysis file for each subwindow to be overwritten.

$ ln -fs ../background/2018041418/mpasout.2018-04-14_21.00.00.nc ./bg.2018-04-14_21.00.00.nc
$ cp ../background/2018041418/mpasout.2018-04-14_21.00.00.nc     ./an.2018-04-14_21.00.00.nc
$ ln -fs ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./bg.2018-04-15_00.00.00.nc
$ cp ../background/2018041418/mpasout.2018-04-15_00.00.00.nc     ./an.2018-04-15_00.00.00.nc
$ ln -fs ../background/2018041418/mpasout.2018-04-15_03.00.00.nc ./bg.2018-04-15_03.00.00.nc
$ cp ../background/2018041418/mpasout.2018-04-15_03.00.00.nc     ./an.2018-04-15_03.00.00.nc

Next, we need to link bump localization files.

$ ln -fs ../localization_pregenerated ./BUMP_files

Next, we need to link observation files.

$ ln -fs ../obs_ioda_pregenerated/2018041500/aircraft_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/gnssro_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/satwind_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/sfc_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/sondes_obs_2018041500.h5  .

Next, we are ready to link the pre-prepared 4denvar.yaml file.

$ ln -sf ../MPAS_JEDI_yamls_scripts/4denvar.yaml ./4denvar.yaml

We are finally ready to link a PBS job script and then submit a job. Note that this 4DEnVar job uses 3 nodes with 64 cores per node for 3 subwindows.

$ ln -fs ../MPAS_JEDI_yamls_scripts/run_4denvar.csh ./
$ qsub run_4denvar.csh

Again, you can check the status of the job using qstat -u ${USER}. When the job is complete, you can check the log file by using vi mpasjedi_4denvar.log.

Again, you can plot cost function and gradient norm reduction as well as analysis increments at one of 3 subwindows.

You may modify the an and bg files in plot_analysis_increment.py to see how the increment changes across the subwindows.

4. Running 3DVar and hybrid-3DEnVar with satellite radiance data

4.1 Running 3DVar

In this practice, we will run MPAS-JEDI 3DVar at global 240 km mesh. The overall procedure is similar to the 3D/4DEnVar practice. However, 3DVar uses the static multivariate background error covariance (B), which contains the climatological characteristics. Here, the pre-generated static B will be used. We hope to provide a practice for static B training in future MPAS-JEDI tutorials.

After changing to our /glade/derecho/scratch/${USER}/mpas_jedi_tutorial directory, create the working directory for 3dvar.

$ cd /glade/derecho/scratch/$USER/mpas_jedi_tutorial
$ mkdir 3dvar
$ cd 3dvar

Set environment variable for the mpas-bundle directory,

$ export bundle_dir=/glade/derecho/scratch/liuz/mpas_bundle_v3_public_gnuSP

Link MPAS physics-related data and tables, MPAS graph, MPAS streams, and MPAS namelist files.

$ ln -fs ../MPAS_namelist_stream_physics_files/*BL ./
$ ln -fs ../MPAS_namelist_stream_physics_files/*DATA ./
$ ln -fs ../MPAS_namelist_stream_physics_files/x1.10242.graph.info.part.64 ./
$ ln -fs ../MPAS_namelist_stream_physics_files/streams.atmosphere_240km ./
$ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.analysis ./
$ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.background ./
$ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.control ./
$ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.ensemble ./
$ ln -fs ../MPAS_namelist_stream_physics_files/namelist.atmosphere_240km ./

Link the background file and copy it as an analysis file.

The file with prefix mpasout contains the variables for "da_state" stream of 2-stream I/O.

And the data assimilation will overwrite several selected analyzed variables (defined in stream_list.atmosphere.analysis) in the analysis file.

$ ln -fs ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./bg.2018-04-15_00.00.00.nc
$ cp ./bg.2018-04-15_00.00.00.nc ./an.2018-04-15_00.00.00.nc

Link MPAS 2-stream files.

$ ln -fs ../MPAS_namelist_stream_physics_files/x1.10242.invariant.nc .
$ ln -fs ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./templateFields.10242.nc

Prepare the pre-generated static B files.

$ ln -fs ../B_Matrix ./

Next, link the observation files to be assimilated. Along the conventional observation, here a single AMSU-A radiance observation from NOAA-18 is added.

$ ln -fs ../obs_ioda_pregenerated/2018041500/aircraft_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/gnssro_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/satwind_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/sfc_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/sondes_obs_2018041500.h5  .
$ ln -fs ../obs_ioda_pregenerated/2018041500/amsua_n18_obs_2018041500.h5

For this 3DVar test, satellite radiance data from NOAA-18's AMSU-A sensor is assimilated, so need coefficient files for CRTM.

$ ln -fs ../crtm_coeffs_v3  ./

Link yaml files:

$ ln -fs ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/geovars.yaml  ./
$ ln -fs ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/keptvars.yaml  ./
$ ln -fs ${bundle_dir}/code/mpas-jedi/test/testinput/obsop_name_map.yaml ./
$ ln -sf ../MPAS_JEDI_yamls_scripts/3dvar.yaml ./

Link and submit pbs job script:

$ ln -sf ../MPAS_JEDI_yamls_scripts/run_3dvar.csh ./
$ qsub run_3dvar.csh

User may check the PBS job status by running qstat -u $USER, or monitoring the log file tail -f mpasjedi_3dvar.log .

You may make figures following similar procedures in previous sections.

  • You may also try to assimilate additional satellite radiance data.

    To do this, additional obs file (for example, ../obs_ioda_pregenerated/2018041500/amsua_n19_obs_2018041500.h5) should be linked to /glade/derecho/scratch/$USER/mpas_jedi_tutorial/3dvar/.

    Also, user need to add the corresponding obs space yaml key in 3dvar.yaml .

  • 4.2 Running Hybrid-3DEnVar

    In this practice, we will run MPAS-JEDI Hybrid-3DEnVar at global 240 km mesh. The hybrid covariance will be made from both static B and ensemble B.

    After changing to /glade/derecho/scratch/${USER}/mpas_jedi_tutorial directory, create the working directory for Hybrid-3DEnVar.

    $ cd /glade/derecho/scratch/$USER/mpas_jedi_tutorial
    $ mkdir hybrid-3denvar
    $ cd hybrid-3denvar
    

    Set environment variable for the mpas-bundle directory,

    $ export bundle_dir=/glade/derecho/scratch/liuz/mpas_bundle_v3_public_gnuSP
    

    Link MPAS physics-related data and tables, MPAS graph, MPAS streams, and MPAS namelist files.

    $ ln -fs ../MPAS_namelist_stream_physics_files/*BL ./
    $ ln -fs ../MPAS_namelist_stream_physics_files/*DATA ./
    $ ln -fs ../MPAS_namelist_stream_physics_files/x1.10242.graph.info.part.64 ./
    $ ln -fs ../MPAS_namelist_stream_physics_files/streams.atmosphere_240km ./
    $ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.analysis ./
    $ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.background ./
    $ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.control ./
    $ ln -fs ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.ensemble ./
    $ ln -fs ../MPAS_namelist_stream_physics_files/namelist.atmosphere_240km ./
    

    Link the background file and copy it as an analysis file.

    $ ln -fs ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./bg.2018-04-15_00.00.00.nc
    $ cp ./bg.2018-04-15_00.00.00.nc ./an.2018-04-15_00.00.00.nc
    

    Link MPAS 2-stream files.

    $ ln -fs ../MPAS_namelist_stream_physics_files/x1.10242.invariant.nc .
    $ ln -fs ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./templateFields.10242.nc
    

    Prepare the pre-generated static B files.

    $ ln -fs ../B_Matrix ./
    

    Link the localization files.

    $ ln -fs ../localization_pregenerated ./BUMP_files
    

    Link the observation files to be assimilated. Along the conventional observation, here a single AMSU-A radiance observation from NOAA-18 is added.

    $ ln -fs ../obs_ioda_pregenerated/2018041500/aircraft_obs_2018041500.h5  .
    $ ln -fs ../obs_ioda_pregenerated/2018041500/gnssro_obs_2018041500.h5  .
    $ ln -fs ../obs_ioda_pregenerated/2018041500/satwind_obs_2018041500.h5  .
    $ ln -fs ../obs_ioda_pregenerated/2018041500/sfc_obs_2018041500.h5  .
    $ ln -fs ../obs_ioda_pregenerated/2018041500/sondes_obs_2018041500.h5  .
    $ ln -fs ../obs_ioda_pregenerated/2018041500/amsua_n18_obs_2018041500.h5
    

    Prepare the coefficient files for CRTM.

    $ ln -fs ../crtm_coeffs_v3  ./
    

    Link yaml files.

    $ ln -fs ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/geovars.yaml  ./
    $ ln -fs ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/keptvars.yaml  ./
    $ ln -fs ${bundle_dir}/code/mpas-jedi/test/testinput/obsop_name_map.yaml ./
    $ ln -fs ../MPAS_JEDI_yamls_scripts/3dhyb.yaml ./
    

    Link and submit pbs job script.

    $ ln -sf ../MPAS_JEDI_yamls_scripts/run_3dhyb.csh ./
    $ qsub run_3dhyb.csh
    

    User may check the PBS job status by running qstat -u $USER, or monitoring the log file tail -f mpasjedi_3dhyb.log .

    User may want to try additional practice as below.

    1. Change the hybrid weights.

      The default 3dhyb.yaml uses 0.5 and 0.5 weights for static B and ensemble B. User can modify these weights, for example, 0.2/0.8 , 0.8/0.2 , 1.0/0.0 , 0.0/1.0 , or even 2.0/1.5 .

        background error:
          covariance model: hybrid
          components:
          - weight:
          value:  0.5
            covariance:
              covariance model: SABER
              ...
          - weight:
          value:  0.5
            covariance:
              covariance model: ensemble
              ...
      

      You may see some changes in the fit-to-obs statistics, convergence, or analysis increment fields.

    5. Running EDA and LETKF

    In this section, we'll get some experience in running single-time EDA and LETKF analysis test.

    5.1 Running single-time EDA analysis

    Here, we will run the single-time EDA analysis, which has a total of 10 3DEnVar members.

    First, We need to create the working directory for EDA test and move to that directory:

    $ mkdir -p /glade/derecho/scratch/$USER/mpas_jedi_tutorial/eda
    $ cd /glade/derecho/scratch/$USER/mpas_jedi_tutorial/eda
    

    Set environment variable for the mpas-bundle directory,

    $ export bundle_dir=/glade/derecho/scratch/liuz/mpas_bundle_v3_public_gnuSP
    

    Then, we need to prepare necessary files for EDA test. Link MPAS physics-related data and table, MPAS graph, MPAS streams, and MPAS namelist files:

    $ ln -sf ../MPAS_namelist_stream_physics_files/*BL .
    $ ln -sf ../MPAS_namelist_stream_physics_files/*DATA .
    $ ln -sf ../MPAS_namelist_stream_physics_files/x1.10242.graph.info.part.64 .
    $ ln -sf ../MPAS_namelist_stream_physics_files/streams.atmosphere_240km .
    $ ln -sf ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.* .
    $ ln -sf ../MPAS_namelist_stream_physics_files/namelist.atmosphere_240km .
    

    Link MPAS 2-stream files:

    $  ln -sf ../MPAS_namelist_stream_physics_files/x1.10242.invariant.nc .
    $  ln -sf ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./templateFields.10242.nc 
    

    Link static yaml files for MPAS-JEDI:

    $ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/geovars.yaml  ./
    $ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/keptvars.yaml  ./
    $ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/obsop_name_map.yaml ./
    

    Prepare the ensemble background as well as ensemble analysis directories and files for EDA. Since we have 20 members, it will be better that we deal with them by creating a simple cshell script prep_an_bg_directories.csh:

    #!/bin/csh
    foreach imem (01 02 03 04 05 06 07 08 09 10)
      mkdir -p bg/mem0${imem} an/mem0${imem}
      set tpath=/glade/derecho/scratch/$USER/mpas_jedi_tutorial
      ln -sf ${tpath}/ensemble/2018041418/${imem}/mpasout.2018-04-15_00.00.00.nc bg/mem0${imem}/bg.2018-04-15_00.00.00.nc
      cp ../ensemble/2018041418/${imem}/mpasout.2018-04-15_00.00.00.nc an/mem0${imem}/an.2018-04-15_00.00.00.nc
    end
    

    After running prep_an_bg_directories.csh, the an and bg directories and files are prepared.

    $ chmod 755 ./prep_an_bg_directories.csh
    $ ./prep_an_bg_directories.csh
    

    Next step, we create a directory dbIn for observation input, and a directory dbOut to store the observation feedback files of all EDA members.

    $ mkdir dbIn 
    $ cd dbIn
    $ ln -sf ../../obs_ioda_pregenerated/2018041500/aircraft_obs_2018041500.h5  ./
    $ ln -sf ../../obs_ioda_pregenerated/2018041500/gnssro_obs_2018041500.h5    ./
    $ ln -sf ../../obs_ioda_pregenerated/2018041500/sfc_obs_2018041500.h5       ./
    $ ln -sf ../../obs_ioda_pregenerated/2018041500/satwind_obs_2018041500.h5   ./
    $ ln -sf ../../obs_ioda_pregenerated/2018041500/sondes_obs_2018041500.h5    ./
    $ cd ..
    

    For dbOut directory, we need to create subdirectories for all EDA members with a simple cshell script, prep_dbout_directory.csh:

    #!/bin/csh
    foreach imem (01 02 03 04 05 06 07 08 09 10)
      mkdir -p dbOut/mem0${imem}
    end
    

    By running the prep_dbout_directory.csh with the command:

    $ chmod 755 ./prep_dbout_directory.csh
    $ ./prep_dbout_directory.csh
    

    the dbOut directory and its subdirectories are created.

    Also, link the localization matrix and static BEC files.

    $ ln -sf ../localization_pregenerated ./bumploc
    $ ln -sf ../B_Matrix     ./
    

    Last, copy related yaml files and scripts for EDA running:

    $ ln -sf ../MPAS_JEDI_yamls_scripts/eda_3denvar.yaml ./
    $ ln -sf ../MPAS_JEDI_yamls_scripts/eda_rtpp.yaml ./
    $ ln -sf ../MPAS_JEDI_yamls_scripts/run_eda_members.csh ./
    $ ln -sf ../MPAS_JEDI_yamls_scripts/run_eda_rtpp.csh ./
    

    The eda_3denvar.yaml is a template yaml file for all 3DEnVar EDA members. the eda_3denvar.yaml file is very similar to 3denvar.yaml. You may do "diff 3denvar.yaml eda_3denvar.yaml" to see their difference.

    18,19c18,19
    <   member: 1
    <   number of members: 1
    ---
    >   member: {{imem}}
    >   number of members: 10
    38d37
    <
    40c39
    <   filename: ./an.$Y-$M-$D_$h.$m.$s.nc
    ---
    >   filename: ../../an/mem{{IMEM}}/an.$Y-$M-$D_$h.$m.$s.nc
    50,51c49,50
    <   - <<: *iterationConfig
    <     ninner: 50
    ---
    > #  - <<: *iterationConfig
    > #    ninner: 50
    69c68
    <     filename: ./bg.2018-04-15_00.00.00.nc
    ---
    >     filename: ../../bg/mem{{IMEM}}/bg.2018-04-15_00.00.00.nc
    80c79
    <             files prefix: ./BUMP_files/bumploc_1200km6km
    ---
    >             files prefix: ../../bumploc/bumploc_1200km6km
    89c88
    <         filename: ../ensemble/2018041418/%iMember%/mpasout.2018-04-15_00.00.00.nc
    ---
    >         filename: ../../bg/mem%iMember%/bg.2018-04-15_00.00.00.nc
    92,93c91,93
    <       zero padding: 2
    <       nmembers: 10
    ---
    >       zero padding: 3
    >       nmembers: 9
    >       except: [{{imem}}]
    95c95
    <     obs perturbations: false
    ---
    >     obs perturbations: true
    103c103
    <             obsfile: ./aircraft_obs_2018041500.h5
    ---
    >             obsfile: ../../dbIn/aircraft_obs_2018041500.h5
    107c107
    <             obsfile: ./obsout_da_aircraft.h5
    ---
    >             obsfile: ../../dbOut/mem{{IMEM}}/obsout_da_aircraft.h5
    131c131
    <             obsfile: ./gnssro_obs_2018041500.h5
    ---
    >             obsfile: ../../dbIn/gnssro_obs_2018041500.h5
    135c135
    <             obsfile: ./obsout_da_gnssroref.h5
    ---
    >             obsfile: ../../dbOut/mem{{IMEM}}/obsout_da_gnssroref.h5
    175c175
    <             obsfile: ./satwind_obs_2018041500.h5
    ---
    >             obsfile: ../../dbIn/satwind_obs_2018041500.h5
    179c179
    <             obsfile: ./obsout_da_satwind.h5
    ---
    >             obsfile: ../../dbOut/mem{{IMEM}}/obsout_da_satwind.h5
    228c228
    <             obsfile: ./sfc_obs_2018041500.h5
    ---
    >             obsfile: ../../dbIn/sfc_obs_2018041500.h5
    232c232
    <             obsfile: ./obsout_da_sfc.h5
    ---
    >             obsfile: ../../dbOut/mem{{IMEM}}/obsout_da_sfc.h5
    262c262
    <             obsfile: ./sondes_obs_2018041500.h5
    ---
    >             obsfile: ../../dbIn/sondes_obs_2018041500.h5
    266c266
    <             obsfile: ./obsout_da_sondes.h5
    ---
    >             obsfile: ../../dbOut/mem{{IMEM}}/obsout_da_sondes.h5
    

    Even though we can run each EDA member simulataneously, for this tutorial we run all 10 EDA members serially in one job, which will take about 10 minutes (one outer loop setting). In run_eda_members.csh, you may modify the line foreach iens to run less EDA members to save time.

    Submit the job script run_eda_members.csh with:

    $ qsub run_eda_members.csh
    

    When all EDA members are done, we will see that all an/mem*/an.2018-04-15_00.00.00.nc are updated, and there are observation feedback files generated in dbOut/mem*, namely obsout_da_*.h5.

    Different from LETKF, which does posterior inflation internally, an offline posterior RTPP inflation can be run after EDA analyses with:

    $ qsub run_eda_rtpp.csh
    

    The posterior RTPP inflation will update all EDA analysis members an/mem*/an.2018-04-15_00.00.00.nc.

    This EDA test is ensemble of 3DEnVar, you could also run ensemble of 3DVar, hybrid-3DEnVar, or even hybrid-4DEnVar, with a corresponding yaml setting. A yaml file named eda_3dhyb.yaml is provided for you to play with.

    We also prepared some NCL scripts for graphics to see the impacts of DA. Copy them to the working directory.

    $ cp ../ncl_scripts/plot_eda_*.ncl .
    

    Check whether the NCL library is available:

    $ which ncl
    

    If the system fails to find ncl, you may need to load the NCL module:

    $ module reset
    $ module load ncl/6.6.2
    

    We can plot the analysis increment of ensemble mean with the script plot_eda_ensmean_anainc.ncl. Specify the diag_var, diag_lev (for 3-D variables), and nens (if run fewer EDA members) in the script,

        diag_var="surface_pressure"
        diag_lev=10
        nens = 10
    

    and then run:

    $ ncl plot_eda_ensmean_anainc.ncl
    

    This will produce a figure named eda_ens_mean_inc_surface_pressure_lev0.png.

    With the plot_eda_ens_spread.ncl, we can plot the ensemble spread of both background and analysis. Similar to the ensemble mean increments, just change the diag_var and diag_lev in the NCL script, and run plot_eda_ens_spread.ncl:

    $ ncl plot_eda_ens_spread.ncl
    

    This will produce a figure eda_ens_spread_surface_pressure_lev0.png.

    We can also plot the vertical profiles of RMSE, BIAS, and total spread of the Innovations (Obs minus Bak) and Residuals (Obs minus Ana) with plot_eda_vert_profile_err.ncl. We need to specify the diag_obs, diag_var and nens (if run fewer EDA members) in the script:

    diag_obs="sondes"
    diag_var="windEastward"
    nens = 10
    

    Running:

    $ ncl plot_eda_vert_profile_err.ncl
    

    will produce a figure file eda_vert_profile_sondes_windEastward.png:

    5.2 Running single-time LETKF analysis

    In this subsection, we will further run a single-time LETKF analysis. First, we need to create the working directory for LETKF and move to that directory:

    $ mkdir -p /glade/derecho/scratch/$USER/mpas_jedi_tutorial/letkf
    $ cd /glade/derecho/scratch/$USER/mpas_jedi_tutorial/letkf
    

    Set environment variable for the mpas-bundle directory,

    $ export bundle_dir=/glade/derecho/scratch/liuz/mpas_bundle_v3_public_gnuSP
    

    Similar to EDA, we first prepare necessary files for LETKF.

    $ ln -sf ../MPAS_namelist_stream_physics_files/*BL .
    $ ln -sf ../MPAS_namelist_stream_physics_files/*DATA .
    $ ln -sf ../MPAS_namelist_stream_physics_files/x1.10242.graph.info.part.64 .
    $ ln -sf ../MPAS_namelist_stream_physics_files/streams.atmosphere_240km .
    $ ln -sf ../MPAS_namelist_stream_physics_files/stream_list.atmosphere.* .
    $ ln -sf ../MPAS_namelist_stream_physics_files/namelist.atmosphere_240km .
    $ ln -sf ../MPAS_namelist_stream_physics_files/x1.10242.invariant.nc .
    $ ln -sf ../background/2018041418/mpasout.2018-04-15_00.00.00.nc ./templateFields.10242.nc
    $ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/geovars.yaml  ./
    $ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/namelists/keptvars.yaml  ./
    $ ln -sf ${bundle_dir}/code/mpas-jedi/test/testinput/obsop_name_map.yaml ./
    

    Now prepare 'bg' and 'an' folders under letkf.

    $ cp ../eda/prep_an_bg_directories.csh .
    $ ./prep_an_bg_directories.csh
    $ cp -r an/mem001 an/mem000
    

    The reason of creating an/mem000 is that LETKF also writes out the mean of ensemble analyses under an/mem000. For observation-related directories, we need to create dbIn, dbOut, and dbAna directories, and link IODA observation files to dbIn directory:

    $ mkdir dbIn dbOut dbAna
    $ cd dbIn
    $ ln -sf ../../obs_ioda_pregenerated/2018041500/aircraft_obs_2018041500.h5  ./
    $ ln -sf ../../obs_ioda_pregenerated/2018041500/gnssro_obs_2018041500.h5    ./
    $ ln -sf ../../obs_ioda_pregenerated/2018041500/sfc_obs_2018041500.h5       ./
    $ ln -sf ../../obs_ioda_pregenerated/2018041500/satwind_obs_2018041500.h5   ./
    $ ln -sf ../../obs_ioda_pregenerated/2018041500/sondes_obs_2018041500.h5    ./
    $ cd ..
    

    link the yaml files and scripts for LETKF:

    $ ln -sf ../MPAS_JEDI_yamls_scripts/letkf_observer.yaml ./
    $ ln -sf ../MPAS_JEDI_yamls_scripts/letkf_solver.yaml ./
    $ ln -sf ../MPAS_JEDI_yamls_scripts/letkf_solver_vloc.yaml ./
    $ ln -sf ../MPAS_JEDI_yamls_scripts/letkf_diagoma.yaml ./
    $ ln -sf ../MPAS_JEDI_yamls_scripts/run_letkf_observer.csh ./
    $ ln -sf ../MPAS_JEDI_yamls_scripts/run_letkf_solver.csh ./
    $ ln -sf ../MPAS_JEDI_yamls_scripts/run_letkf_diagoma.csh ./
    

    letkf_observer.yaml, letkf_solver.yaml, and letkf_diagoma.yaml are used for the three steps of LETKF. letkf_observer.yaml is for calculating the ensemble HofX of background and performing quality control based on the ensemble mean. letkf_solver.yaml is for updating the ensemble mean and ensemble members. lketkf_diagoma.yaml is for calculating the ensemble HofX of analysis for OMA diagnosis.

    We first submit run_letkf_observer.csh:

    $ qsub run_letkf_observer.csh
    

    This observer step will produce obsout_da_*.h5 files in dbOut. In each df5 file, we can see groups of hofx_0_*, hofx_y_mean_xb0, ombg, EffectiveQC0, EffectiveError0.

    Then, submit run_letkf_solver.csh:

    $ qsub run_letkf_solver.csh
    

    This solver step will update an/mem*/an.2018-04-15_00.00.00.nc files, including the ensemble mean of analysis an/mem000/an.2018-04-15_00.00.00.nc.

    Last, submit run_letkf_diagoma.csh:

    $ qsub run_letkf_diagoma.csh
    

    The analysis-diagnos step will generate obsout_*.h5 files in dbAna, similar to the files in dbOut but for HofX of ensemble analysis.

    The previous run only tests the horizontal localization. If we want to also employ the vertical localization, just change

    _height-based obs localizations: &heightAndHorizObsLoc
      <<: *2DLETKFheightAndHorizObsLoc
    

    to

    _height-based obs localizations: &heightAndHorizObsLoc
      <<: *3DLETKFheightAndHorizObsLoc
    

    in letkf_solver.yaml, and then resubmit run_letkf_solver.csh and run_letkf_diagoma.csh. Backup an and dbAna directories before another run.

    Similar to the EDA test, we also prepared some NCL scripts to plot LETKF results.

    $ cp ../ncl_scripts/plot_letkf_*.ncl .
    

    Plotting the analysis increment of ensemble mean with plot_letkf_ensmean_anainc.ncl. We need to specify the diag_var and diag_lev (for 3-D variables) in the NCL script.

        diag_var="surface_pressure"
        diag_lev=10
    

    Then do:

    $ ncl plot_letkf_ensmean_anainc.ncl
    

    This will produce a figure letkf_ens_mean_inc_surface_pressure_lev0.png.

    For plotting ensemble spread of both background and analysis, you could change diag_var and diag_lev in plot_letkf_ens_spread.ncl before running:

    $ ncl plot_letkf_ens_spread.ncl
    

    This will produce a figure letkf_ens_spread_surface_pressure_lev0.png.

    For plotting the vertical profiles of RMSE, BIAS, and total spread of the Innovations (Obs minus Bak) and Residuals (Obs minus Ana) with plot_letkf_vert_profile_err.ncl, we could specify the diag_obs and diag_var in the script:

    diag_obs="sondes"
    diag_var="windEastward"
    

    then run:

    $ ncl plot_letkf_vert_profile_err.ncl
    

    This will produce a figure letkf_vert_profile_sondes_windEastward.png.

    6. Plotting OMB/OMA from two experiments

    In this section, we will make plots for the statistics of OmB/OmA feedback files from two 2-day cycling experiments by using the graphics package. In order to do this, we first generate observation-space statistics following the instructions in Section 6.1, then create the plots from statistics files following the instructions in Section 6.2.

    6.1 Generate statistics of OmB/OmA

    The statistics are generated for each cycle and all ObsSpace (e.g., sondes, aircraft, gnssro, etc.) found in the folder containing the data assimilation feedback files (i.e., obsout_da_*.h5). The statistics are binned globally and by latitude bands as specified in config.py. The binned statistics are stored in HDF5 files located in a folder named stats that is created for each cycle. The statistics are generated by the script DiagnoseObsStatistics.py in graphics.

    Let's begin by checking the directory called omboma_from2experiments:

    $ cd /glade/derecho/scratch/$USER/mpas_jedi_tutorial/omboma_from2experiments
    

    This folder contains sample variational-based DA observation "feedback" files from two experiments Exp1 and Exp2, e.g.,

    $ ls Exp1/CyclingDA/*
    

    You will see obsout_da_amsua_n18.h5 and obsout_da_gnssrobndropp1d.h5 under each cycle time during a 2-day period (9 cycles). We can generate the bias, RMSE, and standard deviation statistics of these OMB/OMA files using

    $ ln -sf ../MPAS_JEDI_yamls_scripts/generate_stats_omboma.csh .
    $ ln -sf ../MPAS_JEDI_yamls_scripts/advanceCYMDH.py .
    $ qsub generate_stats_omboma.csh
    

    The job will take ~5 minutes to complete, and you can take a look at the folder of the statistics files:

    $ ls Exp1/CyclingDA/*/stats
    

    You will see two files stats_da_amsua_n18.h5 and stats_da_gnssrobndropp1d.h5 in each folder. You may check generate_stats_omboma.csh, in which a line below generated statistical files.

    python DiagnoseObsStatistics.py -n ${NUMPROC} -p ${daDiagDir} -o obsout -app variational -nout 1
    
    where
    -n: number of tasks/processors for multiprocessing
    -p: path to DA feedback files (e.g., Exp1/CyclingDA/2018041500)
    -o: prefix for DA feedback files
    -app: application (variational or hofx)
    -nout: number of outer loops

    Also note that advanceCYMDH.py is a python code to help advance the time.

    If statistics files were created, we can proceed to make the plots in the next section!

    6.2 Make plots of OmB/OmA statistics

    Set environment variable for the mpas-bundle directory,

    $ export bundle_dir=/glade/derecho/scratch/liuz/mpas_bundle_v3_public_gnuSP
    

    Let us make a local copy of the graphics package first:

    $ cd /glade/derecho/scratch/$USER/mpas_jedi_tutorial/omboma_from2experiments
    $ cp -r ${bundle_dir}/code/mpas-jedi/graphics .
    $ cd graphics
    

    Then diff and replace analyze_config.py with a pre-prepared one:

    $ diff analyze_config.py ../../MPAS_JEDI_yamls_scripts/analyze_config.py
    $ mv analyze_config.py analyze_config.py_default
    $ cp ../../MPAS_JEDI_yamls_scripts/analyze_config.py .
    

    You can see the changes made in analyze_config.py by diff. Below provides some explanations about settings in analyze_config.py.

    • Set the first and last cycle date time:
      dbConf['firstCycleDTime'] = dt.datetime(2018,4,15,0,0,0)
      dbConf['lastCycleDTime'] = dt.datetime(2018,4,17,0,0,0)
    • Set the time increment between valid date times to 6 hours:
      dbConf['cyTimeInc'] = dt.timedelta(hours=6)
    • Set the verification type to omb/oma:
      VerificationType = 'omb/oma'
    • Set the verification space to obs:
      VerificationSpace = 'obs'
    • Set the workflow type to MPAS-JEDI_tutorial:
      workflowType = 'MPAS-JEDI_tutorial'
      
    • Set the path to the experiment's folder:
      dbConf['expDirectory'] = os.getenv('EXP_DIR','/glade/derecho/scratch/'+user+'/mpas_jedi_tutorial/omboma_from2experiments')
    • Set the the name of the experiment that will be used as reference or control:
      dbConf['cntrlExpName'] = 'exp1'
    • Specify the experiments to be analyzed. Make sure that the value given to cntrlExpName is one of the keys in the dictionary experiments:
      experiments['exp1'] = 'Exp1' + deterministicVerifyDir
      experiments['exp2'] = 'Exp2' + deterministicVerifyDir
    • Last, setting python environment and do

      $ module reset
      $ module load conda
      $ conda activate npl
      
      $ ./SpawnAnalyzeStats.py -a UMMM0008 -app variational -nout 1 -d gnssrobndropp1d
      $ ./SpawnAnalyzeStats.py -a UMMM0008 -app variational -nout 1 -d amsua_n18
      

      Each SpawnAnalyzeStats.py command triggers two PBS jobs for making two types of figures under gnssrobndropp1d_analyses and amsua_n18_analyses directories.

    • BinValAxisProfileDiffCI: vertical profiles of RMS relative differences from the RMS of OmB of Exp1 with confidence intervals (95%), as a function of the impact height for different latitude bands and binned by latitude at 10km
      CYAxisExpLines: time series of the bias, count, RMS, and STD averaged globally and by latitude bands
    • SpawnAnalyzeStats.py can take some arguments (similar as in previous section), such as:

      -a: account
      -app: application (e.g., variational, hofx)
      -nout: number of outer loops in the variational method
      -d: diagSpaces (e.g., amsua_,sonde,airc,sfc,gnssrobndropp1d,satwind)
      

      After jobs complete, you may check gnssrobndropp1d_analyses/CYAxisExpLines/omm, for example,

      $ cd gnssrobndropp1d_analyses/CYAxisExpLines/omm
      $ display QCflag_good_TSeries_0min_gnssrobndropp1d_omm_RMS.pdf
      

      which will look like the figure below

      To view more figures, it is more convenent to transfer them to your local computer via:

      $ scp -r $USER@data-access.ucar.edu:/glade/derecho/scratch/$USER/mpas_jedi_tutorial/omboma_from2experiments/graphics/gnssrobndropp1d_analyses .
      $ scp -r $USER@data-access.ucar.edu:/glade/derecho/scratch/$USER/mpas_jedi_tutorial/omboma_from2experiments/graphics/amsua_n18_analyses .
      

    7. Running regional MPAS-JEDI

    Regional MPAS-JEDI test is under 'conus15km', where all necessary input files are already prepared. You can simply submit a job script by

    $ cd /glade/derecho/scratch/$USER/mpas_jedi_tutorial/conus15km
    $ qsub run_conus15km.csh
    

    8. Converting NCEP BUFR obs into IODA-HDF5 format

    The goal of this session is to create the observation input files needed for running MPAS-JEDI test cases.

    8.1 Compiling the converter

    In mpas_jedi_tutorial directory, create a directory for converting NCEP BUFR observation into IODA-HDF5 format. Then, clone the obs2ioda repository and proceed for compiling the converter.

    $ cd /glade/derecho/scratch/${USER}/mpas_jedi_tutorial 
    $ git clone -b release/4mpas-jedi_v3.0.0 https://github.com/NCAR/obs2ioda
    $ cd obs2ioda/obs2ioda-v2/src/
    

    NCEP BUFR library (https://github.com/NOAA-EMC/NCEPLIBS-bufr) along with NETCDF-C and NETCDF-Fortran libraries. is required to compile obs2ioda-v2.x. Here we have pre-built BUFR_LIB and we put the pre-build BUFR_LIB path in Makefile.

    Load the proper intel compiler modules and then compile the converter by using make command:

    $ source ../../../setup_intel.sh
    $ make
    

    If the compilation is successful, the executable file obs2ioda-v2.x will be generated.

    8.2 Convert prepbufr/bufr files to IODAv2-HDF5 format

    The NCEP bufr input files are under the existing ~obs_bufr folder. Now we need to convert the bufr-format data into the iodav2-hdf5 format under the ~obs_ioda folder.

    $ mkdir /glade/derecho/scratch/${USER}/mpas_jedi_tutorial/obs_ioda
    $ cd /glade/derecho/scratch/${USER}/mpas_jedi_tutorial/obs_ioda
    $ mkdir 2018041500
    $ cd 2018041500
    

    Link the prepbufr/bufr files to the working directory:

    $ ln -fs ../../obs_bufr/2018041500/prepbufr.gdas.20180415.t00z.nr.48h .
    $ ln -fs ../../obs_bufr/2018041500/gdas.1bamua.t00z.20180415.bufr .
    $ ln -fs ../../obs_bufr/2018041500/gdas.gpsro.t00z.20180415.bufr .
    $ ln -fs ../../obs_bufr/2018041500/gdas.satwnd.t00z.20180415.bufr .
    

    Link executables and files:

    $ ln -fs ../../obs2ioda/obs2ioda-v2/src/obs2ioda-v2.x .
    

    Link obs_errtable to work directory:

    $ ln -sf ../../obs_bufr/2018041500/obs_errtable .
    

    Now we can run obs2ioda-v2.x. The usage is:

    $ ./obs2ioda-v2.x [-i input_dir] [-o output_dir] [bufr_filename(s)_to_convert]
    

    If input_dir and output_dir are not specified, the default is the current working directory. If bufr_filename(s)_to_convert is not specified, the code looks for file name, **prepbufr.bufr** (also **satwnd.bufr**, **gnssro.bufr**, **amsua.bufr**, **airs.bufr**, **mhs.bufr**, **iasi.bufr**, **cris.bufr**) in the input/working directory. If the file exists, do the conversion, otherwise skip it.

    $ export LD_LIBRARY_PATH=${NETCDF}/lib:$LD_LIBRARY_PATH
    $ ./obs2ioda-v2.x prepbufr.gdas.20180415.t00z.nr.48h
    $ ./obs2ioda-v2.x gdas.satwnd.t00z.20180415.bufr
    $ ./obs2ioda-v2.x gdas.gpsro.t00z.20180415.bufr
    $ ./obs2ioda-v2.x gdas.1bamua.t00z.20180415.bufr
    

    You should see *.h5 files in the folder.

    8.3 Upgrade IODAv2-HDF5 into IODAv3-HDF5

    Create the directory iodav2 and move amsua and gnssro h5 files to the directory iodav2.

    $ cd /glade/derecho/scratch/${USER}/mpas_jedi_tutorial/obs_ioda/2018041500
    $ mkdir iodav2
    $ mv amsua_*obs* iodav2
    $ mv gnssro_obs_*.h5  iodav2
    

    Due to NetCDF-Fortran interface does not allow reading/writing NF90_STRING, so station_id and variable_names are still written out as

    char station_id(nlocs, nstring)
    char variable_names(nvars, nstring)
    

    rather than

    string station_id(nlocs)
    string variable_names(nvars)
    

    So, for aircraft/satwind/satwnd/sfc/sondes, we need run upgrade executable ioda-upgrade-v1-to-v2.x. The output files for aircraft/satwind/satwnd/sfc/sondes are created in iodav2 directory. The input *h5 files in current directory can be deleted.

    $ export bundle_dir=/glade/derecho/scratch/liuz/mpas_bundle_v3_public_gnuSP
    $ source ${bundle_dir}/code/env-setup/gnu-derecho.sh
    $ export LD_LIBRARY_PATH=${bundle_dir}/build/lib:$LD_LIBRARY_PATH
    $ ln -sf ${bundle_dir}/build/bin/ioda-upgrade-v1-to-v2.x .
    $ ./ioda-upgrade-v1-to-v2.x satwind_obs_2018041500.h5 iodav2/satwind_obs_2018041500.h5
    $ ./ioda-upgrade-v1-to-v2.x satwnd_obs_2018041500.h5 iodav2/satwnd_obs_2018041500.h5
    $ ./ioda-upgrade-v1-to-v2.x sfc_obs_2018041500.h5 iodav2/sfc_obs_2018041500.h5
    $ ./ioda-upgrade-v1-to-v2.x aircraft_obs_2018041500.h5 iodav2/aircraft_obs_2018041500.h5
    $ ./ioda-upgrade-v1-to-v2.x sondes_obs_2018041500.h5 iodav2/sondes_obs_2018041500.h5
    $ rm *.h5
    

    Now we can upgrade iodav2 to iodav3 format by using ioda-upgrade-v2-to-v3.x

    $ ln -sf ${bundle_dir}/build/bin/ioda-upgrade-v2-to-v3.x .
    $ ln -fs ${bundle_dir}/code/ioda/share/ioda/yaml/validation/ObsSpace.yaml .
    $ ./ioda-upgrade-v2-to-v3.x iodav2/aircraft_obs_2018041500.h5 ./aircraft_obs_2018041500.h5 ObsSpace.yaml
    $ ./ioda-upgrade-v2-to-v3.x iodav2/gnssro_obs_2018041500.h5 ./gnssro_obs_2018041500.h5 ObsSpace.yaml
    $ ./ioda-upgrade-v2-to-v3.x iodav2/satwind_obs_2018041500.h5 ./satwind_obs_2018041500.h5 ObsSpace.yaml
    $ ./ioda-upgrade-v2-to-v3.x iodav2/satwnd_obs_2018041500.h5 ./satwnd_obs_2018041500.h5 ObsSpace.yaml
    $ ./ioda-upgrade-v2-to-v3.x iodav2/sfc_obs_2018041500.h5 ./sfc_obs_2018041500.h5 ObsSpace.yaml
    $ ./ioda-upgrade-v2-to-v3.x iodav2/sondes_obs_2018041500.h5 ./sondes_obs_2018041500.h5 ObsSpace.yaml
    $ ./ioda-upgrade-v2-to-v3.x iodav2/amsua_n15_obs_2018041500.h5 ./amsua_n15_obs_2018041500.h5 ObsSpace.yaml
    $ ./ioda-upgrade-v2-to-v3.x iodav2/amsua_n18_obs_2018041500.h5 ./amsua_n18_obs_2018041500.h5 ObsSpace.yaml
    $ ./ioda-upgrade-v2-to-v3.x iodav2/amsua_n19_obs_2018041500.h5 ./amsua_n19_obs_2018041500.h5 ObsSpace.yaml
    $ ./ioda-upgrade-v2-to-v3.x iodav2/amsua_metop-a_obs_2018041500.h5 ./amsua_metop-a_obs_2018041500.h5 ObsSpace.yaml
    $ ./ioda-upgrade-v2-to-v3.x iodav2/amsua_metop-b_obs_2018041500.h5 ./amsua_metop-b_obs_2018041500.h5 ObsSpace.yaml
    

    An additional step is needed for satellite radiance data (e.g, amsua_n15, amsua_metop-a) in order to convert the 'sensorScanPosition' variable from float point to integer. This is a requirement after changes for consistency between UFO and IODA. For this, we have prepared the script 'run_updateSensorScanPosition.csh' that will link fix_float2int.py and update_sensorScanPosition.py, set environment variables, and execute the Python scripts.

    $ ln -sf ../../MPAS_JEDI_yamls_scripts/run_updateSensorScanPosition.csh
    $ ./run_updateSensorScanPosition.csh
    

    To check that radiance files have been updated, run ncdump and check for the variable 'sensorScanPosition' under the 'Metadata' group.

    $ ncdump -h amsua_n15_obs_2018041500.h5 | grep sensorScanPosition
    

    Now you have the proper format ioda files under ~obs_ioda/2018041500 for mpas-jedi tests:

    aircraft_obs_2018041500.h5       amsua_n18_obs_2018041500.h5  satwnd_obs_2018041500.h5
    amsua_metop-a_obs_2018041500.h5  amsua_n19_obs_2018041500.h5  sfc_obs_2018041500.h5
    amsua_metop-b_obs_2018041500.h5  gnssro_obs_2018041500.h5     sondes_obs_2018041500.h5
    amsua_n15_obs_2018041500.h5      satwind_obs_2018041500.h5
    

    8.4 Plotting observation coverage

    Setup python enviorment for plotting.

    Note that we need to load the python environment before executing the python script. If you have already loaded the spack-stack module, reset the module environment before loading python env.

    $ module reset
    $ module load conda
    $ conda activate npl
    

    Copy graphics directory to current directory:

    $ cp -r ${bundle_dir}/code/mpas-jedi/graphics .
    $ cd graphics/standalone
    $ ln -sf ../../../../MPAS_JEDI_yamls_scripts/plot_obs_loc_tut.py .
    $ python plot_obs_loc_tut.py
    

    Now, one of the figures shown here: