SURFEX v7.3
General documentation of Surfex
 All Classes Files Functions Variables Typedefs
/home/dasprezs/EXPORT_v7_3/src/SURFEX/ch_emission_fluxn.F90
Go to the documentation of this file.
00001 !     #########
00002       SUBROUTINE CH_EMISSION_FLUX_n(HPROGRAM,PSIMTIME,PSFSV, PRHOA, PTSTEP, KNBTS_MAX)
00003 !     ######################################################################
00004 !!
00005 !!***  *CH_EMISSION_FLUX_n* - 
00006 !!
00007 !!    PURPOSE
00008 !!    -------
00009 !!      Return a time-dependent emission flux based on tabulated values
00010 !!
00011 !!**  METHOD
00012 !!    ------
00013 !!
00014 !!    AUTHOR
00015 !!    ------
00016 !!    D. Gazen
00017 !!
00018 !!    MODIFICATIONS
00019 !!    -------------
00020 !!    Original 08/02/00
00021 !!    C. Mari  30/10/00 call to MODD_TYPE_EFUTIL and MODD_CST
00022 !!    D.Gazen  01/12/03  change emissions handling for surf. externalization
00023 !!    P.Tulet  01/01/04  change emission conversion factor
00024 !!    P.Tulet  01/01/05  add dust, orilam
00025 !!
00026 !!    EXTERNAL
00027 !!    --------
00028 !!
00029 !!
00030 !!    IMPLICIT ARGUMENTS
00031 !!    ------------------
00032 USE MODD_SV_n,             ONLY: CSV,NSV_CHSBEG,NSV_CHSEND, NSV_AERBEG,  NSV_AEREND
00033 USE MODD_TYPE_EFUTIL,      ONLY: EMISSVAR_T, PRONOSVAR_T
00034 USE MODD_CSTS,             ONLY: NDAYSEC
00035 USE MODD_CH_EMIS_FIELD_n,  ONLY: TSEMISS, TSPRONOSLIST, XTIME_SIMUL
00036 USE MODD_CH_SURF_n,        ONLY: XCONVERSION
00037 !
00038 USE MODI_READ_SURF
00039 USE MODI_INIT_IO_SURF_n
00040 USE MODI_END_IO_SURF_n
00041 USE MODI_GET_LUOUT
00042 !UPG*AERO1
00043 USE MODD_CHS_AEROSOL, ONLY: LCH_AERO_FLUX
00044 USE MODI_CH_AER_EMISSION
00045 !UPG*AERO1
00046 !!
00047 !------------------------------------------------------------------------------
00048 !
00049 !*       0.   DECLARATIONS
00050 !        -----------------
00051 !
00052 USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
00053 USE PARKIND1  ,ONLY : JPRB
00054 !
00055 USE MODI_ABOR1_SFX
00056 !
00057 IMPLICIT NONE
00058 !
00059 !*       0.1  declaration of arguments
00060 !
00061  CHARACTER(LEN=6),   INTENT(IN)  :: HPROGRAM    ! program calling surf. schemes
00062 REAL,               INTENT(IN)  :: PSIMTIME    ! time of simulation in sec UTC
00063                                                ! (counting from midnight of
00064                                                ! the current day)
00065 REAL,DIMENSION(:,:),  INTENT(INOUT) :: PSFSV   ! emission flux in ppp*m/s
00066 REAL, DIMENSION(:),   INTENT(IN)    :: PRHOA     ! air density (kg/m3)
00067 REAL,                 INTENT(IN)    :: PTSTEP    ! atmospheric time-step                 (s)
00068 INTEGER,              INTENT(IN)    :: KNBTS_MAX !max size of TEMISS%NETIMES
00069 
00070 !
00071 !*       0.2  declaration of local variables
00072 !
00073 INTEGER       :: IVERB   ! verbosity level
00074 INTEGER       :: KSIZE1D ! 1D size = X*Y physical domain 
00075 INTEGER       :: JI      ! loop control
00076 REAL          :: ZALPHA  ! interpolation weight
00077 !
00078 INTEGER :: INBTS       ! Number of emission times for a species
00079 INTEGER :: ITIM1,ITIM2 ! first/last time for interpolation
00080 INTEGER :: INDX1,INDX2 ! first/next index for data interpolation
00081 INTEGER :: ISIMTIME, ITPERIOD
00082  CHARACTER (LEN=16)  :: YRECFM          ! LFI article name
00083 TYPE(PRONOSVAR_T),POINTER :: CURPRONOS !Current pronostic variable
00084 !
00085 !*       0.3  declaration of saved local variables
00086 !
00087  CHARACTER(LEN=6), DIMENSION(:), POINTER :: CNAMES
00088 REAL,DIMENSION(SIZE(PSFSV,1),KNBTS_MAX)     :: ZWORK ! temporary array for reading data
00089 REAL,DIMENSION(SIZE(PSFSV,1),SIZE(PSFSV,2)) :: ZEMIS ! interpolated in time emission flux
00090 REAL,DIMENSION(SIZE(PSFSV,1))               :: ZFCO  ! CO flux
00091 INTEGER                          :: INEQ  ! number of chemical var
00092                                           !(=NEQ (chimie gaz) + NSV_AER (chimie aerosol)
00093 INTEGER                          :: IWS   ! window size
00094 INTEGER                          :: IRESP ! return code for I/O
00095 INTEGER                          :: ILUOUT ! Outputlisting unit
00096 LOGICAL                          :: LIOINIT ! True if I/O init done
00097 INTEGER                          :: JW
00098 INTEGER                          :: ITIME
00099 LOGICAL                          :: GCO = .FALSE. ! switch if CO emission are available
00100 REAL(KIND=JPRB) :: ZHOOK_HANDLE
00101 !
00102 !------------------------------------------------------------------------------
00103 !
00104 !*    EXECUTABLE STATEMENTS
00105 !     ---------------------
00106 !
00107 IF (LHOOK) CALL DR_HOOK('CH_EMISSION_FLUX_N',0,ZHOOK_HANDLE)
00108  CALL GET_LUOUT(HPROGRAM,ILUOUT)
00109 LIOINIT = .FALSE.
00110 IVERB   = 5
00111 KSIZE1D = SIZE(PSFSV,1)
00112 INEQ    = SIZE(PSFSV,2)
00113 !
00114 !------------------------------------------------------------------------------
00115 !
00116 !*    3.  INTERPOLATE SURFACE FLUXES IN TIME IF NEEDED
00117 !     ------------------------------------------------
00118 !
00119 IF (XTIME_SIMUL == 0.) THEN
00120    XTIME_SIMUL = PSIMTIME
00121 ELSE
00122    XTIME_SIMUL = XTIME_SIMUL + PTSTEP
00123 END IF
00124 
00125 IF (IVERB >= 5) WRITE(ILUOUT,*) '******** CH_EMISSION_FLUX  ********'
00126 DO JI=1,SIZE(TSEMISS)
00127 ! Simulation time (counting from midnight) is saved
00128   ISIMTIME = XTIME_SIMUL
00129 !
00130   INBTS = SIZE(TSEMISS(JI)%NETIMES) ! 
00131   IWS   = TSEMISS(JI)%NWS           ! Window Size for I/O
00132   INDX1 = TSEMISS(JI)%NDX           ! Current data index
00133 !
00134   IF (INBTS == 1) THEN
00135 !   Time Constant Flux
00136 !   XFWORK already points on data (see ch_buildemiss.f90)
00137     IF (IVERB >= 6) THEN
00138       WRITE(ILUOUT,*) 'NO interpolation for ',TRIM(TSEMISS(JI)%CNAME)
00139       IF (IVERB >= 10 ) WRITE(ILUOUT,*) TSEMISS(JI)%XFWORK
00140     END IF
00141   ELSE
00142     IF (IVERB >= 6) THEN
00143       WRITE(ILUOUT,*) 'Interpolation (T =',ISIMTIME,') : ',TSEMISS(JI)%CNAME
00144     END IF
00145     IF (ISIMTIME < TSEMISS(JI)%NETIMES(1)) THEN
00146 !     Tsim < T(1)=Tmin should not happen but who knows ?
00147       TSEMISS(JI)%NTX = 1
00148     ELSE
00149 !     Check for periodicity when ISIMTIME is beyond last emission time
00150 !     and probably correct ISIMTIME
00151       IF (ISIMTIME > TSEMISS(JI)%NETIMES(INBTS)) THEN 
00152 !       Tsim > T(INBTS)=Tmax
00153         ITPERIOD = (1+(TSEMISS(JI)%NETIMES(INBTS)-&
00154                 TSEMISS(JI)%NETIMES(TSEMISS(JI)%NPX))/NDAYSEC)*NDAYSEC  
00155         ISIMTIME = MODULO(ISIMTIME-TSEMISS(JI)%NETIMES(TSEMISS(JI)%NPX),ITPERIOD)+&
00156                 TSEMISS(JI)%NETIMES(TSEMISS(JI)%NPX)  
00157         IF (IVERB >= 6) THEN
00158           WRITE(ILUOUT,*) '  ITPERIOD = ', ITPERIOD
00159           WRITE(ILUOUT,*) '  ISIMTIME modifie = ', ISIMTIME
00160         END IF
00161         IF (TSEMISS(JI)%NTX == INBTS .AND. ISIMTIME<TSEMISS(JI)%NETIMES(INBTS)) THEN
00162 !         Update time index NTX 
00163           TSEMISS(JI)%NTX = TSEMISS(JI)%NPX
00164 !         Increment data index NDX : NDX correction will occur later
00165 !                                    to assure 1 <= NDX <= IWS
00166           INDX1 = INDX1 + 1
00167         END IF
00168       END IF
00169 !
00170 !     search NTX such that : ETIMES(NTX) < ISIMTIME <= ETIMES(NTX+1)
00171 !     and make NDX follow NTX : NDX correction will occur later
00172 !                               to assure 1 <= NDX <= IWS
00173       DO WHILE (TSEMISS(JI)%NTX < INBTS)
00174         IF (ISIMTIME >= TSEMISS(JI)%NETIMES(TSEMISS(JI)%NTX+1)) THEN
00175           TSEMISS(JI)%NTX = TSEMISS(JI)%NTX + 1
00176           INDX1 = INDX1 + 1
00177           INDX2 = INDX1 + 1
00178         ELSE
00179           EXIT
00180         END IF
00181       END DO
00182     END IF
00183 !
00184 !   Check availability of data within memory Window (XEMISDATA(:,1:IWS))
00185     IF (INDX1 >= IWS) THEN
00186 !
00187 !     Data index reached the memory window limits
00188 !
00189       IF (TSEMISS(JI)%LREAD) THEN 
00190 !
00191 !       File must be read to update XEMISDATA array for this species 
00192 !
00193         IF (.NOT. LIOINIT) THEN
00194 !         Must be done once before reading
00195           CALL INIT_IO_SURF_n(HPROGRAM,'FULL  ','SURF  ','READ ')
00196           IF (IVERB >= 6) WRITE(ILUOUT,*) 'INIT des I/O DONE.'
00197           LIOINIT=.TRUE.
00198         END IF
00199         YRECFM='EMIS_'//TRIM(TSEMISS(JI)%CNAME)
00200         IF (IVERB >= 6)&
00201                WRITE (ILUOUT,*) 'READ emission :',TRIM(YRECFM),&
00202                ', SIZE(ZWORK)=',SIZE(ZWORK,1),INBTS 
00203         CALL READ_SURF(HPROGRAM,YRECFM,ZWORK(:,1:INBTS),IRESP)
00204 !
00205 ! Correction : Replace 999. with 0. value in the Emission FLUX
00206         WHERE(ZWORK(:,1:INBTS) == 999.)
00207           ZWORK(:,1:INBTS) = 0. 
00208         END WHERE
00209         WHERE(ZWORK(:,1:INBTS) == 1.E20)
00210           ZWORK(:,1:INBTS) = 0. 
00211         END WHERE
00212         DO ITIME=1,INBTS
00213         ZWORK(:,ITIME) = ZWORK(:,ITIME)*XCONVERSION(:)
00214         END DO
00215 !
00216 !       
00217         IF ((TSEMISS(JI)%NTX+IWS-1) > INBTS) THEN
00218 !
00219 !         ===== Periodic CASE =====
00220 !
00221           IF (IVERB >= 6)&
00222                  WRITE (ILUOUT,*) 'Periodic CASE : NPX =',TSEMISS(JI)%NPX  
00223           IF (IWS <  (INBTS-TSEMISS(JI)%NPX+1)) THEN
00224 !           Window size is smaller then number of periodical times
00225 !
00226 !           example : IWS=5, NPX=2, INBTS=11, NTX=9
00227 !                               NTX       NPX
00228 !                                |         |
00229 !           time index :      ...9 10 11 # 2 3 4...11 #
00230 !       old data index :[1 2 3 4 5] 
00231 !       new data index :        [1  2  3   4 5]
00232 !                                |  
00233 !                               NDX    
00234 !
00235             TSEMISS(JI)%XEMISDATA(:,1:INBTS-TSEMISS(JI)%NTX+1) = &
00236                    ZWORK(:,TSEMISS(JI)%NTX:INBTS)  
00237 !
00238             IF (IVERB >= 6) THEN
00239               WRITE(ILUOUT,*) 'Window SIZE smaller than INBTS !'
00240               WRITE(ILUOUT,*) 'Window index, Time index'
00241               DO JW=1,INBTS-TSEMISS(JI)%NTX+1
00242                 WRITE(ILUOUT,*) JW,TSEMISS(JI)%NTX+JW-1
00243               END DO
00244             END IF
00245 !
00246             TSEMISS(JI)%XEMISDATA(:,INBTS-TSEMISS(JI)%NTX+2:IWS) = &
00247                    ZWORK(:,TSEMISS(JI)%NPX:TSEMISS(JI)%NPX+IWS-INBTS+TSEMISS(JI)%NTX-2)  
00248 !
00249             IF (IVERB >= 6) THEN
00250               DO JW=INBTS-TSEMISS(JI)%NTX+2,IWS
00251                 WRITE(ILUOUT,*) JW,TSEMISS(JI)%NPX+JW-(INBTS-TSEMISS(JI)%NTX+2)
00252               END DO
00253             END IF
00254             INDX1 = 1
00255             INDX2 = 2
00256           ELSE
00257 !           Window size may get smaller AND it will be the last reading
00258 !
00259 !           example : IWS=6, NPX=7, INBTS=11, NTX=9
00260 !
00261 !                         NTX       NPX NTX
00262 !                          |         |   |
00263 !           time index: ...9 10 11 # 7 8 9 10 11 #
00264 !       old data index: ...6]
00265 !       new data index:             [1 2 3  4  5]
00266 !                                        |
00267 !                                       NDX=NTX-NPX+1
00268 !
00269             IWS = INBTS-TSEMISS(JI)%NPX+1
00270             TSEMISS(JI)%NWS = IWS
00271             TSEMISS(JI)%XEMISDATA(:,1:IWS) = ZWORK(:,TSEMISS(JI)%NPX:INBTS)
00272             IF (IVERB >= 6) THEN
00273               WRITE(ILUOUT,*) 'Window SIZE equal or greater than INBTS !'
00274               WRITE(ILUOUT,*) 'Window index, Time index'
00275               DO JW=1,IWS
00276                 WRITE(ILUOUT,*) JW,TSEMISS(JI)%NPX+JW-1
00277               END DO
00278             END IF
00279             INDX1 = TSEMISS(JI)%NTX-TSEMISS(JI)%NPX+1
00280             INDX2 = MOD((INDX1+1),IWS)
00281             TSEMISS(JI)%LREAD = .FALSE. ! no more reading
00282           END IF
00283         ELSE
00284 !
00285 !         ===== NON periodic (normal) CASE =====
00286 !
00287 ! example : with IWS=5, the window moves forward
00288 !                             NTX
00289 !                              | 
00290 !         time index : 1 2 3 4 5 6 7 8 9 10 11 ... INBTS # 
00291 !     old data index :[1 2 3 4 5] 
00292 !     new data index :        [1 2 3 4 5] 
00293 !                              |
00294 !                             NDX
00295 !
00296           TSEMISS(JI)%XEMISDATA(:,1:IWS) = ZWORK(:,TSEMISS(JI)%NTX:TSEMISS(JI)%NTX+IWS-1)
00297           IF (IVERB >= 6) THEN
00298             WRITE(ILUOUT,*) 'Window index, Time index'
00299             DO JW=1,IWS
00300               WRITE(ILUOUT,*) JW,TSEMISS(JI)%NTX+JW-1
00301             END DO
00302           END IF
00303           INDX1 = 1
00304           INDX2 = 2
00305         END IF
00306       ELSE
00307 !       Data is already in memory because window size is sufficient 
00308 !       to hold INBTS emission times => simply update NDX according to NTX
00309 !       
00310         IF (IWS==INBTS) THEN 
00311 !
00312 !         'Window size' = 'Nb emis times' at INIT (ch_init_emission)
00313 !         so NDX must be set equal to NTX (the window does not move)
00314 ! example :
00315 !                         NPX    NTX
00316 !                          |      | 
00317 !         time index :  1  2  3  ... INBTS
00318 !         data index : [1  2  3  ... INBTS]
00319 !                                 |
00320 !                                NDX
00321 
00322           INDX1 = TSEMISS(JI)%NTX
00323           INDX2 = INDX1+1
00324           IF (INDX2 > IWS) INDX2=TSEMISS(JI)%NPX
00325         ELSE
00326 !          
00327 !         Windows size changed during periodic case
00328 !         NDX must be equal to NTX - NPX + 1
00329 !         (the window does not move)
00330 ! example :
00331 !                                NTX
00332 !                                 | 
00333 !         time index : NPX NPX+1 NPX+2 ... INBTS
00334 !         data index : [1    2    3    ...   IWS]
00335 !                                 |
00336 !                                NDX
00337           INDX1 = TSEMISS(JI)%NTX-TSEMISS(JI)%NPX+1
00338           INDX2 = MOD((INDX1+1),IWS)
00339         END IF
00340       END IF
00341     ELSE ! (INDX1 < IWS)
00342       INDX2 = INDX1+1
00343     END IF
00344 !
00345 !   Don't forget to update NDX with new value INDX1
00346     TSEMISS(JI)%NDX = INDX1
00347 !
00348 !   Compute both times for interpolation
00349     IF (TSEMISS(JI)%NTX < INBTS) THEN 
00350       ITIM1 = TSEMISS(JI)%NETIMES(TSEMISS(JI)%NTX)
00351       ITIM2 = TSEMISS(JI)%NETIMES(TSEMISS(JI)%NTX+1)
00352     ELSE
00353       ITIM1 = TSEMISS(JI)%NETIMES(INBTS)
00354       ITIM2 = TSEMISS(JI)%NETIMES(TSEMISS(JI)%NPX)+ITPERIOD
00355     END IF
00356 !
00357 ! Interpolate variables in time -> update XFWORK
00358 !
00359 !
00360 !  time       :  ITIM1...Tsim...ITIM2
00361 !                  |              |  
00362 !  data index :  INDX1          INDX2
00363 !
00364 !
00365     ZALPHA = (REAL(ISIMTIME) - ITIM1) / (ITIM2-ITIM1)
00366     TSEMISS(JI)%XFWORK(:) = ZALPHA*TSEMISS(JI)%XEMISDATA(:,INDX2) +&
00367             (1.-ZALPHA)*TSEMISS(JI)%XEMISDATA(:,INDX1)  
00368     IF (IVERB >= 6) THEN
00369       WRITE(ILUOUT,*) '  Current time INDEX : ',TSEMISS(JI)%NTX
00370       WRITE(ILUOUT,*) '  TIME : ',ISIMTIME, ' (',ITIM1,',',ITIM2,')'
00371       WRITE(ILUOUT,*) '  Window size : ',TSEMISS(JI)%NWS
00372       WRITE(ILUOUT,*) '  Current data INDEX : ',INDX1,INDX2
00373       IF (IVERB >= 10) WRITE(ILUOUT,*) '  FLUX : ',TSEMISS(JI)%XFWORK
00374     END IF
00375   END IF
00376 END DO
00377 ! 
00378 ! Agregation : flux computation
00379 !
00380 ZEMIS(:,:) = 0.
00381 !
00382 ! Point on head of Pronostic variable list
00383 ! to cover the entire list.
00384 IF (NSV_AEREND > 0) THEN
00385 CNAMES=>CSV(NSV_CHSBEG:NSV_AEREND)
00386 ELSE
00387 CNAMES=>CSV(NSV_CHSBEG:NSV_CHSEND)
00388 END IF
00389 CURPRONOS=>TSPRONOSLIST
00390 DO WHILE(ASSOCIATED(CURPRONOS))
00391   IF (CURPRONOS%NAMINDEX > INEQ) THEN
00392     WRITE(ILUOUT,*) 'FATAL ERROR in CH_EMISSION_FLUXN : SIZE(ZEMIS,2) =',&
00393            INEQ,', INDEX bugge =',CURPRONOS%NAMINDEX  
00394     CALL ABOR1_SFX('CH_EMISSION_FLUXN: FATAL ERROR')
00395   END IF
00396   
00397   ZEMIS(:,CURPRONOS%NAMINDEX) = 0.
00398 !
00399 ! Loop on the number of agreg. coeff.
00400   DO JI=1,CURPRONOS%NBCOEFF
00401 !   Compute agregated flux    
00402     ZEMIS(:,CURPRONOS%NAMINDEX) = ZEMIS(:,CURPRONOS%NAMINDEX)+&
00403             CURPRONOS%XCOEFF(JI)*TSEMISS(CURPRONOS%NEFINDEX(JI))%XFWORK(:)  
00404   END DO
00405 
00406   IF (IVERB >= 6) THEN
00407     WRITE(ILUOUT,*) 'Agregation for ',CNAMES(CURPRONOS%NAMINDEX)
00408     IF (IVERB >= 10) WRITE(ILUOUT,*) 'ZEMIS = ',ZEMIS(:,CURPRONOS%NAMINDEX)
00409   END IF
00410   IF ((CNAMES(CURPRONOS%NAMINDEX) == "CO") .AND. ANY(ZEMIS(:,CURPRONOS%NAMINDEX).GT.0.)) THEN
00411   ZFCO(:) = ZEMIS(:,CURPRONOS%NAMINDEX)
00412   GCO = .TRUE.
00413   END IF
00414 
00415   CURPRONOS=>CURPRONOS%NEXT
00416 !
00417 END DO
00418 !
00419 IF ((LCH_AERO_FLUX).AND.(NSV_AERBEG > 0)) THEN
00420   IF (GCO) THEN
00421     CALL CH_AER_EMISSION(ZEMIS, PRHOA, CSV, NSV_CHSBEG, PFCO=ZFCO)
00422   ELSE
00423     CALL CH_AER_EMISSION(ZEMIS, PRHOA, CSV, NSV_CHSBEG)
00424   ENDIF
00425 END IF
00426 !
00427 PSFSV(:,:) = PSFSV(:,:) + ZEMIS(:,:)
00428 !
00429 IF (LIOINIT) CALL END_IO_SURF_n(HPROGRAM)
00430 !
00431 IF (IVERB >= 6) WRITE(ILUOUT,*) '******** END CH_EMISSION_FLUX  ********'
00432 IF (LHOOK) CALL DR_HOOK('CH_EMISSION_FLUX_N',1,ZHOOK_HANDLE)
00433 !
00434 END SUBROUTINE CH_EMISSION_FLUX_n