Skip to content

Commit

Permalink
Add new capability for surface chemical DA (#1348)
Browse files Browse the repository at this point in the history
TYPE: new feature

KEYWORDS: Chemical DA, Surface Observations, 3DVar, GENBE_2.0

SOURCE: Wei Sun (NCAR/MMM, CAS), Jake Liu (NCAR/MMM), Dan Chen (IUM, Beijing)

DESCRIPTION OF CHANGES:
1. This PR adds the new capability for assimilating the surface chemical/aerosol observations (pm2.5, pm10, O3, NO2, SO2, CO) using 3DVar. 

2. Several new namelist parameters are defined in registry.var_chem under wrfvarchem. The setting of chemicda_opt only works for MOSAIC scheme. The inflation factors of chemical background errors work for both aerosol schemes, but they are only tested under the MOSAIC scheme.
 
&wrfvarchem
chem_cv_options= 10/20: control variables are 4 gas + 15/32 GOCART/MOSAIC (4bin) aerosol variables

chemicda_opt=1/2/3/4/5 # assimilate pm2.5/pm10/pm2.5+pm10/co+o3+so2+no2/6-species
 
var_scaling12=36xmax_outer_iterations, # inflation factors of chemical background errors.

len_scaling12=36xmax_outer_iterations, # inflation factors of chemical background errors.

use_chemic_surfobs = .true., # read in ob_chemsfc.ascii
 /

3. To compile 3DVar with chemical DA capability, set the environment variable "WRF_CHEM" as 1, then ./configure wrfda; compile all_wrfvar as usual. The executable remains da_wrfvar.exe.

4. The chemical background error file be.dat needs to be generated using GENBE_2.0 on https://github.com/wrf-model/GENBE_2.0.

LIST OF MODIFIED FILES:
A       Registry/Registry.wrfchemvar
M       Registry/registry.var_chem
M       compile
M       external/RSL_LITE/gen_comms.c
M       frame/module_domain.F
M       frame/module_driver_constants.F
M       share/mediation_integrate.F
M       share/output_wrf.F
M       tools/gen_allocs.c
M       var/build/da.make
M       var/build/depend.txt
A       var/da/da_chem_sfc/da_ao_stats_chem_sfc.inc
A       var/da/da_chem_sfc/da_calculate_grady_chem_sfc.inc
A       var/da/da_chem_sfc/da_check_max_iv_chem_sfc.inc
A       var/da/da_chem_sfc/da_chem_sfc.f90
A       var/da/da_chem_sfc/da_get_innov_vector_chem_sfc.inc
A       var/da/da_chem_sfc/da_jo_and_grady_chem_sfc.inc
A       var/da/da_chem_sfc/da_jo_chem_sfc.inc
A       var/da/da_chem_sfc/da_oi_stats_chem_sfc.inc
A       var/da/da_chem_sfc/da_print_stats_chem_sfc.inc
A       var/da/da_chem_sfc/da_residual_chem_sfc.inc
A       var/da/da_chem_sfc/da_transform_xtoy_chem_sfc.inc
A       var/da/da_chem_sfc/da_transform_xtoy_chem_sfc_adj.inc
M       var/da/da_control/da_control.f90
A       var/da/da_define_structures/da_allocate_observations_chem_sfc.inc
A       var/da/da_define_structures/da_allocate_y_chem_sfc.inc
M       var/da/da_define_structures/da_deallocate_background_errors.inc
A       var/da/da_define_structures/da_deallocate_y_chem_sfc.inc
M       var/da/da_define_structures/da_define_structures.f90
A       var/da/da_define_structures/da_zero_xchem_type.inc
M       var/da/da_main/da_solve.inc
M       var/da/da_main/da_solve_init.inc
M       var/da/da_main/da_update_firstguess.inc
M       var/da/da_main/da_wrfvar_init2.inc
M       var/da/da_main/da_wrfvar_top.f90
M       var/da/da_minimisation/da_amat_mul.inc
M       var/da/da_minimisation/da_calculate_gradj.inc
M       var/da/da_minimisation/da_calculate_grady.inc
M       var/da/da_minimisation/da_calculate_j.inc
M       var/da/da_minimisation/da_calculate_residual.inc
M       var/da/da_minimisation/da_dot_cv.inc
M       var/da/da_minimisation/da_get_innov_vector.inc
M       var/da/da_minimisation/da_get_var_diagnostics.inc
M       var/da/da_minimisation/da_jo_and_grady.inc
M       var/da/da_minimisation/da_minimisation.f90
M       var/da/da_minimisation/da_minimise_cg.inc
M       var/da/da_minimisation/da_minimise_lz.inc
M       var/da/da_minimisation/da_sensitivity.inc
M       var/da/da_minimisation/da_transform_vtoy.inc
M       var/da/da_minimisation/da_transform_vtoy_adj.inc
M       var/da/da_minimisation/da_write_diagnostics.inc
A       var/da/da_obs/da_fill_obs_structures_chem_sfc.inc
M       var/da/da_obs/da_obs.f90
M       var/da/da_obs/da_transform_xtoy.inc
M       var/da/da_obs/da_transform_xtoy_adj.inc
A       var/da/da_obs_io/da_final_write_obs_chem_sfc.inc
A       var/da/da_obs_io/da_final_write_obs_gas_sfc.inc
M       var/da/da_obs_io/da_obs_io.f90
A       var/da/da_obs_io/da_read_obs_chem_sfc.inc
M       var/da/da_obs_io/da_read_omb_tmp.inc
A       var/da/da_obs_io/da_scan_obs_chem_sfc.inc
A       var/da/da_obs_io/da_write_obs_chem_sfc.inc
M       var/da/da_par_util/da_cv_to_vv.inc
M       var/da/da_par_util/da_par_util.f90
M       var/da/da_par_util/da_vv_to_cv.inc
M       var/da/da_setup_structures/da_rescale_background_errors.inc
M       var/da/da_setup_structures/da_scale_background_errors.inc
M       var/da/da_setup_structures/da_setup_background_errors.inc
M       var/da/da_setup_structures/da_setup_be_regional.inc
M       var/da/da_setup_structures/da_setup_cv.inc
M       var/da/da_setup_structures/da_setup_firstguess.inc
M       var/da/da_setup_structures/da_setup_firstguess_wrf.inc
M       var/da/da_setup_structures/da_setup_obs_structures.inc
A       var/da/da_setup_structures/da_setup_obs_structures_chem_sfc.inc
M       var/da/da_setup_structures/da_setup_structures.f90
M       var/da/da_statistics/da_analysis_stats.inc
M       var/da/da_statistics/da_statistics.f90
M       var/da/da_test/da_check.inc
A       var/da/da_test/da_check_cvtovv_adjoint_chem.inc
M       var/da/da_test/da_check_gradient.inc
A       var/da/da_test/da_check_vchemtox_adjoint.inc
A       var/da/da_test/da_check_vtox_adjoint_chem.inc
M       var/da/da_test/da_test.f90
M       var/da/da_transfer_model/da_transfer_model.f90
A       var/da/da_transfer_model/da_transfer_wrftoxb_chem.inc
M       var/da/da_transfer_model/da_transfer_xatoanalysis.inc
M       var/da/da_transfer_model/da_transfer_xatowrf.inc
A       var/da/da_vtox_transforms/da_transform_vchemtox.inc
A       var/da/da_vtox_transforms/da_transform_vchemtox_adj.inc
M       var/da/da_vtox_transforms/da_transform_vtovv.inc
M       var/da/da_vtox_transforms/da_transform_vtovv_adj.inc
M       var/da/da_vtox_transforms/da_transform_vtox.inc
M       var/da/da_vtox_transforms/da_transform_vtox_adj.inc
M       var/da/da_vtox_transforms/da_vtox_transforms.f90

TESTS CONDUCTED: 
1. WRFDA regression tests passed.
2. New chemical DA is tested with 6 types of surface obs and 4-bin MOSAIC aerosol scheme.

RELEASE NOTE: Add new capability for assimilating surface pm2.5, pm10, O3, CO, NO2, SO2 using 3DVar.
Sun, W., Liu, Z., Chen, D., Zhao, P., and Chen, M., 2020: Development and application of the WRFDA-Chem three-dimensional variational (3DVAR) system: aiming to improve air quality forecasting and diagnose model deficiencies, Atmos. Chem. Phys., 20, 9311-9329.
  • Loading branch information
liujake authored Dec 29, 2020
1 parent e93bbb9 commit a271d9a
Show file tree
Hide file tree
Showing 94 changed files with 6,271 additions and 275 deletions.
16 changes: 16 additions & 0 deletions Registry/Registry.wrfchemvar
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Registry file, WRFCHEMVAR

#INCLUDES
include registry.dimspec
include Registry.EM_COMMON.var
include registry.io_boilerplate
include registry.var
include registry.hyb_coord
include registry.var_chem

state real - ijkft a_scalar 1 - - -
state real - ijkft g_scalar 1 - - -

state real landmask ij misc 1 - i012rhd=(interp_fcnm)u=(copy_fcnm) "LANDMASK" "LAND MASK (1 FOR LAND, 0 FOR WATER)" ""

state real SST ij misc 1 - i01245rh05d=(interp_mask_water_field:lu_index,iswater) "SST" "SEA SURFACE TEMPERATURE" "K"
346 changes: 215 additions & 131 deletions Registry/registry.var_chem

Large diffs are not rendered by default.

34 changes: 22 additions & 12 deletions compile
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,13 @@ else

if ( ! $?DA_ARCHFLAGS ) setenv DA_ARCHFLAGS ""

if ( ( $WRF_CHEM == 1 ) && ( $WRF_DA_CORE == 1 ) ) then
echo " "
echo "WRFDA can not be compiled with WRF_CHEM=1"
echo "unset the WRF_CHEM env variable."
echo " "
exit
endif
# if ( ( $WRF_CHEM == 1 ) && ( $WRF_DA_CORE == 1 ) ) then
# echo " "
# echo "WRFDA can not be compiled with WRF_CHEM=1"
# echo "unset the WRF_CHEM env variable."
# echo " "
# exit
# endif

if ( ( $WRF_DA_CORE == 1 ) && ( ! -d var ) ) then
echo " "
Expand Down Expand Up @@ -253,7 +253,7 @@ else
echo '## WARNING: this file is autogenerated from Registry/Registry.tladj. Changes may be lost' > Registry/Registry
/bin/cat Registry/Registry.tladj >> Registry/Registry
endif
else if (($WRF_EM_CORE == 1)&&($WRF_CHEM == 1 )) then
else if (($WRF_EM_CORE == 1)&&($WRF_CHEM == 1 )&&($WRF_DA_CORE == 0)) then
if ( ! -f Registry/Registry ) then
set overwrite=1
else
Expand Down Expand Up @@ -302,7 +302,11 @@ else
if ( ! -f Registry/Registry ) then
set overwrite=1
else
head -2 Registry/Registry | tail -1 | grep WRFVAR > /dev/null
if ( $WRF_CHEM == 1 ) then
head -2 Registry/Registry | tail -1 | grep WRFCHEMVAR > /dev/null
else
head -2 Registry/Registry | tail -1 | grep WRFVAR > /dev/null
endif
if ( $status ) then
set overwrite=1
else
Expand All @@ -312,11 +316,17 @@ else
endif
endif
if ( $overwrite ) then
echo copying Registry/Registry.wrfvar to Registry/Registry
/bin/rm -f Registry/Registry.rconfig
/bin/cat Registry/Registry.EM_COMMON | grep '^rconfig' > Registry/Registry.rconfig
echo '## WARNING: this file is autogenerated from Registry/Registry.wrfvar Registry/Registry.EM_COMMON.var. Changes may be lost' > Registry/Registry
/bin/cat Registry/Registry.wrfvar >> Registry/Registry
if ($WRF_CHEM == 1 ) then
echo copying Registry/Registry.wrfchemvar to Registry/Registry
echo '## WARNING: this file is autogenerated from Registry/Registry.wrfchemvar Registry/Registry.EM_COMMON.var. Changes may be lost' > Registry/Registry
/bin/cat Registry/Registry.wrfchemvar >> Registry/Registry
else
echo copying Registry/Registry.wrfvar to Registry/Registry
echo '## WARNING: this file is autogenerated from Registry/Registry.wrfvar Registry/Registry.EM_COMMON.var. Changes may be lost' > Registry/Registry
/bin/cat Registry/Registry.wrfvar >> Registry/Registry
endif
endif

set wrfpluspath = ( `grep "^WRFPLUSPATH" configure.wrf | cut -d"=" -f2-` )
Expand Down
38 changes: 33 additions & 5 deletions external/RSL_LITE/gen_comms.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ int print_4d_i1_decls ( FILE *fp , node_t *p, int ad /* 0=argument,1=declaration
{
/* explicit dummy or actual arguments for 4D arrays */
if ( q->mark == 0 ) {
if (strcmp("xbchem%chem_ic",varref) != 0 && strcmp("xachem%chem_ic",varref) != 0) {
fprintf(fp," num_%s, &\n",q->name) ;
}
for ( d = 3 ; d < q->ndims ; d++ ) {
char *colon, r[80],tx[80] ;
strcpy(r,"") ;
Expand All @@ -100,7 +102,11 @@ if ( nta == 1 ) {
}
if ( nta == 2 ) fprintf(fp," a_%s, &\n",varref) ;
#else
if (strcmp("xbchem%chem_ic",varref) != 0 && strcmp("xachem%chem_ic",varref) != 0) {
fprintf(fp," %s, &\n",varref) ;
} else {
fprintf(fp," num_%s, &\n","chem") ;
}
#endif
}
else
Expand Down Expand Up @@ -137,8 +143,12 @@ fprintf(fp," %s, INTENT(INOUT) :: a_%s ( grid%%sm31:grid%%em31,grid%%sm32:grid%
q->type->name , varref , moredims, q->name ) ;
#else
dimspec=dimension_with_ranges( "grid%","",-1,tmp3,q,"","" ) ;
if (strcmp("xbchem%chem_ic",varref) != 0 && strcmp("xachem%chem_ic",varref) != 0) {
fprintf(fp," %s, INTENT(INOUT) :: %s ( %s %snum_%s)\n",
q->type->name , varref , dimspec, moredims, q->name ) ;
} else {
fprintf(fp," INTEGER, INTENT(IN) :: num_%s\n","chem") ;
}
#endif
}
}
Expand Down Expand Up @@ -576,7 +586,11 @@ fprintf(fp,"CALL wrf_debug(3,'calling RSL_LITE_INIT_EXCH %s for Y %s')\n",maxste
if ( n4d > 0 ) {
fprintf(fp, " %d &\n", n3dR ) ;
for ( i = 0 ; i < n4d ; i++ ) {
fprintf(fp," + num_%s &\n", name_4d[i] ) ;
if (strcmp("chem_ic",name_4d[i]) != 0) {
fprintf(fp," + num_%s &\n", name_4d[i] ) ;
} else {
fprintf(fp," + num_%s &\n", "chem" ) ;
}
}
fprintf(fp," , %d, RWORDSIZE, &\n", n2dR ) ;
} else {
Expand Down Expand Up @@ -625,7 +639,11 @@ fprintf(fp,"CALL wrf_debug(3,'calling RSL_LITE_INIT_EXCH %s for Y %s')\n",maxste
if ( n4d > 0 ) {
fprintf(fp, " %d &\n", n3dR ) ;
for ( i = 0 ; i < n4d ; i++ ) {
fprintf(fp," + num_%s &\n", name_4d[i] ) ;
if (strcmp("chem_ic",name_4d[i]) != 0) {
fprintf(fp," + num_%s &\n", name_4d[i] ) ;
} else {
fprintf(fp," + num_%s &\n", "chem" ) ;
}
}
fprintf(fp," , %d, RWORDSIZE, &\n", n2dR ) ;
} else {
Expand Down Expand Up @@ -1281,7 +1299,11 @@ gen_packs_halo ( FILE *fp , node_t *p, char *shw, int xy /* 0=y,1=x */ , int pu
char sd[256], ed[256] , sm[256], em[256] , sp[256], ep[256] ;

set_mem_order( q->members, memord , 3 ) ;
if (strcmp("xbchem%chem_ic",varref) != 0 && strcmp("xachem%chem_ic",varref) != 0) {
fprintf(fp,"DO itrace = PARAM_FIRST_SCALAR, num_%s\n",q->name ) ;
} else {
fprintf(fp,"DO itrace = PARAM_FIRST_SCALAR, num_%s\n","chem" ) ;
}
strcpy(moredims,"") ;
for ( d = q->ndims-1 ; d >= 3 ; d-- ) {
fprintf(fp," DO idim%d = %s_sdim%d,%s_edim%d\n",d-2,q->name,d-2,q->name,d-2 ) ;
Expand Down Expand Up @@ -1315,9 +1337,15 @@ fprintf(fp," DO idim%d = %s_sdim%d,%s_edim%d\n",d-2,q->name,d-2,q->name,d-2 ) ;
strcpy(sm,sd) ; strcpy(em,ed ) ;
strcpy(sp,sd) ; strcpy(ep,ed ) ;
}
fprintf(fp," IF ( SIZE(%s,%d)*SIZE(%s,%d) .GT. 1 ) THEN\n",varref,xdex+1,varref,ydex+1 ) ;
fprintf(fp," CALL %s ( %s,&\n%s ( %s%sitrace),%s,&\nrsl_sendbeg_m, rsl_sendw_m, rsl_sendbeg_p, rsl_sendw_p, &\nrsl_recvbeg_m, rsl_recvw_m, rsl_recvbeg_p, rsl_recvw_p, &\n%s, %d, %d, DATA_ORDER_%s, %d, &\n",
packname, commname, varref , index_with_firstelem("","grid%",-1,tmp4,q,""),moredims, shw, wordsize, xy, pu, memord, xy?(q->stag_x?1:0):(q->stag_y?1:0) ) ;
if (strcmp("xbchem%chem_ic",varref) != 0 && strcmp("xachem%chem_ic",varref) != 0) {
fprintf(fp," IF ( SIZE(%s,%d)*SIZE(%s,%d) .GT. 1 ) THEN\n",varref,xdex+1,varref,ydex+1 ) ;
fprintf(fp," CALL %s ( %s,&\n%s ( %s%sitrace),%s,&\nrsl_sendbeg_m, rsl_sendw_m, rsl_sendbeg_p, rsl_sendw_p, &\nrsl_recvbeg_m, rsl_recvw_m, rsl_recvbeg_p , rsl_recvw_p, &\n%s, %d, %d, DATA_ORDER_%s, %d, &\n",
packname, commname, varref , index_with_firstelem("","grid%",-1,tmp4,q,""),moredims, shw, wordsize, xy, pu, memord, xy?(q->stag_x? 1:0):(q->stag_y?1:0) ) ;
} else {
fprintf(fp," IF ( SIZE(grid%%%s,%d)*SIZE(grid%%%s,%d) .GT. 1 ) THEN\n",varref,xdex+1,varref,ydex+1 ) ;
fprintf(fp," CALL %s ( %s,&\ngrid%%%s ( %s%sitrace),%s,&\nrsl_sendbeg_m, rsl_sendw_m, rsl_sendbeg_p, rsl_sendw_p, &\nrsl_recvbeg_m, rsl_recvw_m, rsl_recvbeg_p , rsl_recvw_p, &\n%s, %d, %d, DATA_ORDER_%s, %d, &\n",
packname, commname, varref , index_with_firstelem("","grid%",-1,tmp4,q,""),moredims, shw, wordsize, xy, pu, memord, xy?(q->stag_x? 1:0):(q->stag_y?1:0) ) ;
}
fprintf(fp,"mytask, ntasks, ntasks_x, ntasks_y, &\n") ;
if ( !strcmp( packname, "RSL_LITE_PACK_SWAP" ) ||
!strcmp( packname, "RSL_LITE_PACK_CYCLE" ) ) {
Expand Down
1 change: 1 addition & 0 deletions frame/module_domain.F
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,7 @@ SUBROUTINE dealloc_linked_lists ( grid )
TYPE(fieldlist), POINTER :: p, q
p => grid%head_statevars
DO WHILE ( ASSOCIATED( p ) )
if (p%varname.eq."chem_ic") exit
q => p ; p => p%next ; DEALLOCATE(q)
ENDDO
NULLIFY(grid%head_statevars) ; NULLIFY( grid%tail_statevars)
Expand Down
5 changes: 5 additions & 0 deletions frame/module_driver_constants.F
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,12 @@ MODULE module_driver_constants

! The maximum number of obs indexes (for conventional DA obs)

#if (WRF_CHEM == 1)
INTEGER , PARAMETER :: num_ob_indexes = 30
#else
INTEGER , PARAMETER :: num_ob_indexes = 29
#endif


! The maximum number of bogus storms

Expand Down
2 changes: 2 additions & 0 deletions share/mediation_integrate.F
Original file line number Diff line number Diff line change
Expand Up @@ -2475,6 +2475,7 @@ END SUBROUTINE open_hist_w
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#if ( WRF_CHEM == 1 )
#if (DA_CORE != 1)
SUBROUTINE med_read_wrf_chem_input ( grid , config_flags )
! Driver layer
Expand Down Expand Up @@ -3150,6 +3151,7 @@ SUBROUTINE med_read_wrf_chem_emissopt3 ( grid , config_flags )
END SUBROUTINE med_read_wrf_chem_emissopt3
#endif
#endif
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Expand Down
2 changes: 1 addition & 1 deletion share/output_wrf.F
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ SUBROUTINE output_wrf ( fid , grid , config_flags, switch , ierr )
#endif
! added by SYHA (09-19-2014)
#if ((WRF_CHEM == 1) && (EM_CORE == 1))
#if ((WRF_CHEM == 1) && (EM_CORE == 1) && (DA_CORE != 1))
IF ( config_flags%perturb_chem_bdy .NE. 0 ) THEN
CALL wrf_put_dom_ti_integer( fid, 'PERTURB_CHEM_BDY', config_flags%perturb_chem_bdy, 1, ierr )
END IF
Expand Down
3 changes: 3 additions & 0 deletions tools/gen_allocs.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,9 @@ gen_dealloc2 ( FILE * fp , char * structname , node_t * node )
}
}
} else {

if (strcmp(fname,"chem_ic")==0) continue ; /* !!! add !!! */

#ifdef USE_ALLOCATABLES
fprintf(fp,
"IF ( ALLOCATED( %s%s ) ) THEN \n", structname, fname ) ;
Expand Down
1 change: 1 addition & 0 deletions var/build/da.make
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ WRFVAR_OBJS = \
da_minimisation.o \
da_vtox_transforms.o \
da_obs.o \
da_chem_sfc.o \
da_obs_io.o \
da_join_iv_for_multi_inc.o \
da_metar.o \
Expand Down
Loading

0 comments on commit a271d9a

Please sign in to comment.