Files
GEOS-Chem-adjoint-v35-note/code/adjoint/inverse_mod.f
2025-10-03 03:39:18 +08:00

5960 lines
203 KiB
Fortran

!$Id: inverse_mod.f,v 1.20 2012/03/04 19:34:15 daven Exp $
MODULE INVERSE_MOD
!
!*****************************************************************************
! Module INVERSE_MOD contains all the subroutines that used to be in
! inverse.f. While having these routines in the top most program file worked
! on SGI, it didn't work on Linux, so had to move all to a module.
! (dkh, 02/05)!
! Module Variables:
! 模块 INVERSE_MOD 包含了所有用于反演的子程序。只能在 SGI 运行,无法在 Linux 运行?
! ============================================================================
! (1 ) COST_FUNC (REAL*8) : Value of cost function 代价函数值
! (2 ) N_CALC (INTEGER) : Optimization iteration number 迭代次数
! (3 ) N_CALC_STOP (INTEGER) : Maximum optimization iteration number 最大迭代次数
! (4 ) F (DOUBLE) : For optimization routine 用于最优化的进程
! (5 ) X (DOUBLE, ALLOC): Vector of active varialbes 激活的状态变量
! (6 ) GRADNT (DOUBLE, ALLOC): Vector of adjoint gradients 伴随梯度向量
! (7 ) XP (DOUBLE, ALLOC): Vector of active strat prod varialbes 平流层源
! (8 ) GRADNT_P (DOUBLE, ALLOC): Vector of strat prod adjoint gradients 平流层源梯度
! (9 ) XL (DOUBLE, ALLOC): Vector of active strat loss varialbes 平流层汇
! (10) GRADNT_L (DOUBLE, ALLOC): Vector of adjoint strat loss gradients 平流层汇梯度
!
! Module Routines
! ============================================================================
! (1 ) SET_SF : Initializes ICS_SF and EMS_SF
! (2 ) SET_LOG_SF : Initializes ICS_SF and EMS_SF for log scaling
! (3 ) GET_X_FROM_SF : Turns SF array into a vector X for optimization
! (4 ) GET_SF_FROM X : Turns vector X into array SF after optimization
! (5 ) GET_GRADNT_FROM_ADJ : Turns ADJ_STT array into vector GRADNT for opt.
! (6 ) MAKE_GDT_FILE : Save GRADNT values at iteration N_CALC to adjtmp/*gdt*
! (7 ) READ_GDT_FILE : Reads saved GRADNT values from previous iterations
! (8 ) MAKE_SF_FILE : Saves SF at iteration N_CALC to adjtmp/*sf*
! (9 ) READ_SF_FILE : Reads saved SF from previous iterations
! (10) EXPAND_NAME : Adds iteration number to file names
! (11) DISPLAY_STUFF : Echo various things at each iteration
! (12) SET_SF_FORFD : Set the scaling factors for finite difference test.
! (13) MAKE_CFN_FILE : Save cost function to cnf.* file
! (14) READ_CFN_FILE : Read cost function from cnf.* file
! (15) SET_OPT_RANGE : Set range of parameters to optimize
! (16) CALC_NOPT : Set range of parameters to optimize
! (17) ITER_CONDITION : Write out iteration diagnostics to gctm.iteration
! (18) MAYBE_DO_GEOS_CHEM_ADJ: For FDTEST determine if need to call adjoint
! (19) DO_SAT_DAIGS : Make satellite diagnostic files
! (20) INIT_INVERSE : Initialize allocatable arrays
! (21) CLEANUP_INVERSE : Deallocatte arrays
!
! Modules referenced by "inverse_mod.f"
! ============================================================================
! (1 ) bpch2_mod.f : Module containing routines for binary pch file I/O
! (2 ) charpak_mod.f : Module containing string handling routines
! (3 ) error_mod.f : Module containing NaN and other error check routines
! (4 ) file_mod.f : Module containing file unit numbers & error checks
! (5 ) grid_mod.f : Module containing horizontal grid information
! (6 ) restart_mod.f : Module containing CHECK_DIMENSIONS
! (7 ) time_mod.f : Module containing routines to compute time & date
!
! NOTES:
! (1 ) Added ACTIVE_VARS == 'EMISSIONS' case. (dkh, 11/27/04)
! (2 ) Added subroutine INIT_REGIONAL_ICS (dkh, 02/12/05)
! (3 ) Now use IDADJxxx (03/03/05)
! (4 ) Don't zero the adjoints of NO3, NIT, and NH4
! (5 ) Now save EMS_ICS from reference run to EMS_ICS_orig, a mod variable
! Also update MAKE_GDT and MAKE_ICS to handle all emissions.
! (dkh, 03/29/05)
! (6 ) Remove all duplicate declarations of N_CALC and N_CALC_STOP. Now this
! is always treated as a module variable. (dkh, 02/15/06)
! (7 ) Update MAKE_ICS_FILE to support writing initial NOx emisions. (dkh, 08/27/06)
! (8 ) Bug fix: change N to 1 in TRACER(I,J,1) while writing scaled
! emissions. (dkh, 10/26/06)
! (9 ) BUG FIX: make ADJ_STT_FD allocatable. (dkh, 03/21/07)
! (10) Update to support LOG_OPT pre-processor option.
! (11) Add support for strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
! (12 ) Add / move satellite diagnostic output here (dkh, 06/25/15)
!*****************************************************************************
!
IMPLICIT NONE
# include "define_adj.h" ! obs operators
!====================================================================
! MODULE VARIABLES ( those that used to be program variables )
!====================================================================
!REAL*8, ALLOCATABLE :: EMS_ICS_orig(:,:,:,:)
REAL*8, ALLOCATABLE :: X(:)
REAL*8, ALLOCATABLE :: GRADNT(:)
!For strat prod & loss SF (hml, 08/11/14)
REAL*8, ALLOCATABLE :: XP(:)
REAL*8, ALLOCATABLE :: GRADNT_P(:)
REAL*8, ALLOCATABLE :: XL(:)
REAL*8, ALLOCATABLE :: GRADNT_L(:)
!====================================================================
! MODULE ROUTINES
!====================================================================
CONTAINS
!-----------------------------------------------------------------------------
SUBROUTINE SET_SF
!
!*****************************************************************************
! Subroutine SET_SF sets the intial conditions used for a GEOS_CHEM run
! (dkh, 9/16/04).
!
! NOTES:
! (1 ) Added ACTIVE_VARS == 'EMISSIONS' case. (dkh, 11/27/04)
! (2 ) Added ACTIVE_VARS == 'FDTEST' case. (dkh, 02/17/05)
! (3 ) Switch to using IDADJxxx (dkh, 03/03/05)
! (4 ) Rename to SET_SF, replace CMN_ADJ with adjoint_array_mod
! (dkh, ks, mak, cs 06/07/09)
! (5 ) Now get first guesses from input.gcadj file (mak, 9/23/09)
! (6 ) Now use ICS_SF_DEFAULT and ICS_SF_DEFAULT instad of ICS_SF_tmp
! and EMS_SF_tmp. (dkh, 02/09/11)
! (7 ) Now support strat fluxes LADJ_STRAT and add flags to avoid accessing
! unallocated arrays (hml, dkh, 02/20/12, adj32_025)
!
!*****************************************************************************
!
! Reference to f90 modules
USE ADJ_ARRAYS_MOD, ONLY : ICS_SF, ICS_SF0
USE ADJ_ARRAYS_MOD, ONLY : EMS_SF, EMS_SF0
USE ADJ_ARRAYS_MOD, ONLY : N_CALC
USE ADJ_ARRAYS_MOD, ONLY : N_CALC_STOP
USE ADJ_ARRAYS_MOD, ONLY : IDADJ_ENH3_an
USE ADJ_ARRAYS_MOD, ONLY : ADCOEMS
USE ADJ_ARRAYS_MOD, ONLY : IFD, JFD, LFD
USE ADJ_ARRAYS_MOD, ONLY : NFD, MFD, EMSFD
USE ADJ_ARRAYS_MOD, ONLY : ICSFD
!USE ADJ_ARRAYS_MOD, ONLY : ICS_SF_tmp, EMS_SF_tmp
USE ADJ_ARRAYS_MOD, ONLY : ICS_SF_DEFAULT
USE ADJ_ARRAYS_MOD, ONLY : EMS_SF_DEFAULT
USE ADJ_ARRAYS_MOD, ONLY : MMSCL
USE ADJ_ARRAYS_MOD, ONLY : PROD_SF, PROD_SF0
USE ADJ_ARRAYS_MOD, ONLY : LOSS_SF, LOSS_SF0
USE ADJ_ARRAYS_MOD, ONLY : PROD_SF_DEFAULT
USE ADJ_ARRAYS_MOD, ONLY : LOSS_SF_DEFAULT
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF, RATE_SF0
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF_DEFAULT
USE ERROR_MOD, ONLY : ERROR_STOP
USE LOGICAL_ADJ_MOD, ONLY : LICS, LADJ_EMS
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT, LADJ_RRATE
USE TRACERID_MOD, ONLY : IDTOX, IDTNOX
# include "CMN_SIZE" ! Size params
# include "define_adj.h" ! obs operators
! local variables
INTEGER :: I
INTEGER :: J
INTEGER :: L
INTEGER :: M
!=================================================================
! SET_SF begins here!
!=================================================================
! Set to defaults or user defined values
IF ( N_CALC_STOP .EQ. 0) THEN
! Set default scaling factors to 1d0 everywhere for reference run
! (perfect model generating pseudo observations)
ICS_SF(:,:,:,:) = 1.d0
IF ( LADJ_EMS ) EMS_SF(:,:,:,:) = 1.d0
IF ( LADJ_STRAT ) THEN
PROD_SF(:,:,:,:) = 1.d0
LOSS_SF(:,:,:,:) = 1.d0
ENDIF
IF ( LADJ_RRATE ) THEN
RATE_SF(:,:,:,:) = 1.d0
ENDIF
ELSE
! Now define defaults for all in input.gcadj (dkh, 02/09/11)
!EMS_SF(:,:,:,:) = 1.d0
!ICS_SF(:,:,:,:) = 1.d0
!! otherwise, use values from input.gcadj file for ICSFD and EMSFD
!EMS_SF(:,:,:,EMSFD) = EMS_SF_tmp
!ICS_SF(:,:,:,ICSFD) = ICS_SF_tmp
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
ICS_SF (I,J,L,:) = ICS_SF_DEFAULT (:)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
IF ( LADJ_EMS ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
EMS_SF(I,J,M,:) = EMS_SF_DEFAULT(:)
IF ( LADJ_STRAT ) THEN
PROD_SF(I,J,M,:) = PROD_SF_DEFAULT(:)
LOSS_SF(I,J,M,:) = LOSS_SF_DEFAULT(:)
ENDIF
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
! Added for reaction rates (tww, 05/15/12)
IF ( LADJ_RRATE ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
RATE_SF(I,J,L,:) = RATE_SF_DEFAULT(:)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
ENDIF
ENDIF
! the following options for PSEUDO_OBS should not become obsolete
! We don't even have to remember to change initial SF between pseudo obs
! and perturbed run, since the adjustment will be made automaticlally above
! the following #if statement can be removed.
! one thing we can add is NFD selection to EMS_SF, so that we don't have to
! perturb all emissions, but only one. not sure if this would be good or
! would just complicate things...
! (mak, 9/23/09)
#if defined ( PSEUDO_OBS )
! Make the initial guess for iteration N_CALC == 1
! BUG FIX: make sure this happens every time the optimization
! cycles through N_CALC = 1 as well. (mak, dkh, 09/08/09)
!IF ( N_CALC == 1 ) THEN
! IF ( N_CALC == 1
! & .or. ( N_CALC == 0 .and. N_CALC_STOP > 1 ) ) THEN
IF ( N_CALC == 1 .or.
& ( N_CALC == 0 .and. N_CALC_STOP > 0 ) ) THEN
! For control parameters = initial conditions
IF ( LICS ) THEN
! Now enforce defaults for all set in input.gcadj (dkh, 02/09/11)
!! BUG FIX: enforce defualt scaling factors before using SF_tmp
!! (dkh, 07/30/10)
!ICS_SF(:,:,:,:) = 1.d0
!
!print*, 'set ICS_SF to', ICS_SF_tmp
!! Start with an initial guess for ICS_SF that is wrong
!! Let's set the default to perturb everything to avoid
!! hardwiring (mak, 6/18/09)
!! now this is done via input.gcadj file (mak, 9/23/09)
!ICS_SF(:,:,:,ICSFD) = ICS_SF_tmp !0.5d0
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
ICS_SF(I,J,L,:) = ICS_SF_DEFAULT(:)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ELSEIF ( LADJ_EMS ) THEN
! Now enforce defaults for all set in input.gcadj (dkh, 02/09/11)
!!! BUG FIX: enforce defualt scaling factors before using SF_tmp
!! (dkh, 07/30/10)
!EMS_SF(:,:,:,:) = 1.d0
!
!! Start with an initial guess for EMS_SF that is wrong
!EMS_SF(:,:,1,EMSFD) = EMS_SF_tmp
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
EMS_SF(I,J,M,:) = EMS_SF_DEFAULT(:)
IF ( LADJ_STRAT ) THEN
PROD_SF(I,J,M,:) = PROD_SF_DEFAULT(:)
LOSS_SF(I,J,M,:) = LOSS_SF_DEFAULT(:)
ENDIF
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
! Added for reaction rates (tww, 05/15/12)
IF ( LADJ_RRATE ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
RATE_SF(I,J,L,:) = RATE_SF_DEFAULT(:)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
ENDIF
ENDIF
#endif
! Save a copy of the initial guess of the scaling factors
! for use later in calculating the a priori penalty term
ICS_SF0 (:,:,:,:) = ICS_SF (:,:,:,:)
! Add flags (hml, 02/23/12)
IF ( LADJ_EMS ) EMS_SF0 (:,:,:,:) = EMS_SF (:,:,:,:)
IF ( LADJ_STRAT ) THEN
PROD_SF0(:,:,:,:) = PROD_SF(:,:,:,:)
LOSS_SF0(:,:,:,:) = LOSS_SF(:,:,:,:)
ENDIF
IF ( LADJ_RRATE ) THEN
RATE_SF0(:,:,:,:) = RATE_SF(:,:,:,:)
ENDIF
! Return to calling program
END SUBROUTINE SET_SF
!-----------------------------------------------------------------------------
SUBROUTINE SET_LOG_SF
!
!*****************************************************************************
! Subroutine SET_LOG_SF sets the intial conditions used for a GEOS_CHEM run
! (dkh, 9/16/04).
!
! NOTES:
! (1 ) Added ACTIVE_VARS == 'EMISSIONS' case. (dkh, 11/27/04)
! (2 ) Added ACTIVE_VARS == 'FDTEST' case. (dkh, 02/17/05)
! (3 ) Switch to using IDADJxxx (dkh, 03/03/05)
! (4 ) Rename to SET_LOG_SF, replace CMN_ADJ with adjoint_array_mod
! (dkh, ks, mak, cs 06/07/09)
! (5 ) Now use ICS_SF_DEFAULT and ICS_SF_DEFAULT instad of ICS_SF_tmp
! and EMS_SF_tmp. (dkh, 02/09/11)
! (6 ) Add flags to avoid accessing unallocated arrays
! (hml, dkh, 02/27/12, adj32_025)
!*****************************************************************************
!
! Reference to f90 modules
USE ADJ_ARRAYS_MOD, ONLY : ICS_SF, ICS_SF0
USE ADJ_ARRAYS_MOD, ONLY : EMS_SF, EMS_SF0
USE ADJ_ARRAYS_MOD, ONLY : N_CALC
USE ADJ_ARRAYS_MOD, ONLY : IDADJ_ENH3_an
USE ADJ_ARRAYS_MOD, ONLY : IFD, JFD, LFD
USE ADJ_ARRAYS_MOD, ONLY : NFD, MFD, EMSFD
USE ADJ_ARRAYS_MOD, ONLY : ICSFD
USE ADJ_ARRAYS_MOD, ONLY : IDADJ_ENH3_an
!USE ADJ_ARRAYS_MOD, ONLY : ICS_SF_tmp, EMS_SF_tmp
USE ADJ_ARRAYS_MOD, ONLY : ICS_SF_DEFAULT
USE ADJ_ARRAYS_MOD, ONLY : EMS_SF_DEFAULT
USE ADJ_ARRAYS_MOD, ONLY : N_CALC_STOP
USE ADJ_ARRAYS_MOD, ONLY : MMSCL
USE ERROR_MOD, ONLY : ERROR_STOP
USE LOGICAL_ADJ_MOD, ONLY : LICS, LADJ_EMS
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT, LADJ_RRATE
USE TRACERID_MOD, ONLY : IDTOX
# include "CMN_SIZE" ! Size params
! Internal varaibles
INTEGER :: I
INTEGER :: J
INTEGER :: L
INTEGER :: M
!=================================================================
! SET_LOG_SF begins here!
!=================================================================
IF ( LADJ_STRAT ) THEN
CALL ERROR_STOP(' LADJ_STRAT not yet implemented for LOG_OPT',
& ' subroutine SET_LOG_SF, inverse_mod.f ' )
ENDIF
IF ( LADJ_RRATE ) THEN
CALL ERROR_STOP(' LADJ_RRATE not yet implemented for LOG_OPT',
& ' subroutine SET_LOG_SF, inverse_mod.f ' )
ENDIF
! Set to defaults or user defined values
! Add flags (hml, 02/23/12)
IF ( N_CALC_STOP .EQ. 0) THEN
! Set default scaling factors to 0d0 everywhere for reference run
! (perfect model generating pseudo observations)
ICS_SF(:,:,:,:) = 0.d0
IF ( LADJ_EMS ) EMS_SF(:,:,:,:) = 0.d0
ELSE
! Now define defaults for all in input.gcadj (dkh, 02/09/11)
!EMS_SF(:,:,:,:) = 0.d0
!ICS_SF(:,:,:,:) = 0.d0
!! otherwise, use values from input.gcadj file for ICSFD and EMSFD
!EMS_SF(:,:,:,EMSFD) = LOG(EMS_SF_tmp)
!ICS_SF(:,:,:,ICSFD) = LOG(ICS_SF_tmp)
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
ICS_SF(I,J,L,:) = LOG(ICS_SF_DEFAULT(:))
ENDDO
ENDDO
ENDDO
! Add flags (hml, 02/23/12)
IF ( LADJ_EMS ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
EMS_SF(I,J,M,:) = LOG(EMS_SF_DEFAULT(:))
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
ENDIF
#if defined ( PSEUDO_OBS )
! BUG FIX: make sure this happens every time the optimization
! cycles through N_CALC = 1 as well. (mak, dkh, 09/08/09)
!IF ( N_CALC == 1 ) THEN
! IF ( N_CALC == 1
! & .or. ( N_CALC == 0 .and. N_CALC_STOP > 1 ) ) THEN
IF ( N_CALC == 1 .or.
& ( N_CALC == 0 .and. N_CALC_STOP > 0 ) ) THEN
! For control parameters = initial conditions
IF ( LICS ) THEN
! Now define defaults for all in input.gcadj (dkh, 02/09/11)
!! BUG FIX: enforce defualt scaling factors before using SF_tmp
!! (dkh, 07/30/10)
!ICS_SF(:,:,:,:) = 0.d0
!
!! Start with an initial guess for ICS_SF that is wrong
!ICS_SF(:,:,:,ICSFD) = LOG(ICS_SF_tmp)
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
ICS_SF(I,J,L,:) = LOG(ICS_SF_DEFAULT(:))
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
IF ( LADJ_EMS ) THEN
! Now define defaults for all in input.gcadj (dkh, 02/09/11)
!! BUG FIX: enforce defualt scaling factors before using SF_tmp
!!! (dkh, 07/30/10)
!EMS_SF(:,:,:,:) = 0.d0
!
!! Start with an initial guess for EMS_SF that is wrong
!EMS_SF(:,:,1,EMSFD) = LOG(EMS_SF_tmp)
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
EMS_SF(I,J,M,:) = LOG(EMS_SF_DEFAULT(:))
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
ENDIF
#endif
! Save a copy of the initial guess of ICS_SF for regularization
ICS_SF0(:,:,:,:) = ICS_SF(:,:,:,:)
! Save a copy of the initial guess of EMS_SF for regularization
! Add flags (hml, 02/23/12)
IF ( LADJ_EMS ) EMS_SF0(:,:,:,:) = EMS_SF(:,:,:,:)
! Return to calling program
END SUBROUTINE SET_LOG_SF
!-----------------------------------------------------------------------------
SUBROUTINE GET_X_FROM_SF
!
!*****************************************************************************
! Subroutine GET_X_FROM_ICS compiles the vector X of initial conditions from
! the array STT_IC. (dkh, 9/16/04)
! 从缩放文件中获取状态向量的初始值
! NOTES:
! (1 ) Added ACTIVE_VARS == 'EMISSIONS' case. (dkh, 11/27/04)
! (2 ) Added ACTIVE_VARS == 'FDTEST' case. (dkh, 02/17/05)
! (3 ) Rename to SET_LOG_SF, replace CMN_ADJ with adjoint_array_mod
! (dkh, ks, mak, cs 06/07/09)
! (4 ) Now support strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
!
!*****************************************************************************
!
! Reference to f90 modules
USE ADJ_ARRAYS_MOD, ONLY : ICS_SF, EMS_SF, MMSCL, NNEMS
USE ADJ_ARRAYS_MOD, ONLY : PROD_SF, LOSS_SF
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF
USE ADJ_ARRAYS_MOD, ONLY : NSTPL, NRRATES
USE ADJ_ARRAYS_MOD, ONLY : IFD, JFD, NFD
USE ERROR_MOD, ONLY : ERROR_STOP
USE LOGICAL_ADJ_MOD, ONLY : LICS, LADJ_EMS
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT, LADJ_RRATE
USE TRACER_MOD, ONLY : ITS_A_TAGCO_SIM
USE TRACER_MOD, ONLY : N_TRACERS
# include "CMN_SIZE" ! Size params
! Local variables
INTEGER :: I, J, L, M, N
INTEGER :: I_DUM
INTEGER :: OFFSET
!=================================================================
! GET_X_FROM_SF begins here! 开始迭代
!=================================================================
IF ( LICS ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L, N, I_DUM)
DO N = 1, N_TRACERS
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * ( J - 1) )
& + ( IIPAR * JJPAR * ( L - 1 ) )
& + ( IIPAR * JJPAR * LLPAR * ( N - 1 ) ) ! 判断变量对应的状态向量位置
! Load X from active tracer concentrations
X(I_DUM) = ICS_SF(I,J,L,N) ! 获取相关状态向量的缩放系数
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
!mkeller:
ENDIF
!ELSEIF ( LADJ_EMS ) THEN
IF ( LADJ_EMS ) THEN
IF ( ITS_A_TAGCO_SIM() ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M, N, I_DUM)
DO N = 1, 1
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * ( J - 1) )
& + ( IIPAR * JJPAR * ( M - 1 ) )
& + ( IIPAR * JJPAR * MMSCL * ( N - 1 ) )
! Load X from active tracer concentrations
X(I_DUM) = EMS_SF(I,J,M,N)
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
IF ( NNEMS == 2 ) THEN
N = 2
print*, IIPAR*JJPAR*MMSCL,'adding backgnd component to X'
X(IIPAR*JJPAR*MMSCL+1) = EMS_SF(1,1,1,N)
ENDIF
ELSE
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M, N, I_DUM)
DO N = 1, NNEMS
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * ( J - 1) )
& + ( IIPAR * JJPAR * ( M - 1 ) )
& + ( IIPAR * JJPAR * MMSCL * ( N - 1 ) )
!mkeller: get proper offset for I_DUM
IF ( LICS ) I_DUM =
& I_DUM + IIPAR * JJPAR * LLPAR * N_TRACERS
! Load X from active tracer concentrations
X(I_DUM) = EMS_SF(I,J,M,N)
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
OFFSET = IIPAR * JJPAR * MMSCL * NNEMS
IF ( LADJ_STRAT ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M, N, I_DUM)
DO N = 1, NSTPL
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * ( J - 1) )
& + ( IIPAR * JJPAR * ( M - 1 ) )
& + ( IIPAR * JJPAR * MMSCL * ( N - 1 ) )
! Load X from active tracer concentrations
XP(I_DUM) = PROD_SF(I,J,M,N)
XL(I_DUM) = LOSS_SF(I,J,M,N)
IF ( I == IFD.and.J == JFD.and.N == NFD )THEN
print*, 'inverse_0: I_DUM = ' ,
& I_DUM
print*, 'inverse_0: XL(I_DUM) = ' ,
& XL(I_DUM)
print*, 'inverse_0: LOSS_SF = ' ,
& LOSS_SF(I,J,M,N)
ENDIF
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
X( IIPAR*JJPAR*MMSCL*NNEMS + 1 :
& IIPAR*JJPAR*MMSCL*(NSTPL+NNEMS)) = XP(:)
X( IIPAR*JJPAR*MMSCL*(NSTPL+NNEMS) + 1 :
& IIPAR*JJPAR*MMSCL*(2*NSTPL+NNEMS)) = XL(:)
! make OFFSET total number of emissions + strat PL scale factors
OFFSET = IIPAR*JJPAR*MMSCL*(2*NSTPL+NNEMS)
ENDIF
! Reaction rates (tww)
IF ( LADJ_RRATE ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L, N, I_DUM )
DO N = 1, NRRATES
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * (J - 1) )
& + ( IIPAR * JJPAR * (L - 1) )
& + ( IIPAR * JJPAR * LLPAR * (N - 1) )
& + OFFSET
!I_DUM = I_DUM + IIPAR * JJPAR * MMSCL * NNEMS
! Combine to the I_DUM equation (hml, 06/10/13)
!I_DUM = I_DUM + OFFSET
! Load X from active variables
X(I_DUM) = RATE_SF(I,J,L,N)
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
ENDIF
ENDIF
! Return to calling program
END SUBROUTINE GET_X_FROM_SF
!-----------------------------------------------------------------------------
SUBROUTINE GET_SF_FROM_X
!
!*****************************************************************************
! Subroutine GET_SF_FROM_X compiles the array of scaling factors from
! the vector X. (dkh, 9/16/04)
!
! NOTES:
! (1 ) Added ACTIVE_VARS == 'EMISSIONS' case. (dkh, 11/27/04)
! (2 ) Added ACTIVE_VARS == 'FDTEST' case. (dkh, 02/17/05)
! (3 ) Rename to SET_LOG_SF, replace CMN_ADJ with adjoint_array_mod
! (dkh, ks, mak, cs 06/07/09)
! (4 ) Now support strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
!
!*****************************************************************************
!
! Reference to f90 modules
USE ADJ_ARRAYS_MOD, ONLY : ICS_SF, EMS_SF, NNEMS, MMSCL
USE ADJ_ARRAYS_MOD, ONLY : PROD_SF, LOSS_SF
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF
USE ADJ_ARRAYS_MOD, ONLY : NSTPL, NRRATES
USE ADJ_ARRAYS_MOD, ONLY : IFD, JFD, NFD
USE ERROR_MOD, ONLY : ERROR_STOP
USE LOGICAL_ADJ_MOD, ONLY : LICS, LADJ_EMS
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT, LADJ_RRATE
USE TRACER_MOD, ONLY : ITS_A_TAGCO_SIM
USE TRACER_MOD, ONLY : N_TRACERS
# include "CMN_SIZE" ! Size params
! Local Variables
INTEGER :: I, J, L, M, N
INTEGER :: I_DUM
INTEGER :: OFFSET
!=================================================================
! GET_SF_FROM_X begins here!
!=================================================================
IF ( LICS ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L, N, I_DUM)
DO N = 1, N_TRACERS
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * ( J - 1) )
& + ( IIPAR * JJPAR * ( L - 1 ) )
& + ( IIPAR * JJPAR * LLPAR * ( N - 1 ) )
! Update the tracer concentrations from X
ICS_SF(I,J,L,N) = X(I_DUM)
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
!ELSEIF ( LADJ_EMS ) THEN
!mkeller:
IF ( LADJ_EMS ) THEN
IF ( ITS_A_TAGCO_SIM() ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M, N, I_DUM)
DO N = 1, 1
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * ( J - 1) )
& + ( IIPAR * JJPAR * ( M - 1 ) )
& + ( IIPAR * JJPAR * MMSCL * ( N - 1 ) )
! Update the tracer concentrations from X
EMS_SF(I,J,M,N) = X(I_DUM)
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
IF ( NNEMS == 2 ) THEN
N = 2
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
! Update the tracer concentrations from X
EMS_SF(I,J,M,N) = X(IIPAR*JJPAR*MMSCL+1)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
ELSE
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M, N, I_DUM)
DO N = 1, NNEMS
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * ( J - 1) )
& + ( IIPAR * JJPAR * ( M - 1 ) )
& + ( IIPAR * JJPAR * MMSCL * ( N - 1 ) )
!mkeller: get proper offset for I_DUM
IF ( LICS ) I_DUM =
& I_DUM + IIPAR * JJPAR * LLPAR * N_TRACERS
! Update the tracer concentrations from X
EMS_SF(I,J,M,N) = X(I_DUM)
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
OFFSET = IIPAR * JJPAR * MMSCL * NNEMS
! For strat prod and loss (hml)
IF ( LADJ_STRAT ) THEN
XP(:) = X(IIPAR*JJPAR*MMSCL*NNEMS+1:
& IIPAR*JJPAR*MMSCL*(NNEMS+NSTPL))
XL(:) = X(IIPAR*JJPAR*MMSCL*(NNEMS+NSTPL)+1:
& IIPAR*JJPAR*MMSCL*(NNEMS+2*NSTPL))
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M, N, I_DUM)
DO N = 1, NSTPL
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * ( J - 1) )
& + ( IIPAR * JJPAR * ( M - 1 ) )
& + ( IIPAR * JJPAR * MMSCL * ( N - 1 ) )
! Update the tracer concentrations from X
PROD_SF(I,J,M,N) = XP(I_DUM)
LOSS_SF(I,J,M,N) = XL(I_DUM)
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
OFFSET = IIPAR*JJPAR*MMSCL*(NNEMS+2*NSTPL)
ENDIF
! Reaction rates (tww)
IF ( LADJ_RRATE ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L, N, I_DUM )
DO N = 1, NRRATES
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * (J - 1) )
& + ( IIPAR * JJPAR * (L - 1 ) )
& + ( IIPAR * JJPAR * LLPAR * (N - 1) )
!I_DUM = I_DUM + IIPAR * JJPAR * MMSCL * NNEMS
! Combine to the I_DUM equation (hml, 06/10/13)
I_DUM = I_DUM + OFFSET
! Update active variables from X
RATE_SF(I,J,L,N) = X(I_DUM)
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
ENDIF
ENDIF
! Return to calling program
END SUBROUTINE GET_SF_FROM_X
!-----------------------------------------------------------------------------
SUBROUTINE GET_GRADNT_FROM_ADJ
!
!*****************************************************************************
! Subroutine GET_GRADNT_FROM_ADJ compiles the gradient vector from the array
! of adjoint values. (dkh, 9/16/04)
!
! NOTES:
! (1 ) Added ACTIVE_VARS == 'EMISSIONS' case. (dkh, 11/27/04)
! (2 ) Added ACTIVE_VARS == 'FDTEST' case. (dkh, 02/17/05)
! (3 ) Don't zero the NIT, NH4 and NO3 gradnts (dkh, 03/03/05)
! (4 ) Now support strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
!
!*****************************************************************************
!
! Reference to f90 modules
USE ADJ_ARRAYS_MOD, ONLY : MMSCL, NNEMS
USE ADJ_ARRAYS_MOD, ONLY : ICS_SF_ADJ, EMS_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : PROD_SF_ADJ, LOSS_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : NSTPL, NRRATES
USE ADJ_ARRAYS_MOD, ONLY : IFD, JFD, LFD, NFD
USE ERROR_MOD, ONLY : ERROR_STOP
USE LOGICAL_ADJ_MOD, ONLY : LICS, LADJ_EMS
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT, LADJ_RRATE
USE TRACER_MOD, ONLY : ITS_A_TAGCO_SIM
USE TRACER_MOD, ONLY : N_TRACERS
# include "CMN_SIZE" ! Size params
! Local Variables
INTEGER :: I, J, L, M, N
INTEGER :: I_DUM
INTEGER :: I_DUM_TMP
INTEGER :: OFFSET
!=================================================================
! GET_GRADNT_FROM_ADJ begins here!
!=================================================================
IF ( LICS ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L, N, I_DUM)
DO N = 1, N_TRACERS
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * ( J - 1) )
& + ( IIPAR * JJPAR * ( L - 1 ) )
& + ( IIPAR * JJPAR * LLPAR * ( N - 1 ) )
GRADNT(I_DUM) = ICS_SF_ADJ(I,J,L,N)
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
!ELSEIF( LADJ_EMS ) THEN
!mkeller:
ENDIF
IF ( LADJ_EMS ) THEN
IF ( ITS_A_TAGCO_SIM() ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M, N, I_DUM)
DO N = 1, 1
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * ( J - 1) )
& + ( IIPAR * JJPAR * ( M - 1 ) )
& + ( IIPAR * JJPAR * MMSCL * ( N - 1 ) )
GRADNT(I_DUM) = EMS_SF_ADJ(I,J,M,N)
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
IF( NNEMS == 2 ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M, N, I_DUM)
DO N = 2, 2 !NNEMS=2, but get zonal average for bkg
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = (IIPAR*JJPAR*MMSCL) + 1
! KLUDGE: Ask MAK about this.
! sum zonally
GRADNT(I_DUM) = GRADNT(I_DUM) + EMS_SF_ADJ(I,J,M,N)
ENDDO
ENDDO
ENDDO
! Update to include CH4 oxidation (zhej, 01/16/12, adj32_017)
! OLD:
!! KLUDGE: Ask MAK about this.
!! average zonally and per layer
!GRADNT(I_DUM) = GRADNT(I_DUM)
& ! / ( IIPAR * JJPAR * LLPAR * MMSCL)
! NEW:
GRADNT(I_DUM) = GRADNT(I_DUM) /
& ( IIPAR * JJPAR * MMSCL)
ENDDO
!$OMP END PARALLEL DO
ENDIF
ELSE
!mkeller: for now don't account for stratospheric production
IF ( .NOT. LADJ_STRAT ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M, N, I_DUM)
DO N = 1, NNEMS
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * ( J - 1) )
& + ( IIPAR * JJPAR * ( M - 1 ) )
& + ( IIPAR * JJPAR * MMSCL * ( N - 1 ) )
! mkeller: get proper offset for I_DUM
IF ( LICS ) I_DUM =
& I_DUM + IIPAR * JJPAR * LLPAR * N_TRACERS
GRADNT(I_DUM) = EMS_SF_ADJ(I,J,M,N)
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
OFFSET = IIPAR * JJPAR * MMSCL * NNEMS
ELSEIF ( LADJ_STRAT ) THEN
! For strat prod & loss (hml, 08/29/11)
I_DUM_TMP = IIPAR * JJPAR * MMSCL * NNEMS
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M, N, I_DUM)
DO N = 1, NSTPL
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * ( J - 1) )
& + ( IIPAR * JJPAR * ( M - 1 ) )
& + ( IIPAR * JJPAR * MMSCL * ( N - 1 ) )
GRADNT_P(I_DUM) = PROD_SF_ADJ(I,J,M,N)
GRADNT_L(I_DUM) = LOSS_SF_ADJ(I,J,M,N)
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
GRADNT( I_DUM_TMP + 1 :
& I_DUM_TMP + IIPAR * JJPAR * MMSCL * NSTPL )
& = GRADNT_P(:)
GRADNT( I_DUM_TMP + IIPAR * JJPAR * MMSCL * NSTPL + 1 :
& IIPAR * JJPAR * MMSCL * 2 * NSTPL )
& = GRADNT_L(:)
!OFFSET = # of emissions + # of strat prod loss
OFFSET = IIPAR * JJPAR * MMSCL * ( 2 * NSTPL + NNEMS )
ENDIF
!ELSEIF ( LADJ_RRATE ) THEN
IF ( LADJ_RRATE ) THEN
! For reaction rates (tww, 05/15/12)
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L, N, I_DUM )
DO N = 1, NRRATES
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
I_DUM = I + ( IIPAR * (J - 1) )
& + ( IIPAR * JJPAR * (L - 1) )
& + ( IIPAR * JJPAR * LLPAR * (N - 1) )
& + OFFSET
!I_DUM = I_DUM + IIPAR*JJPAR*MMSCL*NNEMS
! Combine to the I_DUM equation (hml, 06/10/13)
!I_DUM = I_DUM + OFFSET
GRADNT(I_DUM) = RATE_SF_ADJ(I,J,L,N)
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
ENDIF
ENDIF
! Return to calling program
END SUBROUTINE GET_GRADNT_FROM_ADJ
!------------------------------------------------------------------------------
SUBROUTINE MAKE_GDT_FILE( )
!
!******************************************************************************
! Subroutine MAKE_GDT_FILE creates a binary file of ADJ_xxx
! (dkh, 9/17/04)
!
! Module Variable as Input:
! ============================================================================
! (1 ) N_CALC : Current iteration number
! (2 ) ICS_SF_ADJ : Array of adjoint gradients to be written
! (3 ) EMS_SF_ADJ : Array of adjoint gradients to be written
!
! NOTES:
! (1 ) Just like MAKE_OBS_FILE except
! - write to .adj. file
! (2 ) Changed name to MAKE_GDT_FILE. Now the .adj. files are trajectories,
! and the .gdt. files are final gradients (dkh, 10/03/04)
! (3 ) Added ACTIVE_VARS == 'EMISSIONS' case. (dkh, 11/27/04)
! (4 ) Added ACTIVE_VARS == 'FDTEST' case. (dkh, 02/17/05)
! (5 ) Now use CATEGORY = 'IJ-GDE-$' for 'EMISSIONS' case. (dkh, 03/29/05)
! (6 ) No longer pass COST_FUNC in the header; use cnf.* files. (dkh, 02/13/06)
! (7 ) Rename everything, replace CMN_ADJ, move nonessential stuff
! to diagnostic files (dkh, ks, mak, cs 06/07/09)
! (8 ) Add normalized gradients IJ-GDEN$ (dkh, 05/06/10)
! (9 ) Now support strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
!******************************************************************************
!
! References to F90 modules
USE ADJ_ARRAYS_MOD, ONLY : ICS_SF_ADJ, EMS_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : NNEMS, MMSCL
USE ADJ_ARRAYS_MOD, ONLY : N_CALC
USE ADJ_ARRAYS_MOD, ONLY : EXPAND_NAME
USE ADJ_ARRAYS_MOD, ONLY : COST_FUNC
USE ADJ_ARRAYS_MOD, ONLY : PROD_SF_ADJ, LOSS_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : ID_PROD, ID_LOSS
USE ADJ_ARRAYS_MOD, ONLY : NSTPL
USE BPCH2_MOD
USE DIRECTORY_ADJ_MOD, ONLY : OPTDATA_DIR
USE ERROR_MOD, ONLY : DEBUG_MSG, ERROR_STOP
USE FILE_MOD, ONLY : IU_RST, IOERROR
USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET
USE LOGICAL_ADJ_MOD, ONLY : LICS, LADJ_EMS
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT
USE LOGICAL_MOD, ONLY : LPRT
USE TIME_MOD, ONLY : EXPAND_DATE, GET_TAU
USE TRACER_MOD, ONLY : N_TRACERS
USE TROPOPAUSE_MOD, ONLY : ITS_IN_THE_TROP
! Added for reaction rate sensitivities (tww, 05/08/12)
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF_ADJ, ID_RRATES
USE GCKPP_ADJ_GLOBAL, ONLY : NCOEFF, NCOEFF_EM, JCOEFF
USE LOGICAL_ADJ_MOD, ONLY : LADJ_RRATE
# include "CMN_SIZE" ! Size parameters
# include "comode.h" ! NEMIS(NCS)
! Local Variables
INTEGER :: I, I0, IOS, J, J0, L, M, N, NK
INTEGER :: NP, NL
INTEGER :: YYYY, MM, DD, HH, SS
REAL*4 :: TRACER(IIPAR,JJPAR,LLPAR)
REAL*4 :: EMS_3D(IIPAR,JJPAR,MMSCL)
CHARACTER(LEN=255) :: FILENAME
REAL*4 :: PROD_3D(IIPAR,JJPAR,MMSCL)
REAL*4 :: LOSS_3D(IIPAR,JJPAR,MMSCL)
! For binary punch file, version 2.0
REAL*4 :: LONRES, LATRES
INTEGER, PARAMETER :: HALFPOLAR = 1
INTEGER, PARAMETER :: CENTER180 = 1
! Added for reaction rate sensitivity (tww, 05/08/12)
REAL*4 :: RATE_3D(IIPAR,JJPAR,LLPAR)
CHARACTER(LEN=20) :: OUTPUT_GDT_FILE
CHARACTER(LEN=20) :: MODELNAME
CHARACTER(LEN=40) :: CATEGORY
CHARACTER(LEN=40) :: UNIT
CHARACTER(LEN=40) :: RESERVED = ''
CHARACTER(LEN=80) :: TITLE
!=================================================================
! MAKE_GDT_FILE begins here!
!=================================================================
! Clear intermediate arrays
EMS_3D (:,:,:) = 0d0
PROD_3D(:,:,:) = 0d0
LOSS_3D(:,:,:) = 0d0
! Hardwire output file for now
OUTPUT_GDT_FILE = 'gctm.gdt.NN'
! Define variables for BINARY PUNCH FILE OUTPUT
TITLE = 'GEOS-CHEM GDT File: ' //
& 'Final gradient values '
UNIT = 'none'
CATEGORY = 'IJ-GDT-$'
LONRES = DISIZE
LATRES = DJSIZE
! Call GET_MODELNAME to return the proper model name for
! the given met data being used (bmy, 6/22/00)
MODELNAME = GET_MODELNAME()
! Get the nested-grid offsets
I0 = GET_XOFFSET( GLOBAL=.TRUE. )
J0 = GET_YOFFSET( GLOBAL=.TRUE. )
!=================================================================
! Open the adjoint file for output -- binary punch format
!=================================================================
! Copy the output observation file name into a local variable
FILENAME = TRIM( OUTPUT_GDT_FILE )
! Append the iteration number suffix to the file name
CALL EXPAND_NAME( FILENAME, N_CALC )
! Add the OPTDATA_DIR prefix to the file name
FILENAME = TRIM( OPTDATA_DIR ) // TRIM( FILENAME )
WRITE( 6, 100 ) TRIM( FILENAME )
100 FORMAT( ' - MAKE_GDT_FILE: Writing ', a )
! Open checkpoint file for output
CALL OPEN_BPCH2_FOR_WRITE( IU_RST, FILENAME, TITLE )
IF ( LICS ) THEN
!=================================================================
! Write each observed quantity to the observation file
!=================================================================
DO N = 1, N_TRACERS
!Temporarily store quantities in the TRACER array
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
IF ( ITS_IN_THE_TROP(I,J,L) ) THEN
TRACER(I,J,L) = ICS_SF_ADJ (I,J,L,N)
ELSE
TRACER(I,J,L) = 0d0
ENDIF
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, N,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, LLPAR, I0+1,
& J0+1, 1, TRACER )
ENDDO
ENDIF
IF ( LADJ_EMS ) THEN
! Reset CATEGORY as labeling in gamap is different
CATEGORY = 'IJ-GDE-$'
!=================================================================
! Write each observed quantity to the observation file
!=================================================================
DO N = 1, NNEMS
!Temporarily store quantities in the TRACER array
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
EMS_3D(I,J,M) = REAL(EMS_SF_ADJ(I,J,M,N))
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, N,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, MMSCL, I0+1,
& J0+1, 1, EMS_3D )
ENDDO
! Reset CATEGORY as labeling in gamap is different
CATEGORY = 'IJ-GDEN$'
UNIT = 'none'
!=================================================================
! Write each observed quantity to the observation file
!=================================================================
DO N = 1, NNEMS
!Temporarily store quantities in the TRACER array
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
EMS_3D(I,J,M) = REAL(EMS_SF_ADJ(I,J,M,N))
& / COST_FUNC
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, N,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, MMSCL, I0+1,
& J0+1, 1, EMS_3D )
ENDDO
! Strat prod and loss (hml)
IF ( LADJ_STRAT ) THEN
!==============================================================
! Write each observed quantity to the observation file
!==============================================================
DO N = 1, NSTPL
NP = ID_PROD(N)
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
PROD_3D(I,J,M) = REAL(PROD_SF_ADJ(I,J,M,N))
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
!Temporarily store quantities in the PROD_3D, LOSS_3D array
CATEGORY = 'IJ-GDP-$'
UNIT = 'J'
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, NP,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, MMSCL, I0+1,
& J0+1, 1, PROD_3D )
ENDDO
! Strat loss
DO N = 1, NSTPL
NL = ID_LOSS(N)
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
LOSS_3D(I,J,M) = REAL(LOSS_SF_ADJ(I,J,M,N))
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
CATEGORY = 'IJ-GDL-$'
UNIT = 'J'
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, NL,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, MMSCL, I0+1,
& J0+1, 1, LOSS_3D )
ENDDO
ENDIF
ENDIF
! Added block for reaction rate sensitivity output (tww, 05/08/12)
IF ( LADJ_RRATE ) THEN
!=================================================================
! Write each observed quantity to the observation file
!=================================================================
DO N = NCOEFF_EM+1, NCOEFF
! Temporarily store quantities in the TRACER array
CATEGORY = 'IJ-RATE$'
! Before it is normalized (hml, 06/11/13)
!UNIT = 'none'
UNIT = 'J'
NK = ID_RRATES(N-NCOEFF_EM)
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
RATE_3D(I,J,L) = REAL(RATE_SF_ADJ(I,J,L,N-NCOEFF_EM))
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, NK,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, LLPAR, I0+1,
& J0+1, 1, RATE_3D )
ENDDO
ENDIF
! Close file
CLOSE( IU_RST )
!### Debug
IF ( LPRT ) CALL DEBUG_MSG( '### MAKE_GDT_FILE: wrote file' )
! Return to calling program
END SUBROUTINE MAKE_GDT_FILE
!------------------------------------------------------------------------------
SUBROUTINE READ_GDT_FILE ( )
!
!******************************************************************************
! Subroutine READ_GDT_FILE reads the gctm.gdt file into ADJ_xxx
! (dkh, 9/17/04)
!
! Module Variable as Input:
! ============================================================================
! (1 ) N_CALC : Current iteration number
!
! Notes
! (1 ) now called GDT instead of ADJ
! (2 ) Added ACTIVE_VARS == 'EMISSIONS' case. (dkh, 11/27/04)
! (3 ) Added ACTIVE_VARS == 'FDTEST' case. (dkh, 02/17/05)
! (4 ) Now use CATEGORY = 'IJ-GDE-$' for EMISSIONS case. (dkh, 03/29/05)
! (5 ) No longer pass COST_FUNC in the header; use cnf.* files. (dkh, 02/13/06)
! (6 ) Now support strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
!
!******************************************************************************
!
! References to F90 modules
USE ADJ_ARRAYS_MOD, ONLY : ICS_SF_ADJ, EMS_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : NNEMS, MMSCL
USE ADJ_ARRAYS_MOD, ONLY : N_CALC
USE ADJ_ARRAYS_MOD, ONLY : EXPAND_NAME
USE ADJ_ARRAYS_MOD, ONLY : PROD_SF_ADJ,LOSS_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : NSTPL, NRRATES
USE ADJ_ARRAYS_MOD, ONLY : ID_RRATES
USE BPCH2_MOD, ONLY : OPEN_BPCH2_FOR_READ
USE DIRECTORY_ADJ_MOD, ONLY : OPTDATA_DIR
USE ERROR_MOD, ONLY : DEBUG_MSG, ERROR_STOP
USE FILE_MOD, ONLY : IU_RST, IOERROR
USE LOGICAL_ADJ_MOD, ONLY : LICS, LADJ_EMS
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT, LADJ_RRATE
USE LOGICAL_MOD, ONLY : LPRT
USE RESTART_MOD, ONLY : CHECK_DIMENSIONS
USE TIME_MOD, ONLY : EXPAND_DATE
USE TRACER_MOD, ONLY : N_TRACERS
# include "CMN_SIZE" ! Size parameters
! Local Variables
INTEGER :: I, IOS, J, L, M, N, XX
REAL*4, ALLOCATABLE :: TEMP(:,:,:)
REAL*8 :: SUMTC
CHARACTER(LEN=255) :: FILENAME
! For binary punch file, version 2.0
INTEGER :: NI, NJ, NL
INTEGER :: N_LICS, N_EMS, N_RATE
INTEGER :: N_STRAT_PROD, N_STRAT_LOSS
INTEGER :: IFIRST, JFIRST, LFIRST
INTEGER :: NTRACER, NSKIP
INTEGER :: HALFPOLAR, CENTER180
REAL*4 :: LONRES, LATRES
REAL*8 :: ZTAU0, ZTAU1
CHARACTER(LEN=20) :: MODELNAME
CHARACTER(LEN=40) :: CATEGORY
CHARACTER(LEN=40) :: UNIT
CHARACTER(LEN=40) :: RESERVED
CHARACTER(LEN=20) :: INPUT_GDT_FILE
!=================================================================
! READ_GDT_FILE begins here!
!=================================================================
! Hardwire output file for now
INPUT_GDT_FILE = 'gctm.gdt.NN'
! Initialize some variables
N_LICS = 1
N_EMS = 1
N_STRAT_PROD = 1
N_STRAT_LOSS = 1
N_RATE = 1
IOS = 0
IF ( LLPAR > MMSCL ) THEN
XX = LLPAR
ELSE
XX = MMSCL
ENDIF
ALLOCATE(TEMP(IIPAR,JJPAR,XX))
TEMP(:,:,:) = 0e0
!=================================================================
! Open gradient file and read top-of-file header
!=================================================================
! Copy input file name to a local variable
FILENAME = TRIM( INPUT_GDT_FILE )
! Replace NN tokens in FILENAME w/ actual values
CALL EXPAND_NAME( FILENAME, N_CALC )
! Add OPTDATA_DIR prefix to FILENAME
FILENAME = TRIM( OPTDATA_DIR ) // TRIM( FILENAME )
! Echo some input to the screen
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
WRITE( 6, '(a,/)' ) 'G D T F I L E I N P U T'
WRITE( 6, 100 ) TRIM( FILENAME )
100 FORMAT( ' - READ_GDT_FILE: Reading ', a )
! Open the binary punch file for input
CALL OPEN_BPCH2_FOR_READ( IU_RST, FILENAME )
!=================================================================
! Read adjoints -- store in the TRACER array
!=================================================================
DO WHILE ( .NOT. IOS < 0 )
READ( IU_RST, IOSTAT=IOS )
& MODELNAME, LONRES , LATRES, HALFPOLAR, CENTER180
! IOS < 0 is end-of-file, so exit
IF ( IOS < 0 ) EXIT
! IOS > 0 is a real I/O error -- print error message
IF ( IOS > 0 ) CALL IOERROR( IOS,IU_RST,'read_gdt_file:4' )
READ( IU_RST, IOSTAT=IOS )
& CATEGORY, NTRACER, UNIT, ZTAU0, ZTAU1, RESERVED,
& NI, NJ, NL, IFIRST, JFIRST, LFIRST,
& NSKIP
IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_RST,'read_gdt_file:5')
READ( IU_RST, IOSTAT=IOS )
& ( ( ( TEMP(I,J,L), I=1,NI ), J=1,NJ ), L=1,NL )
IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_RST,'read_gdt_file:6')
!==============================================================
! Assign data from the TRACER array to the ADJ_STT array.
!==============================================================
SELECT CASE ( CATEGORY(1:8) )
! Only process observation data (i.e. aerosol and precursors)
CASE ( 'IJ-GDT-$' )
! Make sure array dimensions are of global size
! (NI=IIPAR; NJ=JJPAR, NL=LLPAR), or stop the run
CALL CHECK_DIMENSIONS( NI, NJ, NL )
ICS_SF_ADJ(:,:,:,N_LICS) = TEMP(:,:,1:LLPAR)
N_LICS = N_LICS + 1
! Only process observation data (i.e. aerosol and precursors)
CASE ( 'IJ-GDE-$' )
EMS_SF_ADJ(:,:,:,N_EMS) = TEMP(:,:,1:MMSCL)
N_EMS = N_EMS + 1
! Only process observation data (i.e. aerosol and precursors)
CASE ( 'IJ-GDP-$' )
PROD_SF_ADJ(:,:,:,N_STRAT_PROD) = TEMP(:,:,1:MMSCL)
N_STRAT_PROD = N_STRAT_PROD + 1
! Only process observation data (i.e. aerosol and precursors)
CASE ( 'IJ-GDL-$' )
LOSS_SF_ADJ(:,:,:,N_STRAT_LOSS) = TEMP(:,:,1:MMSCL)
N_STRAT_LOSS = N_STRAT_LOSS + 1
CASE ( 'IJ-RATE$' )
RATE_SF_ADJ(:,:,:,N_RATE) = TEMP(:,:,1:LLPAR)
N_RATE = N_RATE + 1
END SELECT
ENDDO
IF ( LICS ) THEN
IF ( N_TRACERS .NE. N_LICS - 1 ) CALL ERROR_STOP(
& ' Invalid number LICS found ' , 'READ_GDT_FILE' )
ENDIF
IF ( LADJ_EMS ) THEN
IF ( NNEMS .NE. N_EMS - 1 ) CALL ERROR_STOP(
& ' Invalid number EMS found ' , 'READ_GDT_FILE' )
ENDIF
IF ( LADJ_STRAT ) THEN
IF ( NSTPL .NE. N_STRAT_PROD - 1 ) CALL ERROR_STOP(
& ' Invalid number STRAT_PROD found ' , 'READ_GDT_FILE' )
IF ( NSTPL .NE. N_STRAT_LOSS - 1 ) CALL ERROR_STOP(
& ' Invalid number STRAT_LOSS found ' , 'READ_GDT_FILE' )
ENDIF
IF ( LADJ_RRATE ) THEN
IF ( NRRATES .NE. N_RATE - 1 ) CALL ERROR_STOP(
& ' Invalid number RRATES found ' , 'READ_GDT_FILE' )
ENDIF
! Close file
CLOSE( IU_RST )
!### Debug
IF ( LPRT ) CALL DEBUG_MSG( '### READ_GDT_FILE: read file' )
! Return to calling program
END SUBROUTINE READ_GDT_FILE
! needs to be updated
!-----------------------------------------------------------------------
!
! SUBROUTINE MAKE_GDT_DIAG_FILE( )
!!
!!******************************************************************************
!! Subroutine MAKE_GDT_DIAG_FILE creates a binary file of daignostics
!! relatied to the adjoint gradients. (dkh, 06/07/09)
!! (dkh, 9/17/04)
!!
!! Module Variable as Input:
!! ============================================================================
!! (1 ) N_CALC : Current iteration number
!! (2 ) ICS_SF_ADJ : Array of adjoint gradients to be written
!! (3 ) EMS_SF_ADJ : Array of adjoint gradients to be written
!! (4 ) ADJ_BURNEMIS : Array of biomass burning sensitivities
!! (5 ) ADJ_BIOFUEL : Array of biofuel sensitivities
!! (6 ) ADJ_EMISRR :
!! (7 ) ADJ_EMISRRB :
!!
!! NOTES:
!!
!!******************************************************************************
!!
! ! References to F90 modules
! USE ADJ_ARRAYS_MOD, ONLY : ADJ_BURNEMIS
! USE ADJ_ARRAYS_MOD, ONLY : ADJ_BIOFUEL
! USE ADJ_ARRAYS_MOD, ONLY : ADJ_EMISRR
! USE ADJ_ARRAYS_MOD, ONLY : ADJ_EMISRRB
! USE BPCH2_MOD
! USE DIRECTORY_ADJ_MOD, ONLY : DIAGADJ_DIR
! USE ERROR_MOD, ONLY : DEBUG_MSG, ERROR_STOP
! USE FILE_MOD, ONLY : IU_RST, IOERROR
! USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET
! USE TIME_MOD, ONLY : EXPAND_DATE, GET_TAU
! USE BIOMASS_MOD, ONLY : NBIOTRCE
! USE BIOFUEL_MOD, ONLY : NBFTRACE
!
!# include "CMN_SIZE" ! Size parameters
!# include "CMN" ! LPRT
!# include "comode.h" ! NEMIS(NCS)
!
! ! Local Variables
! INTEGER :: I, I0, IOS, J, J0, L, M, N
! INTEGER :: YYYY, MM, DD, HH, SS
! REAL*4 :: TRACER(IIPAR,JJPAR,LLPAR)
! REAL*4 :: EMS_3D(IIPAR,JJPAR,MMSCL)
! CHARACTER(LEN=255) :: FILENAME
!
! ! For binary punch file, version 2.0
! REAL*4 :: LONRES, LATRES
! INTEGER, PARAMETER :: HALFPOLAR = 1
! INTEGER, PARAMETER :: CENTER180 = 1
!
! CHARACTER(LEN=20) :: OUTPUT_GDT_FILE
! CHARACTER(LEN=20) :: MODELNAME
! CHARACTER(LEN=40) :: CATEGORY
! CHARACTER(LEN=40) :: UNIT
! CHARACTER(LEN=40) :: RESERVED = ''
! CHARACTER(LEN=80) :: TITLE
!
! !=================================================================
! ! MAKE_GDT_FILE begins here!
! !=================================================================
!
! ! Clear intermediate arrays
! EMS_3D(:,:,:) = 0d0
!
! ! Hardwire output file for now
! OUTPUT_GDT_FILE = 'gctm.gdt.diag.NN'
!
! ! Define variables for BINARY PUNCH FILE OUTPUT
! TITLE = 'GEOS-CHEM GDT File: ' //
! & 'Gradient diagnostics '
! LONRES = DISIZE
! LATRES = DJSIZE
!
! ! Call GET_MODELNAME to return the proper model name for
! ! the given met data being used (bmy, 6/22/00)
! MODELNAME = GET_MODELNAME()
!
! ! Get the nested-grid offsets
! I0 = GET_XOFFSET( GLOBAL=.TRUE. )
! J0 = GET_YOFFSET( GLOBAL=.TRUE. )
!
! !=================================================================
! ! Open the adjoint file for output -- binary punch format
! !=================================================================
!
! ! Copy the output observation file name into a local variable
! FILENAME = TRIM( OUTPUT_GDT_FILE )
!
! ! Append the iteration number suffix to the file name
! CALL EXPAND_NAME( FILENAME, N_CALC )
!
! ! Add the OPTDATA_DIR prefix to the file name
! FILENAME = TRIM( DIAGADJTMP_DIR ) // TRIM( FILENAME )
!
! WRITE( 6, 100 ) TRIM( FILENAME )
! 100 FORMAT( ' - MAKE_GDT_FILE: Writing ', a )
!
! ! Open checkpoint file for output
! CALL OPEN_BPCH2_FOR_WRITE( IU_RST, FILENAME, TITLE )
!
! !=================================================================
! ! Normalized sensitivies
! !=================================================================
!
! ! Reset CATEGORY as labeling in gamap is different
! CATEGORY = 'IJ-GDEN$'
! UNIT = '%'
!
! !=================================================================
! ! Write each observed quantity to the observation file
! !=================================================================
! DO N = 1, NNEMS
!
! ! Temporarily store quantities in the TRACER array
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J, M )
! DO M = 1, MMSCL
! DO J = 1, JJPAR
! DO I = 1, IIPAR
! EMS_3D(I,J,M) = REAL(ADJ_EMS(I,J,M,N)) / COST_FUNC
! & * 100d0
! ENDDO
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
!
! CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
! & HALFPOLAR, CENTER180, CATEGORY, N + NNEMS,
! & UNIT, GET_TAU(), GET_TAU(), RESERVED,
! & IIPAR, JJPAR, MMSCL, I0+1,
! & J0+1, 1, EMS_3D )
!
! ENDDO
!
!
! !=================================================================
! ! Normalized VOC sensitivies - EMISRR (anthro hydrocarbons)
! !=================================================================
! CATEGORY = 'DEMISRR'
! DO N = 1, NEMIS(NCS)
!
! ! Temporarily store quantities in the TRACER array
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J, M )
! DO J = 1, JJPAR
! DO I = 1, IIPAR
! EMS_3D(I,J,1) = REAL(ADJ_EMISRR(I,J,N)) / COST_FUNC
! & * 100d0
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! ! dkh debug
! print*, ' ADJ EMISRR = ', maxval(adj_emisrr(:,:,n)), n
!
! CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
! & HALFPOLAR, CENTER180, CATEGORY, N,
! & UNIT, GET_TAU(), GET_TAU(), RESERVED,
! & IIPAR, JJPAR, MMSCL, I0+1,
! & J0+1, 1, EMS_3D )
! ENDDO
!
!
! !=================================================================
! ! Normalized VOC sensitivies - EMISRRB (biogenic hydrocarbons)
! !=================================================================
! CATEGORY = 'DEMISRRB'
! DO N = 1, NEMIS(NCS)
!
! ! Temporarily store quantities in the TRACER array
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J, M )
! DO J = 1, JJPAR
! DO I = 1, IIPAR
! EMS_3D(I,J,1) = REAL(ADJ_EMISRRB(I,J,N)) / COST_FUNC
! & * 100d0
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! ! dkh debug
! print*, ' ADJ EMISRRB = ', maxval(adj_emisrrb(:,:,n)), n
!
! CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
! & HALFPOLAR, CENTER180, CATEGORY, N,
! & UNIT, GET_TAU(), GET_TAU(), RESERVED,
! & IIPAR, JJPAR, MMSCL, I0+1,
! & J0+1, 1, EMS_3D )
! ENDDO
!
! !=================================================================
! ! Normalized VOC sensitivies - BOIFUEL
! !=================================================================
! CATEGORY = 'DBIOFUEL'
! DO N = 1, NBFTRACE
!
! ! Temporarily store quantities in the TRACER array
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J )
! DO J = 1, JJPAR
! DO I = 1, IIPAR
! EMS_3D(I,J,1) = REAL(ADJ_BIOFUEL(I,J,N)) / COST_FUNC
! & * 100d0
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
! & HALFPOLAR, CENTER180, CATEGORY, N,
! & UNIT, GET_TAU(), GET_TAU(), RESERVED,
! & IIPAR, JJPAR, MMSCL, I0+1,
! & J0+1, 1, EMS_3D )
!
! ! dkh debug
! print*, ' ADJ BIOFUEL= ', maxval(ADJ_BIOFUEL(:,:,n)), n
!
! ENDDO
!
!
! !=================================================================
! ! Normalized VOC sensitivies - BURNEMIS
! !=================================================================
! CATEGORY = 'DBURNEMIS'
! DO N = 1, NBIOTRCE
!
! ! Temporarily store quantities in the TRACER array
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J )
! DO J = 1, JJPAR
! DO I = 1, IIPAR
! EMS_3D(I,J,1) = REAL(ADJ_BURNEMIS(I,J,N)) / COST_FUNC
! & * 100d0
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
! & HALFPOLAR, CENTER180, CATEGORY, N,
! & UNIT, GET_TAU(), GET_TAU(), RESERVED,
! & IIPAR, JJPAR, MMSCL, I0+1,
! & J0+1, 1, EMS_3D )
!
! ! dkh debug
! print*, ' ADJ BURNEMIS= ', maxval(ADJ_BURNEMIS(:,:,n)), n
!
! ENDDO
!
! ! Close file
! CLOSE( IU_RST )
!
! !### Debug
! IF ( LPRT ) CALL DEBUG_MSG( '### MAKE_GDT_DIAG_FILE: wrote file' )
!
! ! Return to calling program
! END SUBROUTINE MAKE_GDT_DIAG_FILE
!
!------------------------------------------------------------------------------
SUBROUTINE MAKE_SF_FILE ( )
!
!******************************************************************************
! Subroutine MAKE_SF_FILE creates a binary file of STT_IC or EMS_ICS
! (dkh, 9/17/04)
!
! Module Variable as Input:
! ============================================================================
! (1 ) N_CALC : Current iteration number
! (2 ) ICS_SF : Initial conditions scaling factors
! (3 ) EMS_SF : Emissions scaling factors
!
! NOTES:
! (1 ) Just like MAKE_ADJ_FILE except
! - write to .ics. file
! (2 ) Add support for ACTIVE_VARS == 'EMISSIONS' case (dkh, 11/27/04)
! (3 ) Add support for ACTIVE_VARS == 'FDTEST' case. (dkh, 02/17/05)
! (4 ) Change UNIT to unitless and change title to Scale factors (dkh, 03/06/05)
! (5 ) Change output for ACTIVE_VARS == 'EMISSIONS' case.
! Now use label IJ-EMS-$, and update gamap code accordingly.
! First write the scaling factors, in consecutive species. Temporal
! varations in the emissions, if any, will be in the L direction.
! Next, write out the optimized emissions themselves.
! Finally, write out the difference between orig and optimized emissions.
! (dkh, 03/28/05)
! (6 ) Use EMS_orig instead of ESO4_an_orig so that we can loop over N.
! (7 ) Update to add support for writing NOx emissions. (dkh, 08/27/06)
! (8 ) Only write the value of the scaling facotr in locations where the
! actual emission is greater than zero. Also include the current
! scale emissions themselves in every *ics* file. (dkh, 09/22/06)
! (9 ) Add suppport for LOG_OPT
! (10) Standardize units for saving emissions. (dkh, 06/16/07)
! (11) Add option to print prior and posterior emissions totals. (dkh, 06/16/07)
! (12) Change names, replace CMN_ADJ. (dkh, ks, mak, cs 06/08/09)
! (13) Now support strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
!******************************************************************************
!
! References to F90 modules
USE ADJ_ARRAYS_MOD, ONLY : N_CALC, ICS_SF, EMS_SF
USE ADJ_ARRAYS_MOD, ONLY : MMSCL, NNEMS, EMS_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : EXPAND_NAME
USE ADJ_ARRAYS_MOD, ONLY : N_CALC_TOTAL, EMS_SF_DEFAULT
USE ADJ_ARRAYS_MOD, ONLY : MMSCL, NNEMS
USE ADJ_ARRAYS_MOD, ONLY : PROD_SF, LOSS_SF
USE ADJ_ARRAYS_MOD, ONLY : ID_PROD, ID_LOSS
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF, ID_RRATES
USE ADJ_ARRAYS_MOD, ONLY : NSTPL, NRRATES
USE GCKPP_ADJ_GLOBAL, ONLY : NCOEFF, NCOEFF_EM, JCOEFF
USE BPCH2_MOD
USE DIRECTORY_MOD, ONLY : TEMP_DIR
USE DIRECTORY_ADJ_MOD, ONLY : OPTDATA_DIR
USE ERROR_MOD, ONLY : DEBUG_MSG, ERROR_STOP
USE FILE_MOD, ONLY : IU_RST, IOERROR
USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET
USE GRID_MOD, ONLY : GET_AREA_CM2
USE LOGICAL_ADJ_MOD, ONLY : LICS, LADJ_EMS
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT, LADJ_RRATE
USE LOGICAL_MOD, ONLY : LPRT
USE TIME_MOD, ONLY : EXPAND_DATE, GET_TAU
USE TIME_MOD, ONLY : GET_TS_CHEM
USE TIME_MOD, ONLY : GET_TS_EMIS
USE TIME_MOD, ONLY : GET_TAUb, GET_TAUe
USE TRACER_MOD, ONLY : N_TRACERS
USE TROPOPAUSE_MOD, ONLY : ITS_IN_THE_TROP
# include "CMN_SIZE" ! Size parameters
# include "CMN_O3" ! EMISRN
# include "comode.h" ! NEMIS(NCS)
! Local Variables
INTEGER :: I, I0, IOS, J, J0, L, M, N, NK
INTEGER :: NP, NL
INTEGER :: YYYY, MM, DD, HH, SS
INTEGER :: NOFFSET
REAL*4 :: TRACER(IIPAR,JJPAR,LLPAR)
CHARACTER(LEN=255) :: FILENAME
REAL*8 :: TEMP
REAL*8 :: NEMIS_DT
REAL*8 :: USA_MASK(IIPAR,JJPAR)
REAL*8 :: EMS_TOTAL(NNEMS)
REAL*4 :: EMS_PERCENT(IIPAR,JJPAR,NNEMS)
LOGICAL, PARAMETER :: LPRINT_TOTAL = .TRUE.
! For binary punch file, version 2.0
REAL*4 :: LONRES, LATRES
INTEGER, PARAMETER :: HALFPOLAR = 1
INTEGER, PARAMETER :: CENTER180 = 1
CHARACTER(LEN=20) :: OUTPUT_SF_FILE
CHARACTER(LEN=20) :: MODELNAME
CHARACTER(LEN=40) :: CATEGORY
CHARACTER(LEN=40) :: UNIT
CHARACTER(LEN=40) :: RESERVED = ''
CHARACTER(LEN=80) :: TITLE
! Parameters
REAL*8, PARAMETER :: SEC_PER_YEAR = 3.1536d7
REAL*8, PARAMETER :: MIN_PER_YEAR = 5.2560d5
REAL*8, PARAMETER :: TG_PER_KG = 1d-09
!=================================================================
! MAKE_SF_FILE begins here!
!=================================================================
! Hardwire output file for now
OUTPUT_SF_FILE = 'gctm.sf.NN'
! Define variables for BINARY PUNCH FILE OUTPUT
TITLE = 'GEOS-CHEM SF File: ' //
& 'Scale Factors'
UNIT = 'unitless'
CATEGORY = 'IJ-ICS-$'
LONRES = DISIZE
LATRES = DJSIZE
! Call GET_MODELNAME to return the proper model name for
! the given met data being used (bmy, 6/22/00)
MODELNAME = GET_MODELNAME()
! Get the nested-grid offsets
I0 = GET_XOFFSET( GLOBAL=.TRUE. )
J0 = GET_YOFFSET( GLOBAL=.TRUE. )
!=================================================================
! Open the adjoint file for output -- binary punch format
!=================================================================
! Copy the output observation file name into a local variable
FILENAME = TRIM( OUTPUT_SF_FILE )
! Replace NN token w/ actual value
CALL EXPAND_NAME( FILENAME, N_CALC )
! Add OPTDATA_DIR prefix to FILENAME
FILENAME = TRIM( OPTDATA_DIR ) // TRIM( FILENAME )
WRITE( 6, 100 ) TRIM( FILENAME )
100 FORMAT( ' - MAKE_SF_FILE: Writing ', a )
! Open checkpoint file for output
CALL OPEN_BPCH2_FOR_WRITE( IU_RST, FILENAME, TITLE )
IF ( LICS ) THEN
CATEGORY = 'IJ-ICS-$'
!=================================================================
! Write each observed quantity to the ics file
!=================================================================
DO N = 1, N_TRACERS
!Temporarily store quantities in the TRACER array
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
IF ( ITS_IN_THE_TROP(I,J,L) ) THEN
TRACER(I,J,L) = ICS_SF(I,J,L,N)
ELSE
TRACER(I,J,L) = 1d0
ENDIF
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, N,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, LLPAR, I0+1,
& J0+1, 1, TRACER )
ENDDO
ENDIF
IF ( LADJ_EMS ) THEN
CATEGORY = 'IJ-EMS-$'
UNIT = 'unitless'
!=================================================================
! Write each observed quantity to the ics file
!=================================================================
DO N = 1, NNEMS
!Temporarily store quantities in the TRACER array
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M , TEMP )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
TRACER(I,J,M) = EMS_SF(I,J,M,N)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, N,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, MMSCL, I0+1,
& J0+1, 1, TRACER )
ENDDO
IF ( LADJ_STRAT ) THEN
!==============================================================
! Write each observed quantity to the ics file
!==============================================================
DO N = 1, NSTPL
NP = ID_PROD(N)
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
TRACER(I,J,M) = PROD_SF(I,J,M,N)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
!Temporarily store quantities in the TRACER array
CATEGORY = 'IJ-STRP$'
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, NP,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, MMSCL, I0+1,
& J0+1, 1, TRACER )
ENDDO
DO N = 1, NSTPL
NP = ID_LOSS(N)
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
TRACER(I,J,M) = LOSS_SF(I,J,M,N)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
CATEGORY = 'IJ-STRL$'
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, NL,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, MMSCL, I0+1,
& J0+1, 1, TRACER )
ENDDO
ENDIF
IF ( LADJ_RRATE ) THEN
!==============================================================
! Write each observed quantity to the ics file
!==============================================================
DO N = NCOEFF_EM+1, NCOEFF
NK = ID_RRATES(N-NCOEFF_EM)
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
TRACER(I,J,L) = RATE_SF(I,J,L,N-NCOEFF_EM)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
CATEGORY = 'IJ-RATSF'
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, NK,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, LLPAR, I0+1,
& J0+1, 1, TRACER )
ENDDO
ENDIF
ENDIF
!### Debug
IF ( LPRT ) CALL DEBUG_MSG( '### MAKE_SF_FILE: wrote file' )
! Return to calling program
END SUBROUTINE MAKE_SF_FILE
! needs to be updated:
!!------------------------------------------------------------------------------
!
! SUBROUTINE MAKE_SF_DIAG_FILE ( )
!!
!!******************************************************************************
!! Subroutine MAKE_SF_DIAG_FILE creates a binary file of diagnostics
!! related to scaling factor values. (dkh, 06/08/09)
!!
!! Module Variable as Input:
!! ============================================================================
!! (1 ) N_CALC : Current iteration number
!! (2 ) ICS_SF : Initial conditions scaling factors
!! (3 ) EMS_SF : Emissions scaling factors
!!
!! NOTES:
!! (1) Split this off from MAKE_ICS_FILE (dkh, ks, mak, cs 06/08/09)
!!******************************************************************************
!!
! ! References to F90 modules
! USE ADJ_ARRAYS_MOD, ONLY : EMS_SF, ICS_SF
! USE BPCH2_MOD
! USE ERROR_MOD, ONLY : DEBUG_MSG, ERROR_STOP
! USE DIRECTORY_MOD, ONLY : TEMP_DIR
! USE DIRECTORY_ADJ_MOD, ONLY : DIAGADJTMP_DIR
! USE FILE_MOD, ONLY : IU_RST, IOERROR
! USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET, GET_AREA_CM2
! USE TIME_MOD, ONLY : EXPAND_DATE, GET_TAU
! USE TIME_MOD, ONLY : GET_TS_CHEM
! USE TIME_MOD, ONLY : GET_TS_EMIS
! USE TIME_MOD, ONLY : GET_TAUb, GET_TAUe
! USE TRACERID_MOD, ONLY : IDTNH3, IDTNOX, IDTBCPI, IDTSO2
! USE SULFATE_MOD, ONLY : EMS_orig
! USE LIGHTNING_NOX_MOD, ONLY : EMS_orig_li
! USE EMISSIONS_MOD, ONLY : BIOFUEL_orig
! USE EMISSIONS_MOD, ONLY : BURNEMIS_orig
! USE EMISSIONS_MOD, ONLY : EMISRR_orig
! USE EMISSIONS_MOD, ONLY : EMISRRB_orig
! USE BIOMASS_MOD, ONLY : NBIOTRCE
! USE BIOFUEL_MOD, ONLY : NBFTRACE
! USE DAO_MOD, ONLY : BXHEIGHT
!
!
!# include "CMN_SIZE" ! Size parameters
!# include "CMN" ! LPRT, LLIGHTNOX
!# include "CMN_O3" ! EMISRN
!# include "comode.h" ! NEMIS(NCS)
!
! ! Local Variables
! INTEGER :: I, I0, IOS, J, J0, L, M, N
! INTEGER :: YYYY, MM, DD, HH, SS
! INTEGER :: NOFFSET
! REAL*4 :: TRACER(IIPAR,JJPAR,LLPAR)
! REAL*4 :: TRACER_VOC(IIPAR,JJPAR,20)
! REAL*4 :: TRACER_US(IIPAR,JJPAR,LLPAR)
! CHARACTER(LEN=255) :: FILENAME
! REAL*8 :: TEMP
! REAL*8 :: NEMIS_DT
! REAL*8 :: USA_MASK(IIPAR,JJPAR)
! REAL*8 :: EMS_TOTAL(NNEMS)
! REAL*4 :: EMS_PERCENT(IIPAR,JJPAR,NNEMS)
! LOGICAL, PARAMETER :: LPRINT_TOTAL = .TRUE.
!
! ! For binary punch file, version 2.0
! REAL*4 :: LONRES, LATRES
! INTEGER, PARAMETER :: HALFPOLAR = 1
! INTEGER, PARAMETER :: CENTER180 = 1
!
! CHARACTER(LEN=20) :: OUTPUT_SF_DIAG_FILE
! CHARACTER(LEN=20) :: MODELNAME
! CHARACTER(LEN=40) :: CATEGORY
! CHARACTER(LEN=40) :: UNIT
! CHARACTER(LEN=40) :: RESERVED = ''
! CHARACTER(LEN=80) :: TITLE
!
! ! Parameters
! REAL*8, PARAMETER :: SEC_PER_YEAR = 3.1536d7
! REAL*8, PARAMETER :: MIN_PER_YEAR = 5.2560d5
! REAL*8, PARAMETER :: TG_PER_KG = 1d-09
!
! !=================================================================
! ! MAKE_SF_DIAG_FILE begins here!
! !=================================================================
!
! ! Hardwire output file for now
! OUTPUT_SF_DIAG_FILE = 'gctm.sf.diag.NN'
!
! ! Define variables for BINARY PUNCH FILE OUTPUT
! TITLE = 'GEOS-CHEM SF File: ' //
! & 'Scale Factors Diagnostics'
! UNIT = 'unitless'
! LONRES = DISIZE
! LATRES = DJSIZE
!
! ! Call GET_MODELNAME to return the proper model name for
! ! the given met data being used (bmy, 6/22/00)
! MODELNAME = GET_MODELNAME()
!
! ! Get the nested-grid offsets
! I0 = GET_XOFFSET( GLOBAL=.TRUE. )
! J0 = GET_YOFFSET( GLOBAL=.TRUE. )
!
! !=================================================================
! ! Open the adjoint file for output -- binary punch format
! !=================================================================
!
! ! Copy the output observation file name into a local variable
! FILENAME = TRIM( OUTPUT_SF_DIAG_FILE )
!
! ! Replace NN token w/ actual value
! CALL EXPAND_NAME( FILENAME, N_CALC )
!
! ! Add OPTDATA_DIR prefix to FILENAME
! FILENAME = TRIM( DIAGADJTMP_DIR ) // TRIM( FILENAME )
!
! WRITE( 6, 100 ) TRIM( FILENAME )
! 100 FORMAT( ' - MAKE_SF_DIAG_FILE: Writing ', a )
!
! ! Open checkpoint file for output
! CALL OPEN_BPCH2_FOR_WRITE( IU_RST, FILENAME, TITLE )
!
! IF ( NEMS ) THEN
!
!
! ! Also write the actual emissions.
! ! Go ahead and include this every time.
! CATEGORY = 'IJ-EM0-$'
! UNIT = 'molecule/cm2/s'
!
! ! emdt / sim = hr / sim * min / hr * emdt / min
! NEMIS_DT = ( GET_TAUe() - GET_TAUb() ) * 60d0 / GET_TS_EMIS()
!
! DO N = 1, NNEMS
!
! ! Compile TRACER [ molec / cm2 / s ]
! ! Get the actual emission in the current cell
! ! Original emissions are in EMS_orig, but in a variety of unit
!
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J )
! DO J = 1, JJPAR
! DO I = 1, IIPAR
!
! ! lightning NOx
! IF ( N == IDADJEMS_ENOxli ) THEN
!
! ! Add to prevent allocation segfault (dkh, 10/10/08)
! IF ( LLIGHTNOX ) THEN
!
! ! molec NOx / cm2 / s total sim -> molec NOx / cm2 / s
! TRACER(I,J,N) = EMS_orig_li(I,J)
! & / NEMIS_DT ! number of emissions
!
! ELSE
! TRACER(I,J,N) = 0D0
! ENDIF
!
!
! ! soil NOx
! ELSEIF ( N == IDADJEMS_ENOxso ) THEN
!
! ! molec NOx / cm2 / s total -> molec / cm2 / s
! TRACER(I,J,N) = EMS_orig(I,J,N)
! & / NEMIS_DT ! number of emissions
!
!
! ! BC / OC
! ELSEIF ( N == IDADJEMS_BCan .or. N == IDADJEMS_OCan .or.
! & N == IDADJEMS_BCbb .or. N == IDADJEMS_OCbb .or.
! & N == IDADJEMS_BCbf .or. N == IDADJEMS_OCbf )
! & THEN
!
! ! Convert from kg / yr to molec C / cm2 / s
! TRACER(I,J,N) = EMS_orig(I,J,N)
! & * XNUMOL(IDTBCPI)
! & / GET_AREA_CM2(J)
! & / SEC_PER_YEAR
!
!
! ! Anth NOx
! ELSEIF ( N == IDADJEMS_ENOx1 .or. N == IDADJEMS_ENOx2 )
! & THEN
!
! ! Convert from kg / box / emdt to molec / cm2 / s
! TRACER(I,J,N) = EMS_orig(I,J,N)
! & * XNUMOL(IDTNOX)
! & / GET_AREA_CM2(J)
! & / ( GET_TS_EMIS() * 60.d0 ) ! seconds per emdt
!
! ! NH3
! ELSEIF ( N == IDADJEMS_ENH3_an .or.
! & N == IDADJEMS_ENH3_na .or.
! & N == IDADJEMS_ENH3_bb .or.
! & N == IDADJEMS_ENH3_bf )
! & THEN
!
! ! Convert from kg NH3 / box / s to molec / cm2 / s
! TRACER(I,J,N) = EMS_orig(I,J,N)
! & * XNUMOL(IDTNH3)
! & / GET_AREA_CM2(J)
!
! ! SO2
! ELSEIF ( N == IDADJEMS_ESO2_bb .or.
! & N == IDADJEMS_ESO2_bf .or.
! & N == IDADJEMS_ESO2_sh )
! & THEN
!
! ! Convert from kg SO2 / box / s to molec / cm2 / s
! TRACER(I,J,N) = EMS_orig(I,J,N)
! & * XNUMOL(IDTSO2)
! & / GET_AREA_CM2(J)
!
! ! Volcano SO2 emissions (dkh, cklee 09/14/08)
! ELSEIF ( N == IDADJEMS_ESO2_ev .or. !(added,cklee)
! & N == IDADJEMS_ESO2_nv ) !(added,cklee)
! & THEN
! ! Convert from kg SO2 / box / s total to molec / cm2 / s
! TRACER(I,J,N) = EMS_orig(I,J,N)
! & * XNUMOL(IDTSO2)
! & / GET_AREA_CM2(J)
! & / NEMIS_DT
!
! ! Anth SOx
! ELSEIF ( N == IDADJEMS_ESOx1 .or.
! & N == IDADJEMS_ESOx2 ) THEN
!
! ! it's already in molec SOx / cm2 / s
! TRACER(I,J,N) = EMS_orig(I,J,N)
!
! ELSE
!
! CALL ERROR_STOP('undefined emissions',
! & 'inverse_mod.f')
! ENDIF
!
!#if defined ( LOG_OPT )
! ! Apply current scaling
! TRACER(I,J,N) = TRACER(I,J,N) * EXP(EMS_ICS(I,J,1,N))
!
!#else
! ! Apply current scaling
! TRACER(I,J,N) = TRACER(I,J,N) * EMS_ICS(I,J,1,N)
!#endif
!
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
! & HALFPOLAR, CENTER180, CATEGORY, 50+N,
! & UNIT, GET_TAU(), GET_TAU(), RESERVED,
! & IIPAR, JJPAR, 1, I0+1,
! & J0+1, 1, TRACER(:,:,N) )
!
! ENDDO
!
!
! ! Also write the normalized emissions
! CALL READ_USA_MASK( USA_MASK )
! CATEGORY = 'IJ-EMP-$'
! UNIT = '%'
!
! EMS_TOTAL(:) = 0d0
! EMS_PERCENT(:,:,:) = 0d0
!
! DO N = 1, NNEMS
!
! ! Note: not in parallel, would need another tmp array for that
! DO J = 1, JJPAR
! DO I = 1, IIPAR
!
! IF ( USA_MASK(I,J) > 0d0 ) THEN
!
! EMS_TOTAL(N) = EMS_TOTAL(N)
! & + TRACER(I,J,N) * GET_AREA_CM2(J)
! ENDIF
!
! ENDDO
! ENDDO
!
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J )
! DO J = 1, JJPAR
! DO I = 1, IIPAR
!
! IF ( EMS_TOTAL(N) == 0d0 .or.
! & USA_MASK(I,J) == 0d0 ) THEN
!
! ! Not sure what to store as "actual emission" for lightning NOx
! EMS_PERCENT(I,J,N) = 0d0
!
! ELSE
!
! ! emissions percentages
! EMS_PERCENT(I,J,N) = TRACER(I,J,N) * GET_AREA_CM2(J)
! & / EMS_TOTAL(N) * 100d0
!
! ENDIF
!
!
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
! & HALFPOLAR, CENTER180, CATEGORY, 50+N+NNEMS,
! & UNIT, GET_TAU(), GET_TAU(), RESERVED,
! & IIPAR, JJPAR, 1, I0+1,
! & J0+1, 1, EMS_PERCENT(:,:,N) )
!
! ! dkh debug
! print*, 'EMS_PERCENT total = ', SUM(EMS_PERCENT(:,:,N)), N
!
! ENDDO
!
! !NOFFSET = 0
!
! ! VOC emissions -- anth hydrocarbons (EMISRR)
! CATEGORY = 'EMISRR'
! print*, 'make_ics db: nemis = ', NEMIS(NCS)
! DO N = 1, NEMIS(NCS)
!
! ! Compile TRACER [ molec / cm2 / s ]
! ! Get the actual emission in the current cell
! ! Original emissions are in EMS_orig, but in a variety of unit
!
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J )
! DO J = 1, JJPAR
! DO I = 1, IIPAR
!
! ! molec C / box / s total sim -> molec C / cm2 / s
! TRACER_VOC(I,J,N) = EMISRR_orig(I,J,N)
! & / GET_AREA_CM2(J)
! & / NEMIS_DT
!
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
! & HALFPOLAR, CENTER180, CATEGORY, N,
! & UNIT, GET_TAU(), GET_TAU(), RESERVED,
! & IIPAR, JJPAR, 1, I0+1,
! & J0+1, 1, TRACER_VOC(:,:,N) )
!
! ! dkh debug
! print*, 'max EMISRR = ', MAXVAL(EMISRR_orig(:,:,N)), N
!
! ENDDO
!
! ! VOC emissions -- biogenic hydrocarbons (EMISRRB)
! CATEGORY = 'EMISRRB'
! DO N = 1, NEMIS(NCS)
!
! ! Compile TRACER [ molec / cm2 / s ]
! ! Get the actual emission in the current cell
! ! Original emissions are in EMS_orig, but in a variety of unit
!
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J )
! DO J = 1, JJPAR
! DO I = 1, IIPAR
!
! ! molec C / box / s total sim -> molec C / cm2 / s
! TRACER_VOC(I,J,N) = EMISRRB_orig(I,J,N)
! & / GET_AREA_CM2(J)
! & / NEMIS_DT
!
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
! & HALFPOLAR, CENTER180, CATEGORY, N,
! & UNIT, GET_TAU(), GET_TAU(), RESERVED,
! & IIPAR, JJPAR, 1, I0+1,
! & J0+1, 1, TRACER_VOC(:,:,N) )
!
! ! dkh debug
! print*, 'max EMISRRB = ', MAXVAL(EMISRRB_orig(:,:,N)), N
!
! ENDDO
! !NOFFSET = NOFFSET + NEMIS(NCS)
!
! ! VOC emissions - BIOFUEL
! CATEGORY = 'BIOFUEL'
! DO N = 1, NBFTRACE
!
! ! Compile TRACER [ molec / cm2 / s ]
! ! Get the actual emission in the current cell
! ! Original emissions are in EMS_orig, but in a variety of unit
!
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J )
! DO J = 1, JJPAR
! DO I = 1, IIPAR
!
! ! molec C / cm3 / s total sim -> molec C / cm2 / s
! TRACER_VOC(I,J,N) = BIOFUEL_orig(N,I,J)
! & * BXHEIGHT(I,J,1) * 100d0
! & / NEMIS_DT
!
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
! & HALFPOLAR, CENTER180, CATEGORY, N,
! & UNIT, GET_TAU(), GET_TAU(), RESERVED,
! & IIPAR, JJPAR, 1, I0+1,
! & J0+1, 1, TRACER_VOC(:,:,N) )
!
! ! dkh debug
! print*, 'max BIOFUEL = ', MAXVAL(BIOFUEL_orig(N,:,:)), N
!
! ENDDO
!
! !NOFFSET = NOFFSET + NBFTRACE
!
! ! VOC emissions - BURNEMIS
! CATEGORY = 'BURNEMIS'
! DO N = 1, NBIOTRCE
!
! ! Compile TRACER [ molec / cm2 / s ]
! ! Get the actual emission in the current cell
! ! Original emissions are in EMS_orig, but in a variety of unit
!
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J )
! DO J = 1, JJPAR
! DO I = 1, IIPAR
!
! ! molec C / cm3 / s total sim -> molec C / cm2 / s
! TRACER_VOC(I,J,N) = BURNEMIS_orig(N,I,J)
! & * BXHEIGHT(I,J,1) * 100d0
! & / NEMIS_DT
!
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
! & HALFPOLAR, CENTER180, CATEGORY, N,
! & UNIT, GET_TAU(), GET_TAU(), RESERVED,
! & IIPAR, JJPAR, 1, I0+1,
! & J0+1, 1, TRACER_VOC(:,:,N) )
!
! ! dkh debug
! print*, 'max BURNEMIS= ', MAXVAL(BURNEMIS_orig(N,:,:)), N
!
! ENDDO
!
! ENDIF
!
! ! Close file
! CLOSE( IU_RST )
!
! IF ( LPRINT_TOTAL ) THEN
! ! print out scaled emissions totals
! CALL READ_USA_MASK( USA_MASK )
!
! ! Tracer is now going to be in units of Tg X / yr / box
! TRACER =0d0
! TRACER_US=0d0
!
! IF ( NNEMS > LLPAR ) CALL ERROR_STOP('baddd','inverse_mod')
!
! DO N = 1, NNEMS
!
! ! Units of emission for NOx from EMISRN are different
! ! Units of carbon emission also different. Skip em
!
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J )
! DO J = 1, JJPAR
! DO I = 1, IIPAR
!
! ! Get the actual emission in the current cell
!
! ! lightning NOx
! IF ( N == IDADJEMS_ENOxli ) THEN
! IF ( LLIGHTNOX ) THEN
!
! ! molec NOx / cm2 / s -> Tg N / yr
! TRACER(I,J,N) = EMS_orig_li(I,J)
! & / NEMIS_DT ! number of emissions
! & * SEC_PER_YEAR ! s/yr
! & * GET_AREA_CM2(J) ! cm^2
! & / XNUMOL(IDTNOX) ! molec / kg of NO2
! & * TG_PER_KG ! Tg / kg
! & * 14.d0 / 46.d0 ! g N / g NO2
!
! TRACER_US(I,J,N) = TRACER(I,J,N) * USA_MASK(I,J)
! ELSE
! TRACER(I,J,N) = 0d0
! TRACER_US(I,J,N) = 0d0
! ENDIF
!
! ! soil NOx
! ELSEIF ( N == IDADJEMS_ENOxso ) THEN
!
! ! Not sure what to store as "actual emission" for soil NOx
! !TRACER(I,J,N) = 0d0
! ! molec NOx / cm2 / s total -> Tg N / yr
! TRACER(I,J,N) = EMS_orig(I,J,N)
! & / NEMIS_DT
! & * SEC_PER_YEAR ! s/yr
! & * GET_AREA_CM2(J) ! cm^2
! & / XNUMOL(IDTNOX) ! molec / g of NO2
! & * TG_PER_KG ! Tg / kg
! & * 14.d0 / 46.d0 ! g N / g NO2
!
! TRACER_US(I,J,N) = TRACER(I,J,N) * USA_MASK(I,J)
!
!
! ! BC / OC
! ELSEIF ( N == IDADJEMS_BCan .or. N == IDADJEMS_OCan .or.
! & N == IDADJEMS_BCbb .or. N == IDADJEMS_OCbb .or.
! & N == IDADJEMS_BCbf .or. N == IDADJEMS_OCbf )
! & THEN
!
! ! Convert from kg C / yr to Tg C / year
! TRACER(I,J,N) = EMS_orig(I,J,N) * TG_PER_KG
! TRACER_US(I,J,N) = EMS_orig(I,J,N) * TG_PER_KG
! & * USA_MASK(I,J)
!
! ! Anth NOx
! ELSEIF ( N == IDADJEMS_ENOx1 .or. N == IDADJEMS_ENOx2 )
! & THEN
!
! ! Convert from kg NOx / emdt to Tg N / year
! TRACER(I,J,N) = EMS_orig(I,J,N) * TG_PER_KG
! & * MIN_PER_YEAR / GET_TS_EMIS()
! & * 14d0 / 46d0
! TRACER_US(I,J,N) = EMS_orig(I,J,N) * TG_PER_KG
! & * MIN_PER_YEAR / GET_TS_EMIS()
! & * 14d0 / 46d0
! & * USA_MASK(I,J)
!
! ! SO2
! ELSEIF ( N == IDADJEMS_ESO2_bb .or.
! & N == IDADJEMS_ESO2_bf .or.
! & N == IDADJEMS_ESO2_sh )
!
! & THEN
!
! ! Convert from kg SO2 / box / s to Tg S / year
! TRACER(I,J,N) = EMS_orig(I,J,N)
! & * SEC_PER_YEAR * TG_PER_KG
! & * 0.5d0
! TRACER_US(I,J,N) = EMS_orig(I,J,N)
! & * SEC_PER_YEAR * TG_PER_KG
! & * 0.5d0 * USA_MASK(I,J)
!
! ! Volcano SO2 emissions (dkh, cklee 09/14/08)
! ELSEIF ( N == IDADJEMS_ESO2_ev .or.
! & N == IDADJEMS_ESO2_nv )
! & THEN
! ! Convert from kg SO2 / box / s total to Tg S / year
! TRACER(I,J,N) = EMS_orig(I,J,N)
! & * SEC_PER_YEAR * TG_PER_KG
! & * 0.5d0
! & / NEMIS_DT
! TRACER_US(I,J,N) = EMS_orig(I,J,N)
! & * SEC_PER_YEAR * TG_PER_KG
! & * 0.5d0 * USA_MASK(I,J)
! & / NEMIS_DT
!
! ! NH3
! ELSEIF ( N == IDADJEMS_ENH3_an .or.
! & N == IDADJEMS_ENH3_na .or.
! & N == IDADJEMS_ENH3_bb .or.
! & N == IDADJEMS_ENH3_bf )
! & THEN
!
! ! Convert from kg NH3 / box / s to Tg N / year
! TRACER(I,J,N) = EMS_orig(I,J,N)
! & * SEC_PER_YEAR * TG_PER_KG
! & * 14d0 / 17d0
! TRACER_US(I,J,N) = EMS_orig(I,J,N)
! & * SEC_PER_YEAR * TG_PER_KG
! & * 14d0 / 17d0
! & * USA_MASK(I,J)
!
! ! Anth SOx
! ELSEIF ( N == IDADJEMS_ESOx1 .or.
! & N == IDADJEMS_ESOx2 )
! & THEN
!
! ! Convert from molec SOx / cm2 / s to Tg S / year
! TRACER(I,J,N) = EMS_orig(I,J,N) * GET_AREA_CM2(J)
! & / XNUMOL(IDTSO2)
! & * SEC_PER_YEAR * TG_PER_KG
! & * 0.5d0
! TRACER_US(I,J,N) = EMS_orig(I,J,N) * GET_AREA_CM2(J)
! & / XNUMOL(IDTSO2)
! & * SEC_PER_YEAR * TG_PER_KG
! & * 0.5d0
! & * USA_MASK(I,J)
!
! ELSE
!
! CALL ERROR_STOP('undefined emissions',
! & 'inverse_mod.f')
!
! ENDIF
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! ENDDO
!
! print*, 'PRIOR EMISSIONS'
! print*, 'TOTAL SOx1 [Tg S/y] = ', SUM(TRACER(:,:,1))
! print*, 'TOTAL SOx2 [Tg S/y] = ', SUM(TRACER(:,:,2))
! print*, 'TOTAL SO2_sh [Tg S/y] = ', SUM(TRACER(:,:,3))
! print*, 'TOTAL SO2_bb [Tg S/y] = ', SUM(TRACER(:,:,4))
! print*, 'TOTAL SO2_bf [Tg S/y] = ', SUM(TRACER(:,:,5))
! print*, 'TOTAL NH3_bb [Tg N/y] = ', SUM(TRACER(:,:,6))
! print*, 'TOTAL NH3_bf [Tg N/y] = ', SUM(TRACER(:,:,7))
! print*, 'TOTAL NH3_an [Tg N/y] = ', SUM(TRACER(:,:,8))
! print*, 'TOTAL NH3_na [Tg N/y] = ', SUM(TRACER(:,:,9))
! print*, 'TOTAL BCan [Tg C/y] = ', SUM(TRACER(:,:,10))
! print*, 'TOTAL OCan [Tg C/y] = ', SUM(TRACER(:,:,11))
! print*, 'TOTAL BCbf [Tg C/y] = ', SUM(TRACER(:,:,12))
! print*, 'TOTAL OCbf [Tg C/y] = ', SUM(TRACER(:,:,13))
! print*, 'TOTAL BCbb [Tg C/y] = ', SUM(TRACER(:,:,14))
! print*, 'TOTAL OCbb [Tg C/y] = ', SUM(TRACER(:,:,15))
! print*, 'TOTAL NOx1 [Tg N/y] = ', SUM(TRACER(:,:,16))
! print*, 'TOTAL NOx2 [Tg N/y] = ', SUM(TRACER(:,:,17))
! print*, 'TOTAL NOx_li [Tg N/y] = ', SUM(TRACER(:,:,18))
! print*, 'TOTAL NOx_so [Tg N/y] = ', SUM(TRACER(:,:,19))
! print*, 'TOTAL SO2_ev [Tg S/y] = ', SUM(TRACER(:,:,20))
! print*, 'TOTAL SO2_nv [Tg S/y] = ', SUM(TRACER(:,:,21))
! print*, 'TOTAL US SOx1 [Tg S/y] = ', SUM(TRACER_US(:,:,1))
! print*, 'TOTAL US SOx2 [Tg S/y] = ', SUM(TRACER_US(:,:,2))
! print*, 'TOTAL US SO2_sh [Tg S/y] = ', SUM(TRACER_US(:,:,3))
! print*, 'TOTAL US SO2_bb [Tg S/y] = ', SUM(TRACER_US(:,:,4))
! print*, 'TOTAL US SO2_bf [Tg S/y] = ', SUM(TRACER_US(:,:,5))
! print*, 'TOTAL US NH3_bb [Tg N/y] = ', SUM(TRACER_US(:,:,6))
! print*, 'TOTAL US NH3_bf [Tg N/y] = ', SUM(TRACER_US(:,:,7))
! print*, 'TOTAL US NH3_an [Tg N/y] = ', SUM(TRACER_US(:,:,8))
! print*, 'TOTAL US NH3_na [Tg N/y] = ', SUM(TRACER_US(:,:,9))
! print*, 'TOTAL US BCan [Tg C/y] = ', SUM(TRACER_US(:,:,10))
! print*, 'TOTAL US OCan [Tg C/y] = ', SUM(TRACER_US(:,:,11))
! print*, 'TOTAL US BCbf [Tg C/y] = ', SUM(TRACER_US(:,:,12))
! print*, 'TOTAL US OCbf [Tg C/y] = ', SUM(TRACER_US(:,:,13))
! print*, 'TOTAL US BCbb [Tg C/y] = ', SUM(TRACER_US(:,:,14))
! print*, 'TOTAL US OCbb [Tg C/y] = ', SUM(TRACER_US(:,:,15))
! print*, 'TOTAL US NOx1 [Tg N/y] = ', SUM(TRACER_US(:,:,16))
! print*, 'TOTAL US NOx2 [Tg N/y] = ', SUM(TRACER_US(:,:,17))
! print*, 'TOTAL US NOx_li [Tg N/y] = ', SUM(TRACER_US(:,:,18))
! print*, 'TOTAL US NOx_so [Tg N/y] = ', SUM(TRACER_US(:,:,19))
! print*, 'TOTAL US SO2_ev [Tg N/y] = ', SUM(TRACER_US(:,:,20))
! print*, 'TOTAL US SO2_nv [Tg N/y] = ', SUM(TRACER_US(:,:,21))
!
!
! DO N = 1, NNEMS
!
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J )
! DO J = 1, JJPAR
! DO I = 1, IIPAR
!#if defined ( LOG_OPT )
! ! Apply current scaling
! TRACER(I,J,N) = TRACER(I,J,N) * EXP(EMS_ICS(I,J,1,N))
! TRACER_US(I,J,N) = TRACER_US(I,J,N)
! & * EXP(EMS_ICS(I,J,1,N))
!
!#else
! ! Apply current scaling
! TRACER(I,J,N) = TRACER(I,J,N) * EMS_ICS(I,J,1,N)
! TRACER_US(I,J,N) = TRACER_US(I,J,N) * EMS_ICS(I,J,1,N)
!#endif
!
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! ENDDO
!
! print*, 'POSTERIOR EMISSIONS'
! print*, 'TOTAL SOx1 [Tg S/y] = ', SUM(TRACER(:,:,1))
! print*, 'TOTAL SOx2 [Tg S/y] = ', SUM(TRACER(:,:,2))
! print*, 'TOTAL SO2_sh [Tg S/y] = ', SUM(TRACER(:,:,3))
! print*, 'TOTAL SO2_bb [Tg S/y] = ', SUM(TRACER(:,:,4))
! print*, 'TOTAL SO2_bf [Tg S/y] = ', SUM(TRACER(:,:,5))
! print*, 'TOTAL NH3_bb [Tg N/y] = ', SUM(TRACER(:,:,6))
! print*, 'TOTAL NH3_bf [Tg N/y] = ', SUM(TRACER(:,:,7))
! print*, 'TOTAL NH3_an [Tg N/y] = ', SUM(TRACER(:,:,8))
! print*, 'TOTAL NH3_na [Tg N/y] = ', SUM(TRACER(:,:,9))
! print*, 'TOTAL BCan [Tg C/y] = ', SUM(TRACER(:,:,10))
! print*, 'TOTAL OCan [Tg C/y] = ', SUM(TRACER(:,:,11))
! print*, 'TOTAL BCbf [Tg C/y] = ', SUM(TRACER(:,:,12))
! print*, 'TOTAL OCbf [Tg C/y] = ', SUM(TRACER(:,:,13))
! print*, 'TOTAL BCbb [Tg C/y] = ', SUM(TRACER(:,:,14))
! print*, 'TOTAL OCbb [Tg C/y] = ', SUM(TRACER(:,:,15))
! print*, 'TOTAL NOx1 [Tg N/y] = ', SUM(TRACER(:,:,16))
! print*, 'TOTAL NOx2 [Tg N/y] = ', SUM(TRACER(:,:,17))
! print*, 'TOTAL NOx_li [Tg N/y] = ', SUM(TRACER(:,:,18))
! print*, 'TOTAL NOx_so [Tg N/y] = ', SUM(TRACER(:,:,19))
! print*, 'TOTAL SO2_ev [Tg S/y] = ', SUM(TRACER(:,:,20))
! print*, 'TOTAL SO2_nv [Tg S/y] = ', SUM(TRACER(:,:,21))
! print*, 'TOTAL US SOx1 [Tg S/y] = ', SUM(TRACER_US(:,:,1))
! print*, 'TOTAL US SOx2 [Tg S/y] = ', SUM(TRACER_US(:,:,2))
! print*, 'TOTAL US SO2_sh [Tg S/y] = ', SUM(TRACER_US(:,:,3))
! print*, 'TOTAL US SO2_bb [Tg S/y] = ', SUM(TRACER_US(:,:,4))
! print*, 'TOTAL US SO2_bf [Tg S/y] = ', SUM(TRACER_US(:,:,5))
! print*, 'TOTAL US NH3_bb [Tg N/y] = ', SUM(TRACER_US(:,:,6))
! print*, 'TOTAL US NH3_bf [Tg N/y] = ', SUM(TRACER_US(:,:,7))
! print*, 'TOTAL US NH3_an [Tg N/y] = ', SUM(TRACER_US(:,:,8))
! print*, 'TOTAL US NH3_na [Tg N/y] = ', SUM(TRACER_US(:,:,9))
! print*, 'TOTAL US BCan [Tg C/y] = ', SUM(TRACER_US(:,:,10))
! print*, 'TOTAL US OCan [Tg C/y] = ', SUM(TRACER_US(:,:,11))
! print*, 'TOTAL US BCbf [Tg C/y] = ', SUM(TRACER_US(:,:,12))
! print*, 'TOTAL US OCbf [Tg C/y] = ', SUM(TRACER_US(:,:,13))
! print*, 'TOTAL US BCbb [Tg C/y] = ', SUM(TRACER_US(:,:,14))
! print*, 'TOTAL US OCbb [Tg C/y] = ', SUM(TRACER_US(:,:,15))
! print*, 'TOTAL US NOx1 [Tg N/y] = ', SUM(TRACER_US(:,:,16))
! print*, 'TOTAL US NOx2 [Tg N/y] = ', SUM(TRACER_US(:,:,17))
! print*, 'TOTAL US NOx_li [Tg N/y] = ', SUM(TRACER_US(:,:,18))
! print*, 'TOTAL US NOx_so [Tg N/y] = ', SUM(TRACER_US(:,:,19))
! print*, 'TOTAL US SO2_ev [Tg N/y] = ', SUM(TRACER_US(:,:,20))
! print*, 'TOTAL US SO2_nv [Tg N/y] = ', SUM(TRACER_US(:,:,21))
!
!
! ENDIF
!
!
! !### Debug
!
! IF ( LPRT ) CALL DEBUG_MSG( '### MAKE_SF_DIAG_FILE: wrote file' )
!
! ! Return to calling program
! END SUBROUTINE MAKE_SF_DIAG_FILE
!
!!------------------------------------------------------------------------------
!
SUBROUTINE READ_SF_FILE ( )
!
!******************************************************************************
! Subroutine READ_SF_FILE reads the gctm.sf.* file into ICS_SF or EMS_SF
! (dkh, 9/17/04)
!
! Module Variable as Input:
! ============================================================================
! (1 ) N_CALC : Current iteration number
!
! Notes
! (1 ) Add support for ACTIVE_VARS == 'EMISSIONS' case (dkh, 11/27/04)
! (2 ) Add support for ACTIVE_VARS == 'FDTEST' case (dkh, 02/17/05)
! (3 ) Now use CATEGORY = 'IJ-EMS-$' for ACTIVE_VARS == 'EMISSIONS' case.
! (dkh, 03/28/05)
! (4 ) Change name from ICS to SF, replace CMN_ADJ (dkh, ks, mak, cs 06/08/09)
! (5 ) Now support strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
!******************************************************************************
!
! References to F90 modules
USE ADJ_ARRAYS_MOD, ONLY : EMS_SF, ICS_SF
USE ADJ_ARRAYS_MOD, ONLY : N_CALC
USE ADJ_ARRAYS_MOD, ONLY : NNEMS, MMSCL
USE ADJ_ARRAYS_MOD, ONLY : EXPAND_NAME
USE ADJ_ARRAYS_MOD, ONLY : PROD_SF, LOSS_SF
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF
USE ADJ_ARRAYS_MOD, ONLY : NSTPL, NRRATES
USE BPCH2_MOD, ONLY : OPEN_BPCH2_FOR_READ
USE DIRECTORY_ADJ_MOD, ONLY : OPTDATA_DIR
USE ERROR_MOD, ONLY : DEBUG_MSG, ERROR_STOP
USE FILE_MOD, ONLY : IU_RST, IOERROR
USE LOGICAL_ADJ_MOD, ONLY : LICS, LADJ_EMS
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT, LADJ_RRATE
USE LOGICAL_MOD, ONLY : LPRT
USE RESTART_MOD, ONLY : CHECK_DIMENSIONS
USE TIME_MOD, ONLY : EXPAND_DATE
USE TRACER_MOD, ONLY : N_TRACERS
# include "CMN_SIZE" ! Size parameters
# include "CMN" ! LPRT
! Local Variables
INTEGER :: I, IOS, J, L, M, N
REAL*4 :: TRACER(IIPAR,JJPAR,LLPAR)
REAL*8 :: SUMTC
CHARACTER(LEN=255) :: FILENAME
! For binary punch file, version 2.0
INTEGER :: NI, NJ, NL
INTEGER :: IFIRST, JFIRST, LFIRST
INTEGER :: NTRACER, NSKIP
INTEGER :: HALFPOLAR, CENTER180
REAL*4 :: LONRES, LATRES
REAL*8 :: ZTAU0, ZTAU1
CHARACTER(LEN=20) :: MODELNAME
CHARACTER(LEN=40) :: CATEGORY
CHARACTER(LEN=40) :: UNIT
CHARACTER(LEN=40) :: RESERVED
CHARACTER(LEN=20) :: INPUT_SF_FILE
!=================================================================
! READ_SF_FILE begins here!
!=================================================================
! Hardwire output file for now
INPUT_SF_FILE = 'gctm.sf.NN'
! Initialize some variables
TRACER(:,:,:) = 0e0
!=================================================================
! Open SF file and read top-of-file header
!=================================================================
! Copy input file name to a local variable
FILENAME = TRIM( INPUT_SF_FILE )
! Replace NN token w/ actual value
CALL EXPAND_NAME( FILENAME, N_CALC )
! Add OPTDATA_DIR prefix to FILENAME
FILENAME = TRIM( OPTDATA_DIR ) // TRIM( FILENAME )
! can hardwire this to read a specific file from another run:
!FILENAME = TRIM( 'opt_ics/ADJv27fi04r10/gctm.ics.16' )
! Echo some input to the screen
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
WRITE( 6, '(a,/)' ) 'S F F I L E I N P U T'
WRITE( 6, 100 ) TRIM( FILENAME )
100 FORMAT( 'READ_SF_FILE: Reading ', a )
! Open the binary punch file for input
CALL OPEN_BPCH2_FOR_READ( IU_RST, FILENAME )
IF ( LICS ) THEN
!=================================================================
! Read initial conditions -- store in the TRACER array
!=================================================================
DO N = 1, N_TRACERS
READ( IU_RST, IOSTAT=IOS )
& MODELNAME, LONRES, LATRES, HALFPOLAR, CENTER180
! IOS < 0 is end-of-file, so exit
IF ( IOS < 0 ) EXIT
! IOS > 0 is a real I/O error -- print error message
IF ( IOS > 0 ) CALL IOERROR( IOS,IU_RST,'read_ics_file:4' )
READ( IU_RST, IOSTAT=IOS )
& CATEGORY, NTRACER, UNIT, ZTAU0, ZTAU1, RESERVED,
& NI, NJ, NL, IFIRST, JFIRST, LFIRST,
& NSKIP
IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_RST,'read_ics_file:5')
READ( IU_RST, IOSTAT=IOS )
& ( ( ( TRACER(I,J,L), I=1,NI ), J=1,NJ ), L=1,NL )
IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_RST,'read_ics_file:6')
!==============================================================
! Assign data from the TRACER array to the xxx_IC array.
!==============================================================
! Only process observation data (i.e. aerosol and precursors)
IF ( CATEGORY(1:8) == 'IJ-ICS-$' ) THEN
! Make sure array dimensions are of global size
! (NI=IIPAR; NJ=JJPAR, NL=LLPAR), or stop the run
CALL CHECK_DIMENSIONS( NI, NJ, NL )
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
ICS_SF (I,J,L,N) = TRACER(I,J,L)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
ENDDO
ENDIF
IF ( LADJ_EMS ) THEN
!=================================================================
! Read emission scale factors -- store in the TRACER array
!=================================================================
DO N = 1, NNEMS
READ( IU_RST, IOSTAT=IOS )
& MODELNAME, LONRES, LATRES, HALFPOLAR, CENTER180
! IOS < 0 is end-of-file, so exit
IF ( IOS < 0 ) EXIT
! IOS > 0 is a real I/O error -- print error message
IF ( IOS > 0 ) CALL IOERROR( IOS,IU_RST,'read_ics_file:4' )
READ( IU_RST, IOSTAT=IOS )
& CATEGORY, NTRACER, UNIT, ZTAU0, ZTAU1, RESERVED,
& NI, NJ, NL, IFIRST, JFIRST, LFIRST,
& NSKIP
IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_RST,'read_ics_file:5')
READ( IU_RST, IOSTAT=IOS )
& ( ( ( TRACER(I,J,L), I=1,NI ), J=1,NJ ), L=1,NL )
IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_RST,'read_ics_file:6')
!==============================================================
! Assign data from the TRACER array to the xxx_IC array.
!==============================================================
! Only process observation data (i.e. aerosol and precursors)
IF ( CATEGORY(1:8) == 'IJ-EMS-$' ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
EMS_SF(I,J,M,N) = TRACER(I,J,M)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
ENDDO
! Strat prod and loss (hml)
IF ( LADJ_STRAT ) THEN
!=================================================================
! Read strat prod & loss scale factors -- store in the TRACER array
!=================================================================
DO N = 1, NSTPL
READ( IU_RST, IOSTAT=IOS )
& MODELNAME, LONRES, LATRES, HALFPOLAR, CENTER180
! IOS < 0 is end-of-file, so exit
IF ( IOS < 0 ) EXIT
! IOS > 0 is a real I/O error -- print error message
IF ( IOS > 0 ) CALL IOERROR( IOS,IU_RST,
& 'read_strat_file:4' )
READ( IU_RST, IOSTAT=IOS )
& CATEGORY, NTRACER, UNIT, ZTAU0, ZTAU1, RESERVED,
& NI, NJ, NL, IFIRST, JFIRST, LFIRST,
& NSKIP
IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_RST,
& 'read_strat_file:5')
READ( IU_RST, IOSTAT=IOS )
& ( ( ( TRACER(I,J,L), I=1,NI ), J=1,NJ ), L=1,NL )
IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_RST,
& 'read_strat_file:6')
!==============================================================
! Assign data from the TRACER array to the xxx_STR array.
!==============================================================
! Only process observation data (i.e. aerosol and precursors)
IF ( CATEGORY(1:8) == 'IJ-STRP$' ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
PROD_SF(I,J,M,N) = TRACER(I,J,M)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
ENDDO
!=================================================================
! Read strat prod & loss scale factors -- store in the TRACER array
!=================================================================
DO N = 1, NSTPL
READ( IU_RST, IOSTAT=IOS )
& MODELNAME, LONRES, LATRES, HALFPOLAR, CENTER180
! IOS < 0 is end-of-file, so exit
IF ( IOS < 0 ) EXIT
! IOS > 0 is a real I/O error -- print error message
IF ( IOS > 0 ) CALL IOERROR( IOS,IU_RST,
& 'read_strat_file:4' )
READ( IU_RST, IOSTAT=IOS )
& CATEGORY, NTRACER, UNIT, ZTAU0, ZTAU1, RESERVED,
& NI, NJ, NL, IFIRST, JFIRST, LFIRST,
& NSKIP
IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_RST,
& 'read_strat_file:5')
READ( IU_RST, IOSTAT=IOS )
& ( ( ( TRACER(I,J,L), I=1,NI ), J=1,NJ ), L=1,NL )
IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_RST,
& 'read_strat_file:6')
IF ( CATEGORY(1:8) == 'IJ-STRL$' ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, M )
DO M = 1, MMSCL
DO J = 1, JJPAR
DO I = 1, IIPAR
LOSS_SF(I,J,M,N) = TRACER(I,J,M)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
ENDDO
ENDIF
IF ( LADJ_RRATE ) THEN
!=================================================================
! Read rxn rate scale factors -- store in the TRACER array
!=================================================================
DO N = 1, NRRATES
READ( IU_RST, IOSTAT=IOS )
& MODELNAME, LONRES, LATRES, HALFPOLAR, CENTER180
! IOS < 0 is end-of-file, so exit
IF ( IOS < 0 ) EXIT
! IOS > 0 is a real I/O error -- print error message
IF ( IOS > 0 ) CALL IOERROR( IOS,IU_RST,
& 'read_sf_file:rate1' )
READ( IU_RST, IOSTAT=IOS )
& CATEGORY, NTRACER, UNIT, ZTAU0, ZTAU1, RESERVED,
& NI, NJ, NL, IFIRST, JFIRST, LFIRST,
& NSKIP
IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_RST,
& 'read_sf_file:rate2' )
READ( IU_RST, IOSTAT=IOS )
& ( ( ( TRACER(I,J,L), I=1,NI ), J=1,NJ ), L=1,NL )
IF ( IOS /= 0 ) CALL IOERROR( IOS,IU_RST,
& 'read_sf_file:rate3' )
IF ( CATEGORY(1:8) == 'IJ-RATSF' ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, LLPAR
DO J = 1, JJPAR
DO I = 1, IIPAR
RATE_SF(I,J,L,N) = TRACER(I,J,L)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF
ENDDO
ENDIF
ENDIF
! Close file
CLOSE( IU_RST )
!### Debug
IF ( LPRT ) CALL DEBUG_MSG( '### READ_SF_FILE: read file' )
! Return to calling program
END SUBROUTINE READ_SF_FILE
!-----------------------------------------------------------------------
SUBROUTINE MAKE_SAT_DIAG_FILE ( type)
!
!******************************************************************************
! Subroutine MAKE_DIAG_FILE creates a binary file of a diagnostic array
! calculated in CALC_ADJ_FORCING in adjoint_mod.f
! (mak, 02/09/06, 2/17/06, zhe 08/29/10)
!
! ============================================================================
! (1 ) MODEL_BIAS
! NOTES:
! (1 ) Just like MAKE_ADJ_FILE except
! - write to .force. file
! (2 ) Add support for ACTIVE_VARS == 'EMISSIONS' case (dkh, 11/27/04)
! (3 ) Add support for ACTIVE_VARS == 'FDTEST' case. (dkh, 02/17/05)
! (4 ) Change UNIT to unitless and change title to Scale factors (dkh, 03/06/05)
! (5 ) Change output for ACTIVE_VARS == 'EMISSIONS' case.
! Now use label IJ-EMS-$, and update gamap code accordingly.
! First write the scaling factors, in consecutive species. Temporal
! varations in the emissions, if any, will be in the L direction.
! Next, write out the optimized emissions themselves.
! Finally, write out the difference between orig and optimized emissions.
! (dkh, 03/28/05)
! (6 ) Use EMS_orig instead of ESO4_an_orig so that we can loop over N.
! (7 ) Move EMS_org declaration to CMN_ADJ, (mak)
! (8 ) Updated to v8, adj_group, 6/09/09, (mak, 6/22/09)
! (9 ) Bug fixed, the flog SDFLAG is added, zhe 8/29/10
! (10) Update MOPITT obs operators (zhe, 1/19/11)
!******************************************************************************
!
! References to F90 modules
USE BPCH2_MOD
USE ERROR_MOD, ONLY : DEBUG_MSG, ERROR_STOP
USE FILE_MOD, ONLY : IU_RST, IOERROR
USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET
USE TIME_MOD, ONLY : EXPAND_DATE, GET_TAU, GET_CT_EMIS
USE ADJ_ARRAYS_MOD, ONLY : GET_MODEL_BIAS, GET_FORCING,
& GET_MODEL, GET_OBS, COST_ARRAY,
& COST_ARRAY, GET_DOFS,
& OBS_COUNT, GET_EMS_ORIG,
& N_CALC, SAT, DAYS, MMSCL
USE ADJ_ARRAYS_MOD, ONLY : EXPAND_NAME
#if defined ( MOPITT_V5_CO_OBS) || defined (MOPITT_V6_CO_OBS )
USE MOPITT_OBS_MOD, ONLY : OBS_HOUR_MOPITT !(zhe 1/19/11)
#endif
#if defined(AIRS_CO_OBS)
USE AIRS_CO_OBS_MOD, ONLY : OBS_HOUR_AIRS_CO
#endif
USE DIRECTORY_ADJ_MOD, ONLY : DIAGADJ_DIR
USE LOGICAL_MOD, ONLY : LPRT
USE LOGICAL_ADJ_MOD, ONLY : LHMOD, LHOBS, LMODBIAS, LOBS_COUNT,
& LDOFS
# include "CMN_SIZE" ! Size parameters
# include "CMN_DIAG" ! TRCOFFSET, TINDEX
! Arguments
integer, intent(in) :: type ! type of diag file
INTEGER :: NN
! Local Variables
INTEGER :: I, I0, IOS, J, J0, L, M, N,H,s
REAL*4 :: TRACER(IIPAR,JJPAR,DAYS,sat)
REAL*4, ALLOCATABLE :: TRACER_EMS(:,:,:)
REAL*4, ALLOCATABLE :: TRACER_COST(:,:,:)
CHARACTER(LEN=255) :: FILENAME
! For binary punch file, version 2.0
REAL*4 :: LONRES, LATRES
INTEGER, PARAMETER :: HALFPOLAR = 1
INTEGER, PARAMETER :: CENTER180 = 1
CHARACTER(LEN=20) :: OUTPUT_ICS_FILE
CHARACTER(LEN=20) :: MODELNAME
CHARACTER(LEN=40) :: RESERVED = ''
CHARACTER(LEN=80) :: TITLE
LOGICAL :: SDFLAG
! INPUTS:
CHARACTER(LEN=40) :: CATEGORY
CHARACTER(LEN=40) :: UNIT
!=================================================================
! MAKE_SAT_DIAG_FILE begins here!
!=================================================================
SDFLAG = .FALSE.
! Hardwire output file for now
IF( TYPE == 1 .AND. LHMOD ) THEN
OUTPUT_ICS_FILE = 'gctm.model.NN'
UNIT = 'molec/cm2'
CATEGORY = 'IJ-AVG-$'
SDFLAG = .TRUE.
ELSEIF( TYPE == 2 .AND. LHOBS ) THEN
OUTPUT_ICS_FILE = 'gctm.obs.NN'
UNIT = 'molec/cm2'
CATEGORY = 'IJ-AVG-$'
TITLE = 'GEOS-CHEM observation file: '
SDFLAG = .TRUE.
ELSEIF( TYPE ==3 .AND. LMODBIAS ) THEN
OUTPUT_ICS_FILE = 'gctm.modelbias.NN'
UNIT = '%'
CATEGORY = 'IJ-AVG-$'
TITLE = 'GEOS-CHEM model bias File: ' //
& 'model - obs bias'
SDFLAG = .TRUE.
c$$$ IF( type == 4 ) THEN
c$$$
c$$$ OUTPUT_ICS_FILE = 'gctm.emsorig'
c$$$ TITLE = 'GEOS-CHEM emissions file: '
ELSEIF( TYPE == 5 .AND. LOBS_COUNT ) THEN
OUTPUT_ICS_FILE = 'gctm.costf.NN'
TITLE = 'GEOS-CHEM cost file: '
SDFLAG = .TRUE.
ELSEIF( TYPE == 6 .AND. LDOFS ) THEN
OUTPUT_ICS_FILE = 'gctm.dofs.NN'
TITLE = 'Degrees of Freedom of Signal for sats: '
UNIT = 'unitless'
CATEGORY = 'IJ-DOF-$'
SDFLAG = .TRUE.
! (zhe, dkh, 02/04/11)
ELSEIF( TYPE == 7 ) THEN
OUTPUT_ICS_FILE = 'gctm.forcing.NN'
TITLE = 'Adjoint forcing: '
UNIT = 'unitless'
CATEGORY = 'IJ-AVG-$'
SDFLAG = .TRUE.
ENDIF
IF (SDFLAG) THEN
! zero TRACER array, for clarity
TRACER(:,:,:,:) = 0d0
! Define variables for BINARY PUNCH FILE OUTPUT
! now passed in
LONRES = DISIZE
LATRES = DJSIZE
! Call GET_MODELNAME to return the proper model name for
! the given met data being used (bmy, 6/22/00)
MODELNAME = GET_MODELNAME()
! Get the nested-grid offsets
I0 = GET_XOFFSET( GLOBAL=.TRUE. )
J0 = GET_YOFFSET( GLOBAL=.TRUE. )
!=================================================================
! Open the adjoint file for output -- binary punch format
!=================================================================
! Copy the output observation file name into a local variable
FILENAME = TRIM( OUTPUT_ICS_FILE )
! Replace NN token w/ actual value
CALL EXPAND_NAME( FILENAME, N_CALC )
! Add OPT_DATA_DIR prefix to FILENAME
FILENAME = TRIM( DIAGADJ_DIR ) // TRIM( FILENAME )
WRITE( 6, 100 ) TRIM( FILENAME )
100 FORMAT( ' - MAKE_SAT_DIAG_FILE: Writing ', a )
! Open checkpoint file for output
CALL OPEN_BPCH2_FOR_WRITE( IU_RST, FILENAME, TITLE )
!=================================================================
! Write each observed quantity to the ics file
!=================================================================
!Temporarily store quantities in the TRACER array
! Loop over number of satellites
DO s = 1, sat
IF( TYPE == 1 ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, DAYS
DO J = 1, JJPAR
DO I = 1, IIPAR
! average over all days, add all days in IDL
TRACER(I,J,L,s) = GET_MODEL(I,J,L,s)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ELSEIF( TYPE == 2 ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L)
DO L = 1, DAYS
DO J = 1, JJPAR
DO I = 1, IIPAR
! average over all days, add all days in IDL
TRACER(I,J,L,s) = GET_OBS(I,J,L,s)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
print*, 'obs#:', s
print*, 'min obs:',minval(tracer(:,:,:,s))
print*, 'max obs:',maxval(tracer(:,:,:,s))
ELSEIF( TYPE == 3 ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, DAYS
DO J = 1, JJPAR
DO I = 1, IIPAR
! average over all days, add all days in IDL
TRACER(I,J,L,s) = GET_MODEL_BIAS(I,J,L,s)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
! (zhe, dkh, 02/04/11)
ELSEIF( TYPE == 7 ) THEN
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, DAYS
DO J = 1, JJPAR
DO I = 1, IIPAR
! average over all days, add all days in IDL
TRACER(I,J,L,s) = GET_FORCING(I,J,L)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
ENDIF ! TYPE
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, s,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, DAYS, I0+1,
& J0+1, 1, TRACER(:,:,:,s) )
ENDDO ! s = 1,SAT
IF (TYPE .EQ. 6 ) THEN
DO s = 1, sat
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L )
DO L = 1, DAYS
DO J = 1, JJPAR
DO I = 1, IIPAR
! average over all days, add all days in IDL
TRACER(I,J,L,s) = GET_DOFS(I,J,L,s)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, s,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, DAYS, I0+1,
& J0+1, 1, TRACER(:,:,:,s) )
ENDDO ! s = 1,SAT
ENDIF !TYPE == 6
! Comment for now and later decide if we want it (mak,6/22/09)
c$$$ IF( TYPE == 4 ) THEN
c$$$ ALLOCATE (TRACER_EMS(IIPAR,JJPAR,MMSCL))
c$$$ TRACER_EMS = 0e0
c$$$
c$$$ ! The following taken from ND29
c$$$ UNIT = 'kg/box/h'
c$$$ CATEGORY ='CO--SRCE'
c$$$ NN = TINDEX(29,1)
c$$$
c$$$!$OMP PARALLEL DO
c$$$!$OMP+DEFAULT( SHARED )
c$$$!$OMP+PRIVATE( I, J, M)
c$$$ DO M = 1, MMSCL
c$$$ DO J = 1, JJPAR
c$$$ DO I = 1, IIPAR
c$$$ ! average over all days, add all days in IDL
c$$$ TRACER_EMS(I,J,M) = GET_EMS_ORIG(I,J,M)*EMS_ICS(I,J,M,1)
c$$$ & /DBLE(GET_CT_EMIS() )
c$$$ ENDDO
c$$$ ENDDO
c$$$ ENDDO
c$$$!$OMP END PARALLEL DO
c$$$
c$$$ CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
c$$$ & HALFPOLAR, CENTER180, CATEGORY, NN,
c$$$ & UNIT, GET_TAU(), GET_TAU(), RESERVED,
c$$$ & IIPAR, JJPAR, MMSCL, I0+1,
c$$$ & J0+1, 1, TRACER_EMS )
c$$$
c$$$
c$$$ IF( ALLOCATED( TRACER_EMS ) ) DEALLOCATE(TRACER_EMS)
c$$$
c$$$ ENDIF ! TYPE=4
IF( TYPE == 5 ) THEN
!ALLOCATE (TRACER_COST(IFDSIZE, JFDSIZE, LFDSIZE ))
ALLOCATE (TRACER_COST(IIPAR, JJPAR, DAYS ))
TRACER_COST = 0e0
! The following taken from ND29
UNIT = 'unitless'
CATEGORY ='COSTF'
NN = 8301
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L)
DO L = 1, DAYS !LFDSIZE
DO J = 1, JJPAR !JFDSIZE
DO I = 1, IIPAR !IFDSIZE
! COST_ARRAY
TRACER_COST(I,J,L) = COST_ARRAY(I,J,L)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
!print*, 'min/max of COST_ARRAY going to file:'
!print*, minval(TRACER_COST), maxval(TRACER_COST)
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, NN,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, DAYS, I0+1,
& J0+1, 1, TRACER_COST )
PRINT*, 'FINISHED STORING COSTF'
IF( ALLOCATED( TRACER_COST ) ) DEALLOCATE(TRACER_COST)
ALLOCATE (TRACER_COST(IIPAR,JJPAR,1))
TRACER_COST = 0e0
! The following taken from ND29
UNIT = 'unitless'
CATEGORY ='OBSCT'
NN = 8401
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L)
DO L = 1, 1
DO J = 1, JJPAR
DO I = 1, IIPAR
! OBS_COUNT ARRAY
TRACER_COST(I,J,1) = OBS_COUNT(I,J)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, NN,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, 1, I0+1,
& J0+1, 1, TRACER_COST )
print*, 'finished saving OBSCT, tot obs#:',sum(obs_count)
#if defined (MOPITT_V5_CO_OBS) || defined (MOPITT_V6_CO_OBS)
! store OBS_HOUR, but note that it's only for the last day of sim
CATEGORY ='OBSHR'
NN = 8501
TRACER_COST(:,:,:) = 0e0
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L)
DO L = 1, 1
DO J = 1, JJPAR
DO I = 1, IIPAR
! OBS_COUNT ARRAY
TRACER_COST(I,J,1) = OBS_HOUR_MOPITT(I,J)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, NN,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, 1, I0+1,
& J0+1, 1, TRACER_COST )
PRINT*, 'FINISHED OBS HOUR MOPITT'
#endif
#if defined(AIRS_CO_OBS)
! store OBS_HOUR, but note that it's only for the last day of sim
CATEGORY ='OBSHR'
NN = 8502
TRACER_COST(:,:,:) = 0e0
!$OMP PARALLEL DO
!$OMP+DEFAULT( SHARED )
!$OMP+PRIVATE( I, J, L)
DO L = 1, 1
DO J = 1, JJPAR
DO I = 1, IIPAR
! OBS_COUNT ARRAY
TRACER_COST(I,J,1) = OBS_HOUR_AIRS_CO(I,J)
ENDDO
ENDDO
ENDDO
!$OMP END PARALLEL DO
CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
& HALFPOLAR, CENTER180, CATEGORY, NN,
& UNIT, GET_TAU(), GET_TAU(), RESERVED,
& IIPAR, JJPAR, 1, I0+1,
& J0+1, 1, TRACER_COST )
PRINT*, 'FINISHED storing OBS_HOUR_AIRS_CO'
#endif
IF( ALLOCATED( TRACER_COST ) ) DEALLOCATE(TRACER_COST)
ENDIF ! TYPE=5
! Close file
CLOSE( IU_RST )
!### Debug
IF( LPRT ) CALL DEBUG_MSG( '### MAKE_SAT_DIAG_FILE: wrote file')
ENDIF !SDFLAG
! Return to calling program
END SUBROUTINE MAKE_SAT_DIAG_FILE
!------------------------------------------------------------------------------
! Now move this in adj_arrays_mod.f (dkh, 10/15/09)
!
! SUBROUTINE EXPAND_NAME( FILENAME, N_ITRN )
!!
!!******************************************************************************
!! Subroutine EXPAND_DATE replaces "NN" token within
!! a filename string with the actual values. (bmy, 6/27/02, 12/2/03)
!! (dkh, 9/22/04)
!!
!! Arguments as Input:
!! ============================================================================
!! (1 ) FILENAME (CHARACTER) : Filename with tokens to replace
!! (2 ) N_ITRN (INTEGER ) : Current iteration number
!!
!!
!! Arguments as Output:
!! ============================================================================
!! (1 ) FILENAME (CHARACTER) : Modified filename
!!
!! NOTES:
!! (1 ) Based on EXPAND_DATE
!!
!!******************************************************************************
!!
! ! References to F90 modules
! USE CHARPAK_MOD, ONLY : STRREPL
! USE ERROR_MOD, ONLY : ERROR_STOP
!
!# include "define.h"
!
! ! Arguments
! CHARACTER(LEN=*), INTENT(INOUT) :: FILENAME
! INTEGER, INTENT(IN) :: N_ITRN
!
! ! Local variables
! CHARACTER(LEN=2) :: NN_STR
!
! !=================================================================
! ! EXPAND_NAME begins here!
! !=================================================================
!
!#if defined( LINUX_PGI )
!
! ! Use ENCODE statement for PGI/Linux (bmy, 9/29/03)
! ENCODE( 2, '(i2.2)', NN_STR ) N_ITRN
!
!#else
!
! ! For other platforms, use an F90 internal write (bmy, 9/29/03)
! WRITE( NN_STR, '(i2.2)' ) N_ITRN
!
!#endif
!
! ! Replace NN token w/ actual value
! CALL STRREPL( FILENAME, 'NN', NN_STR )
!
!
! ! Return to calling program
! END SUBROUTINE EXPAND_NAME
!
!!-----------------------------------------------------------------------------
SUBROUTINE DISPLAY_STUFF( LOCATION )
!
!********************************************************************************
! Subroutine DISPLAY_STUFF writes output to the screen during optimization
! (dkh, 11/28/04)
!
! NOTES
! (1 ) Rearragne the structure so that LOCATION is outermost selection, then
! ACTIVE_VARS == xx is subselection. Add support for LOCATION 4 ( final
! iteration ). dkh, 02/17/05
! (2 ) Update to v8 and new interface/var names (mak, 6/19/09)
! (3 ) Now support strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
!
!********************************************************************************
!
! References to f90 modules
USE ERROR_MOD, ONLY : ERROR_STOP
USE ADJ_ARRAYS_MOD, ONLY : COST_FUNC
USE ADJ_ARRAYS_MOD, ONLY : COST_FUNC_SAV
USE ADJ_ARRAYS_MOD, ONLY : FD_DIFF
USE ADJ_ARRAYS_MOD, ONLY : IFD, JFD, MFD, LFD, NFD, EMSFD
USE ADJ_ARRAYS_MOD, ONLY : EMS_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : ICS_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : STT_ADJ_FD
USE ADJ_ARRAYS_MOD, ONLY : N_CALC, N_CALC_STOP
USE ADJ_ARRAYS_MOD, ONLY : ICS_SF, EMS_SF
USE ADJ_ARRAYS_MOD, ONLY : NNEMS, ICSFD
USE ADJ_ARRAYS_MOD, ONLY : STRFD
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF, RATE_SF0
USE ADJ_ARRAYS_MOD, ONLY : RATFD
USE ADJ_ARRAYS_MOD, ONLY : PROD_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : LOSS_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : PROD_SF, LOSS_SF
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : NSTPL, NRRATES
USE LOGICAL_ADJ_MOD, ONLY : LFDTEST, LADJ_EMS, LICS
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT, LADJ_RRATE
USE LOGICAL_ADJ_MOD, ONLY : LFD_SPOT
USE TRACER_MOD, ONLY : N_TRACERS
# include "CMN_SIZE" ! Size params
! Argument
INTEGER :: LOCATION
! Local variables
INTEGER :: I_DUM
INTEGER :: N
REAL*8 :: FINAL_ADJ_GRAD
REAL*8 :: FINAL_FD_GRAD
!============================================================
! DISPLAY_STUFF starts here!
!============================================================
SELECT CASE ( LOCATION )
! Read/Write an iteration
CASE( 1 )
IF ( LICS ) THEN
WRITE(6,*) ' ICS_SF(1,1,1,:) is ', ICS_SF(1,1,1,:)
WRITE(6,*) ' ICS_SF(:,:,1,1) range is ',
& MINVAL(ICS_SF(:,:,1,1) ),
& ' to ', MAXVAL(ICS_SF(:,:,1,1) )
WRITE(6,*) ' ICS_SF(1,1,:,1) range is ',
& MINVAL(ICS_SF(1,1,:,1) ),
& ' to ', MAXVAL(ICS_SF(1,1,:,1) )
ELSEIF( LADJ_EMS ) THEN
! Nothing
ELSEIF( LFDTEST ) THEN
IF (LICS) THEN
WRITE(6,*) ' ICS_SF(FD) is ',ICS_SF(IFD,JFD,LFD,ICSFD)
ENDIF
IF (LADJ_EMS) THEN
WRITE(6,*) ' EMS_SF(FD) is ',EMS_SF(IFD,JFD,LFD,EMSFD)
! Strat prod and loss (hml)
IF (LADJ_STRAT) THEN
WRITE(6,*) ' PROD_SF(FD) is '
& ,PROD_SF(IFD,JFD,LFD,STRFD)
WRITE(6,*) ' LOSS_SF(FD) is '
& ,LOSS_SF(IFD,JFD,LFD,STRFD)
ENDIF
! Reaction rates (tww)
IF (LADJ_RRATE) THEN
WRITE(6,*) ' RATE_SF(FD) is '
& , RATE_SF(IFD,JFD,LFD,RATFD)
ENDIF
ENDIF
ELSE
CALL ERROR_STOP( 'ACTIVE_VARS not defined!',
& 'DISPLAY_STUFF' )
ENDIF
! After loading gradient
CASE( 2 )
IF ( LICS .AND. LADJ_EMS ) THEN
WRITE(6,*) ' ICS_SF(:,:,1,1) range is ',
& MINVAL( ICS_SF(:,:,1,1) ), ' to ',
& MAXVAL( ICS_SF(:,:,1,1) )
WRITE(6,*) ' EMS_SF(:,:,1,1) range is ',
& MINVAL( EMS_SF(:,:,1,1) ), ' to ',
& MAXVAL( EMS_SF(:,:,1,1) )
print*, ' GRADNT range is',
& MINVAL( GRADNT ), ' to ',
& MAXVAL( GRADNT )
ELSEIF ( LFDTEST .AND. LICS ) THEN
! for now, the I_DUM calculation is only supported for LICS,
! not LADJ_EMS (mak, 6/22/09)
I_DUM = IFD + ( IIPAR * ( JFD - 1) )
& + ( IIPAR * JJPAR * ( LFD - 1 ) )
& + ( IIPAR * JJPAR * LLPAR * ( ICSFD - 1 ) )
WRITE(6,*) ' GRADNT(FD) = ', GRADNT(I_DUM)
WRITE(6,*) ' MIN/MAX ICS_SF_ADJ = ',
& MINVAL(ICS_SF_ADJ(:,:,:,:)),
& MAXVAL(ICS_SF_ADJ(:,:,:,:))
ELSEIF ( LFDTEST .AND. LADJ_EMS ) THEN
WRITE(6,*) ' MIN/MAX EMS_SF_ADJ = ',
& MINVAL(EMS_SF_ADJ(:,:,:,:)),
& MAXVAL(EMS_SF_ADJ(:,:,:,:))
! Strat prod and loss (hml)
IF ( LADJ_STRAT ) THEN
WRITE(6,*) ' MIN/MAX PROD_SF_ADJ = ',
& MINVAL(PROD_SF_ADJ(:,:,:,:)),
& MAXVAL(PROD_SF_ADJ(:,:,:,:))
WRITE(6,*) ' MIN/MAX LOSS_SF_ADJ = ',
& MINVAL(LOSS_SF_ADJ(:,:,:,:)),
& MAXVAL(LOSS_SF_ADJ(:,:,:,:))
ENDIF
! Reaction rates (tww)
IF ( LADJ_RRATE ) THEN
WRITE(6,*) ' MIN/MAX RATE_SF_ADJ = ',
& MINVAL(RATE_SF_ADJ(:,:,:,:)),
& MAXVAL(RATE_SF_ADJ(:,:,:,:))
ENDIF
ELSEIF ( LICS ) THEN
! print*, 'gradnt', gradnt(1),
! & gradnt(1+iipar*jjpar*llpar*(1)) ,
! & gradnt(1+iipar*jjpar*llpar*2),
! & gradnt(1+iipar*jjpar*llpar*3)
ELSEIF ( LADJ_EMS ) THEN
WRITE(6,*) ' EMS_SF(:,:,1,1) range is ',
& MINVAL( EMS_SF(:,:,1,1) ), ' to ',
& MAXVAL( EMS_SF(:,:,1,1) )
print*, ' GRADNT range is',
& MINVAL( GRADNT ), ' to ',
& MAXVAL( GRADNT )
! Strat prod and loss (hml)
IF ( LADJ_STRAT ) THEN
WRITE(6,*) ' PROD_SF(:,:,1,1) range is ',
& MINVAL( PROD_SF(:,:,1,1) ), ' to ',
& MAXVAL( PROD_SF(:,:,1,1) )
WRITE(6,*) ' LOSS_SF(:,:,1,1) range is ',
& MINVAL( LOSS_SF(:,:,1,1) ), ' to ',
& MAXVAL( LOSS_SF(:,:,1,1) )
print*, ' PROD_GRADNT range is',
& MINVAL( GRADNT_P ), ' to ',
& MAXVAL( GRADNT_P )
print*, ' LOSS_GRADNT range is',
& MINVAL( GRADNT_L ), ' to ',
& MAXVAL( GRADNT_L )
ENDIF
! Reaction rates (tww)
IF ( LADJ_RRATE ) THEN
WRITE(6,*) ' RATE_SF(:,:,1,1) range is ',
& MINVAL( RATE_SF(:,:,1,1) ), ' to ',
& MAXVAL( RATE_SF(:,:,1,1) )
ENDIF
ELSE
CALL ERROR_STOP( 'ACTIVE VARS not defined!',
& 'DISPLAY_STUFF, inverse_mod.f' )
ENDIF
! For all values of ACTIVE_VARS...
WRITE(6,*) ' cost function', COST_FUNC
IF ( N_CALC > 1 ) THEN
WRITE(6,*) ' local change = ',
& COST_FUNC / COST_FUNC_SAV(N_CALC - 1),
& ' = current / previous '
ENDIF
WRITE(6,*) ' total change so far = ',
& COST_FUNC / COST_FUNC_SAV(1),
& ' = currrent / initial '
! Compute an iteration
CASE( 3 )
WRITE(6,*) ' COMPUTING NEW VALUES FOR N_CALC = ',
& N_CALC
IF( LFDTEST .AND. LICS) THEN
WRITE(6,*) ' COMPUTING NEW VALUES FOR N_CALC = ',
& N_CALC
IF (LICS) THEN
WRITE(6,*) ' CURRENT ICS_SF(FD) IS ',
& ICS_SF(IFD,JFD,LFD,ICSFD)
ENDIF
IF (LADJ_EMS) THEN
WRITE(6,*) ' CURRENT EMS_SF(FD) IS ',
& EMS_SF(IFD,JFD,MFD,EMSFD)
ENDIF
ELSEIF ( LICS ) THEN
WRITE(6,*) ' CURRENT ICS_SF(1,1,1,:) IS ',
& ICS_SF(1,1,1,:)
WRITE(6,*) ' ICS_SF(:,:,1,1) range is ',
& MINVAL(ICS_SF(:,:,1,1) ),
& ' to ', MAXVAL(ICS_SF(:,:,1,1) )
WRITE(6,*) ' ICS_SF(1,1,:,1) range is ',
& MINVAL(ICS_SF(1,1,:,1) ),
& ' to ', MAXVAL(ICS_SF(1,1,:,1) )
WRITE(6,*) ' RANGE OF ICS_SF(:,:,:,:) IS ',
& MINVAL(ICS_SF), ' TO ',
& MAXVAL(ICS_SF)
ELSEIF( LADJ_EMS ) THEN
! Nothing
ELSE
CALL ERROR_STOP( 'ACTIVE VARS not defined!',
& 'DISPLAY_STUFF, inverse_mod.f' )
ENDIF
!After the final iteration
CASE( 4 )
! For all values of ACTIVE_VARS...
WRITE(6,*) 'COST_FUNC = ', COST_FUNC
IF ( COST_FUNC_SAV(1) > 0d0 )
& WRITE(6,*) 'COST_FUNC reduction = ',
& COST_FUNC / COST_FUNC_SAV(1)
! Add gradient diagnostics (dkh, 06/24/09)
IF ( LICS ) THEN
DO N = 1, N_TRACERS
WRITE(6,*) 'MIN ICS_SF_ADJ = ',
& MINVAL(ICS_SF_ADJ(:,:,:,N)), N
WRITE(6,*) 'MAX ICS_SF_ADJ = ',
& MAXVAL(ICS_SF_ADJ(:,:,:,N)), N
ENDDO
ENDIF
IF ( LADJ_EMS ) THEN
DO N = 1, NNEMS
WRITE(6,*) 'MIN EMS_SF_ADJ = ',
& MINVAL(EMS_SF_ADJ(:,:,:,N)), N
WRITE(6,*) 'MAX EMS_SF_ADJ = ',
& MAXVAL(EMS_SF_ADJ(:,:,:,N)), N
ENDDO
! strat prod and loss (hml)
IF ( LADJ_STRAT ) THEN
DO N = 1, NSTPL
WRITE(6,*) 'MIN PROD_SF_ADJ = ',
& MINVAL(PROD_SF_ADJ(:,:,:,N)), N
WRITE(6,*) 'MAX PROD_SF_ADJ = ',
& MAXVAL(PROD_SF_ADJ(:,:,:,N)), N
WRITE(6,*) 'MIN LOSS_SF_ADJ = ',
& MINVAL(LOSS_SF_ADJ(:,:,:,N)), N
WRITE(6,*) 'MAX LOSS_SF_ADJ = ',
& MAXVAL(LOSS_SF_ADJ(:,:,:,N)), N
ENDDO
ENDIF
! reaction rates (tww)
IF ( LADJ_RRATE ) THEN
DO N = 1, NRRATES
WRITE(6,*) 'MIN RATE_SF_ADJ = ',
& MINVAL(RATE_SF_ADJ(:,:,:,N)), N
WRITE(6,*) 'MAX RATE_SF_ADJ = ',
& MAXVAL(RATE_SF_ADJ(:,:,:,N)), N
ENDDO
ENDIF
ENDIF
! Compile statistics from the finite difference test.
! Calculate final gradients after two iterations.
! Now only do this for a SPOT test (dkh, 02/21/11)
!IF ( LFDTEST .AND. N_CALC == 2 ) THEN
IF ( LFD_SPOT .AND. N_CALC == 2 ) THEN
IF ( LADJ_EMS ) THEN
! Determine the gradient calculated using the adjoint method
! as an average of the gradient at FD_PERT [ STT_ADJ_FD(1) ]
! and FD_PERT + FD_DIFF [ STT_ADJ_FD(2) ].
STT_ADJ_FD(2) = EMS_SF_ADJ(IFD,JFD,MFD,EMSFD)
FINAL_ADJ_GRAD = .5d0
& * ( STT_ADJ_FD(1) + STT_ADJ_FD(2) )
ELSEIF ( LICS ) THEN
! Determine the gradient calculated using the adjoint method
! as an average of the gradient at FD_PERT [ STT_ADJ_FD(1) ]
! and FD_PERT + FD_DIFF [ STT_ADJ_FD(2) ].
STT_ADJ_FD(2) = ICS_SF_ADJ(IFD,JFD,LFD,ICSFD)
FINAL_ADJ_GRAD = .5d0
& * ( STT_ADJ_FD(1) + STT_ADJ_FD(2) )
ENDIF
! The finite difference gradient is
! [ J( FD_PERT + FD_DIFF ) - J( FD_PERT ) ] / FD_DIFF
FINAL_FD_GRAD = ( COST_FUNC - COST_FUNC_SAV(1) )
& / ( FD_DIFF )
! Echo results to the screen
WRITE(6,*) ' ADJOINT gradient = ', FINAL_ADJ_GRAD
WRITE(6,*) ' FN DIFF gradient = ', FINAL_FD_GRAD
WRITE(6,*) ' ADJ / FD = ',
& FINAL_ADJ_GRAD / FINAL_FD_GRAD
ENDIF
!
WRITE(6,*) 'FORCE EXIT AFTER ', N_CALC_STOP,' ITERATIONS.'
CASE DEFAULT
! Nothing
!
END SELECT
END SUBROUTINE DISPLAY_STUFF
! needs to be updated
!!----------------------------------------------------------------------
!!
!! SUBROUTINE INIT_REGIONAL_EMS
!!
!!********************************************************************************
!! Subroutine INIT_REGIONAL_EMS initializes spatially dependent emissions factors
!! (dkh, 12/04/04)
!!
!! NOTES
!! (1 ) Updated to add random noise. (dkh, 08/27/06)
!!********************************************************************************
!!
!# include "CMN_SIZE" ! Size params
!
! ! Local variables
! INTEGER :: I, J
! DOUBLE PRECISION :: RAN
!
! !============================================================
! ! INIT_REGIONAL_EMS begins here!
! !============================================================
! WRITE(6,*) ' U S E S P A T I A L L Y V A R I A B L E '
! WRITE(6,*) ' E M I S S I O N S S C A L I N G S F O R '
! WRITE(6,*) ' R E F E R E N C E C A L C U L A T I O N '
!
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J, RAN )
! DO I = 1, IIPAR
! DO J = 1, JJPAR
!
! ! Nor Am
! IF ( I < 28 .AND. J > 28 ) THEN
! EMS_SF(I,J,1,IDADJEMS_ESOx1) = 0.8D0
! EMS_SF(I,J,1,IDADJEMS_ESOx2) = 0.8D0
! EMS_SF(I,J,1,IDADJEMS_ENOx1) = 0.85D0
! EMS_SF(I,J,1,IDADJEMS_ENOx2) = 0.85D0
!
! ! Europe
! ELSEIF ( I > 27 .AND. I < 48 .AND. J > 28 ) THEN
! EMS_SF(I,J,1,IDADJEMS_ESOx1) = 0.7D0
! EMS_SF(I,J,1,IDADJEMS_ESOx2) = 0.7D0
! EMS_SF(I,J,1,IDADJEMS_ENOx1) = 0.95D0
! EMS_SF(I,J,1,IDADJEMS_ENOx2) = 0.95D0
!
! ! Asia / India
! ELSEIF ( I > 47 .AND. J > 20 ) THEN
! EMS_SF(I,J,1,IDADJEMS_ESOx1) = 1.3D0
! EMS_SF(I,J,1,IDADJEMS_ESOx2) = 1.3D0
! EMS_SF(I,J,1,IDADJEMS_ENOx1) = 1.2D0
! EMS_SF(I,J,1,IDADJEMS_ENOx2) = 1.2D0
!
! ! The rest of the Southern Hemisphere
! ELSE
! EMS_SF(I,J,1,IDADJEMS_ESOx1) = 0.75D0
! EMS_SF(I,J,1,IDADJEMS_ESOx2) = 0.75D0
! EMS_SF(I,J,1,IDADJEMS_ENOx1) = 0.77D0
! EMS_SF(I,J,1,IDADJEMS_ENOx2) = 0.77D0
!
! ENDIF
!
! RAN = DRAN(I+J)
!
! ! add a small bit of random variation
! EMS_SF(I,J,1,IDADJEMS_ESOx1) = EMS_SF(I,J,1,IDADJEMS_ESOx1)
! & + RAN / 20
! EMS_SF(I,J,1,IDADJEMS_ESOx2) = EMS_SF(I,J,1,IDADJEMS_ESOx2)
! & + RAN / 20
! EMS_SF(I,J,1,IDADJEMS_ENOx1) = EMS_SF(I,J,1,IDADJEMS_ENOx1) +
! & + RAN / 20
! EMS_SF(I,J,1,IDADJEMS_ENOx2) = EMS_SF(I,J,1,IDADJEMS_ENOx2) +
! & + RAN / 20
!
! ENDDO
! ENDDO
!!OMP END PARALLEL DO
! END SUBROUTINE INIT_REGIONAL_EMS
!!----------------------------------------------------------------------
SUBROUTINE SET_SF_FORFD
!
!*****************************************************************************
! Subroutine SET_SF_FORFD is used to initialize ICS_SF during the second
! iteration to the orginal value + FD_DIFF. dkh, 02/17/05
!
! NOTES:
! (1 ) Add support for 2nd order FD calculation
! (2 ) Add support for FD_GLOB option (dkh, 10/11/08)
! (3 ) Now initialize EMS_SF to FD_BKGRND (dkh, 10/11/08)
! (4 ) Change name to SET_SF_FORFD, replace CMN_ADJ, simplify the definition
! of the FD pert (dkh, ks, mak, cs 06/07/09)
! (5 ) Now support strat fluxes LADJ_STRAT and add flags to avoid accessing
! unallocated arrays (hml, dkh, 02/20/12, adj32_025)
!*****************************************************************************
!
! Reference to f90 modules
USE ADJ_ARRAYS_MOD, ONLY : ICS_SF, ICS_SF0
USE ADJ_ARRAYS_MOD, ONLY : EMS_SF, EMS_SF0
USE ADJ_ARRAYS_MOD, ONLY : IFD,JFD,LFD,NFD
USE ADJ_ARRAYS_MOD, ONLY : PROD_SF, PROD_SF0
USE ADJ_ARRAYS_MOD, ONLY : LOSS_SF, LOSS_SF0
USE ADJ_ARRAYS_MOD, ONLY : MFD, EMSFD
USE ADJ_ARRAYS_MOD, ONLY : FD_DIFF
USE ADJ_ARRAYS_MOD, ONLY : N_CALC
USE ADJ_ARRAYS_MOD, ONLY : ICSFD
USE ADJ_ARRAYS_MOD, ONLY : STRFD
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF, RATE_SF0
USE ADJ_ARRAYS_MOD, ONLY : RATFD
USE LOGICAL_ADJ_MOD, ONLY : LFD_SPOT
USE LOGICAL_ADJ_MOD, ONLY : LFD_GLOB
USE LOGICAL_ADJ_MOD, ONLY : LICS, LADJ_EMS
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT, LADJ_RRATE
# include "CMN_SIZE" ! Size params
!=================================================================
! SET_SF_FORFD begins here!
!=================================================================
ICS_SF(:,:,:,:) = ICS_SF0(:,:,:,:)
IF ( LADJ_EMS ) EMS_SF(:,:,:,:) = EMS_SF0(:,:,:,:)
IF ( LADJ_STRAT ) THEN
PROD_SF(:,:,:,:) = PROD_SF0(:,:,:,:)
LOSS_SF(:,:,:,:) = LOSS_SF0(:,:,:,:)
ENDIF
IF ( LADJ_RRATE ) THEN
RATE_SF(:,:,:,:) = RATE_SF0(:,:,:,:)
ENDIF
! Nudge the scaling factor value only in the FD cell
IF ( LFD_SPOT ) THEN
! for initial conditions :
IF ( LICS ) THEN
IF ( N_CALC == 2 ) THEN
ICS_SF(IFD,JFD,LFD,ICSFD) = ICS_SF(IFD,JFD,LFD,ICSFD)
& + FD_DIFF
ELSEIF ( N_CALC == 3 ) THEN
ICS_SF(IFD,JFD,LFD,ICSFD) = ICS_SF(IFD,JFD,LFD,ICSFD)
& - FD_DIFF
ENDIF
! for boundary conditions :
ELSEIF ( LADJ_EMS ) THEN
! Strat prod and loss (hml)
IF ( .NOT. LADJ_STRAT .AND. .NOT. LADJ_RRATE ) THEN
IF ( N_CALC == 2 ) THEN
EMS_SF(IFD,JFD,MFD,EMSFD) = EMS_SF(IFD,JFD,MFD,EMSFD)
& + FD_DIFF
ELSEIF ( N_CALC == 3 ) THEN
EMS_SF(IFD,JFD,MFD,EMSFD) = EMS_SF(IFD,JFD,MFD,EMSFD)
& - FD_DIFF
ENDIF
ELSEIF ( LADJ_STRAT ) THEN
IF ( N_CALC == 2 ) THEN
LOSS_SF(IFD,JFD,MFD,STRFD) = LOSS_SF(IFD,JFD,MFD,STRFD)
& + FD_DIFF
ELSEIF ( N_CALC == 3 ) THEN
LOSS_SF(IFD,JFD,MFD,STRFD) = LOSS_SF(IFD,JFD,MFD,STRFD)
& - FD_DIFF
ENDIF
! Reaction rates (tww)
ELSEIF ( LADJ_RRATE ) THEN
IF ( N_CALC == 2 ) THEN
RATE_SF(IFD,JFD,LFD,RATFD) = RATE_SF(IFD,JFD,LFD,RATFD)
& + FD_DIFF
ELSEIF ( N_CALC == 3 ) THEN
RATE_SF(IFD,JFD,LFD,RATFD) = RATE_SF(IFD,JFD,LFD,RATFD)
& - FD_DIFF
ENDIF
ENDIF
ENDIF
! Perturb thoughout model domain.
ELSEIF ( LFD_GLOB ) THEN
! for test with no transport:
print*, 'PERTURB GLOBALLY !!!!'
IF ( LICS ) THEN
IF ( N_CALC == 2 ) THEN
ICS_SF(:,:,LFD,ICSFD) = ICS_SF(:,:,LFD,ICSFD) + FD_DIFF
ELSEIF ( N_CALC == 3 ) THEN
ICS_SF(:,:,LFD,ICSFD) = ICS_SF(:,:,LFD,ICSFD) - FD_DIFF
ENDIF
ELSEIF ( LADJ_EMS ) THEN
! Strat prod and loss (hml)
IF ( .NOT. LADJ_STRAT .AND. .NOT. LADJ_RRATE ) THEN
IF ( N_CALC == 2 ) THEN
EMS_SF(:,:,MFD,EMSFD) = EMS_SF(:,:,MFD,EMSFD)
& + FD_DIFF
ELSEIF ( N_CALC == 3 ) THEN
EMS_SF(:,:,MFD,EMSFD) = EMS_SF(:,:,MFD,EMSFD)
& - FD_DIFF
ENDIF
! Make RRATE default when both turned on (hml, 06/08/13)
!ELSEIF ( LADJ_STRAT ) THEN
ELSEIF ( LADJ_STRAT .AND. .NOT. LADJ_RRATE ) THEN
IF ( N_CALC == 2 ) THEN
LOSS_SF(:,:,MFD,STRFD) = LOSS_SF(:,:,MFD,STRFD)
& + FD_DIFF
ELSEIF ( N_CALC == 3 ) THEN
LOSS_SF(:,:,MFD,STRFD) = LOSS_SF(:,:,MFD,STRFD)
& - FD_DIFF
ENDIF
! Reaction rates (tww)
ELSEIF ( LADJ_RRATE ) THEN
IF ( N_CALC == 2 ) THEN
RATE_SF(:,:,LFD,RATFD) = RATE_SF(:,:,LFD,RATFD)
& + FD_DIFF
ELSEIF ( N_CALC == 3 ) THEN
RATE_SF(:,:,LFD,RATFD) = RATE_SF(:,:,LFD,RATFD)
& - FD_DIFF
ENDIF
ENDIF
ENDIF
ENDIF
! Return to calling program
END SUBROUTINE SET_SF_FORFD
!------------------------------------------------------------------------------
SUBROUTINE MAKE_CFN_FILE( )
!
!******************************************************************************
! Subroutine MAKE_CFN_FILE creates a cfn.NN file which stores the current
! iteration number and cost function value. (dkh, 02/13/06)
!
! Module Variable as Input:
! ============================================================================
! (1 ) N_CALC : Current iteration number
!
! Module Variable as Output:
! ============================================================================
! (1 ) COST_FUNC : Current cost function value
!
! NOTES:
!
!******************************************************************************
!
! Reference to f90 modules
USE ADJ_ARRAYS_MOD, ONLY : N_CALC, COST_FUNC
USE ADJ_ARRAYS_MOD, ONLY : EXPAND_NAME
USE DIRECTORY_ADJ_MOD, ONLY : OPTDATA_DIR
USE FILE_MOD, ONLY : IOERROR
# include "CMN_SIZE"
! Local variables
CHARACTER(LEN=80) :: OUTPUT_CFN_FILE
CHARACTER(LEN=120) :: REMOVE_CFN_FILE_CMD
CHARACTER(LEN=80) :: FILENAME
INTEGER :: IOS
!=================================================================
! MAKE_CFN_FILE begins here!
!=================================================================
! Make file name
OUTPUT_CFN_FILE = 'cfn.NN'
! Copy the output observation file name into a local variable
FILENAME = TRIM( OUTPUT_CFN_FILE )
! Append the iteration number suffix to the file name
CALL EXPAND_NAME( FILENAME, N_CALC )
! Add the OPTDATA_DIR prefix to the file name
FILENAME = TRIM( OPTDATA_DIR ) // TRIM( FILENAME )
!=================================================================
! Open the cfn file for output
!=================================================================
WRITE( 6, 100 ) TRIM( FILENAME )
100 FORMAT( ' - MAKE_CFN_FILE: Writing ', a )
! Remove any previous cfn files for the current iteration
REMOVE_CFN_FILE_CMD = 'rm ' // TRIM (FILENAME)
CALL SYSTEM ( TRIM( REMOVE_CFN_FILE_CMD ) )
! Open file for input
OPEN( 65, FILE=TRIM( FILENAME ), STATUS='UNKNOWN',
& IOSTAT=IOS, FORM='FORMATTED', ACCESS='SEQUENTIAL',
& POSITION='APPEND' )
! Error check
IF ( IOS /= 0 ) CALL IOERROR( IOS, 65, 'write_cost_func:1')
! Write iteration number and cost function
WRITE( 65, *) N_CALC, COST_FUNC
! Return to calling program
END SUBROUTINE MAKE_CFN_FILE
!------------------------------------------------------------------------------
SUBROUTINE READ_CFN_FILE( )
!
!******************************************************************************
! Subroutine READ_CFN_FILE reads the value fo the cost function at iteration
! NN from the cfn.NN file. (dkh, 02/13/06)
!
! Module Variable as Input:
! ============================================================================
! (1 ) N_CALC : Current iteration number
!
! Module variable as Output:
! ============================================================================
! (1 ) COST_FUNC : Cost function value
!
! NOTES:
!
!******************************************************************************
!
! Reference to f90 modules
USE ADJ_ARRAYS_MOD, ONLY : COST_FUNC
USE ADJ_ARRAYS_MOD, ONLY : N_CALC
USE ADJ_ARRAYS_MOD, ONLY : EXPAND_NAME
USE DIRECTORY_ADJ_MOD, ONLY : OPTDATA_DIR
USE FILE_MOD, ONLY : IOERROR
USE ERROR_MOD, ONLY : ERROR_STOP
# include "CMN_SIZE"
! Local variables
CHARACTER(LEN=80) :: OUTPUT_CFN_FILE
CHARACTER(LEN=80) :: FILENAME
INTEGER :: N, N_TMP, IOS
REAL*8 :: CFN_TMP, COST_FUNC_check
LOGICAL :: FOUND = .FALSE.
!=================================================================
! READ_CFN_FILE begins here!
!=================================================================
! Make file name
OUTPUT_CFN_FILE = 'cfn.NN'
! Copy the output observation file name into a local variable
FILENAME = TRIM( OUTPUT_CFN_FILE )
! Append the iteration number suffix to the file name
CALL EXPAND_NAME( FILENAME, N_CALC )
! Add the OPTDATA_DIR prefix to the file name
FILENAME = TRIM( OPTDATA_DIR ) // TRIM( FILENAME )
!=================================================================
! Open the cost function file for input
!=================================================================
WRITE( 6, 100 ) TRIM( FILENAME )
100 FORMAT( ' - READ_CFN_FILE: Reading ', a )
! Open file for input -- readonly
OPEN( 65, FILE=TRIM( FILENAME ), STATUS='UNKNOWN',
& IOSTAT=IOS, FORM='FORMATTED', ACCESS='SEQUENTIAL',
& POSITION='REWIND')
! Error check
IF ( IOS /= 0 ) CALL IOERROR( IOS, 65, 'read_cost_func:1')
! Read values in file
READ( 65, *) N_TMP, CFN_TMP
! Check to make sure that we're reading the correct file. If so, update
! COST_FUNC with the value from the file.
IF ( N_TMP == N_CALC) THEN
COST_FUNC = CFN_TMP
FOUND = .TRUE.
ENDIF
! Error check
IF ( .NOT. FOUND ) THEN
CALL ERROR_STOP('Cost function value missing', 'inverse_mod' )
ENDIF
! Return to calling program
END SUBROUTINE READ_CFN_FILE
!------------------------------------------------------------------------------
SUBROUTINE SET_OPT_RANGE( )
!
!******************************************************************************
! Subroutine SET_OPT_RANGE sets the range of the emissions which we
! wish to optimize by setting all others to zero. (dkh, 10/17/06)
!
!
! Module variables as Input:
! ============================================================================
! (1 ) EMS_SF_ADJ : All emissions gradients
! (2 ) ICS_SF_ADJ : All tracer gradients
! (3 ) OPT_THIS_EMS : Logial array of emissions to optimize
! (4 ) OPT_THIS_ICS : Logial array of initial conditions to optimize
!
! Module variables as Output:
! ============================================================================
! (1 ) EMS_SF_ADJ : All emissions gradients
! (2 ) ICS_SF_ADJ : All tracer gradients
!
! NOTES:
! (1 ) Replace CMN_ADJ, update naming, add spatial filter from ks
! (dkh, ks, mak, cs 06/07/09)
! (2 ) Now support strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
!******************************************************************************
!
! Reference to f90 modules
USE ADJ_ARRAYS_MOD, ONLY : ICS_SF_ADJ, EMS_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : NNEMS
USE ADJ_ARRAYS_MOD, ONLY : OPT_THIS_EMS, OPT_THIS_TRACER
USE ADJ_ARRAYS_MOD, ONLY : PROD_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : LOSS_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : OPT_THIS_PROD
USE ADJ_ARRAYS_MOD, ONLY : OPT_THIS_LOSS
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF
USE ADJ_ARRAYS_MOD, ONLY : NSTPL, NRRATES
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT
USE LOGICAL_ADJ_MOD, ONLY : LICS, LADJ_EMS
USE TRACER_MOD, ONLY : N_TRACERS
! added for reaction rates (tww, 05/15/12)
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF_ADJ
USE ADJ_ARRAYS_MOD, ONLY : OPT_THIS_RATE
USE ADJ_ARRAYS_MOD, ONLY : NRRATES, RATFD
USE LOGICAL_ADJ_MOD, ONLY : LADJ_RRATE
# include "CMN_SIZE" ! Size params
! Local variables
INTEGER I, J, M, N
!=================================================================
! SET_OPT_RANGE begins here!
!=================================================================
! dkh debug
print*, ' SET_OPT_RANGE: MIN / MAX ICS_SF_ADJ = ',
& MINVAL(ICS_SF_ADJ), MAXVAL(ICS_SF_ADJ)
IF ( LICS ) THEN
DO N = 1, N_TRACERS
IF ( .not. OPT_THIS_TRACER(N) ) THEN
ICS_SF_ADJ(:,:,:,N) = 0d0
ENDIF
ENDDO
ENDIF
! dkh debug
print*, ' SET_OPT_RANGE 2 : MIN / MAX ICS_SF_ADJ = ',
& MINVAL(ICS_SF_ADJ), MAXVAL(ICS_SF_ADJ)
! Zero the gradients of the species we don't want to optimize
IF ( LADJ_EMS ) THEN
DO N = 1, NNEMS
IF ( .not. OPT_THIS_EMS(N) ) THEN
EMS_SF_ADJ(:,:,:,N) = 0d0
ENDIF
ENDDO
! Strat prod and loss (hml)
IF ( LADJ_STRAT ) THEN
DO N = 1, NSTPL
IF ( .not. OPT_THIS_PROD(N) ) THEN
PROD_SF_ADJ(:,:,:,N) = 0d0
ENDIF
IF ( .not. OPT_THIS_LOSS(N) ) THEN
LOSS_SF_ADJ(:,:,:,N) = 0d0
ENDIF
ENDDO
ENDIF
! reaction rates (tww, 05/15/12)
IF ( LADJ_RRATE ) THEN
! tww debug
print*, ' SET_OPT_RANGE 3 : MIN / MAX RATE_SF_ADJ = ',
& MINVAL(RATE_SF_ADJ), MAXVAL(RATE_SF_ADJ)
print*, 'OPT_THIS_RATE = ', OPT_THIS_RATE(:)
print*, 'RATFD = ', RATFD
DO N = 1, NRRATES
IF ( .not. OPT_THIS_RATE(N) ) THEN
RATE_SF_ADJ(:,:,:,N) = 0d0
ENDIF
ENDDO
! tww debug
print*,' SET_OPT_RANGE 4 : MIN / MAX RATE_SF_ADJ = ',
& MINVAL(RATE_SF_ADJ), MAXVAL(RATE_SF_ADJ)
! tww debug
print*,' SET_OPT_RANGE 5 : MIN / MAX RATE_SF_ADJ(RATFD) = ',
& MINVAL(RATE_SF_ADJ(:,:,:,RATFD)),
& MAXVAL(RATE_SF_ADJ(:,:,:,RATFD))
ENDIF
ENDIF
! ! Only consider gradients in specific spatial range
!
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J, M, N )
! DO N = 1, NNEMS
! DO M = 1, MMSCL
! DO J = 1, JJPAR
! DO I = 1, IIPAR
!
! ! Zero the gradients which we don't
! ! want to optimize
!! IF ( (( I < 42 .and. I > 34 ) .and. ! IN
!! & ( J > 32 .and. J < 39 )) ! EUROPE
!! IF ( (( I > 18 .and. I < 23 ) .and. ! IN
!! & ( J > 30 .and. J < 35 )) ! Eastern US
!! IF ( (( I < 19 .or. I > 22 ) .or. ! not IN
!! & ( J < 31 .or. J > 34 )) ! Eastern US
! IF ( (( I < 12 .or. I > 22 ) .or. ! not IN
! & ( J < 31 .or. J > 34 )) ! US
! & .or.
! & ( .not. OPT_THIS_EMS(N) ) ) THEN
!
! EMS_SF_ADJ(I,J,M,N) = 0d0
!
! ENDIF
!
! ENDDO
! ENDDO
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! old code from ks
!#if defined ( TES_O3_OBS )
!
! ! Zero the gradients above NLEVS
! ICS_FD_ADJ(:,:,NLEVS+1:LLPAR,:) = 0d0
!
! ! Smoothly drive gradients to zero at poles
! IF (NLAT_TO_IGNORE > 0) THEN
!
! DO N = 1, N_TRACERS
! DO L = 1, NLEVS
! DO J = 1, NLAT_TO_IGNORE
! DO I = 1, IIPAR
! TEMP = NLAT_TO_IGNORE - J
! FACTOR = COS( (TEMP / ( NLAT_TO_IGNORE - 1 ) )
! & * ( pi / 2 )**2
! ICS_FD_ADJ(I,J,L,N) = ICS_FD_ADJ(I,J,L,N) * FACTOR
! ENDDO
! ENDDO
! ENDDO
! ENDDO
!
! DO N = 1, N_TRACERS
! DO L = 1, NLEVS
! DO J = JJPAR - NLAT_TO_IGNORE + 1, JJPAR
! DO I = 1,IIPAR
! TEMP = NLAT_TO_IGNORE - J
! FACTOR = COS( (TEMP / ( NLAT_TO_IGNORE - 1 ) )
! & * ( pi / 2 )**2
! ICS_FD_ADJ(I,J,L,N) = ICS_FD_ADJ(I,J,L,N) * FACTOR
! ENDDO
! ENDDO
! ENDDO
! ENDDO
!
! ENDIF
!#endif
! Return to calling program
END SUBROUTINE SET_OPT_RANGE
!------------------------------------------------------------------------------
DOUBLE PRECISION FUNCTION DRAN(K)
C
C RANDOM NUMBER GENERATOR - BASED ON ALGORITHM 266 BY PIKE AND
C HILL (MODIFIED BY HANSSON), COMMUNICATIONS OF THE ACM,
C VOL. 8, NO. 10, OCTOBER 1965.
C
C THE SINGLE PRECISION VERSION OF THIS SUBPROGRAM IS INTENDED
C FOR USE ON COMPUTERS WITH FIXED POINT WORDLENGTH OF AT
C LEAST 29 BITS. IT IS BEST IF THE FLOATING POINT
C SIGNIFICAND HAS AT MOST 29 BITS.
C
C FOLLOWING CODY AND WAITE'S RECOMMENDATION (P .14), WE
C PRODUCE A PAIR OF RANDOM NUMBERS AND USE RAN1 +
C 2**(-29)*RAN2 IN AN ATTEMPT TO GENERATE ABOUT 58 RANDOM BITS.
C
INTEGER IY,J,K
DATA IY /100001/
C
J = K
IY = IY * 125
IY = IY - (IY/2796203) * 2796203
DRAN = DBLE(FLOAT(IY)) / 2796203.0D+00
C
IY = IY * 125
IY = IY - (IY/2796203) * 2796203
DRAN = DRAN + (DBLE(FLOAT(IY)) / 2796203.0D+00) / 536870912.0D+00
RETURN
C ---------- LAST CARD OF DRAN ----------
END FUNCTION DRAN
! needs to be updated:
!--------------------------------------------------------------------------------
!
! SUBROUTINE UPDATE_HESSIAN( )
!
!******************************************************************************
! Subroutine UPDATE_HESSIAN constructs an approximation of the inverse
! Hessian using the DFP formula (see Muller and Stavrakou, 2005, eqn 18).
!
! This routine is set up to be used offline so that the Hessian is
! only approximated at the end of a convered optimization. To implement,
! uncomment code in 3 places in inverse.f
!
! The initial estimate can be identiy matrix or initial estimate of uncertainty
!
! It takes too long to consider all possible correlations, so we apply the
! following filters:
! - Only consider corelations between emissions of
! - anth SOx (surface and stack)
! - anth NOx (surface and stack)
! - anth NH3
! - natural NH3
! - Only within the U.S.
! - Only in places where ADJ_EMS at first iteration is > 1d-4
!
! If these filters are changes, the array diminsion HMAX will need to be
! updated. To determine the size of the MASD parameter, do a dry run,
! then go back and update.
!
! NOTES:
!
!******************************************************************************
!
!
! print*, ' SUBROUTINE UPDATE_HESSIAN needs to be updated '
! print*, ' SUBROUTINE UPDATE_HESSIAN needs to be updated '
! print*, ' SUBROUTINE UPDATE_HESSIAN needs to be updated '
! print*, ' SUBROUTINE UPDATE_HESSIAN needs to be updated '
!
! ! Reference to f90 modules
!
!# include "CMN_SIZE"
!
! ! Arguments
!
! ! Local variables
! INTEGER, PARAMETER :: HMAX = 3675
!
! INTEGER :: I, J, M, N, II, JJ, NITR
!
! REAL*8, SAVE :: USA_MASK(IIPAR,JJPAR)
!
! INTEGER, SAVE :: IIMAP(IIPAR,JJPAR,MMSCL,NNEMS) = 0d0
! INTEGER, SAVE :: MAPI(HMAX), MAPJ(HMAX)
! INTEGER, SAVE :: MAPM(HMAX), MAPN(HMAX)
!
! REAL*8, SAVE :: EMS_SF_OLD(IIPAR,JJPAR,MMSCL,NNEMS)
! REAL*8, SAVE :: ADJ_EMS_OLD(IIPAR,JJPAR,MMSCL,NNEMS)
! REAL*8, SAVE :: HINV(HMAX,HMAX)
! LOGICAL, SAVE :: FIRST = .TRUE.
!
! REAL*8 :: S(HMAX), Y(HMAX), YTS, YTHINVY
! REAL*8 :: YTS_INV, YTHINVY_INV
! REAL*8 :: SST(HMAX,HMAX), HINVY(HMAX), YTHINV(HMAX)
! REAL*8 :: HINVYYTHINV(HMAX,HMAX)
!
! !=================================================================
! ! UPDATE_HESSIAN begins here!
! !=================================================================
!
! PRINT*, ' UPDATE HESSIAN AT ITERATE ', N_CALC
!
!
! IF ( FIRST ) THEN
!
! ! Initialize HINV to the identity matrix (or initial unc. est)
! HINV(:,:) = 0d0
!
! DO JJ = 1, HMAX
! DO II = 1, HMAX
!
! IF ( II == JJ ) HINV(II,II) = 0.3d0
!
! ENDDO
! ENDDO
!
! ! Get USA mask
! CALL READ_USA_MASK( USA_MASK )
!
! ! dkh debug
! print*, ' yea yea eya'
!
! II = 0
!
! DO N = 1, NNEMS
! DO M = 1, MMSCL
! DO J = 1, JJPAR
! DO I = 1, IIPAR
!
! ! Spatial filter
! ! Only in US:
!! IF ( USA_MASK(I,J) == 0d0 ) CYCLE
! ! Only in places where emissions are nonzero
! IF ( ABS(ADJ_EMS(I,J,M,N)) < 1d-4 ) CYCLE
!
! IF (
! & N == IDADJEMS_ESOx1 .or.
! & N == IDADJEMS_ESOx2 .or.
! & N == IDADJEMS_ENOx1 .or.
! & N == IDADJEMS_ENOx2 .or.
! & N == IDADJEMS_ENH3_an .or.
! & N == IDADJEMS_ENH3_na
! & ) THEN
!
!
! ! Update vector index
! II = II + 1
!
! ! Save mapping arrays
! IIMAP(I,J,M,N) = II
! MAPI(II) = I
! MAPJ(II) = J
! MAPM(II) = M
! MAPN(II) = N
!
! ENDIF
!
! ENDDO
! ENDDO
! ENDDO
! ENDDO
!
!
! EMS_ICS_OLD(:,:,:,:) = EMS_ICS(:,:,:,:)
! ADJ_EMS_OLD(:,:,:,:) = ADJ_EMS(:,:,:,:)
! print*, ' UPDATE HESSIAN, pts founds = ', II
! CALL MAKE_HESS_FILE( HINV, USA_MASK , HMAX, IIMAP , 1 )
! FIRST = .FALSE.
!
!
! print*, 'EMS_ICS = ', EMS_ICS(19,33,1,IDADJEMS_ESOx2)
! print*, 'EMS_ICS_OLD = ', EMS_ICS_OLD(19,33,1,IDADJEMS_ESOx2)
! print*, 'ADJ_EMS = ', ADJ_EMS(19,33,1,IDADJEMS_ESOx2)
! print*, 'ADJ_EMS_OLD = ', ADJ_EMS_OLD(19,33,1,IDADJEMS_ESOx2)
!
! RETURN
! ENDIF
!
!
! DO II = 1, HMAX
!
! I = MAPI(II)
! J = MAPJ(II)
! M = MAPM(II)
! N = MAPN(II)
!
! ! find s_k = f_{k+1} - f_{k}
! S(II) = EMS_ICS(I,J,M,N) - EMS_ICS_OLD(I,J,M,N)
!
! ! find y_k = grad_{k+1} - grad_{k}
! Y(II) = ADJ_EMS(I,J,M,N) - ADJ_EMS_OLD(I,J,M,N)
!
! ENDDO
!
! print*, ' UPDATE HESSIAN, pts founds = ', II
!
! print*, 'EMS_ICS = ', EMS_ICS(19,33,1,IDADJEMS_ESOx2)
! print*, 'EMS_ICS_OLD = ', EMS_ICS_OLD(19,33,1,IDADJEMS_ESOx2)
! print*, 'ADJ_EMS = ', ADJ_EMS(19,33,1,IDADJEMS_ESOx2)
! print*, 'ADJ_EMS_OLD = ', ADJ_EMS_OLD(19,33,1,IDADJEMS_ESOx2)
!
! ! Rotate
! EMS_ICS_OLD(:,:,:,:) = EMS_ICS(:,:,:,:)
! ADJ_EMS_OLD(:,:,:,:) = ADJ_EMS(:,:,:,:)
!
! !----------------------------------------------------------
! ! Update inverse Hessian
! !----------------------------------------------------------
!
! ! y^T*s
! YTS = 0d0
! DO II = 1, HMAX
!
! YTS = YTS + Y(II) * S(II)
!
! ENDDO
!
! print*, ' YTS = ', YTS , N_CALC
!
! ! s * s^T / YTS
! DO II = 1, HMAX
! DO JJ = 1, HMAX
!
! SST(II,JJ) = S(II) * S(JJ)
!
! ENDDO
! ENDDO
!
! ! HINV * y
! DO II = 1, HMAX
!
! HINVY(II) = 0D0
!
! DO JJ = 1, HMAX
!
! HINVY(II) = HINVY(II) + HINV(II,JJ) * Y(JJ)
!
! ENDDO
! ENDDO
!
! ! y^T * HINV
! DO JJ = 1, HMAX
!
! YTHINV(JJ) = 0d0
!
! DO II = 1, HMAX
!
! YTHINV(JJ) = YTHINV(JJ) + Y(II) * HINV(II,JJ)
!
! ENDDO
! ENDDO
!
!
! ! HINVY * YTHINV
! DO JJ = 1, HMAX
! DO II = 1, HMAX
!
! HINVYYTHINV(II,JJ) = HINVY(II) * YTHINV(JJ)
!
! ENDDO
! ENDDO
!
!
! ! YT * HINVY
! YTHINVY = 0d0
! DO II = 1, HMAX
! YTHINVY = YTHINVY + Y(II) * HINVY(II)
! ENDDO
! print*, 'YTHINVY = ', YTHINVY
!
! ! HINV = HINV + SST * (1/YTS) - HINVYYTHINV * (1/YTHINVY)
! YTS_INV = 1 / YTS
! YTHINVY_INV = 1 / YTHINVY
! DO JJ = 1, HMAX
! DO II = 1, HMAX
!
! HINV(II,JJ) = HINV(II,JJ)
! & + SST(II,JJ) * YTS_INV
! & - HINVYYTHINV(II,JJ) * YTHINVY_INV
!
! ENDDO
! ENDDO
!
! print*, ' MAX HINV = ', MAXVAL(HINV(:,:))
! print*, ' MIN HINV = ', MINVAL(HINV(:,:))
!
! NITR = N_CALC
!
! CALL MAKE_HESS_FILE( HINV, USA_MASK , HMAX, IIMAP , NITR )
!
! ! Return to calling program
! END SUBROUTINE UPDATE_HESSIAN
!!------------------------------------------------------------------------------
! needs to be updated
!
! SUBROUTINE MAKE_HESS_FILE( HINV, USA_MASK , HMAX, IIMAP, NITR )
!!
!!******************************************************************************
!! Subroutine MAKE_HESS_FILE creates a binary file of selected elements
!! of the approximate inverse hessian. (dkh, 05/15/07)
!!
!! Arguments as Input:
!! ============================================================================
!! (1 ) HINV : Current estimate of inverse hessian
!!
!! Module Variable as Input:
!! ============================================================================
!! (1 ) N_CALC : Current iteration number
!!
!! NOTES:
!! (1 ) Just like MAKE_GDT_FILE except
!! - pass NITR as an argument
!!******************************************************************************
!!
!
! ! References to F90 modules
! USE BPCH2_MOD
! USE ERROR_MOD, ONLY : DEBUG_MSG, ERROR_STOP
! USE FILE_MOD, ONLY : IU_RST, IOERROR
! USE GRID_MOD, ONLY : GET_XOFFSET, GET_YOFFSET
! USE TIME_MOD, ONLY : EXPAND_DATE, GET_TAU
!
!# include "CMN_SIZE" ! Size parameters
!# include "CMN_SETUP" !
!# include "CMN" ! LPRT
!# include "CMN_ADJ" ! NADJ, OPTDATA_DIR, ACTIVE_VARS
!
!
! ! Arguments
! INTEGER :: HMAX
! REAL*8 :: HINV(HMAX,HMAX)
! REAL*8 :: USA_MASK(IIPAR,JJPAR)
! INTEGER :: IIMAP(IIPAR,JJPAR,MMSCL,NNEMS)
! INTEGER :: NITR
!
! ! Local Variables
! INTEGER :: I, I0, IOS, J, J0, L, M, N, II, JJ
! INTEGER :: YYYY, MM, DD, HH, SS
! REAL*4 :: TRACER(IIPAR,JJPAR,LLPAR)
! REAL*4 :: EMS_3D(IIPAR,JJPAR,MMSCL)
! CHARACTER(LEN=255) :: FILENAME
!
! ! For binary punch file, version 2.0
! REAL*4 :: LONRES, LATRES
! INTEGER, PARAMETER :: HALFPOLAR = 1
! INTEGER, PARAMETER :: CENTER180 = 1
!
! CHARACTER(LEN=20) :: OUTPUT_GDT_FILE
! CHARACTER(LEN=20) :: MODELNAME
! CHARACTER(LEN=40) :: CATEGORY
! CHARACTER(LEN=40) :: UNIT
! CHARACTER(LEN=40) :: RESERVED = ''
! CHARACTER(LEN=80) :: TITLE
!
! !=================================================================
! ! MAKE_HESS_FILE begins here!
! !=================================================================
!
! ! Clear intermediate arrays
! EMS_3D(:,:,:) = 0d0
!
! ! Hardwire output file for now
!#if defined( GEOS_1 ) || defined( GEOS_STRAT )
! OUTPUT_GDT_FILE = 'gctm.invhess.NN'
!#else
! OUTPUT_GDT_FILE = 'gctm.invhess.NN'
!#endif
!
! ! Define variables for BINARY PUNCH FILE OUTPUT
! TITLE = 'GEOS-CHEM Adjoint File: ' //
! & 'Inverse hessian '
! UNIT = 'none'
! CATEGORY = 'IJ-INVH-'
! LONRES = DISIZE
! LATRES = DJSIZE
!
! ! Call GET_MODELNAME to return the proper model name for
! ! the given met data being used (bmy, 6/22/00)
! MODELNAME = GET_MODELNAME()
!
! ! Get the nested-grid offsets
! I0 = GET_XOFFSET( GLOBAL=.TRUE. )
! J0 = GET_YOFFSET( GLOBAL=.TRUE. )
!
! !=================================================================
! ! Open the adjoint file for output -- binary punch format
! !=================================================================
!
! ! Copy the output observation file name into a local variable
! FILENAME = TRIM( OUTPUT_GDT_FILE )
!
! ! Append the iteration number suffix to the file name
! CALL EXPAND_NAME( FILENAME, NITR )
!
! ! Add the OPTDATA_DIR prefix to the file name
! FILENAME = TRIM( OPTDATA_DIR ) // TRIM( FILENAME )
!
! WRITE( 6, 100 ) TRIM( FILENAME )
! 100 FORMAT( ' - MAKE_HESS_FILE: Writing ', a )
!
! ! Open checkpoint file for output
! CALL OPEN_BPCH2_FOR_WRITE( IU_RST, FILENAME, TITLE )
!
!! IF ( ACTIVE_VARS == 'TRACERS'.OR.
!! & ACTIVE_VARS == 'FDTEST' ) THEN
! IF ( ACTIVE_VARS == 'TRACERS' ) THEN
!
! CALL ERROR_STOP( 'inverse hessian not supported ',
! & ' MAKE_HESS_FILE, inverse_mod.f')
!
! ELSEIF ( ACTIVE_VARS == 'EMISSIONS' .OR.
! & ACTIVE_VARS == 'FDTEST' ) THEN
!
! ! Reset CATEGORY as labeling in gamap is different
! CATEGORY = 'IJ-INVH-'
!
! !=================================================================
! ! Write each observed quantity to the observation file
! !=================================================================
! DO N = 1, NNEMS
!
! !Temporarily store quantities in the TRACER array
! EMS_3D(I,J,M) = 0d0
!
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J, M, II )
! DO M = 1, MMSCL
! DO J = 1, JJPAR
! DO I = 1, IIPAR
!
!
! II = IIMAP(I,J,M,N)
! IF ( II == 0 ) CYCLE
!
! IF ( HINV(II,II) > 0 ) THEN
! EMS_3D(I,J,M) = REAL(SQRT(HINV(II,II)))
! ELSE
! print*, I, J, M, N, II
! CALL ERROR_STOP('non positive hessian diagonal ',
! & 'inverse_mod.f')
! ENDIF
!
! ENDDO
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
! & HALFPOLAR, CENTER180, CATEGORY, N,
! & UNIT, GET_TAU(), GET_TAU(), RESERVED,
! & IIPAR, JJPAR, MMSCL, I0+1,
! & J0+1, 1, EMS_3D )
!
! ENDDO
!
! ! Reset CATEGORY as labeling in gamap is different
! CATEGORY = 'IJ-COREL'
!
! !=================================================================
! ! Write correlation for a given cell
! !=================================================================
! DO N = 1, NNEMS
!
! ! target cell
! JJ = IIMAP(13,33,1,IDADJEMS_ENH3_an)
!
! !Temporarily store quantities in the TRACER array
! EMS_3D(I,J,M) = 0d0
!
!!$OMP PARALLEL DO
!!$OMP+DEFAULT( SHARED )
!!$OMP+PRIVATE( I, J, M, II )
! DO M = 1, MMSCL
! DO J = 1, JJPAR
! DO I = 1, IIPAR
!
!
! II = IIMAP(I,J,M,N)
! !IF ( II == 0 ) CYCLE
! IF ( II == 0 ) THEN
! EMS_3D(I,J,M) = 0d0
! ELSE
! EMS_3D(I,J,M) = REAL(HINV(II,JJ)/(SQRT(HINV(II,II))
! & * SQRT(HINV(JJ,JJ))))
! ENDIF
!
! ENDDO
! ENDDO
! ENDDO
!!$OMP END PARALLEL DO
!
! CALL BPCH2( IU_RST, MODELNAME, LONRES, LATRES,
! & HALFPOLAR, CENTER180, CATEGORY, N,
! & UNIT, GET_TAU(), GET_TAU(), RESERVED,
! & IIPAR, JJPAR, MMSCL, I0+1,
! & J0+1, 1, EMS_3D )
!
! ENDDO
! ELSE
! CALL ERROR_STOP( 'ACTIVE_VARS not defined!',
! & 'MAKE_HESS_FILE' )
! ENDIF
!
! ! Close file
! CLOSE( IU_RST )
!
! !### Debug
! IF ( LPRT ) CALL DEBUG_MSG( '### MAKE_HESS_FILE: wrote file' )
!
! ! Return to calling program
! END SUBROUTINE MAKE_HESS_FILE
!------------------------------------------------------------------------------
! SUBROUTINE READ_USA_MASK( USA_MASK )
!!
!!******************************************************************************
!! Subroutine READ_USA_MASK reads the USA mask from disk. The USA mask is
!! the fraction of the grid box (I,J) which lies w/in the continental USA.
!! (rch, bmy, 11/10/04, 10/3/05)
!!
!! NOTES:
!! (1 ) Now can read data for GEOS and GCAP grids (bmy, 8/16/05)
!! (2 ) Now make sure all USE statements are USE, ONLY (bmy, 10/3/05)
!!******************************************************************************
!!
! ! Reference to F90 modules
! !USE BPCH2_MOD, ONLY : GET_NAME_EXT_2D, GET_RES_EXT
! USE BPCH2_MOD, ONLY : GET_RES_EXT
! USE BPCH2_MOD, ONLY : GET_TAU0, READ_BPCH2
!
!#include "CMN_SIZE"
!
! ! Local variables
! REAL*4 :: ARRAY(IGLOB,JGLOB,1)
! REAL*8 :: XTAU
! REAL*8 :: USA_MASK(IGLOB,JGLOB)
! CHARACTER(LEN=255) :: FILENAME
!
!
! !=================================================================
! ! READ_USA_MASK begins here!
! !=================================================================
!
! ! File name
! ! Argg - haven't initialized the forward model yet, so DATA_DIR undefined
! ! Just put the mask in the home directory
!! FILENAME = TRIM( DATA_DIR ) //
!! & 'EPA_NEI_200411/usa_mask.' // GET_NAME_EXT_2D() //
! FILENAME =
! & 'usa_mask.geos' //
! & '.' // GET_RES_EXT()
!
! ! Echo info
! WRITE( 6, 100 ) TRIM( FILENAME )
! 100 FORMAT( ' - READ_USA_MASK: Reading ', a )
!
! ! Get TAU0 for Jan 1985
! XTAU = GET_TAU0( 1, 1, 1985 )
!
! ! USA mask is stored in the bpch file as #2
! CALL READ_BPCH2( FILENAME, 'LANDMAP', 2,
! & XTAU, IGLOB, JGLOB,
! & 1, ARRAY, QUIET=.TRUE. )
!
! ! Cast to REAL*8
! !CALL TRANSFER_2D( ARRAY(:,:,1), USA_MASK )
! USA_MASK(:,:) = ARRAY(:,:,1)
!
! ! Return to calling program
! END SUBROUTINE READ_USA_MASK
!
!!------------------------------------------------------------------------------
SUBROUTINE CALC_NOPT
!
!******************************************************************************
! Subroutine CALC_NOPT calculates the number of paramteres to optimize
! 子程序用于计算需要优化的参数数量
! NOTES:
! (1 ) Set NOPT for initial conditions to 3D: IIPAR*JJPAR*LLPAR*N_TRACERS to
! be consistent with other parts of the code (mak, 6/18/09)
! (2 ) Now support strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
!******************************************************************************
!
! References to F90 modules
USE ADJ_ARRAYS_MOD, ONLY : NOPT
USE ADJ_ARRAYS_MOD, ONLY : MMSCL, NNEMS
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF
USE ADJ_ARRAYS_MOD, ONLY : NSTPL, NRRATES
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT, LADJ_RRATE
USE LOGICAL_ADJ_MOD, ONLY : LADJ_EMS, LICS
USE TRACER_MOD, ONLY : N_TRACERS, ITS_A_TAGCO_SIM
# include "CMN_SIZE"
!=================================================================
! CALC_NOPT begins here!
!=================================================================
! if optimizing both initial emissions and initial conditions
IF ( LADJ_EMS .AND. LICS ) THEN
NOPT = IIPAR * JJPAR * MMSCL * NNEMS +
& IIPAR * JJPAR * LLPAR * N_TRACERS
! if optimizing emissions only
ELSEIF ( LADJ_EMS ) THEN
NOPT = IIPAR * JJPAR * MMSCL * NNEMS
IF ( ITS_A_TAGCO_SIM() .AND. NNEMS == 2 ) THEN
NOPT = IIPAR * JJPAR * MMSCL + 1
ENDIF
! Strat prod and loss (hml)
!!IF ( LADJ_STRAT .AND. .NOT. LADJ_RRATE ) THEN
IF ( LADJ_STRAT ) THEN
NOPT = NOPT + IIPAR * JJPAR * MMSCL * NSTPL * 2
!!NOPT = IIPAR * JJPAR * MMSCL * ( NSTPL * 2 + NNEMS )
ENDIF
! Reaction rates (tww)
!!! To avoid double counting (hml, 06/11/13)
!!IF ( LADJ_RRATE .AND. LADJ_STRAT ) THEN
IF ( LADJ_RRATE ) THEN
NOPT = NOPT + IIPAR * JJPAR * LLPAR * NRRATES
ENDIF
!!NOPT = IIPAR * JJPAR * LLPAR
!! * ( NRRATES+ NNEMS + NSTPL*2 )
!!ELSEIF ( LADJ_RRATE .AND. .NOT. LADJ_STRAT ) THEN
!!NOPT = IIPAR * JJPAR * LLPAR * ( NRRATES + NNEMS )
!!ENDIF
! if optimizing initial conditions only
ELSEIF ( LICS ) THEN
NOPT = IIPAR * JJPAR * LLPAR * N_TRACERS
ENDIF
PRINT*, 'Max size of control vector is:', NOPT
! Return to calling program
END SUBROUTINE CALC_NOPT
!------------------------------------------------------------------------------
SUBROUTINE ITER_CONDITION( IT )
!
!******************************************************************************
! Subroutine ITER_CONDITION output information which will be used
! to determine whether the convergence has been reached (zhe 11/28/10)
!
! Variable as Input:
! ============================================================================
! (1 ) IT : Current iteration number
!
! NOTES:
! (1 ) Place output in DIAGADJ_DIR instead of OPTDATA_DIR (dkh, 02/04/11)
! (2 ) Now support strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
!******************************************************************************
!
! References to F90 modules
USE ADJ_ARRAYS_MOD, ONLY : COST_FUNC_SAV
USE DIRECTORY_ADJ_MOD, ONLY : DIAGADJ_DIR
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT, LADJ_RRATE
USE LOGICAL_ADJ_MOD, ONLY : LATF
# include "CMN_SIZE" ! Size parameters
! Arguments
INTEGER :: IT
! Local variables
INTEGER :: I
REAL*4 :: PG, NG, PS, NS
CHARACTER(LEN=255) :: FILENAME
LOGICAL, SAVE :: FIRST = .TRUE.
! For strat prod and loss (hml)
REAL*4 :: PG_P, PG_L, NG_P, NG_L
REAL*4 :: PS_P, PS_L, NS_P, NS_L
!=================================================================
! ITER_CONDITION begins here!
!=================================================================
PG = 0.0
NG = 0.0
PS = 0.0
NS = 0.0
! For strat prod and loss (hml)
PG_P = 0.0
NG_p = 0.0
PS_P = 0.0
NS_P = 0.0
PG_L = 0.0
NG_L = 0.0
PS_L = 0.0
NS_L = 0.0
FILENAME = 'gctm.iteration'
FILENAME = TRIM( DIAGADJ_DIR ) // TRIM( FILENAME )
IF ( FIRST ) THEN
OPEN (99, FILE = FILENAME, STATUS ='REPLACE')
WRITE(99, 1001)
WRITE(99, 1002)
FIRST = .FALSE.
ENDIF
! For strat prod and loss (hml)
IF ( LADJ_STRAT ) THEN
DO I = 1, IIPAR * JJPAR
IF ( GRADNT_P(I) .GT. 0 .AND. GRADNT_L(I) .GT. 0 ) THEN
PG_P = PG_P + GRADNT_P(I)
PG_L = PG_L + GRADNT_L(I)
ELSE
NG_P = NG_P + GRADNT_P(I)
NG_L = NG_L + GRADNT_L(I)
ENDIF
IF ( XP(I) .GT. 1 .AND. XL(I) .GT. 1 ) THEN
PS_P = PS_P + XP(I) - 1
PS_L = PS_L + XL(I) - 1
ELSE
NS_P = NS_P + XP(I) - 1
NS_L = NS_L + XL(I) - 1
ENDIF
ENDDO
WRITE(99, 1005) IT, LATF, COST_FUNC_SAV(IT),
& COST_FUNC_SAV(IT)/COST_FUNC_SAV(1), PG_P, PG_L,
& NG_P, NG_L, PS_P, PS_L, NS_P, NS_L
ELSE
DO I = 1, IIPAR * JJPAR
IF ( GRADNT(I) .GT. 0 ) THEN
PG = PG + GRADNT(I)
ELSE
NG = NG + GRADNT(I)
ENDIF
IF ( X(I) .GT. 1 ) THEN
PS = PS + X(I) - 1
ELSE
NS = NS + X(I) - 1
ENDIF
ENDDO
WRITE(99, 1003) IT, LATF, COST_FUNC_SAV(IT),
& COST_FUNC_SAV(IT)/COST_FUNC_SAV(1), PG, NG, PS, NS
ENDIF
1001 format ('GEOS-CHEM ADJOINT CONVERGNECE CONDITION',/,/,
+ 'IT = iteration number',/,
+ 'A = accepted iteration',/,
+ 'F = cost fun',/,
+ 'FdF0 = cost fun reduction',/,
+ 'PG = total positive gradient',/,
+ 'NG = total negative gradient',/,
+ 'PS = total underestimated scaling factor',/,
+ 'NS = total overestimated scaling factor',/)
1002 format (/,3x,'IT',2x,'A',7x,'F',10x,'FdF0',9x,'PG',12x,'NG',
+ 10x,'PS',10x,'NS')
1003 format (3x,i2,2x,L1,2x,E12.6,2x,F8.6,2x,E11.5,2x,
+ E12.5,2x,F9.2,2x,F10.2)
! Strat prod and loss (hml)
1004 format (/,3x,'IT',2x,'A',7x,'F',10x,'FdF0',9x,'PG_P',12x,'PG_L',
+ 12x,'NG_P',10x,'NG_L',10x,'PS_P',10x,'PS_L',10x,'NS_P',
+ 10x,'NS_L')
1005 format (3x,i2,2x,L1,2x,E12.6,2x,F8.6,2x,E11.5,2x,E11.5,2x,
+ E12.5,2x,E12.5,2x,F9.2,2x,F9.2,2x,F10.2,2x,F10.2)
! Return to calling program
END SUBROUTINE ITER_CONDITION
!--------------------------------------------------------------------------------
SUBROUTINE MAYBE_DO_GEOS_CHEM_ADJ( )
!
!******************************************************************************
! Subroutine MAYBE_DO_GEOS_CHEM_ADJ is called for FDTESTS and determines
! whether or not the adjoint model needs to be run. (dkh, 02/21/11)
!
! Module variables as Input:
! ============================================================================
! (1 ) LFD_GLOB (LOGICAL) : Switch to perform global finite diff test
! (2 ) LFD_SPOT (LOGICAL) : Switch to perform spot finite diff test
! (3 ) N_CALC_STOP (INTEGER) : Current iteration number
!
! NOTES:
!
!******************************************************************************
!
! Reference to f90 modules
USE ADJ_ARRAYS_MOD, ONLY : N_CALC_STOP
USE ERROR_MOD, ONLY : ERROR_STOP
USE LOGICAL_ADJ_MOD, ONLY : LFD_GLOB
USE LOGICAL_ADJ_MOD, ONLY : LFD_SPOT
USE GEOS_CHEM_ADJ_MOD, ONLY : DO_GEOS_CHEM_ADJ
!=================================================================
! MAYBE_DO_GEOS_CHEM_ADJ begins here!
!=================================================================
! For global finite difference test we compare the average of
! two finite difference sensitivities with an adjoint sensitivity
! around the base case.
IF ( LFD_GLOB ) THEN
! Only calculate the adjoint during the first iteration
IF ( N_CALC_STOP == 1 ) THEN
CALL DO_GEOS_CHEM_ADJ
! Don't bother with more than 3 iterations
ELSEIF ( N_CALC_STOP > 3 ) THEN
CALL ERROR_STOP('To many iterations for FD_GLOB',
& 'inverse_mod.f' )
ENDIF
! For SPOT finite difference test we compare the average of
! two adjoint sensitivities with a finite difference sensitivity
! around the base case + 1/2 FD_DIFF
ELSEIF ( LFD_SPOT ) THEN
! calculate the adjoint during the first and second iteration
IF ( N_CALC_STOP == 1 .or. N_CALC_STOP == 2 ) THEN
CALL DO_GEOS_CHEM_ADJ
! Don't bother with more than 2 iteratoins
ELSEIF ( N_CALC_STOP > 2 ) THEN
CALL ERROR_STOP('To many iterations for FD_SPOT',
& 'inverse_mod.f' )
ENDIF
ENDIF
! Return to calling program
END SUBROUTINE MAYBE_DO_GEOS_CHEM_ADJ
!------------------------------------------------------------------------------
SUBROUTINE DO_SAT_DIAGS( )
!
!******************************************************************************
! Subroutine DO_SAT_DIAGS writes satellite diagnostics
! (mkeller, 06/15)
!
! NOTES:
!
!******************************************************************************
!
# include "define_adj.h" ! Obs operator flags
! References to F90 modules
#if defined(TES_O3_OBS) || defined(MOPITT_V5_CO_OBS) || defined (MOPITT_V6_CO_OBS )
USE HDF5
#endif
USE GRID_MOD, ONLY : GET_XMID, GET_YMID
USE DIRECTORY_ADJ_MOD, ONLY : DIAGADJ_DIR
USE ADJ_ARRAYS_MOD, ONLY : N_CALC, N_CALC_STOP
USE ADJ_ARRAYS_MOD, ONLY : EXPAND_NAME
USE LOGICAL_ADJ_MOD, ONLY : LSAT_HDF_L2, LSAT_HDF_L3, LDCOSAT
#if defined(OMI_NO2_OBS)
!USE OMI_NO2_OBS_MOD, ONLY : MAKE_OMI_BIAS_FILE_HDF5
#endif
#if defined(TES_O3_OBS)
USE TES_O3_MOD, ONLY : MAKE_TES_BIAS_FILE_HDF5
#endif
#if defined(MOPITT_V5_CO_OBS) || defined (MOPITT_V6_CO_OBS )
USE MOPITT_OBS_MOD, ONLY : MAKE_MOPITT_BIAS_FILE_HDF5
#endif
! Local variables
CHARACTER(LEN=255) :: FILENAME_HDF5
INTEGER :: FILE_ID
INTEGER :: HDF_ERR
!=================================================================
! DO_SAT_DIAGS begins here!
!=================================================================
#if defined(TES_O3_OBS) || defined(MOPITT_V5_CO_OBS) || defined (MOPITT_V6_CO_OBS )
! HDF based diagnostics (mkeller, 06/15)
IF ( LSAT_HDF_L2 .or. LSAT_HDF_L3 ) THEN
FILENAME_HDF5 = TRIM("satellite_diagnostics.NN.h5")
CALL EXPAND_NAME( FILENAME_HDF5, N_CALC )
FILENAME_HDF5 = TRIM( DIAGADJ_DIR ) //
& TRIM( FILENAME_HDF5 )
! create satellite diagnostic file
CALL H5FCREATE_F( FILENAME_HDF5, H5F_ACC_TRUNC_F, FILE_ID,
& HDF_ERR )
#if defined( OMI_NO2_OBS )
!CALL MAKE_OMI_BIAS_FILE_HDF5( FILE_ID )
#endif
#if defined( TES_O3_OBS )
CALL MAKE_TES_BIAS_FILE_HDF5( FILE_ID )
#endif
#if defined( MOPITT_V5_CO_OBS ) || defined (MOPITT_V6_CO_OBS )
CALL MAKE_MOPITT_BIAS_FILE_HDF5( FILE_ID )
#endif
CALL H5FCLOSE_F( FILE_ID, HDF_ERR )
ENDIF
#endif
!==============================================================
! Diagnostics (original from mak, non HDF output)
!==============================================================
! store satellite diagnostics
! for now CO, but subroutines all general, just need linking
! (mak 6/19/09)
IF ( LDCOSAT ) THEN
!Store FORCING, MOP_MOD_DIFF and MODEL_BIAS
!CALL MAKE_FORCING_FILE
!CALL MAKE_MOPMOD_FILE
! store model, mopitt and model bias to files
! model
CALL MAKE_SAT_DIAG_FILE( 1 )
! obs and DOFs
IF( N_CALC_STOP == 1) THEN
CALL MAKE_SAT_DIAG_FILE( 2 )
ENDIF
CALL MAKE_SAT_DIAG_FILE( 6 )
CALL MAKE_SAT_DIAG_FILE( 7 )
! model bias (wrt satellite data)
CALL MAKE_SAT_DIAG_FILE( 3 )
! store COST_ARRAY, OBS_COUNT, OBS_HOUR*
CALL MAKE_SAT_DIAG_FILE( 5 )
ENDIF
END SUBROUTINE DO_SAT_DIAGS
!------------------------------------------------------------------------------
SUBROUTINE INIT_INVERSE
!
!******************************************************************************
! Subroutine INIT_INVERSE initializes and zeros all allocatable arrays
! declared in "inverse_mod.f" (dkh, 1/26/05)
!
! NOTES:
! (1 ) Now also allocate EMS_ICS_orig (dkh, 03/29/05)
! (2 ) Now check for incompatible preproc. definitions and ACTIVE_VARS. (dkh, 10/17/06)
! (3 ) Now support strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
!
!******************************************************************************
!
! References to F90 modules
USE ADJ_ARRAYS_MOD, ONLY : NOPT
USE ADJ_ARRAYS_MOD, ONLY : RATE_SF
USE ADJ_ARRAYS_MOD, ONLY : NSTPL, NRRATES
USE ADJ_ARRAYS_MOD, ONLY : MMSCL
USE LOGICAL_ADJ_MOD, ONLY : LADJ_STRAT, LADJ_RRATE, LADJ
USE ERROR_MOD, ONLY : ALLOC_ERR, ERROR_STOP
# include "CMN_SIZE" ! Size parameters
! Local variables
LOGICAL, SAVE :: IS_INIT = .FALSE.
INTEGER :: AS, I
!=================================================================
! INIT_INVERSE begins here!
!=================================================================
! Return if we have already initialized
IF ( IS_INIT ) RETURN
!fp
IF ( LADJ ) THEN
!Allocate arrays
ALLOCATE( GRADNT( NOPT ), STAT = AS )
IF ( AS /= 0 ) CALL ALLOC_ERR( 'GRADNT' )
ENDIF
ALLOCATE( X( NOPT ), STAT = AS )
IF ( AS /= 0 ) CALL ALLOC_ERR( 'X' )
IF ( LADJ_STRAT ) THEN
ALLOCATE( GRADNT_P( IIPAR*JJPAR*MMSCL*NSTPL ), STAT = AS )
IF ( AS /= 0 ) CALL ALLOC_ERR( 'GRADNT_P' )
ALLOCATE( GRADNT_L( IIPAR*JJPAR*MMSCL*NSTPL ), STAT = AS )
IF ( AS /= 0 ) CALL ALLOC_ERR( 'GRADNT_L' )
ALLOCATE( XP( IIPAR*JJPAR*MMSCL*NSTPL ), STAT = AS )
IF ( AS /= 0 ) CALL ALLOC_ERR( 'XP' )
ALLOCATE( XL( IIPAR*JJPAR*MMSCL*NSTPL ), STAT = AS )
IF ( AS /= 0 ) CALL ALLOC_ERR( 'XL' )
ENDIF
END SUBROUTINE INIT_INVERSE
!------------------------------------------------------------------------------
! Return to calling program
SUBROUTINE CLEANUP_INVERSE
!
!******************************************************************************
! Subroutine CLEANUP_INVERE deallocates all previously allocated arrays
! for inverse_mod -- call at the end of the program (dkh, 1/26/05)
!
! NOTES:
! (1 ) Now also deallocate EMS_ICS_orig (dkh, 03/29/05)
! (2 ) No longer make EMS_ICS an array in this module (dkh, 06/08/09)
! (3 ) Now support strat fluxes LADJ_STRAT (hml, dkh, 02/20/12, adj32_025)
!******************************************************************************
!
!=================================================================
! CLEANUP_INVERSE begins here!
!=================================================================
IF ( ALLOCATED( GRADNT ) ) DEALLOCATE( GRADNT )
IF ( ALLOCATED( X ) ) DEALLOCATE( X )
! Return to calling program
END SUBROUTINE CLEANUP_INVERSE
!------------------------------------------------------------------------------
END MODULE INVERSE_MOD