123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761 |
- !#################################################################
- !
- ! tracer mass
- !
- !### macro's #####################################################
- !
- #define TRACEBACK write (gol,'("in ",a," (",a,", line",i5,")")') rname, __FILE__, __LINE__; call goErr
- #define IF_NOTOK_RETURN(action) if (status/=0) then; TRACEBACK; action; return; end if
- #define IF_ERROR_RETURN(action) if (status> 0) then; TRACEBACK; action; return; end if
- !
- #include "tm5.inc"
- !
- !#################################################################
- !
- ! Declare non-transported tracers : chem_data (type), chem_dat (var)
- ! Declare transported tracers : mass_data (type), mass_dat (var)
- ! Allocate both transported and non-transported tracers : tracer_init
- ! Free allocated tracers : tracer_done
- !
- MODULE TRACER_DATA
- use GO, only : gol, goErr, goPr
- use dims, only : nregions
- use tm5_distgrid, only : dgrid, Get_DistGrid
- IMPLICIT NONE
- PRIVATE
-
- public :: mass_data, mass_dat ! type and array for transported tracers
- public :: chem_data, chem_dat ! type and array for non-transported tracers
- public :: tracer_init ! allocate tracers arrays
- public :: tracer_done ! deallocate tracers arrays
-
- public :: AdjustTracer
- public :: tracer_print ! tracer and air masses in one box (location hardwire)
- public :: par_check_mass ! print min/max/total of Air, All-tracers, and one tracer
- public :: init_short ! init non-transported tracers (used when istart=4 or 5)
- #ifndef __GFORTRAN__
- public :: init_non_zero ! init tracer to small non-zero (used when istart=2)
- #endif
- #ifdef with_feedback
- public :: Tracer_Fill_Slabs
- #endif
-
- ! --- const --------------------------------------
- character(len=*), parameter :: mname = 'tracer_data'
- TYPE MASS_DATA ! --- TRANSPORTED TRACERS
- !
- ! All to be allocated with halo=2
- !
- ! rm tracer masses (kg)
- ! rxm tracer slopes in kg/(halfgridsize)
- ! rym tracer slopes in kg/(halfgridsize)
- ! rzm tracer slopes in kg/(halfgridsize)
- !
- real,dimension(:,:,:,:),pointer :: rm
- #ifdef slopes
- real,dimension(:,:,:,:),pointer :: rxm
- real,dimension(:,:,:,:),pointer :: rym
- real,dimension(:,:,:,:),pointer :: rzm
- #ifdef secmom
- real,dimension(:,:,:,:),pointer :: rxxm
- real,dimension(:,:,:,:),pointer :: rxym
- real,dimension(:,:,:,:),pointer :: rxzm
- real,dimension(:,:,:,:),pointer :: ryym
- real,dimension(:,:,:,:),pointer :: ryzm
- real,dimension(:,:,:,:),pointer :: rzzm
- #endif
- #endif
- integer :: halo
- END TYPE MASS_DATA
-
- TYPE CHEM_DATA ! --- NON-TRANSPORTED TRACERS
- real,dimension(:,:,:,:),pointer :: rm
- integer :: halo
- END TYPE CHEM_DATA
-
- ! --- VAR ------------------------------
-
- ! transported tracer masses
- type(mass_data), target :: mass_dat(nregions)
-
- ! non-transported tracer masses
- ! Note expected 4th dim : (:,:,:,ntracet+1:ntracet+ntrace_chem)
- type(chem_data), target :: chem_dat(nregions)
- CONTAINS
- !
- ! ======================================================================
- !
- SUBROUTINE TRACER_INIT
- use dims, only : lm
- use chem_param, only : ntracet, ntrace_chem
- integer :: i1, i2, j1, j2
- integer :: n, l_halo
- l_halo = 2 ! to adapt accordingly
-
- ! allocate transported tracers
- do n=1, nregions
- call Get_DistGrid( dgrid(n), I_STRT=i1, I_STOP=i2, &
- J_STRT=j1, J_STOP=j2 )
- mass_dat(n)%halo = l_halo
-
- allocate( mass_dat(n)%rm( i1-l_halo:i2+l_halo, j1-l_halo:j2+l_halo, lm(n), ntracet) )
- #ifdef slopes
- allocate( mass_dat(n)%rxm( i1-l_halo:i2+l_halo, j1-l_halo:j2+l_halo, lm(n), ntracet) )
- allocate( mass_dat(n)%rym( i1-l_halo:i2+l_halo, j1-l_halo:j2+l_halo, lm(n), ntracet) )
- allocate( mass_dat(n)%rzm( i1-l_halo:i2+l_halo, j1-l_halo:j2+l_halo, lm(n), ntracet) )
- #ifdef secmom
- allocate( mass_dat(n)%rxxm( i1-l_halo:i2+l_halo, j1-l_halo:j2+l_halo, lm(n), ntracet) )
- allocate( mass_dat(n)%rxym( i1-l_halo:i2+l_halo, j1-l_halo:j2+l_halo, lm(n), ntracet) )
- allocate( mass_dat(n)%rxzm( i1-l_halo:i2+l_halo, j1-l_halo:j2+l_halo, lm(n), ntracet) )
- allocate( mass_dat(n)%ryym( i1-l_halo:i2+l_halo, j1-l_halo:j2+l_halo, lm(n), ntracet) )
- allocate( mass_dat(n)%ryzm( i1-l_halo:i2+l_halo, j1-l_halo:j2+l_halo, lm(n), ntracet) )
- allocate( mass_dat(n)%rzzm( i1-l_halo:i2+l_halo, j1-l_halo:j2+l_halo, lm(n), ntracet) )
- #endif
- #endif
-
- mass_dat(n)%rm =0.0
- #ifdef slopes
- mass_dat(n)%rxm=0.0
- mass_dat(n)%rym=0.0
- mass_dat(n)%rzm=0.0
- #ifdef secmom
- mass_dat(n)%rxxm=0.0
- mass_dat(n)%rxym=0.0
- mass_dat(n)%rxzm=0.0
- mass_dat(n)%ryym=0.0
- mass_dat(n)%ryzm=0.0
- mass_dat(n)%rzzm=0.0
- #endif
- #endif
- ! allocate non-transported tracers, if any
- if ( ntrace_chem > 0 ) then
- chem_dat(n)%halo = 0
- allocate( chem_dat(n)%rm(i1:i2, j1:j2, lm(n), ntracet+1:ntracet+ntrace_chem) )
- chem_dat(n)%rm = 0.0
- else
- nullify( chem_dat(n)%rm )
- end if
- end do
-
- END SUBROUTINE TRACER_INIT
- !
- ! ======================================================================
- !
- SUBROUTINE TRACER_DONE
- USE CHEM_PARAM, ONLY : NTRACE_CHEM
- integer :: n
- ! allocate transported tracers
- do n=1, nregions
- ! deallocate transported tracers
- if(associated( mass_dat(n)%rm)) nullify( mass_dat(n)%rm)
- #ifdef slopes
- if(associated( mass_dat(n)%rxm)) nullify( mass_dat(n)%rxm)
- if(associated( mass_dat(n)%rym)) nullify( mass_dat(n)%rym)
- if(associated( mass_dat(n)%rzm)) nullify( mass_dat(n)%rzm)
- #ifdef secmom
- if(associated( mass_dat(n)%rxxm)) nullify( mass_dat(n)%rxxm)
- if(associated( mass_dat(n)%rxym)) nullify( mass_dat(n)%rxym)
- if(associated( mass_dat(n)%rxzm)) nullify( mass_dat(n)%rxzm)
- if(associated( mass_dat(n)%ryym)) nullify( mass_dat(n)%ryym)
- if(associated( mass_dat(n)%ryzm)) nullify( mass_dat(n)%ryzm)
- if(associated( mass_dat(n)%rzzm)) nullify( mass_dat(n)%rzzm)
- #endif
- #endif
- ! deallocate non-transported tracers, if any
- if ( ntrace_chem > 0 ) then
- if(associated( chem_dat(n)%rm)) nullify( chem_dat(n)%rm)
- end if
-
- end do
-
- END SUBROUTINE TRACER_DONE
-
- !------------------------------------------------------------------------------
- ! TM5 !
- !------------------------------------------------------------------------------
- !BOP
- !
- ! !IROUTINE: INIT_SHORT
- !
- ! !DESCRIPTION: Initialise short lived chemical compounds to a reasonable
- ! value e.g NO2 = NOX. It is called from initexit/start when istart=4 or 5.
- !\\
- !\\
- ! !INTERFACE:
- !
- SUBROUTINE INIT_SHORT( region )
- !
- ! !USES:
- !
- use tm5_distgrid, only : dgrid, Get_DistGrid
- use chem_param, only : ino2, inox
- !
- ! !INPUT PARAMETERS:
- !
- integer, intent(in) :: region
- !
- ! !REVISION HISTORY:
- ! 7 May 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
- !
- !EOP
- !------------------------------------------------------------------------------
- !BOC
- integer :: i1,j1,j2,i2
- call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
- if ( (ino2 > 0) .and. (inox > 0)) then
- chem_dat(region)%rm(i1:i2, j1:j2, :, ino2) = mass_dat(region)%rm(i1:i2, j1:j2, :, inox)
- endif
- END SUBROUTINE INIT_SHORT
- !EOC
- #ifndef __GFORTRAN__
- !------------------------------------------------------------------------------
- ! TM5 !
- !------------------------------------------------------------------------------
- !BOP
- !
- ! !IROUTINE: INIT_NON_ZERO
- !
- ! !DESCRIPTION: Set tracer initial values to some small value.
- ! It is called from initexit/start when ISTART = 2.
- !\\
- !\\
- SUBROUTINE INIT_NON_ZERO
- !
- ! !USES:
- !
- use chem_param, only : fscale, ntracet, ntrace, ntrace_chem, ino2, inox
- use meteodata, only : m_dat
- !
- ! !REVISION HISTORY:
- ! 2 Apr 2010 - P. Le Sager -
- !
- ! !REMARKS:
- ! - A remnant from old debugging/benchmark. Has one advantage: can be
- ! used to set to non-zero start values, which is important for chemistry.
- ! - Could be set to values based on process number for debugging. See commented code.
- !EOP
- !------------------------------------------------------------------------------
- !BOC
- real, dimension(:,:,:,:), pointer :: rm
- #ifdef slopes
- real, dimension(:,:,:,:), pointer :: rxm, rym, rzm
- #ifdef secmom
- real, dimension(:,:,:,:), pointer :: rxxm, rxym, rxzm, ryym, ryzm, rzzm
- #endif
- #endif
- integer :: rank, i0, i1, j0, j1, n, region
- real, dimension(:,:,:), pointer :: m
- ! --- begin --------------------------------
- do region=1,nregions
- call Get_DistGrid( dgrid(region), I_STRT=i0, I_STOP=i1, J_STRT=j0, J_STOP=j1 )
- ! pseudo-random number ( for now just retrieve rank )
- rank = ( i1 / (i1-i0) ) * ( j1 / (j1-j0) ) - 1
- m => m_dat(region)%data
- do n=1,ntracet
- mass_dat(region)%rm(:,:,:,n) = 1e-30 * m / fscale(n)
- !--for something not totally uniform and processor dependant
- ! ! fill transported tracers
- ! do n=1,ntracet
- ! mass_dat(region)%rm( i0:i1, j0:j1,:,n) = (rank+1)*1e-9*m/fscale(n)
- ! enddo
- enddo
- ! non-transported tracers
- if ( ntrace_chem > 0 ) then
- do n=ntracet+1,ntrace
- chem_dat(region)%rm(:,:,:,n) = 1e-30 * m/fscale(n)
- end do
- endif
- if ( (ino2 > 0) .and. (inox > 0)) then
- chem_dat(region)%rm(:,:,:,ino2) = mass_dat(region)%rm(:,:,:,inox)
- endif
- #ifdef slopes
- mass_dat(region)%rxm = 0.0
- mass_dat(region)%rym = 0.0
- mass_dat(region)%rzm = 0.0
- #ifdef secmom
- mass_dat(region)%rxxm = 0.0
- mass_dat(region)%rxym = 0.0
- mass_dat(region)%rxzm = 0.0
- mass_dat(region)%ryym = 0.0
- mass_dat(region)%ryzm = 0.0
- mass_dat(region)%rzzm = 0.0
- #endif
- #endif
- nullify(m)
- enddo
- !write(gol,*) ' rm initialized at mixing ratio of 1e-30' ; call goPr
- END SUBROUTINE INIT_NON_ZERO
- !EOC
- #endif
-
-
- !
- ! Tracer slopes (kg/half cell) and second moments (kg/(half cell)^2)
- ! are adjusted with the same factor as applied to the total mass
- ! (background: if the concentration 'in the middle' is decreased
- ! by a factor 0.5, then the concentrations at the boundaries are
- ! also changed with a factor 0.5 :
- !
- ! ^ | | | |
- ! tracer| 6 | o | |
- ! mass | | - | | |
- ! (kg) 4 | o | -> | |
- ! | - | 3 | _ o
- ! 2 o | 2 | _ o |
- ! | | 1 o |
- ! --------------- ---------------
- !
- ! 15 Nov 2011 - P. Le Sager - adapted for lon-lat MPI domain decomposition
- !
- subroutine AdjustTracer( drm, region, i, j, l, k, status )
- use GO , only : gol, goErr
- ! --- in/out -----------------------------
-
- real, intent(in) :: drm ! tracer mass change (kg)
- integer, intent(in) :: region
- integer, intent(in) :: i, j ! cell indices
- integer, intent(in) :: l ! local level
- integer, intent(in) :: k ! tracer index
- integer, intent(out) :: status
-
- ! --- const -------------------------------
-
- character(len=*), parameter :: rname = mname//'/AdjustTracer'
-
- ! --- local -------------------------------
-
- real, dimension(:,:,:,:), pointer :: rm
- #ifdef slopes
- real, dimension(:,:,:,:), pointer :: rxm, rym, rzm
- #ifdef secmom
- real, dimension(:,:,:,:), pointer :: rxxm, rxym, rxzm, ryym, ryzm, rzzm
- #endif
- #endif
- real :: rm_old
- real :: skf
- ! --- begin -----------------------------
-
- ! set pointers
- rm => mass_dat(region)%rm
- #ifdef slopes
- rxm => mass_dat(region)%rxm
- rym => mass_dat(region)%rym
- rzm => mass_dat(region)%rzm
- #ifdef secmom
- rxxm => mass_dat(region)%rxxm
- rxym => mass_dat(region)%rxym
- rxzm => mass_dat(region)%rxzm
- ryym => mass_dat(region)%ryym
- ryzm => mass_dat(region)%ryzm
- rzzm => mass_dat(region)%rzzm
- #endif
- #endif
- ! store old tracer mass:
- rm_old = rm(i,j,l,k)
-
- ! store new tracer mass:
- rm(i,j,l,k) = rm_old + drm
- #ifdef slopes
- ! adjust concentration gradients
- ! scale factor to be applied; trap devision by zero:
- if ( (rm(i,j,l,k) > tiny(1.0)) .and. (rm_old > tiny(0.0)) ) then
- skf = rm(i,j,l,k) / rm_old
- else
- skf = 0.0
- end if
- ! adjust slopes:
- rxm(i,j,l,k) = rxm(i,j,l,k) * skf
- rym(i,j,l,k) = rym(i,j,l,k) * skf
- rzm(i,j,l,k) = rzm(i,j,l,k) * skf
- #ifdef secmom
- ! adjust second moments:
- rxxm(i,j,l,k) = rxxm(i,j,l,k) * skf
- rxym(i,j,l,k) = rxym(i,j,l,k) * skf
- rxzm(i,j,l,k) = rxzm(i,j,l,k) * skf
- ryym(i,j,l,k) = ryym(i,j,l,k) * skf
- ryzm(i,j,l,k) = ryzm(i,j,l,k) * skf
- rzzm(i,j,l,k) = rzzm(i,j,l,k) * skf
- #endif
- #endif
-
- ! ok
- status = 0
-
- end subroutine AdjustTracer
-
- !--------------------------------------------------------------------------
- ! TM5 !
- !--------------------------------------------------------------------------
- !BOP
- !
- ! !IROUTINE: TRACER_PRINT
- !
- ! !DESCRIPTION: Debug tool. Print value of tracer mass and air mass in one
- ! box, with message at the begining
- !\\
- !\\
- ! !INTERFACE:
- !
- SUBROUTINE TRACER_PRINT( region, message, status )
- !
- ! !USES:
- !
- use GO
- use dims, only : im, jm, lm
- use chem_param, only : ntrace, ntracet, names
- use meteodata, only : m_dat, phlb_dat
- !
- ! !INPUT PARAMETERS:
- !
- character(len=*), intent(in) :: message
- integer, intent(in) :: region
- !
- ! !OUTPUT PARAMETERS:
- !
- integer, intent(out) :: status
- !
- ! !REVISION HISTORY:
- ! 15 Feb 2012 - P. Le Sager
- !
- !EOP
- !------------------------------------------------------------------------
- !BOC
- character(len=*), parameter :: rname = mname//'/tracer_print'
- integer :: ii, jj, ll, kk, i1, j1, i2, j2
- real :: pat, patx, paty, patz, patm, patp
-
- ! set those for the box/tracer used to debug, revert to (1,1,1,1) when you are done
- ii=1
- jj=1
- ll=1
- kk=1
- call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2)
- if((ii<i1).or.(ii>i2).or.(jj<j1).or.(jj>j2)) then
- status=0
- return
- endif
- if (kk <= ntracet) then
- pat = mass_dat(region)%rm (ii,jj,ll,kk)
- #ifdef slopes
- patx = mass_dat(region)%rxm(ii,jj,ll,kk)
- paty = mass_dat(region)%rym(ii,jj,ll,kk)
- patz = mass_dat(region)%rzm(ii,jj,ll,kk)
- #endif
- else if (kk <= ntrace) then
- pat = chem_dat(region)%rm(ii,jj,ll,kk)
- #ifdef slopes
- patx = 0.
- paty = 0.
- patz = 0.
- #endif
- else
- write(gol,*) "out of range tracer index"; call goErr
- status=1
- IF_NOTOK_RETURN(status=1)
- end if
-
- patm = m_dat(region)%data(ii,jj,ll)
- patp = phlb_dat(region)%data(ii,jj,ll)
- ! Decide what to write:
- #ifdef slopes
- write (gol,*) message//" "//names(kk), pat, patx, paty, patz, patm ; call goBug
- #else
- write (gol,*) message//" "//names(kk), pat, patm ; call goBug
- #endif
- ! ok
- status = 0
-
- END SUBROUTINE TRACER_PRINT
- !EOC
- !--------------------------------------------------------------------------
- ! TM5 !
- !--------------------------------------------------------------------------
- !BOP
- !
- ! !IROUTINE: PAR_CHECK_MASS
- !
- ! !DESCRIPTION: Debug tool. Print min, max, and sum of air mass and tracer
- ! mass.
- !\\
- !\\
- ! !INTERFACE:
- !
- SUBROUTINE PAR_CHECK_MASS( region, text, tr_id, debug )
- !
- ! !USES:
- !
- use meteodata, only : m_dat
- use tm5_distgrid, only : reduce
- use partools, only : isRoot
- !
- ! !INPUT PARAMETERS:
- !
- integer, intent(in) :: region
- character(len=*), intent(in) :: text
- integer, optional, intent(in) :: tr_id
- logical, optional, intent(in) :: debug ! if true, REDUCE prints min/maxloc
- !
- ! !REVISION HISTORY:
- ! 15 Feb 2012 - P. Le Sager - v0
- !
- !EOP
- !------------------------------------------------------------------------
- !BOC
- real, dimension(:,:,:), pointer :: m
- real, dimension(:,:,:,:), pointer :: rm
- real :: min_one, max_one, tot_one
- integer :: status, trid
- logical :: dbg_
- ! check input
- trid=1
- if(present(tr_id)) trid=tr_id
- dbg_=.false.
- if(present(debug)) dbg_=debug
-
- rm => mass_dat(region)%rm
- m => m_dat(region)%data
- ! air mass
- call REDUCE( dgrid(region), m, m_dat(region)%halo, 'MAX', max_one, status, debug=dbg_)
- call REDUCE( dgrid(region), m, m_dat(region)%halo, 'MIN', min_one, status, debug=dbg_)
- call REDUCE( dgrid(region), m, m_dat(region)%halo, 'SUM', tot_one, status, debug=dbg_)
- if ( isRoot ) then
- write(gol,*) text//' [par_check_mass] AIR min, max, sum: ', min_one, max_one, tot_one ; call goPr
- endif
- ! all transported tracers
- call REDUCE( dgrid(region), rm, mass_dat(region)%halo, 'MAX', max_one, status, debug=dbg_)
- call REDUCE( dgrid(region), rm, mass_dat(region)%halo, 'MIN', min_one, status, debug=dbg_)
- call REDUCE( dgrid(region), rm, mass_dat(region)%halo, 'SUM', tot_one, status, debug=dbg_)
- if ( isRoot ) then
- write(gol,*) text//' [par_check_mass] RM min, max, sum: ', min_one, max_one, tot_one ; call goPr
- endif
- nullify(m)
- ! one selected tracer
- m => mass_dat(region)%rm(:,:,:,trid) ! no need for temp arr since slice is in last dimension
-
- call REDUCE( dgrid(region), m, mass_dat(region)%halo, 'MAX', max_one, status, debug=dbg_)
- call REDUCE( dgrid(region), m, mass_dat(region)%halo, 'MIN', min_one, status, debug=dbg_)
- call REDUCE( dgrid(region), m, mass_dat(region)%halo, 'SUM', tot_one, status, debug=dbg_)
- if ( isRoot ) then
- write(gol,*) text//' [par_check_mass] ID, min, max, sum: ', trid, min_one, max_one, tot_one ; call goPr
- endif
- nullify(m)
-
- END SUBROUTINE PAR_CHECK_MASS
- !EOC
-
- !
- ! Convert and put a slab of tracer mass (with given unit and tracer id)
- ! into tracer mass array (in kg); adust slopes too.
- !
- #ifdef with_feedback
-
- subroutine Tracer_Fill_Slabs( region, itr, unit, rm_k, status )
-
- use dims , only : im, jm, lm
- use chem_param , only : ntrace, ntracet, fscale
- use partools , only : myid, root
- use partools , only : previous_par, tracer_loc, tracer_id, tracer_active
- use partools , only : lmloc, lmar, offsetl
- use partools , only : Par_Gather_From_Levels
- use meteodata , only : m_dat
-
- ! --- in/out -------------------------------------
-
- integer, intent(in) :: region
- integer, intent(in) :: itr
- character(len=*), intent(in) :: unit
- real, intent(in) :: rm_k(:,:,:)
- integer, intent(out) :: status
-
- ! --- const ------------------------------
- character(len=*), parameter :: rname = mname//'/Tracer_Fill_Slabs'
-
- ! --- local ---------------------------------
-
- integer :: i, j, l, lmr
- integer :: i01, i02, j01, j02, lmr
- ! --- begin ----------------------------------
- ! local grid size
- lmr = lm(region)
- call Get_DistGrid( dgrid(region), I_STRT=i01, I_STOP=i02, &
- J_STRT=j01, J_STOP=j02 )
-
- ! check input:
- if ( any(shape(rm_k)/=(/i02-i01+1,j02-j01+1,lmr/)) ) then
- write (gol,'("shape of output grid not ok:")'); call goErr
- write (gol,'(" shape(rm_k) : ",3i4)') shape(rm_k); call goErr
- write (gol,'(" i02-i01+1,j02-j01+1,lmr : ",3i4)') i02-i01+1,j02-j01+1,lmr; call goErr
- TRACEBACK; status=1; return
- end if
-
- ! transported or short lived tracer ?
- if ( (itr >= 1) .and. (itr <= ntracet) ) then
- ! rm_k was in given unit; convert x_t to kg :
- select case ( unit )
-
- case ( 'kg' )
- ! x_t already in kg
- ! apply unit conversion from (kg plc tracer) to (kg tm tracer)
- rm_k = rm_k / plc_kg_from_tm(itr)
- case ( 'mass-mixing-ratio' )
- ! mass mixing ratio
- ! apply unit conversion from (kg plc tracer) to (kg tm tracer)
- rm_k = rm_k / plc_kg_from_tm(itr)
- rm_k = rm_k * m_dat(region)%data(i01:i02,j01:j02,:)
- case ( 'volume-mixing-ratio' )
- ! volume mixing ratio = mass mixing ratio * fscale
- ! apply unit conversion from (kg plc tracer) to (kg tm tracer)
- rm_k = rm_k / plc_kg_from_tm(itr)
- rm_k = rm_k * m_dat(region)%data(i01:i02,j01:j02,:) / fscale(itr)
- case default
- write (gol,'("unsupported unit for par tracer : ",a)') unit; call goErr
- TRACEBACK; status=1; return
- end select
- ! replace new mass rm_k by difference with rm :
- rm_k = rm_k - mass_dat(region)%rm_t(i01:i02,j01:j02,:,itr) ! kg
-
- ! add change in kg to tracer arrays, adjust slopes:
- do l = 1, lmr
- do j = j01, j02
- do i = i01, i02
- ! adjust tracer arrays for local indices:
- call AdjustTracer( rm_k(i,j,l), region, i, j, l, itr, status )
- IF_NOTOK_RETURN(status=1)
- end do
- end do
- end do
- else if ( (itr > ntracet) .and. (itr <= ntrace) ) then
- ! rm_k was in given unit; convert x_k to kg :
- select case ( unit )
- case ( 'kg' )
- ! x_k already in kg
- case ( 'mass-mixing-ratio' )
- ! mass mixing ratio to tracer mass:
- x_k = x_k * m_dat(region)%data(i01:i02,j01:j02,:)
- case ( 'volume-mixing-ratio' )
- ! volume mixing ratio = mass mixing ratio * fscale
- x_k = x_k * m_dat(region)%data(i01:i02,j01:j02,:) / fscale(itr)
- case default
- write (gol,'("unsupported unit for non-transported tracer slab : ",a)') unit; call goErr
- TRACEBACK; status=1; return
- end select
- ! replace short-lived tracer:
- chem_dat(region)%rm(:,:,:,itr) = rm_k ! kg
- else
- write (gol,'("unsupported tracer index : ",i4)') itr; call goErr
- write (gol,'(" ntrace, ntracet : ",2i4)') ntrace, ntracet; call goErr
- TRACEBACK; status=1; return
- end if ! transported or chem-only
- ! ok
- status = 0
-
- end subroutine Tracer_Fill_Slabs
- #endif
- END MODULE TRACER_DATA
|