# namcouple.sh writes the OASIS3-MCT namcouple file to standard out. The # content of the file is based on the selected components in the $config # variable (function has_config) # Set coupling frequencies (in seconds) between components (( ${cpl_freq_atm_oce_sec:-} )) && cpl_freq_atm_oce_sec=${cpl_freq_atm_oce_sec} (( ${cpl_freq_atm_ctm_hrs:-} )) && cpl_freq_atm_ctm_sec=$(( cpl_freq_atm_ctm_hrs * 3600 )) (( ${cpl_freq_atm_lpjg_hrs:-} )) && cpl_freq_atm_lpjg_sec=$(( cpl_freq_atm_lpjg_hrs * 3600 )) cpl_freq_ccycle_sec=$(( 24 * 3600 )) # Set coupling field lags (( ${ifs_time_step_sec:-} )) && lag_atm_oce=${ifs_time_step_sec} (( ${nem_time_step_sec:-} )) && lag_oce_atm=${nem_time_step_sec} (( ${ifs_time_step_sec:-} )) && lag_atm_ctm=${ifs_time_step_sec} (( ${tm5_time_step_sec:-} )) && lag_ctm_atm=${tm5_time_step_sec} (( ${ifs_time_step_sec:-} )) && (( ${cpl_freq_atm_ctm_sec:-} )) && \ lag_atm_ctm_mid=$(( (((cpl_freq_atm_ctm_sec / ifs_time_step_sec)+1)/2 +1) * ifs_time_step_sec )) (( ${ifs_time_step_sec:-} )) && lag_atm_lpjg=${ifs_time_step_sec} || lag_atm_lpjg=0 (( ${lpjg_time_step_sec:-} )) && lag_lpjg_atm=${lpjg_time_step_sec} || lag_lpjg_atm=0 # Set lucia variable to produce the logs for a post processing analysis (( ${lucia:-} )) || lucia='' # Check consistency of model timesteps and coupling frequencies ck_cpl_freq(){ # expects to be called as: ck_cpl_freq coupling_frequency model_timestep if (($(($1%$2)))) then echo "*EE* model timestep $2 does not divide coupling frequency $1 " 1>&2 return 1 fi } if has_config ifs tm5 then ck_cpl_freq $cpl_freq_atm_ctm_sec $tm5_time_step_sec || exit 1 ck_cpl_freq $cpl_freq_atm_ctm_sec $ifs_time_step_sec || exit 1 fi if has_config ifs nemo then ck_cpl_freq $cpl_freq_atm_oce_sec $nem_time_step_sec || exit 1 ck_cpl_freq $cpl_freq_atm_oce_sec $ifs_time_step_sec || exit 1 fi # Atmosphere/Land grids (note that TM5 and LPJG require IFS) if (( ${ifs_res_hor:-} )) then # IFS grid point grids case ${ifs_res_hor} in 159) atm_grid=A080 ;; 255) atm_grid=A128 ;; 511) atm_grid=A256 ;; 799) atm_grid=A400 ;; *) echo "*EE* Unsupported horizontal resolution (IFS): ${ifs_res_hor}" 1>&2 exit 1 ;; esac # LPJG lpjg_grid=${atm_grid} # IFS grid point grids without land-sea mask atm_grid_nm=$(echo ${atm_grid} | sed 's/A/B/') # IFS/TM5 spectral grids atm_grid_sh=T${ifs_res_hor} ctm_grid_sh=C${ifs_res_hor} # TM5 grid point grids (C: no mask, L: land masked; O: ocean masked) ctm_grid=CTM3 ctm_nx=120 ctm_ny=90 # ctm_grid_sfc=CTM1 ctm_nx_sfc=360 ctm_ny_sfc=180 fi # NEMO grids (( ${nem_res_hor:-} )) && case ${nem_res_hor} in 1) oce_grid=O1t0 ;; 025) oce_grid=Ot25 ;; *) echo "*EE* Unsupported horizontal resolution (NEMO): ${nem_res_hor}" 1>&2 exit 1 ;; esac # Functions expcat and explvl expand their arguments into coupling field names # with the appropriate extensions for categories/levels and according to the # syntax needed in the namcouple file. # # Usage: expcat NUM FLDA FLDB # explvl NUM_START NUM_END FLDA FLDB # function expcat() { printf "$2.C%.3d" 1 [ $1 -gt 1 ] && printf ":$2.C%.3d" $(eval echo {2..$1}) printf " $3.C%.3d" 1 [ $1 -gt 1 ] && printf ":$3.C%.3d" $(eval echo {2..$1}) } function explvl() { printf "$3.L%.3d" $1 [ $2 -gt $1 ] && printf ":$3.L%.3d" $(eval echo {$(($1+1))..$2}) printf " $4.L%.3d" $1 [ $2 -gt $1 ] && printf ":$4.L%.3d" $(eval echo {$(($1+1))..$2}) } # Functions expfield_* split one 3D variable into \$nbundle namcouple entries. # They are dedicated to TM5-IFS coupling. # # ***** MACHINE DEPENDENCY - there is an optimum number of levels you can bundle: # Set nbundle to \$tm5_exch_nlevs for one entry per level, # set it to 1 to bundle all levels into one entry. # The smaller nbundle is, the faster the coupling is. But if too small, the # model may start swapping. # nbundle_cutoff is for the feedback (done with 24 of 34 levels, or all levels) if has_config tm5 then [[ ${tm5_exch_nlevs} == 34 ]] && nbundle=3 && nbundle_cutoff=2 [[ ${tm5_exch_nlevs} == 10 ]] && nbundle=1 && nbundle_cutoff=1 [[ ${tm5_exch_nlevs} == 4 ]] && nbundle=1 && nbundle_cutoff=1 nlev=${tm5_exch_nlevs:-999} (( $nbundle > $nlev )) && nbundle=$nlev ia=$(($nlev/$nbundle)) ib=$(($nlev%$nbundle)) nlev_cutoff=${tm5_exch_nlevs_cutoff:-999} (( $nbundle_cutoff > $nlev_cutoff )) && nbundle_cutoff=$nlev_cutoff ia_cutoff=$(($nlev_cutoff/$nbundle_cutoff)) ib_cutoff=$(($nlev_cutoff%$nbundle_cutoff)) fi function expfield_sh() { # args = ifs-var, tm5-var, CF-code, restart, header for k in $(eval echo {1..$nbundle}) do start=$(( (k-1)*ia+1 )) extra=$(( (k-1)(k-1) )) && ((end+=1)) cat <(k-1) )) && ((end+=1)) cat <(k-1) )) && ((end+=1)) cat <(k-1) )) && ((end+=1)) cat <(k-1) )) && ((end+=1)) cat <(k-1) )) && ((end+=1)) cat < tm5 has_config ifs tm5:co2 && (( nfields+=(12 + 8*nbundle) )) || : has_config ifs tm5:chem && (( nfields+=(39 + 13*nbundle) )) || : # tm5 -> ifs has_config ifs tm5:o3fb && (( nfields+=nbundle )) || : has_config ifs tm5:ch4fb && (( nfields+=nbundle )) || : has_config ifs tm5:co2fb && (( nfields+=nbundle )) || : has_config ifs tm5:aerfb && (( nfields+=(67*nbundle_cutoff) )) || : # tm5 <-> lpjg has_config lpjg tm5:co2 && (( nfields+=2 )) || : # tm5 <-> pisces has_config pisces tm5:co2 && (( nfields+=2 )) || : # The following while loop reads the rest of this file (until the # END_OF_NAMCOUPLE marker) and processes any #defcfg and #enddef directives. # Note that the "IFS=" at the loop header is necessary to preserve leading # spaces. (IFS stands for Input Field Separator and has nothing to do with the # atmosphere model) # # The $lineout variable controls whether a particular line is send to standard # out. It is set to true before the loop as a default. # # Set 'set +u' is necessary because Bash here-documents (the part # between '<