midas_adjointTest sourceΒΆ

   1program midas_adjointTest
   2  !
   3  !:Purpose: Main program for adjoint test applications, i.e., testing if the identity
   4  !          :math:`<x,L(y)> = <L^T(x),y>` is respected.
   5  !
   6  !:Algorithm: Initialize a random grid-point space statevector :math:`x` and a random
   7  !            control vector :math:`y`.  Compute :math:`L(y)` by the action of a linear
   8  !            operator and compute the inner product :math:`<x,L(y)>`.  Then compute
   9  !            :math:`L^T(x)` through the action of the corresponding adjoint operator
  10  !            and the inner product :math:`<L^T(x),y>`.  Verify if both inner products
  11  !            are equal.
  12  !
  13  !            --
  14  !
  15  !:File I/O: The required input files vary according to the application (see options below).
  16  !
  17  !================================================= ==============================================================
  18  ! Input and Output Files (square root covariances)  Description of file
  19  !================================================= ==============================================================
  20  ! ``flnml``                                         In - Main namelist file with parameters user may modify
  21  ! ``trlm_01``                                       In - Background state (a.k.a. trial) file
  22  ! ``analysisgrid``                                  In - File defining grid for computing the analysis increment
  23  ! ``bgcov``                                         In - Static (i.e. NMC) B matrix file for NWP fields
  24  ! ``ensemble/$YYYYMMDDHH_006_$NNNN``                In - Ensemble member files defining ensemble B matrix
  25  ! ``innerProd.txt``                                 Out - Results of inner products and their difference
  26  !================================================= ==============================================================
  27  !
  28  !:Synopsis: There are several flavors of tests that can be run. The choice is configured
  29  !           in the namelist block ``NAMADT`` with the variable ``test`` (see below).
  30  !           All tests follow this general synopsis:
  31  !
  32  !           - initialize with gaussian noise (``rng_gaussian()``) a statevector
  33  !             :math:`x` and a control vector :math:`y`.
  34  !
  35  !           - apply the corresponding square root operator on :math:`y` to obtain :math:`Ly`
  36  !
  37  !           - compute the inner product :math:`<x ,Ly>`
  38  !
  39  !           - apply the corresponding square root adjoint operator on :math:`x` to
  40  !             obtain :math:`L^T(x)`
  41  !
  42  !           - compute the inner product :math:`<L^Tx,y>`
  43  !
  44  !           - print :math:`<x,L(y)>`, :math:`<L^T(x),y>` and their relative difference
  45  !
  46  !:Options: `List of namelist blocks <../namelists_in_each_program.html#adjointtest>`_
  47  !          that can affect the ``adjointTest`` program.
  48  !
  49  !          * As described in the algorithm section, four different tests are implemented.
  50  !            The test that is conducted is chosen through the namelist variable
  51  !            `&NAMADT Test` that can be either
  52  !
  53  !             * **'Bhi'** : test the adjoint of the square root of the homogeneous and
  54  !               isotropic covariance matrix.  The namelist block `&NAMBHI` will
  55  !               configure the covariance matrix properties.
  56  !
  57  !             * **'Bens'** : test the adjoint of the square root of the ensemble covariance
  58  !               matrix.  The namelist block `&NAMBEN` will configure the covariance
  59  !               matrix properties.
  60  !
  61  !             * **'loc'** : test the adjoint of the square root of localized covariance
  62  !               matrix.
  63  !
  64  !             * **'advEns'** : test the adjoint of the advection operator on ensemble
  65  !
  66  !             * **'advGSV'** : test the adjoint of the advection operator on a single
  67  !               statevector
  68  !
  69  use version_mod
  70  use codePrecision_mod
  71  use ramDisk_mod
  72  use utilities_mod
  73  use midasMpi_mod
  74  use mathPhysConstants_mod
  75  use horizontalCoord_mod
  76  use verticalCoord_mod
  77  use timeCoord_mod
  78  use gridStateVector_mod
  79  use gridVariableTransforms_mod
  80  use bMatrixHI_mod
  81  use bMatrixEnsemble_mod
  82  use randomNumber_mod
  83  use advection_mod
  84  use ensembleStateVector_mod
  85  use localization_mod
  86  use lamBmatrixHI_mod
  87  implicit none
  88
  89  type(struct_vco),       pointer :: vco_anl  => null()
  90  type(struct_hco),       pointer :: hco_anl  => null()
  91  type(struct_hco),       pointer :: hco_core => null()
  92
  93  type(struct_gsv) :: statevector_x
  94  type(struct_gsv) :: statevector_y
  95  type(struct_gsv) :: statevector_Ly
  96  type(struct_gsv) :: statevector_LTx
  97
  98  real(8) :: innerProduct1_local, innerProduct2_local, innerProduct1_global, innerProduct2_global
  99
 100  real(8), allocatable ::  controlVector1(:)
 101  real(8), allocatable ::  controlVector2(:)
 102
 103  integer :: get_max_rss, ierr, cvDim, nulnam, fnom, fclos
 104  character(len=20) ::  test ! adjoint test type ('Bhi','Bens','advEns','advGSV','loc')
 105  NAMELIST /NAMADT/test
 106
 107  call ver_printNameAndVersion('adjointTest','Various tests of adjoint codes')
 108
 109  !
 110  !- 1.  Settings and module initializations
 111  !
 112  write(*,*)
 113  write(*,*) '> midas-adjointTest: setup - START'
 114
 115  !- 1.1 mpi
 116  call mmpi_initialize
 117
 118  !- 1.2 timings
 119  call tmg_init(mmpi_myid, 'TMG_INFO')
 120  call utl_tmg_start(0,'Main')
 121
 122  !- 1.3 RAM disk usage
 123  call ram_setup
 124
 125  !- 1.4 Temporal grid and set dateStamp from env variable
 126  call tim_setup()
 127  if (tim_getDateStamp()==0) then
 128    call utl_abort('midas-adjointTest: dateStamp was not set')
 129  end if
 130
 131  !- 1.6 Constants
 132  if ( mmpi_myid == 0 ) then
 133    call mpc_printConstants(6)
 134    call pre_printPrecisions
 135  end if
 136
 137  !- 1.8 Variables of the model states
 138  call gsv_setup
 139
 140  !- 1.9 Set the horizontal domain
 141  call hco_SetupFromFile(hco_anl, './analysisgrid', 'ANALYSIS') ! IN
 142  if ( hco_anl % global ) then
 143    hco_core => hco_anl
 144  else
 145    !- Iniatilized the core (Non-Exteded) analysis grid
 146    call hco_SetupFromFile( hco_core, './analysisgrid', 'COREGRID') ! IN
 147  end if
 148
 149  !- 1.10 Initialize the vertical coordinate
 150  call vco_SetupFromFile( vco_anl,        & ! OUT
 151                          './analysisgrid') ! IN
 152
 153  write(*,*)
 154  write(*,*) '> midas-adjointTest: setup - END'
 155  write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
 156
 157  !- 1.11 Variable transforms
 158  call gvt_Setup(hco_anl, hco_core, vco_anl)
 159
 160  !- 1.12 Test selection
 161  test = 'Bhi' ! default test 
 162
 163  if ( .not. utl_isNamelistPresent('NAMADT','./flnml') ) then
 164    if (mmpi_myid == 0) then
 165      write(*,*) 'midas-adjointTest: namadt is missing in the namelist. '&
 166                 //'The default values will be taken.'
 167    end if
 168  else
 169    nulnam=0
 170    ierr=fnom(nulnam, './flnml', 'FTN+SEQ+R/O', 0)
 171    read(nulnam, nml=namadt, iostat=ierr)
 172    if(ierr.ne.0) call utl_abort('midas-adjointTest: Error reading namelist')
 173    if( mmpi_myid == 0 ) write(*,nml=namadt)
 174    ierr=fclos(nulnam)
 175  end if
 176
 177  !
 178  !- 2.  The tests
 179  !
 180 
 181  write(*,*)
 182  write(*,*) '> midas-adjointTest: '//test
 183  if ( test == 'Bhi') then
 184    !- 2.1 Bhi
 185    call check_bhi
 186  else if ( test == 'Bens') then  
 187    !- 2.2 Bens
 188    call check_bens
 189  else if ( test == 'advEns') then
 190    !- 2.3 AdvectionENS
 191    call check_advectionENS
 192  else if ( test == 'advGSV') then 
 193    !- 2.4 AdvectionGSV
 194    call check_advectionGSV
 195  else if ( test == 'loc') then
 196    !- 2.5 Localization
 197    call check_loc 
 198  !else if ( test == 'addMem') then
 199  !  !- 2.6 Localization
 200  !  call check_addmem
 201  else
 202    call utl_abort('midas-adjointTest: inexistant test label ('//test//')')
 203  end if
 204
 205  !
 206  !- 3.  Ending
 207  !
 208  write(*,*)
 209  write(*,*) '> midas-adjointTest: Ending'
 210  call utl_tmg_stop(0)
 211  call tmg_terminate(mmpi_myid, 'TMG_INFO')
 212
 213  call rpn_comm_finalize(ierr) 
 214
 215contains
 216
 217  !--------------------------------------------------------------------------
 218  !- check Bhi
 219  !--------------------------------------------------------------------------
 220  subroutine check_bhi()
 221    implicit none
 222
 223    ! Locals:
 224    integer :: seed, kIndex, stepIndex, latIndex, lonIndex, cvIndex
 225    real(8), pointer :: field4d_r8(:,:,:,:), field3d_Ly_r8(:,:,:), field3d_x_r8(:,:,:)
 226
 227    call gvt_setupRefFromTrialFiles('HU')
 228    if (hco_anl%global) then
 229      call bhi_Setup( hco_anl, vco_anl, & ! IN
 230                      cvdim )             ! OUT
 231    else
 232      call lbhi_Setup( hco_anl, hco_core, vco_anl, & ! IN
 233                      cvdim )                        ! OUT
 234    end if
 235
 236    call gsv_allocate(statevector_x  , tim_nstepobsinc, hco_anl, vco_anl, &
 237                      mpi_local_opt=.true., &
 238                      allocHeight_opt=.false., allocPressure_opt=.false.)
 239
 240    call gsv_allocate(statevector_Ly , tim_nstepobsinc, hco_anl, vco_anl, &
 241                      mpi_local_opt=.true., &
 242                      allocHeight_opt=.false., allocPressure_opt=.false.)
 243
 244    allocate ( controlVector1(cvDim) )
 245    
 246    ! x
 247    !statevector_x%gd3d_r8(:,:,:) = 13.3d0
 248    call gsv_getField(statevector_x,field4d_r8)
 249    seed=1
 250    call rng_setup(abs(seed+mmpi_myid))
 251    do kIndex = statevector_x%mykBeg, statevector_x%mykEnd
 252      do stepIndex = 1, statevector_x%numStep
 253        do latIndex = statevector_x%myLatBeg, statevector_x%myLatEnd
 254          do lonIndex = statevector_x%myLonBeg, statevector_x%myLonEnd
 255            field4d_r8(lonIndex,latIndex,kIndex,stepIndex) = rng_gaussian()
 256          end do
 257        end do
 258      end do
 259    end do
 260
 261    ! y
 262    !controlVector1(:) = 2.4d0
 263    do cvIndex = 1, cvDim
 264      controlVector1(cvIndex) = rng_gaussian()
 265    end do
 266
 267    ! y
 268    !controlVector1 = 0.d0
 269    !if (hco_anl%global) then
 270    !  call bhi_bSqrtAd( statevector_x, &  ! IN
 271    !                    controlVector1)  ! OUT
 272    !else
 273    !  call lbhi_bSqrtAdj( statevector_x, &  ! IN
 274    !                      controlVector1)  ! OUT
 275    !end if
 276
 277    ! Ly
 278    if (hco_anl%global) then
 279      call bhi_bSqrt( controlVector1, & ! IN
 280                      statevector_Ly )  ! OUT
 281    else
 282      call lbhi_bSqrt( controlVector1, & ! IN
 283                       statevector_Ly )  ! OUT
 284    end if
 285
 286
 287    ! <x ,L(y)>
 288    innerProduct1_local = 0.d0
 289    call gsv_getField(statevector_Ly,field3d_Ly_r8)
 290    call gsv_getField(statevector_x, field3d_x_r8 )
 291    call euclid(innerProduct1_local, &
 292         field3d_x_r8(statevector_Ly%myLonBeg:statevector_Ly%myLonEnd,statevector_Ly%myLatBeg:statevector_Ly%myLatEnd,:), &
 293         field3d_Ly_r8(statevector_Ly%myLonBeg:statevector_Ly%myLonEnd,statevector_Ly%myLatBeg:statevector_Ly%myLatEnd,:), &
 294         statevector_Ly%myLonBeg, statevector_Ly%myLonEnd, statevector_Ly%myLatBeg, statevector_Ly%myLatEnd, statevector_Ly%nk, 1)
 295    write(*,*) "<x     ,L(y)> local = ",innerProduct1_local
 296    call rpn_comm_allreduce(innerProduct1_local,innerProduct1_global,1,"mpi_double_precision","mpi_sum","GRID",ierr)
 297    write(*,*) "<x     ,L(y)> global= ",innerProduct1_global
 298    
 299    ! L_T(x)
 300    allocate ( controlVector2(cvDim) )
 301    controlVector2 = 0.d0
 302    if (hco_anl%global) then
 303      call bhi_bSqrtAd( statevector_x, &  ! IN
 304                        controlVector2 ) ! OUT
 305    else
 306      call lbhi_bSqrtAdj( statevector_x, &  ! IN
 307                         controlVector2 ) ! OUT
 308    end if
 309
 310    ! <L_T(x),y>
 311    innerProduct2_local = 0.d0
 312    call euclid(innerProduct2_local, controlVector2, controlVector1, 1, cvDim, 1, 1, 1, 1)
 313    print*,"<Lt(x) ,y   > local = ",innerProduct2_local
 314    call rpn_comm_allreduce(innerProduct2_local,innerProduct2_global,1,"mpi_double_precision","mpi_sum","GRID",ierr)
 315    write(*,*) "<Lt(x) ,y   > global= ",innerProduct2_global
 316    
 317    ! Results
 318    call checkAndOutputInnerProd
 319    
 320    deallocate(controlVector2)
 321    deallocate(controlVector1)
 322
 323    call gsv_deallocate(statevector_x)
 324    call gsv_deallocate(statevector_Ly)
 325
 326  end subroutine check_bhi
 327
 328  !--------------------------------------------------------------------------
 329  !- check Bens
 330  !--------------------------------------------------------------------------
 331  subroutine check_bens()
 332    implicit none
 333
 334    ! Locals:
 335    integer :: seed, kIndex, stepIndex, latIndex, lonIndex
 336    integer, allocatable :: cvDimPerInstance(:)
 337    real(8), pointer :: field4d_Ly_r8(:,:,:,:), field4d_x_r8(:,:,:,:)
 338
 339    call gvt_setupRefFromTrialFiles('HU')
 340    call ben_Setup( hco_anl, hco_core, vco_anl, & ! IN
 341                    cvdimPerInstance )  ! OUT
 342
 343    cvDim = cvdimPerInstance(1)
 344    call gsv_allocate(statevector_x  , tim_nstepobsinc, hco_anl, vco_anl, &
 345                      mpi_local_opt=.true., &
 346                      allocHeight_opt=.false., allocPressure_opt=.false.)
 347    call gsv_allocate(statevector_Ly , tim_nstepobsinc, hco_anl, vco_anl, &
 348                      mpi_local_opt=.true., &
 349                      allocHeight_opt=.false., allocPressure_opt=.false.)
 350
 351    allocate ( controlVector1(cvdim) )
 352
 353    ! x
 354    seed=1
 355    call rng_setup(abs(seed+mmpi_myid))
 356    call gsv_getField(statevector_x,field4d_x_r8)
 357    do kIndex = statevector_x%mykBeg, statevector_x%mykEnd
 358      do stepIndex = 1, statevector_x%numStep
 359        do latIndex = statevector_x%myLatBeg, statevector_x%myLatEnd
 360          do lonIndex = statevector_x%myLonBeg, statevector_x%myLonEnd
 361            field4d_x_r8(lonIndex,latIndex,kIndex,stepIndex) = rng_gaussian()
 362          end do
 363        end do
 364      end do
 365    end do
 366
 367    ! y
 368    controlVector1 = 0.d0
 369    call ben_bSqrtAd( 1, statevector_x, &  ! IN
 370                      controlVector1)  ! OUT
 371
 372    ! Ly
 373    call ben_bSqrt( 1, controlVector1, & ! IN
 374                    statevector_Ly )  ! OUT
 375
 376    ! <x ,L(y)>
 377    innerProduct1_local = 0.d0
 378    call gsv_getField(statevector_Ly,field4d_Ly_r8)
 379    call gsv_getField(statevector_x, field4d_x_r8 )
 380    call euclid(innerProduct1_local, &
 381         field4d_x_r8(statevector_Ly%myLonBeg:statevector_Ly%myLonEnd,statevector_Ly%myLatBeg:statevector_Ly%myLatEnd,:,:), &
 382         field4d_Ly_r8(statevector_Ly%myLonBeg:statevector_Ly%myLonEnd,statevector_Ly%myLatBeg:statevector_Ly%myLatEnd,:,:), &
 383         statevector_Ly%myLonBeg, statevector_Ly%myLonEnd, statevector_Ly%myLatBeg, statevector_Ly%myLatEnd, statevector_Ly%nk, statevector_Ly%numStep)
 384    write(*,*) "<x     ,L(y)> local = ",innerProduct1_local
 385    call rpn_comm_allreduce(innerProduct1_local,innerProduct1_global,1,"mpi_double_precision","mpi_sum","GRID",ierr)
 386    write(*,*) "<x     ,L(y)> global= ",innerProduct1_global
 387    
 388    ! L_T(x)
 389    allocate ( controlVector2(cvDim) )
 390    controlVector2 = 0.d0
 391    call ben_bSqrtAd( 1, statevector_x, &  ! IN
 392                      controlVector2 )  ! OUT
 393    
 394    ! <L_T(x),y>
 395    innerProduct2_local = 0.d0
 396    call euclid(innerProduct2_local, controlVector2, controlVector1, 1, cvDim, 1, 1, 1, 1)
 397    print*,"<Lt(x) ,y   > local = ",innerProduct2_local
 398    call rpn_comm_allreduce(innerProduct2_local,innerProduct2_global,1,"mpi_double_precision","mpi_sum","GRID",ierr)
 399    write(*,*) "<Lt(x) ,y   > global= ",innerProduct2_global
 400
 401    ! Results
 402    call checkAndOutputInnerProd
 403    
 404    deallocate(controlVector2)
 405    deallocate(controlVector1)
 406
 407    call gsv_deallocate(statevector_x)
 408    call gsv_deallocate(statevector_Ly)
 409
 410  end subroutine check_bens
 411
 412  !--------------------------------------------------------------------------
 413  !- check Loc
 414  !--------------------------------------------------------------------------
 415  subroutine check_loc()
 416    implicit none
 417
 418    ! Locals:
 419    integer :: seed, kIndex, stepIndex, latIndex, lonIndex, dateStamp
 420    integer :: numStepAmplitude, amp3dStepIndex, memberIndex
 421    type(struct_ens) :: ensAmplitude_x
 422    type(struct_ens) :: ensAmplitude_Ly
 423    type(struct_loc), pointer :: loc => null()
 424    real(8), pointer     :: ens_oneLev(:,:,:,:)
 425    real(8), pointer :: field4d_Ly_r8(:,:,:,:), field4d_x_r8(:,:,:,:)
 426    character(len=4), parameter  :: varNameALFAatm(1) = (/ 'ALFA' /)
 427    character(len=4), parameter  :: varNameALFAsfc(1) = (/ 'ALFS' /)
 428    character(len=4)             :: varNameALFA(1)
 429    integer,allocatable :: dateStampList(:)
 430    integer, allocatable :: cvDimPerInstance(:)
 431
 432    allocate(dateStampList(tim_nstepobsinc))
 433    call tim_getstamplist(dateStampList,tim_nstepobsinc,tim_getDatestamp())
 434
 435    dateStamp = tim_getDatestamp()
 436    write(*,*) 'check_loc: tim_getDatestamp = ', dateStamp
 437    write(*,*) 'check_loc: dateStampList = ', dateStampList(:)
 438
 439    call ben_Setup( hco_anl, hco_core, vco_anl, & ! IN
 440                    cvDimPerInstance )             ! OUT
 441
 442    cvDim = cvDimPerInstance(1)
 443
 444    loc => ben_getLoc(1)
 445    if ( cvDim /= loc%cvDim ) then
 446      call utl_abort('check_loc: cvDim /= loc%cvDim')
 447    end if
 448    numStepAmplitude = ben_getNumStepAmplitudeAssimWindow()
 449    if ( numStepAmplitude /= 1 ) then
 450      call utl_abort('check_loc: not yet adapted for localization advection')
 451    end if
 452    amp3dStepIndex   = ben_getAmp3dStepIndexAssimWindow()
 453
 454    if (loc%vco%Vcode == 5002 .or. loc%vco%Vcode == 5005) then
 455      varNameALFA(:) = varNameALFAatm(:)
 456    else ! vco_anl%Vcode == -1
 457      varNameALFA(:) = varNameALFAsfc(:)
 458    end if
 459
 460    call gsv_allocate(statevector_x  , numStepAmplitude, loc%hco, loc%vco, &
 461                      mpi_local_opt=.true., varNames_opt=varNameALFA, dataKind_opt=8)
 462    call gsv_allocate(statevector_Ly , numStepAmplitude, loc%hco, loc%vco, &
 463                      mpi_local_opt=.true., varNames_opt=varNameALFA, dataKind_opt=8)
 464
 465    call ens_allocate(ensAmplitude_x, loc%nEnsOverDimension, numStepAmplitude, loc%hco, loc%vco, &
 466                      datestampList=dateStampList, varNames_opt=varNameALFA, dataKind_opt=8)    
 467    call ens_allocate(ensAmplitude_Ly, loc%nEnsOverDimension, numStepAmplitude, loc%hco, loc%vco, &
 468                      datestampList=dateStampList, varNames_opt=varNameALFA, dataKind_opt=8)
 469
 470    allocate ( controlVector1(cvDim) )
 471
 472    ! x
 473    seed=1
 474    call rng_setup(abs(seed+mmpi_myid))
 475    do kIndex = 1, ens_getNumK(ensAmplitude_x)
 476      ens_oneLev => ens_getOneLev_r8(ensAmplitude_x,kIndex)
 477      do memberIndex = 1, loc%nEnsOverDimension
 478        do stepIndex = 1,numStepAmplitude
 479          do latIndex = statevector_x%myLatBeg, statevector_x%myLatEnd
 480            do lonIndex = statevector_x%myLonBeg, statevector_x%myLonEnd
 481              ens_oneLev(memberIndex,stepIndex,lonIndex,latIndex) = rng_gaussian()
 482            end do
 483          end do
 484        end do
 485      end do
 486    end do
 487
 488    ! y
 489    controlVector1 = 0.d0
 490    call loc_LsqrtAd(loc,             & ! IN
 491                     ensAmplitude_x,  & ! IN
 492                     controlVector1,  & ! OUT
 493                     amp3dStepIndex)    ! IN
 494
 495    ! Ly
 496    call loc_Lsqrt  (loc,           & ! IN
 497                     controlVector1, & ! IN
 498                     ensAmplitude_Ly,  & ! OUT
 499                     amp3dStepIndex)  ! IN
 500
 501    ! <x ,L(y)>
 502    innerProduct1_local = 0.d0
 503    call gsv_getField(statevector_Ly,field4d_Ly_r8)
 504    call gsv_getField(statevector_x, field4d_x_r8 )
 505    do memberIndex = 1, loc%nEnsOverDimension
 506      call ens_copyMember(ensAmplitude_x , statevector_x , memberIndex)
 507      call ens_copyMember(ensAmplitude_Ly, statevector_Ly, memberIndex)
 508      call euclid(innerProduct1_local, &
 509           field4d_x_r8(statevector_Ly%myLonBeg:statevector_Ly%myLonEnd,statevector_Ly%myLatBeg:statevector_Ly%myLatEnd,:,:), &
 510           field4d_Ly_r8(statevector_Ly%myLonBeg:statevector_Ly%myLonEnd,statevector_Ly%myLatBeg:statevector_Ly%myLatEnd,:,:), &
 511           statevector_Ly%myLonBeg, statevector_Ly%myLonEnd, statevector_Ly%myLatBeg, statevector_Ly%myLatEnd, statevector_Ly%nk, statevector_Ly%numStep)
 512    end do
 513    write(*,*) "<x     ,L(y)> local = ",innerProduct1_local
 514    call rpn_comm_allreduce(innerProduct1_local,innerProduct1_global,1,"mpi_double_precision","mpi_sum","GRID",ierr)
 515    write(*,*) "<x     ,L(y)> global= ",innerProduct1_global
 516    
 517    ! L_T(x)
 518    allocate ( controlVector2(cvDim) )
 519    controlVector2 = 0.d0
 520    call loc_LsqrtAd(loc,             & ! IN
 521                     ensAmplitude_x,  & ! IN
 522                     controlVector2,  & ! OUT
 523                     amp3dStepIndex)    ! IN
 524
 525    ! <L_T(x),y>
 526    innerProduct2_local = 0.d0
 527    call euclid(innerProduct2_local, controlVector2, controlVector1, 1, cvDim, 1, 1, 1, 1)
 528    print*,"<Lt(x) ,y   > local = ",innerProduct2_local
 529    call rpn_comm_allreduce(innerProduct2_local,innerProduct2_global,1,"mpi_double_precision","mpi_sum","GRID",ierr)
 530    write(*,*) "<Lt(x) ,y   > global= ",innerProduct2_global
 531    
 532    ! Results
 533    call checkAndOutputInnerProd
 534    
 535    deallocate(controlVector2)
 536    deallocate(controlVector1)
 537
 538    call gsv_deallocate(statevector_x)
 539    call gsv_deallocate(statevector_Ly)
 540
 541    call ens_deallocate(ensAmplitude_x)
 542    call ens_deallocate(ensAmplitude_Ly)
 543
 544  end subroutine check_loc
 545
 546!!$  !--------------------------------------------------------------------------
 547!!$  !- check addMem
 548!!$  !--------------------------------------------------------------------------
 549!!$  subroutine check_addmem()
 550!!$    implicit none
 551!!$
 552!!$    integer :: seed, kIndex, stepIndex, latIndex, lonIndex
 553!!$    integer :: numStepAmplitude, amp3dStepIndex, memberIndex
 554!!$
 555!!$    type(struct_ens) :: ensAmplitude_LTx
 556!!$    type(struct_ens) :: ensAmplitude_y
 557!!$
 558!!$    type(struct_loc), pointer :: loc => null()
 559!!$
 560!!$    real(8), pointer     :: ens_oneLev(:,:,:,:)
 561!!$
 562!!$    character(len=4), parameter  :: varNameALFAatm(1) = (/ 'ALFA' /)
 563!!$    character(len=4), parameter  :: varNameALFAsfc(1) = (/ 'ALFS' /)
 564!!$    character(len=4)             :: varNameALFA(1)
 565!!$
 566!!$    integer,allocatable :: dateStampList(:)
 567!!$
 568!!$    allocate(dateStampList(tim_nstepobsinc))
 569!!$    call tim_getstamplist(dateStampList,tim_nstepobsinc,tim_getDatestamp())
 570!!$
 571!!$    write(*,*) 'JFC tim_getDatestamp = ', tim_getDatestamp()
 572!!$    write(*,*) 'JFC dateStampList = ', dateStampList(:)
 573!!$
 574!!$    call ben_Setup( hco_anl, hco_core, vco_anl, & ! IN
 575!!$                    cvdim )             ! OUT
 576!!$
 577!!$    write(*,*) 'JFC ben_Setup done '
 578!!$    
 579!!$    
 580!!$    loc => ben_getLoc(1)
 581!!$    if ( cvDim /= loc%cvDim ) then
 582!!$      call utl_abort('check_loc: cvDim /= loc%cvDim')
 583!!$    end if
 584!!$    numStepAmplitude = ben_getNumStepAmplitudeAssimWindow()
 585!!$    if ( numStepAmplitude /= 1 ) then
 586!!$      call utl_abort('check_loc: not yet adapted for localization advection')
 587!!$    end if
 588!!$    amp3dStepIndex   = ben_getAmp3dStepIndexAssimWindow()
 589!!$
 590!!$    if (loc%vco%Vcode == 5002 .or. loc%vco%Vcode == 5005) then
 591!!$      varNameALFA(:) = varNameALFAatm(:)
 592!!$    else ! vco_anl%Vcode == -1
 593!!$      varNameALFA(:) = varNameALFAsfc(:)
 594!!$    end if
 595!!$
 596!!$    call gsv_allocate(statevector_x  , tim_nstepobsinc, hco_anl, vco_anl, &
 597!!$                      mpi_local_opt=.true., &
 598!!$                      allocHeight_opt=.false., allocPressure_opt=.false.)
 599!!$    call gsv_allocate(statevector_Ly , tim_nstepobsinc, hco_anl, vco_anl, &
 600!!$                      mpi_local_opt=.true., &
 601!!$                      allocHeight_opt=.false., allocPressure_opt=.false.)
 602!!$
 603!!$    call gsv_allocate(statevector_LTx  , numStepAmplitude, loc%hco, loc%vco, &
 604!!$                      mpi_local_opt=.true., varNames_opt=varNameALFA, dataKind_opt=8)
 605!!$    call gsv_allocate(statevector_y , numStepAmplitude, loc%hco, loc%vco, &
 606!!$                      mpi_local_opt=.true., varNames_opt=varNameALFA, dataKind_opt=8)
 607!!$
 608!!$    call ens_allocate(ensAmplitude_LTx, loc%nEnsOverDimension, numStepAmplitude, loc%hco, loc%vco, &
 609!!$                        datestampList=dateStampList, varNames_opt=varNameALFA, dataKind_opt=8)    
 610!!$    call ens_allocate(ensAmplitude_y, loc%nEnsOverDimension, numStepAmplitude, loc%hco, loc%vco, &
 611!!$                        datestampList=dateStampList, varNames_opt=varNameALFA, dataKind_opt=8)
 612!!$
 613!!$    ! x
 614!!$    seed=1
 615!!$    call rng_setup(abs(seed+mmpi_myid))
 616!!$    do kIndex = statevector_x%mykBeg, statevector_x%mykEnd
 617!!$      do stepIndex = 1, statevector_x%numStep
 618!!$        do latIndex = statevector_x%myLatBeg, statevector_x%myLatEnd
 619!!$          do lonIndex = statevector_x%myLonBeg, statevector_x%myLonEnd
 620!!$            statevector_x%gd_r8(lonIndex,latIndex,kIndex,stepIndex) = rng_gaussian()
 621!!$          end do
 622!!$        end do
 623!!$      end do
 624!!$    end do
 625!!$
 626!!$    ! y
 627!!$    do kIndex = 1, ens_getNumK(ensAmplitude_y)
 628!!$      ens_oneLev => ens_getOneLev_r8(ensAmplitude_y,kIndex)
 629!!$      do memberIndex = 1, loc%nEnsOverDimension
 630!!$        do stepIndex = 1,tim_nstepobsinc
 631!!$          do latIndex = statevector_x%myLatBeg, statevector_x%myLatEnd
 632!!$            do lonIndex = statevector_x%myLonBeg, statevector_x%myLonEnd
 633!!$              ens_oneLev(memberIndex,stepIndex,lonIndex,latIndex) = rng_gaussian()
 634!!$            end do
 635!!$          end do
 636!!$        end do
 637!!$      end do
 638!!$    end do
 639!!$
 640!!$    ! Ly
 641!!$    call addEnsMember( ensAmplitude_y,    & ! IN
 642!!$                       statevector_Ly,    & ! OUT 
 643!!$                       1, .false. )         ! IN
 644!!$
 645!!$    ! <x ,L(y)>
 646!!$    innerProduct1_local = 0.d0
 647!!$    call euclid(innerProduct1_local, &
 648!!$         statevector_x %gd_r8(statevector_Ly%myLonBeg:statevector_Ly%myLonEnd,statevector_Ly%myLatBeg:statevector_Ly%myLatEnd,:,:), &
 649!!$         statevector_Ly%gd_r8(statevector_Ly%myLonBeg:statevector_Ly%myLonEnd,statevector_Ly%myLatBeg:statevector_Ly%myLatEnd,:,:), &
 650!!$         statevector_Ly%myLonBeg, statevector_Ly%myLonEnd, statevector_Ly%myLatBeg, statevector_Ly%myLatEnd, statevector_Ly%nk, statevector_Ly%numStep)
 651!!$    write(*,*) "<x     ,L(y)> local = ",innerProduct1_local
 652!!$    call rpn_comm_allreduce(innerProduct1_local,innerProduct1_global,1,"mpi_double_precision","mpi_sum","GRID",ierr)
 653!!$    write(*,*) "<x     ,L(y)> global= ",innerProduct1_global
 654!!$    
 655!!$    ! L_T(x)
 656!!$    call addEnsMemberad( statevector_x,   & ! IN 
 657!!$                         ensAmplitude_LTx,  & ! OUT
 658!!$                         1, .false. )       ! IN
 659!!$
 660!!$    ! <L_T(x),y>
 661!!$    innerProduct2_local = 0.d0
 662!!$    do memberIndex = 1, loc%nEnsOverDimension
 663!!$      call ens_copyMember(ensAmplitude_LTx, statevector_LTx, memberIndex)
 664!!$      call ens_copyMember(ensAmplitude_y  , statevector_y  , memberIndex)
 665!!$      call euclid(innerProduct2_local, &
 666!!$           statevector_LTx %gd_r8(statevector_y%myLonBeg:statevector_y%myLonEnd,statevector_y%myLatBeg:statevector_y%myLatEnd,:,:), &
 667!!$           statevector_y%gd_r8(statevector_y%myLonBeg:statevector_y%myLonEnd,statevector_y%myLatBeg:statevector_y%myLatEnd,:,:), &
 668!!$           statevector_y%myLonBeg, statevector_y%myLonEnd, statevector_y%myLatBeg, statevector_y%myLatEnd, statevector_y%nk, statevector_y%numStep)
 669!!$    end do
 670!!$    print*,"<Lt(x) ,y   > local = ",innerProduct2_local
 671!!$    call rpn_comm_allreduce(innerProduct2_local,innerProduct2_global,1,"mpi_double_precision","mpi_sum","GRID",ierr)
 672!!$    write(*,*) "<Lt(x) ,y   > global= ",innerProduct2_global
 673!!$    
 674!!$    ! Results
 675!!$    call checkAndOutputInnerProd
 676!!$    
 677!!$    call gsv_deallocate(statevector_LTx)
 678!!$    call gsv_deallocate(statevector_y)
 679!!$    call gsv_deallocate(statevector_x)
 680!!$    call gsv_deallocate(statevector_Ly)
 681!!$
 682!!$    call ens_deallocate(ensAmplitude_LTx)
 683!!$    call ens_deallocate(ensAmplitude_y)
 684!!$
 685!!$  end subroutine check_addmem
 686
 687  !--------------------------------------------------------------------------
 688  !- check AdvectionENS
 689  !--------------------------------------------------------------------------
 690  subroutine check_advectionENS()
 691    implicit none
 692
 693    ! Locals:
 694    integer :: seed, kIndex, stepIndex, latIndex, lonIndex, dateStamp
 695    type(struct_adv)  :: adv_analInc
 696    type(struct_ens) :: ens_x, ens_Ly, ens_y, ens_LTx
 697    character(len=32)   :: directionAnlInc
 698    character(len=4), parameter  :: varNameALFA(1) = (/ 'ALFA' /)
 699    real(8), pointer     :: ens_oneLev(:,:,:,:)
 700    real(8), pointer     :: field4d_Ly_r8(:,:,:,:), field4d_x_r8(:,:,:,:)
 701    real(8), pointer     :: field4d_LTx_r8(:,:,:,:), field4d_y_r8(:,:,:,:)
 702    real(8) :: delT_hour
 703    real(8), allocatable :: advectFactor(:)
 704    integer :: numStepAdvect, numStepReferenceFlow, nEns, memberIndex
 705    integer,allocatable :: dateStampList(:)
 706
 707    allocate(dateStampList(tim_nstepobsinc))
 708    call tim_getstamplist(dateStampList,tim_nstepobsinc,tim_getDatestamp())
 709
 710    dateStamp = tim_getDatestamp()
 711    write(*,*) 'check_advectionENS: tim_getDatestamp = ', dateStamp
 712    write(*,*) 'check_advectionENS: dateStampList = ', dateStampList(:)
 713
 714    directionAnlInc = 'fromFirstTimeIndex' !'towardFirstTimeIndexInverse'
 715    delT_hour = 1.0d0 !tim_dstepobsinc
 716    numStepAdvect             = tim_nstepobsinc
 717    numStepReferenceFlow      = 7
 718    allocate(advectFactor(vco_anl%nLev_M))
 719    advectFactor(:) = 0.75D0
 720    nEns = 1
 721
 722    call adv_setup( adv_analInc,                                             & ! OUT
 723                    directionAnlInc, hco_anl, vco_anl,                       & ! IN
 724                    numStepAdvect, dateStampList,              & ! IN
 725                    numStepReferenceFlow, delT_hour, advectFactor,           & ! IN
 726                    'MMLevsOnly', steeringFlowFilename_opt='ensemble/forecast_for_advection' ) ! IN
 727
 728    deallocate(advectFactor)
 729    
 730    call ens_allocate(ens_x, nEns, numStepAdvect, hco_anl, vco_anl, dateStampList, &
 731                      hco_core_opt=hco_core, varNames_opt=varNameALFA, dataKind_opt=8)
 732    call ens_allocate(ens_Ly, nEns, numStepAdvect, hco_anl, vco_anl, dateStampList, &
 733                      hco_core_opt=hco_core, varNames_opt=varNameALFA, dataKind_opt=8)
 734    call ens_allocate(ens_y, nEns, numStepAdvect, hco_anl, vco_anl, dateStampList, &
 735                      hco_core_opt=hco_core, varNames_opt=varNameALFA, dataKind_opt=8)
 736    call ens_allocate(ens_LTx, nEns, numStepAdvect, hco_anl, vco_anl, dateStampList, &
 737                      hco_core_opt=hco_core, varNames_opt=varNameALFA, dataKind_opt=8)
 738
 739    call gsv_allocate(statevector_x  , tim_nstepobsinc, hco_anl, vco_anl, &
 740                      mpi_local_opt=.true., &
 741                      allocHeight_opt=.false., allocPressure_opt=.false.)
 742    call gsv_allocate(statevector_Ly , tim_nstepobsinc, hco_anl, vco_anl, &
 743                      mpi_local_opt=.true., &
 744                      allocHeight_opt=.false., allocPressure_opt=.false.)
 745    call gsv_allocate(statevector_y  , tim_nstepobsinc, hco_anl, vco_anl, &
 746                      mpi_local_opt=.true., &
 747                      allocHeight_opt=.false., allocPressure_opt=.false.)
 748    call gsv_allocate(statevector_LTx , tim_nstepobsinc, hco_anl, vco_anl, &
 749                      mpi_local_opt=.true., &
 750                      allocHeight_opt=.false., allocPressure_opt=.false.)
 751
 752    ! x
 753    seed=1
 754    call rng_setup(abs(seed+mmpi_myid))
 755    do kIndex = 1, ens_getNumK(ens_x)
 756      ens_oneLev => ens_getOneLev_r8(ens_x,kIndex)
 757      do memberIndex = 1, nEns
 758        do stepIndex = 1,tim_nstepobsinc
 759          do latIndex = statevector_x%myLatBeg, statevector_x%myLatEnd
 760            do lonIndex = statevector_x%myLonBeg, statevector_x%myLonEnd
 761              ens_oneLev(memberIndex,stepIndex,lonIndex,latIndex) = rng_gaussian()
 762            end do
 763          end do
 764        end do
 765      end do
 766    end do
 767
 768    ! y
 769    call ens_copy(ens_x, & ! IN
 770                  ens_y)  ! OUT
 771    call adv_ensemble_ad( ens_y, & ! INOUT
 772                          adv_analInc, nEns )      ! IN
 773    ! Ly
 774    call ens_copy(ens_y, ens_Ly)
 775    call adv_ensemble_tl( ens_Ly, & ! INOUT
 776                          adv_analInc, nEns )     ! IN
 777
 778    ! <x ,L(y)>
 779    innerProduct1_local = 0.d0
 780    call gsv_getField(statevector_Ly,field4d_Ly_r8)
 781    call gsv_getField(statevector_x, field4d_x_r8 )
 782    do memberIndex = 1, nEns
 783      call ens_copyMember(ens_x , statevector_x , memberIndex)
 784      call ens_copyMember(ens_Ly, statevector_Ly, memberIndex)
 785      call euclid(innerProduct1_local, &
 786           field4d_x_r8(statevector_Ly%myLonBeg:statevector_Ly%myLonEnd,statevector_Ly%myLatBeg:statevector_Ly%myLatEnd,:,:), &
 787           field4d_Ly_r8(statevector_Ly%myLonBeg:statevector_Ly%myLonEnd,statevector_Ly%myLatBeg:statevector_Ly%myLatEnd,:,:), &
 788           statevector_Ly%myLonBeg, statevector_Ly%myLonEnd, statevector_Ly%myLatBeg, statevector_Ly%myLatEnd, statevector_Ly%nk, statevector_Ly%numStep)
 789    end do
 790    write(*,*) "<x     ,L(y)> local = ",innerProduct1_local
 791    call rpn_comm_allreduce(innerProduct1_local,innerProduct1_global,1,"mpi_double_precision","mpi_sum","GRID",ierr)
 792    write(*,*) "<x     ,L(y)> global= ",innerProduct1_global
 793    
 794    ! L_T(x)
 795    call ens_copy(ens_x, & ! IN
 796                  ens_LTx)  ! OUT
 797    call adv_ensemble_ad( ens_LTx, & ! INOUT
 798                          adv_analInc, nEns )      ! IN
 799    
 800    ! <L_T(x),y>
 801    innerProduct2_local = 0.d0
 802    call gsv_getField(statevector_LTx,field4d_LTx_r8)
 803    call gsv_getField(statevector_y,  field4d_y_r8 )
 804    do memberIndex = 1, nEns
 805      call ens_copyMember(ens_LTx, statevector_LTx, memberIndex)
 806      call ens_copyMember(ens_y  , statevector_y  , memberIndex)
 807      call euclid(innerProduct2_local, &
 808           field4d_LTx_r8(statevector_y%myLonBeg:statevector_y%myLonEnd,statevector_y%myLatBeg:statevector_y%myLatEnd,:,:), &
 809           field4d_y_r8(statevector_y%myLonBeg:statevector_y%myLonEnd,statevector_y%myLatBeg:statevector_y%myLatEnd,:,:), &
 810           statevector_y%myLonBeg, statevector_y%myLonEnd, statevector_y%myLatBeg, statevector_y%myLatEnd, statevector_y%nk, statevector_y%numStep)
 811    end do
 812    print*,"<Lt(x) ,y   > local = ",innerProduct2_local
 813    call rpn_comm_allreduce(innerProduct2_local,innerProduct2_global,1,"mpi_double_precision","mpi_sum","GRID",ierr)
 814    write(*,*) "<Lt(x) ,y   > global= ",innerProduct2_global
 815    
 816    ! Results
 817    call checkAndOutputInnerProd
 818
 819    call gsv_deallocate(statevector_x)
 820    call gsv_deallocate(statevector_Ly)
 821    call gsv_deallocate(statevector_LTx)
 822    call gsv_deallocate(statevector_y)
 823
 824    call ens_deallocate(ens_x)
 825    call ens_deallocate(ens_Ly)
 826    call ens_deallocate(ens_LTx)
 827    call ens_deallocate(ens_y)
 828
 829  end subroutine check_advectionENS
 830
 831  !--------------------------------------------------------------------------
 832  !- check AdvectionGSV
 833  !--------------------------------------------------------------------------
 834  subroutine check_advectionGSV()
 835    implicit none
 836
 837    ! Locals:
 838    integer :: seed, kIndex, stepIndex, latIndex, lonIndex, dateStamp
 839    type(struct_adv)  :: adv_analInc
 840    character(len=32)   :: directionAnlInc
 841    real(8) :: delT_hour
 842    real(8), allocatable :: advectFactor(:)
 843    real(8), pointer     :: field4d_x_r8(:,:,:,:), field4d_y_r8(:,:,:,:)
 844    real(8), pointer     :: field4d_LTx_r8(:,:,:,:), field4d_Ly_r8(:,:,:,:)
 845    integer :: numStepAdvect, numStepReferenceFlow
 846    integer,allocatable :: dateStampList(:)
 847
 848    allocate(dateStampList(tim_nstepobsinc))
 849    call tim_getstamplist(dateStampList,tim_nstepobsinc,tim_getDatestamp())
 850
 851    dateStamp = tim_getDatestamp()
 852    write(*,*) 'check_advectionGSV: tim_getDatestamp = ', dateStamp
 853    write(*,*) 'check_advectionGSV: dateStampList = ', dateStampList(:)
 854
 855    directionAnlInc = 'fromFirstTimeIndex' !'towardFirstTimeIndexInverse'
 856    delT_hour = 1.0d0 !tim_dstepobsinc
 857    numStepAdvect             = tim_nstepobsinc
 858    numStepReferenceFlow      = 7
 859    advectFactor = 0.75D0
 860
 861    call adv_setup( adv_analInc,                                             & ! OUT
 862                    directionAnlInc, hco_anl, vco_anl,                       & ! IN
 863                    numStepAdvect, dateStampList,              & ! IN
 864                    numStepReferenceFlow, delT_hour, advectFactor,           & ! IN
 865                    'allLevs', steeringFlowFilename_opt='ensemble/forecast_for_advection' ) ! IN
 866
 867    call gsv_allocate(statevector_x  , tim_nstepobsinc, hco_anl, vco_anl, &
 868                      mpi_local_opt=.true., &
 869                      allocHeight_opt=.false., allocPressure_opt=.false.)
 870    call gsv_allocate(statevector_Ly , tim_nstepobsinc, hco_anl, vco_anl, &
 871                      mpi_local_opt=.true., &
 872                      allocHeight_opt=.false., allocPressure_opt=.false.)
 873    call gsv_allocate(statevector_y  , tim_nstepobsinc, hco_anl, vco_anl, &
 874                      mpi_local_opt=.true., &
 875                      allocHeight_opt=.false., allocPressure_opt=.false.)
 876    call gsv_allocate(statevector_LTx , tim_nstepobsinc, hco_anl, vco_anl, &
 877                      mpi_local_opt=.true., &
 878                      allocHeight_opt=.false., allocPressure_opt=.false.)
 879
 880    ! x
 881    seed=1
 882    call rng_setup(abs(seed+mmpi_myid))
 883    call gsv_getField(statevector_x,  field4d_x_r8 )
 884    do kIndex = statevector_x%mykBeg, statevector_x%mykEnd
 885      do stepIndex = 1, statevector_x%numStep
 886        do latIndex = statevector_x%myLatBeg, statevector_x%myLatEnd
 887          do lonIndex = statevector_x%myLonBeg, statevector_x%myLonEnd
 888            field4d_x_r8(lonIndex,latIndex,kIndex,stepIndex) = rng_gaussian()
 889          end do
 890        end do
 891      end do
 892    end do
 893
 894    ! y
 895    call gsv_getField(statevector_y,  field4d_y_r8 )
 896    do kIndex = statevector_y%mykBeg, statevector_y%mykEnd
 897      do stepIndex = 1, statevector_y%numStep
 898        do latIndex = statevector_y%myLatBeg, statevector_y%myLatEnd
 899          do lonIndex = statevector_y%myLonBeg, statevector_y%myLonEnd
 900            field4d_y_r8(lonIndex,latIndex,kIndex,stepIndex) = rng_gaussian()
 901          end do
 902        end do
 903      end do
 904    end do
 905
 906    ! Ly
 907    call gsv_copy(statevector_y, & ! IN
 908                  statevector_Ly)  ! OUT
 909    call adv_statevector_tl( statevector_Ly, & ! INOUT
 910                             adv_analInc )     ! IN
 911
 912    ! <x ,L(y)>
 913    innerProduct1_local = 0.d0
 914    call gsv_getField(statevector_x,  field4d_x_r8 )
 915    call gsv_getField(statevector_Ly, field4d_Ly_r8 )
 916    call euclid(innerProduct1_local, &
 917         field4d_x_r8(statevector_Ly%myLonBeg:statevector_Ly%myLonEnd,statevector_Ly%myLatBeg:statevector_Ly%myLatEnd,:,:), &
 918         field4d_Ly_r8(statevector_Ly%myLonBeg:statevector_Ly%myLonEnd,statevector_Ly%myLatBeg:statevector_Ly%myLatEnd,:,:), &
 919         statevector_Ly%myLonBeg, statevector_Ly%myLonEnd, statevector_Ly%myLatBeg, statevector_Ly%myLatEnd, statevector_Ly%nk, statevector_Ly%numStep)
 920    write(*,*) "<x     ,L(y)> local = ",innerProduct1_local
 921    call rpn_comm_allreduce(innerProduct1_local,innerProduct1_global,1,"mpi_double_precision","mpi_sum","GRID",ierr)
 922    write(*,*) "<x     ,L(y)> global= ",innerProduct1_global
 923    
 924    ! L_T(x)
 925    call gsv_copy(statevector_x, & ! IN
 926                  statevector_LTx)  ! OUT
 927    call adv_statevector_ad( statevector_LTx, & ! INOUT
 928                             adv_analInc )      ! IN
 929    
 930    ! <L_T(x),y>
 931    innerProduct2_local = 0.d0
 932    call gsv_getField(statevector_LTx, field4d_LTx_r8 )
 933    call gsv_getField(statevector_y,   field4d_y_r8 )
 934    call euclid(innerProduct2_local, &
 935         field4d_LTx_r8(statevector_y%myLonBeg:statevector_y%myLonEnd,statevector_y%myLatBeg:statevector_y%myLatEnd,:,:), &
 936         field4d_y_r8(statevector_y%myLonBeg:statevector_y%myLonEnd,statevector_y%myLatBeg:statevector_y%myLatEnd,:,:), &
 937         statevector_y%myLonBeg, statevector_y%myLonEnd, statevector_y%myLatBeg, statevector_y%myLatEnd, statevector_y%nk, statevector_y%numStep)
 938!    call euclid(innerProduct2_local, controlVector2, controlVector1, 1, cvDim, 1, 1, 1, 1)
 939    print*,"<Lt(x) ,y   > local = ",innerProduct2_local
 940    call rpn_comm_allreduce(innerProduct2_local,innerProduct2_global,1,"mpi_double_precision","mpi_sum","GRID",ierr)
 941    write(*,*) "<Lt(x) ,y   > global= ",innerProduct2_global
 942    
 943    ! Results
 944    call checkAndOutputInnerProd
 945
 946    call gsv_deallocate(statevector_x)
 947    call gsv_deallocate(statevector_Ly)
 948    call gsv_deallocate(statevector_LTx)
 949    call gsv_deallocate(statevector_y)
 950
 951  end subroutine check_advectionGSV
 952  
 953  !--------------------------------------------------------------------------
 954  !- Inner product computation
 955  !--------------------------------------------------------------------------
 956  subroutine euclid (pvalue,px,py,nis,nie,njs,nje,nk,nStep)
 957    implicit none
 958
 959    ! Arguments:
 960    integer, intent(in)    ::  nis
 961    integer, intent(in)    ::  nie
 962    integer, intent(in)    ::  njs
 963    integer, intent(in)    ::  nje
 964    integer, intent(in)    ::  nk
 965    integer, intent(in)    ::  nStep
 966    real(8), intent(in)    ::  px(nis:nie,njs:nje,nk,nStep)
 967    real(8), intent(in)    ::  py(nis:nie,njs:nje,nk,nStep)
 968    real(8), intent(inout) ::  pvalue
 969
 970    ! Locals:
 971    integer :: i,j,k,s
 972
 973    do s = 1, nStep
 974      do k = 1,nk
 975        do j = njs, nje
 976          do i = nis, nie
 977            pvalue = pvalue + px(i,j,k,s) * py(i,j,k,s)
 978          end do
 979        end do
 980      end do
 981    end do
 982
 983  end subroutine euclid
 984
 985  !--------------------------------------------------------------------------
 986  !- Inner product comparison
 987  !--------------------------------------------------------------------------
 988  subroutine checkAndOutputInnerProd()
 989    implicit none
 990
 991    ! Locals:
 992    integer :: fun
 993
 994    if ( mmpi_myid == 0 ) then
 995      open(newunit=fun, file="innerProd.txt", status="new", action="write")
 996      write(fun,'(A20)') test
 997      write(fun, '(G23.16)') innerProduct1_global
 998      write(fun, '(G23.16)') innerProduct2_global
 999      write(fun, '(G23.16)') innerProduct2_global-innerProduct1_global
1000      write(*,*)
1001      if ( innerProduct2_global + innerProduct1_global /= 0.d0 ) then
1002        write(fun, '(G23.16,A1)') 100.d0 * (abs(innerProduct2_global-innerProduct1_global) &
1003                                          /(0.5d0*(innerProduct2_global+innerProduct1_global)) ), &
1004                                  '%'
1005        write(*,'(A20,1X,A,1X,G23.16)') test, ": InnerProd Difference(%) = ", &
1006             100.d0 * (abs(innerProduct2_global-innerProduct1_global) / &
1007             (0.5d0*(innerProduct2_global+innerProduct1_global)) )
1008      else
1009        write(fun, '(A23)') 'InnerProduct = 0 ERROR'
1010        write(*,*) 'InnerProduct = 0 !!! Obviously, something went wrong...'
1011      end if
1012      close(fun)
1013    end if
1014
1015  end subroutine checkAndOutputInnerProd
1016
1017end program midas_adjointTest