12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817 |
- #define TRACEBACK write (gol,'("in ",a," (",a,i6,")")') 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"
- !
- !------------------------------------------------------------------------------
- ! TM5 !
- !------------------------------------------------------------------------------
- !BOP
- !
- ! !MODULE: SEDIMENTATION
- !
- ! !DESCRIPTION: This module calculates sedimentation of aerosol particles.
- ! Also the deposition at the surface is calculated here since
- ! it uses similar routines.
- !
- ! It is assumed that the distribution is described by nmodes log-normal
- ! distributions as described in chem_param.F90.
- !
- ! Each mode has a number and mass and a sigma_lognormal. Number and mass are
- ! related and the mean aerosol radius can thus be calculated for each mode.
- !
- ! mass=pi*4./3.*radius**3.*number*exp(9./2.*ln2s) /1e18*density, with:
- !
- ! density = density of aerosol type
- ! ln2s = (alog(sigma_lognormal(mode)))**2
- ! mass = mode mass
- ! number = mode number
- !
- ! mode1 : accumulation
- ! mode2 : coarse
- ! mode3 : super coarse (ss) coarse
- !
- ! For each mode a separate fall velocity is calculated according to the mass
- ! and number mean radii. Water take-up by seasalt particles is taken into
- ! account. This changes the density, radius, and sigma of the distribution.
- !
- ! Also included is the deposition calculation. based on a lookup table
- ! calculated for a reference aerosol density (e.g. 1800 kg/m3) and a number of
- ! radii. This deposition curve is convoluted with the number/volume
- ! distribution of the aerosols.
- !
- ! Again, for SS the water takeup is accounted for, and the effects on density,
- ! sigma and radius are calculated. The density has effect on the impaction
- ! term is the depotion calculation. This can be modeled by a shift in the
- ! radius. Thus the radii of the lookup table are adapted for density
- ! differences when impaction becomes important.
- !
- ! routine Sedimentation_Init : initialisation of sedimentation routine
- ! routine Sedimentation_Done : free memory
- ! routine sedimentation_calcv : calculate velocities
- ! routine deposition_calcv : calculate velocities
- ! routine Sedimentation_Apply : do the accutual sedimentation
- !\\
- !\\
- ! !INTERFACE:
- !
- MODULE SEDIMENTATION
- !
- ! !USES:
- !
- use GO, only: gol, goPr, goErr, goBug
- use GO, only: GO_Timer_Def, GO_Timer_End, GO_Timer_Start
- use Binas, only: grav, xmair, Avog
- use dims, only: nregions
- use tm5_distgrid, only: dgrid, Get_DistGrid, gather
- use partools, only: isRoot
- use global_types, only: d3_data, emis_data, aerosol_emis_data
- use chem_param, only: ntracet, imsa, inh4
- #ifdef with_m7
- use chem_param, only: inus_n, iso4nus, iais_n, iso4ais, ibcais, ipomais
- use chem_param, only: iacs_n, iso4acs, ibcacs, ipomacs, issacs, iduacs
- use chem_param, only: icos_n, iso4cos, ibccos, ipomcos, isscos, iducos
- use chem_param, only: iaii_n, ibcaii, ipomaii, iaci_n, iduaci, icoi_n, iducoi
- #else
- use chem_param, only: iso4
- #endif
- use chem_param, only: nmod
- #ifdef with_budgets
- use budget_global, only: nbudg, nbud_vg, nzon_vg
- #endif
- IMPLICIT NONE
- PRIVATE
- !
- ! !PUBLIC MEMBER FUNCTIONS:
- !
- public Sedimentation_Init, Sedimentation_Done
- public Sedimentation_Apply
- public calculate_rh
- public aerosol_radius
- !
- ! !PUBLIC DATA MEMBERS:
- !
- real, dimension(nregions), public :: sum_drydep, sum_sedimentation ! budgets for tracer #1 (significant on root only)
- type(d3_data), dimension(nregions), public :: rh, rha ! rh (0-1), cloudfree vs. allsky
- #ifdef with_m7
- integer, parameter, public :: nsed=27 ! number of tracers for which sedimentation is applied
- integer, parameter, dimension(nsed), public :: ised = (/ inh4, imsa, &
- inus_n, iso4nus, iais_n, iso4ais, ibcais, ipomais, &
- iacs_n, iso4acs, ibcacs, ipomacs, issacs, iduacs, &
- icos_n, iso4cos, ibccos, ipomcos, isscos, iducos, &
- iaii_n, ibcaii, ipomaii, iaci_n, iduaci, icoi_n, &
- iducoi /)
- #else
- ! sedimentation of few gas-phase species
- integer, parameter, public :: nsed= 3 ! number of tracers for which sedimentation is applied
- integer, parameter, dimension(nsed), public :: ised = (/ iso4, inh4, imsa /)
- #endif
- !
- ! !PRIVATE DATA MEMBERS:
- !
- integer, dimension(ntracet) :: sindex ! pointer to match ntracet array with nsed
- ! Mean values at the surface, per mode (i,j,mode)
- type(aerosol_emis_data), dimension(nregions) :: vn_deposition_mean ! number mean deposition velocity (m/s)
- type(aerosol_emis_data), dimension(nregions) :: vn_sedimentation_mean ! number mean sedim. velocity at surface (m/s)
- type(aerosol_emis_data), dimension(nregions) :: vm_deposition_mean ! mass mean deposition velocity (m/s)
- type(aerosol_emis_data), dimension(nregions) :: vm_sedimentation_mean ! mass mean sedim. velocity at surface (m/s)
- type(d3_data), dimension(nregions,nmod) :: vn_sedimentation ! number sedimentation velocities (Pa/s)
- type(emis_data), dimension(nregions,nmod) :: vn_deposition ! number deposition velocity (Pa/s)
- type(d3_data), dimension(nregions,nmod) :: vm_sedimentation ! mass sedimentation velocities (Pa/s)
- type(emis_data), dimension(nregions,nmod) :: vm_deposition ! mass deposition velocity (Pa/s)
- integer, dimension(nregions) :: n_deposition_mean ! counter
- integer, dimension(nregions) :: n_sedimentation_mean ! counter
- logical, parameter :: vd_in_deposition = .false. ! is sedimentation treated in deposition routine?
- integer, parameter :: ndp = 3 ! limit of the velocity to ndp times the layer thickness
- ! iteration will account for a fall length through multiple layers
- real, parameter :: m_to_pa = 7.24e16*grav*xmair*1e3/Avog !factor from m/s --> Pa/s
- !
- ! !PUBLIC TYPES:
- !
- #ifdef with_budgets
- ! budget terms on grid basis:
- type, public :: buddep_data
- real, dimension(:,:,:,:), pointer :: sed ! im,jm,nbud_vg,nsed
- end type buddep_data
- type(buddep_data),dimension(nregions),target,public :: buddep_m7_dat
- #endif
- integer :: itim_appl
-
- real :: sigma, density
- character(len=*), parameter :: mname = 'sedimentation'
- !
- ! !REVISION HISTORY:
- ! Feb 2004 by MK -
- ! 2 Apr 2010 - P. Le Sager - Optimize arrays de/allocation if m7 is not used.
- ! 19 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
- !
- ! !REMARKS:
- ! (1) Only relative humidity is used when not using m7.
- ! (2) sedimentation is defined at the bottom of the gridbox (see init)
- ! (3) Note the switch from emiss_data to aerosol_emiss_data type for the
- ! *_mean variables (simplify and speedup mpi comm in sedimentation_done)
- !
- ! !TODO:
- !
- !EOP
- !------------------------------------------------------------------------------
- CONTAINS
- !------------------------------------------------------------------------------
- ! TM5 !
- !------------------------------------------------------------------------------
- !BOP
- !
- ! !IROUTINE: SEDIMENTATION_INIT
- !
- ! !DESCRIPTION: allocate memory, map ised
- !\\
- !\\
- ! !INTERFACE:
- !
- SUBROUTINE SEDIMENTATION_INIT ( status )
- !
- ! !USES:
- !
- use dims, only : lm, iglbsfc
- use chem_param, only : ntracet
- use meteodata, only : Set, spm_dat, temper_dat, humid_dat, cc_dat, phlb_dat
- use meteodata, only : lsp_dat, cp_dat
- !
- ! !OUTPUT PARAMETERS:
- !
- integer,intent(out) :: status
- !
- ! !REVISION HISTORY:
- ! 2 Apr 2010 - P. Le Sager - Added test on "with_m7"
- ! 20 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
- !
- ! !REMARKS:
- !
- !EOP
- !------------------------------------------------------------------------------
- !BOC
- character(len=*), parameter :: rname = mname//'/Sedimentation_Init'
- integer :: region, lmr, i
- integer :: imode, n, i1, i2, j1, j2
- ! --- begin ---------------------------------
- ! meteo to be used
- do region = 1, nregions
- call Set( temper_dat(region), status, used=.true. )
- call Set( phlb_dat(region), status, used=.true. )
- call Set( humid_dat(region), status, used=.true. )
- call Set( cc_dat(region), status, used=.true. )
- call Set( lsp_dat(region), status, used=.true. )
- call Set( cp_dat(region), status, used=.true. )
- end do
- #ifdef with_m7
- ! Calculate mapping of ntracer to sedimentation arrays:
- sindex(:) = 0
- do i=1,nsed
- do n=1,ntracet
- if(ised(i) == n) sindex(n) = i
- enddo
- enddo
- #endif
- ! Allocate
- do region = 1, nregions
- call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
- lmr=lm(region)
-
- #ifdef with_m7
- #ifdef with_budgets
- sum_sedimentation(region) = 0.0
- sum_drydep(region) = 0.0
- allocate( buddep_m7_dat(region)%sed(i1:i2, j1:j2, nbud_vg, nsed) )
- buddep_m7_dat(region)%sed = 0.0
- #endif
- allocate(vn_deposition_mean (region)%surf(i1:i2, j1:j2, nmod)) ! defined at bottom of surface layer
- allocate(vn_sedimentation_mean(region)%surf(i1:i2, j1:j2, nmod)) ! defined at bottom of surface layer
- allocate(vm_sedimentation_mean(region)%surf(i1:i2, j1:j2, nmod)) ! defined at bottom of surface layer
- allocate(vm_deposition_mean (region)%surf(i1:i2, j1:j2, nmod)) ! defined at bottom of surface layer
- vn_deposition_mean (region)%surf = 0.0
- vn_sedimentation_mean(region)%surf = 0.0
- vm_sedimentation_mean(region)%surf = 0.0
- vm_deposition_mean (region)%surf = 0.0
-
- do imode = 1, nmod
- allocate(vn_sedimentation(region,imode)%d3 (i1:i2, j1:j2, lmr)) ! defined at bottom of layer
- allocate(vn_deposition (region,imode)%surf(i1:i2, j1:j2 )) ! defined at bottom of surface layer
- allocate(vm_sedimentation(region,imode)%d3 (i1:i2, j1:j2, lmr)) ! defined at bottom of layer
- allocate(vm_deposition (region,imode)%surf(i1:i2, j1:j2 )) ! defined at bottom of surface layer
- vn_sedimentation(region,imode)%d3 = 0.0
- vn_deposition (region,imode)%surf = 0.0
- vm_sedimentation(region,imode)%d3 = 0.0
- vm_deposition (region,imode)%surf = 0.0
- enddo
- #endif
- allocate( rh(region)%d3(i1:i2, j1:j2, lmr))
- allocate(rha(region)%d3(i1:i2, j1:j2, lmr))
- n_deposition_mean(region) = 0
- n_sedimentation_mean(region) = 0
- enddo
- call GO_Timer_Def( itim_appl, 'sedimentation appl', status )
- IF_NOTOK_RETURN(status=1)
-
- status = 0
- END SUBROUTINE SEDIMENTATION_INIT
- !EOC
- !------------------------------------------------------------------------------
- ! TM5 !
- !------------------------------------------------------------------------------
- !BOP
- !
- ! !IROUTINE: SEDIMENTATION_DONE
- !
- ! !DESCRIPTION: gather/aggregate/write budgets, and free memory
- !\\
- !\\
- ! !INTERFACE:
- !
- SUBROUTINE SEDIMENTATION_DONE( status )
- !
- ! !USES:
- !
- use io_hdf, only : DFACC_WRITE, io_write, DFNT_INT32
- use dims, only : im, jm
- #ifdef with_budgets
- use budget_global, only : budget_file_global, nbud_vg, budg_dat, nbudg, NHAB
- use file_hdf, only : THdfFile, TSds
- use file_hdf, only : Init, Done, WriteAttribute, WriteData, SetDim
- use Dims, only : region_name
- use partools, only : par_reduce_element
- #endif
- !
- ! !OUTPUT PARAMETERS:
- !
- integer, intent(out) :: status
- !
- ! !REMARKS:
- !
- !EOP
- !------------------------------------------------------------------------------
- !BOC
- character(len=*), parameter :: rname = mname//'/Sedimentation_Done'
- Integer :: region, i1, i2, j1, j2
- #ifdef with_m7
- #ifdef with_budgets
- type(THdfFile) :: io
- type(TSds) :: sds
- integer :: j, i, n, nzone, nzone_v
- real, dimension(nbudg, nbud_vg, nsed) :: budsedg
- real, dimension(nbudg, nbud_vg, nsed) :: budsedg_all ! for buggy MPI
- real, dimension(:,:), allocatable :: budget2d ! to gather budget terms on PEs
- real, dimension(:,:,:), allocatable :: budget3d
- real, dimension(:,:,:,:),allocatable :: budget4d
- #endif
- #endif
- integer :: imode
- ! --- begin ------------------------------
- #ifdef with_m7
- #ifdef with_budgets
- ! open file
- if( isRoot ) then
- call Init(io, budget_file_global, 'write', status)
- IF_NOTOK_RETURN(status=1)
- call WriteAttribute(io,'sum_drydep_m7',sum_drydep,status)
- IF_NOTOK_RETURN(status=1)
- call WriteAttribute(io,'sum_sedimentation_m7',sum_sedimentation,status)
- IF_NOTOK_RETURN(status=1)
- call WriteAttribute(io,'nsed',nsed,status)
- IF_NOTOK_RETURN(status=1)
- call WriteAttribute(io,'ised',ised,status)
- IF_NOTOK_RETURN(status=1)
- endif
- budsedg(:,:,:) = 0.0
- REG: do region=1,nregions
- call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
-
- !-- bin aggregated sed budget
- do n=1,nsed
- do j=j1,j2
- do i=i1,i2
- nzone = budg_dat(region)%nzong(i,j)
- budsedg(nzone,:,n) = budsedg(nzone,:,n) + buddep_m7_dat(region)%sed(i,j,:,n)
- end do
- end do
- end do
-
- !-- write Non-Horizontally-Aggregated-Budgets
- if (NHAB) then
- ! gather sed budget and write to file
- if (isRoot )then
- allocate(budget4d(im(region), jm(region), nbud_vg, nsed))
- else
- allocate(budget4d(1,1,1,1))
- end if
-
- call GATHER( dgrid(region), buddep_m7_dat(region)%sed, budget4d, 0, status)
- IF_NOTOK_RETURN(status=1)
- if(isRoot )then
- call Init(Sds,io, 'buddep_dat_sed_'//region_name(region),(/im(region),jm(region),nbud_vg,nsed/), 'real(4)', status)
- IF_NOTOK_RETURN(status=1)
- call WriteAttribute(Sds,'ised',ised,status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 0, 'im_'//region_name(region),'longitude', (/(j, j=1,im(region))/), status)
- call SetDim(Sds, 1, 'jm_'//region_name(region),'latitude', (/(j, j=1,jm(region))/), status)
- call SetDim(Sds, 2, 'nbud_vg','vertical layer', (/(j, j=1,nbud_vg)/), status)
- call SetDim(Sds, 3, 'nsed','sedimentation', (/(j, j=1,nsed)/), status)
- call WriteData(Sds, budget4d ,status)
- IF_NOTOK_RETURN(status=1)
- call Done(Sds, status)
- IF_NOTOK_RETURN(status=1)
- endif
- deallocate(budget4d)
-
-
- ! gather deposition velocities and write to file
- if (isRoot ) then
- allocate(budget3d(im(region), jm(region), nmod))
- else
- allocate(budget3d(1,1,1))
- end if
- call GATHER( dgrid(region), vn_deposition_mean(region)%surf, budget3d, 0, status)
- IF_NOTOK_RETURN(status=1)
- if(isRoot ) then
- if (n_deposition_mean(region)==0)then
- budget3d = 0.
- else
- budget3d = budget3d / n_deposition_mean(region)
- end if
-
- call Init(Sds,io, 'vd_n_'//region_name(region),(/im(region),jm(region),nmod/), 'real(4)', status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 0, 'im_'//region_name(region),'longitude', (/(j, j=1,im(region))/), status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 1, 'jm_'//region_name(region),'latitude', (/(j, j=1,jm(region))/), status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 2, 'nmodes','deposition modes', (/(j, j=1,nmod)/), status)
- IF_NOTOK_RETURN(status=1)
- call WriteData(Sds, budget3d ,status)
- IF_NOTOK_RETURN(status=1)
- call Done(Sds, status)
- IF_NOTOK_RETURN(status=1)
- endif
- ! gather and write deposition velocities (mass tracers)
- call GATHER( dgrid(region), vm_deposition_mean(region)%surf, budget3d, 0, status)
- IF_NOTOK_RETURN(status=1)
-
- if(isRoot ) then
- if (n_deposition_mean(region)==0)then
- budget3d = 0.
- else
- budget3d = budget3d / n_deposition_mean(region)
- end if
-
- call Init(Sds,io, 'vd_m_'//region_name(region),(/im(region),jm(region),nmod/), 'real(4)', status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 0, 'im_'//region_name(region),'longitude', (/(j, j=1,im(region))/), status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 1, 'jm_'//region_name(region),'latitude', (/(j, j=1,jm(region))/), status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 2, 'nmodes','deposition modes', (/(j, j=1,nmod)/), status)
- IF_NOTOK_RETURN(status=1)
- call WriteData(Sds, budget3d ,status)
- IF_NOTOK_RETURN(status=1)
- call Done(Sds, status)
- IF_NOTOK_RETURN(status=1)
- endif
- ! gather and write sedimentation velocities
- call GATHER( dgrid(region), vn_sedimentation_mean(region)%surf, budget3d, 0, status)
- IF_NOTOK_RETURN(status=1)
- if(isRoot ) then
- if (n_sedimentation_mean(region)==0)then
- budget3d = 0.
- else
- budget3d = budget3d / n_sedimentation_mean(region)
- end if
- call Init(Sds,io, 'vs_n_'//region_name(region),(/im(region),jm(region),nmod/), 'real(4)', status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 0, 'im_'//region_name(region),'longitude', (/(j, j=1,im(region))/), status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 1, 'jm_'//region_name(region),'latitude', (/(j, j=1,jm(region))/), status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 2, 'nmodes','deposition modes', (/(j, j=1,nmod)/), status)
- IF_NOTOK_RETURN(status=1)
- call WriteData(Sds, budget3d ,status)
- IF_NOTOK_RETURN(status=1)
- call Done(Sds, status)
- IF_NOTOK_RETURN(status=1)
- endif
- ! gather and write sedimentation velocities (mass tracers)
- call GATHER( dgrid(region), vm_sedimentation_mean(region)%surf, budget3d, 0, status)
- IF_NOTOK_RETURN(status=1)
- if(isRoot) then
- if (n_sedimentation_mean(region)==0)then
- budget3d = 0.
- else
- budget3d = budget3d / n_sedimentation_mean(region)
- end if
- call Init(Sds,io, 'vs_m_'//region_name(region),(/im(region),jm(region),nmod/), 'real(4)', status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 0, 'im_'//region_name(region),'longitude', (/(j, j=1,im(region))/), status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 1, 'jm_'//region_name(region),'latitude', (/(j, j=1,jm(region))/), status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 2, 'nmodes','deposition modes', (/(j, j=1,nmod)/), status)
- IF_NOTOK_RETURN(status=1)
- call WriteData(Sds, budget3d ,status)
- IF_NOTOK_RETURN(status=1)
- call Done(Sds, status)
- IF_NOTOK_RETURN(status=1)
- endif
- deallocate(budget3d)
-
- endif ! NHAB
- enddo REG ! regions
- !------- Gather and write aggregated budget
- ! Sum up contribution from each proc into root array
- call PAR_REDUCE_ELEMENT( budsedg, 'SUM', budsedg_all, status )
- IF_NOTOK_RETURN(status=1)
- if(isRoot )then
- call Init(Sds, io, 'budsed_m7', (/nbudg,nbud_vg,nsed/), 'real(8)', status)
- IF_NOTOK_RETURN(status=1)
- call SetDim(Sds, 0, 'nbudg', 'horizontal region', (/(j, j=1,nbudg)/), status)
- call SetDim(Sds, 1, 'nbud_vg', 'vertical layer', (/(j, j=1,nbud_vg)/), status)
- call SetDim(Sds, 2, 'nsed', 'sedimentation', (/(j, j=1,nsed)/), status)
- IF_NOTOK_RETURN(status=1)
- call WriteData(Sds, budsedg_all, status)
- IF_NOTOK_RETURN(status=1)
- call Done(Sds, status)
- IF_NOTOK_RETURN(status=1)
- call Done(io, status)
- IF_NOTOK_RETURN(status=1)
- endif
- #endif /* BUDGET */
- #endif /* M7 */
- !-------- Done
- do region = 1, nregions
- #ifdef with_m7
- #ifdef with_budgets
- deallocate( buddep_m7_dat(region)%sed)
- #endif
- deallocate( vn_deposition_mean (region)%surf )
- deallocate( vn_sedimentation_mean(region)%surf )
- deallocate( vm_deposition_mean (region)%surf )
- deallocate( vm_sedimentation_mean(region)%surf )
-
- do imode = 1, nmod
- deallocate(vn_sedimentation(region,imode)%d3 )
- deallocate(vn_deposition (region,imode)%surf)
- deallocate(vm_sedimentation(region,imode)%d3 )
- deallocate(vm_deposition (region,imode)%surf)
- enddo
- #endif
- deallocate(rh(region)%d3)
- deallocate(rha(region)%d3)
-
- enddo
- status = 0
- END SUBROUTINE SEDIMENTATION_DONE
- !EOC
- !------------------------------------------------------------------------------
- ! TM5 !
- !------------------------------------------------------------------------------
- !BOP
- !
- ! !IROUTINE: DEPOSITION_CALCV
- !
- ! !DESCRIPTION: calculate velocities
- !\\
- !\\
- ! !INTERFACE:
- !
- SUBROUTINE DEPOSITION_CALCV( region, status )
- !
- ! !USES:
- !
- use global_data, only : mass_dat, region_dat
- use meteodata, only : spm_dat, temper_dat, cc_dat
- use chem_param, only : sigma_lognormal, density_ref
- use chem_param, only : mode_start, mode_end, names
- use dims, only : at, bt, nsrce, tref, im, jm, lm, okdebug
- use chem_param, only : nrdep, lur
- use dry_deposition, only : vd=>vda
- use binas, only : pi
- use partools, only : par_reduce
- #ifdef with_m7
- use m7_data, only : dens_mode, rw_mode ! density (kg/m3) r (m)
- #endif
- !
- ! !INPUT PARAMETERS:
- !
- integer, intent(in) :: region
- !
- ! !OUTPUT PARAMETERS:
- !
- integer, intent(out) :: status
- !
- ! !REVISION HISTORY:
- ! 2 Apr 2010 - P. Le Sager -
- ! 21 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
- !
- ! !REMARKS:
- ! (1) Called only if m7 used.
- !
- !EOP
- !------------------------------------------------------------------------------
- !BOC
- character(len=*), parameter :: rname = mname//'/DEPOSITION_CALCV'
- real, dimension(:,:,:), pointer :: p ! surface pressure (Pa)
- real, dimension(:,:,:), pointer :: t ! temperature (K)
- real, dimension(:,:,:), pointer :: cc ! cloud_cover (0-1)
- real, dimension(:,:,:,:), pointer :: rm ! tracer array (kg)
- real :: pb ! pressure at bottom of box (Pa)
- real :: dt ! general timestep (s)
- real :: dp ! pressure difference layer
- integer :: i,j,l, mode, n, proc, itn, itracer
- real :: temp ! temperature
- real :: to_pascal
- real, dimension(nmod) :: lns
- real :: radius
- real, dimension(nmod,2) :: vd_mean_all, vd_max_all
- real, dimension(nmod,2) :: vd_mean, vd_max
- integer, dimension(nmod,2) :: nvd, nvd_all
- real, dimension(nmod) :: r_mean_all, r_max_all
- real, dimension(nmod) :: r_mean, r_max
- integer, dimension(nmod) :: nr, nr_all
- real, dimension(nrdep) :: d_aer ! diameter vd loopup table (um)
- real, dimension(nrdep) :: nnumb,nvolume ! number and volume distribution
- real, dimension(nrdep) :: vdi ! for the integration
- real, dimension(nrdep) :: vdi_def ! for the integration
- real, dimension(nrdep) :: lure ! effective loo
- real, dimension(nrdep) :: ddpi ! integration bin-sizes
- real, dimension(nrdep+1) :: dlogdp,ddp ! integration edges
- real, dimension(nrdep) :: logdp,logde ! log(diameter)
- real :: dpg, ntot, vt
- real :: lnsigma, rho_aer, sigma
- integer :: ir, ir1, nshift, nrd, nglob
- integer :: i1, i2, j1, j2
- !________________________start_________________________________
- nullify(rm)
- nullify(p)
- nullify(t)
- nullify(cc)
- rm => mass_dat (region)%rm
- p => spm_dat (region)%data
- t => temper_dat(region)%data
- cc => cc_dat (region)%data
- dt = float(nsrce)/(2*tref(region)) ! timestep
- do mode =1,nmod
- lns(mode) = log(sigma_lognormal(mode))
- enddo
- ! calculate the binsizes (um) around the radii of the pre-calculated vd's
- d_aer = 2.0*lur ! diameter (um)
- logdp = log10(d_aer) ! log(diameter)
- n_deposition_mean(region) = n_deposition_mean(region) + 1
- call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
- if (okdebug) then
- if (isRoot) then
- write(gol,*) '________________________________________________________________________________' ; call goPr
- write(gol,*) 'Statistics for the deposition routine:' ; call goPr
- write(gol,*) '________________________________________________________________________________' ; call goPr
- write(gol,*) 'level mode r_mean r_max(um) vd_n(cm/s) vd_max(cm/s) vd_m(cm/s) vd_mmax(cm/s) ' ; call goPr
- write(gol,*) '________________________________________________________________________________' ; call goPr
- end if
- vd_mean = 0.0
- r_mean = 0.0
- vd_max = 0.0
- r_max = 0.0
- nvd = 0
- nr = 0
- endif
- !$OMP PARALLEL &
- !$OMP default (none) &
- !$OMP shared (region, t, at, bt, p, dt, vd, &
- !$OMP rm, rh, logdp, &
- !$OMP vn_deposition_mean, vn_deposition, vm_deposition_mean, vm_deposition, &
- !$OMP lur, sigma_lognormal, mode_start, mode_end) &
- !$OMP shared (okdebug, vd_mean, vd_max, nvd, r_max, r_mean, nr) &
- #ifdef with_m7
- !$OMP shared (rw_mode, dens_mode) &
- #endif
- !$OMP private (i, j, l, temp, pb, dp, to_pascal, vdi_def, &
- !$OMP itn, radius, vdi, sigma, lnsigma, density, &
- !$OMP lure, dlogdp, logde, nshift, nrd, &
- !$OMP ddp, ddpi, d_aer, dpg, ntot, nnumb, nvolume, vt)
- l = 1
- do j=j1,j2
- do i=i1,i2
- temp = t(i,j,1) ! at surface to temp box
- pb = at(l) + bt(l)*p(i,j,1) ! pressure at bottom of box (Pa)
- dp = (at(l)-at(l+1)) + p(i,j,1)*(bt(l)-bt(l+1)) ! layer thickness
- to_pascal = m_to_pa*dt*pb/temp ! convert from m/s ---> Pa/timestep
- do n=1,nrdep
- vdi_def(n) = vd(region,n)%surf(i,j)
- enddo
- #ifdef with_m7
- M7MODES: do mode = 1, nmod
- itn = mode_start(mode) ! position of number tracer
- ! compute radius:
- radius = rw_mode(region,mode)%d3(i,j,1)
- ! initial deposition velocities for increasing radia:
- vdi = vdi_def
- sigma = sigma_lognormal(mode)
- lnsigma = log(sigma)
- density = dens_mode(region,mode)%d3(i,j,1)
- if(okdebug) then
- if(radius > tiny(radius)) then
- r_mean(mode) = r_mean(mode) + radius
- nr(mode) = nr(mode) + 1
- r_max(mode) = max(r_max(mode), radius)
- endif
- endif
- RADENS: if (radius > 1e-11 .and. density > 1e-2) then
- ! account for density different than density_ref of the look-up table (lur --> vdi):
- lure(:) = lur(:)
- logde(:) = logdp(:)
- do ir = 2, nrdep
- if(vdi(ir) > vdi(ir-1)) exit ! for bigger r's : impaction dominates (density effects)
- if ( ir == nrdep ) exit ! trap upper boundary
- enddo
- do ir1 = ir, nrdep
- lure(ir1) = lur(ir1)*sqrt(density_ref/density)
- logde(ir1) = log10(2*lure(ir1))
- enddo
- ! compress look-up table such that radii are increasing monotonic:
- nshift = 0
- ir1 = ir
- do
- if ( logde(ir1) > logde(ir-1) ) exit
- nshift = nshift + 1
- ir = ir -1
- if(ir == 1) exit
- enddo
- nrd = nrdep - nshift
- if (nshift > 0) then
- do ir1 = ir, nrd
- logde(ir1) = logde(ir1+nshift)
- lure(ir1) = lure(ir1+nshift)
- vdi(ir1) = vdi(ir1+nshift)
- enddo
- endif
- ! do the integration of the shifted lookup table:
- dlogdp(1) = -3.0
- do ir=2,nrd
- dlogdp(ir) = 0.5*(logde(ir-1)+logde(ir)) ! take middle of the log scale
- enddo
- dlogdp(nrd+1) = 3.0 ! 1000 um
- ddp(1:nrd+1) = 10**dlogdp(1:nrd+1)
- ddpi(1:nrd) = ddp(2:nrd+1)-ddp(1:nrd) ! integration intervals (um)
- d_aer(1:nrd) = 2.0*lure(1:nrd)
- ! perform convolution with log-normal distribution:
- dpg = 2*radius*1e6 ! diameter in um
- ntot = rm(i,j,1,itn)
- ! calculate the distribution (number and mass) over the deposition bins:
- if(ntot > 1.0 .and. radius > tiny(radius) ) then ! you need some aerosol!
- do n=1,nrd
- nnumb(n) = ntot/(sqrt(2.*pi)*d_aer(n)*lnsigma)*exp(-(log(d_aer(n))-log(dpg))**2/(2*lnsigma**2))
- nvolume(n) = nnumb(n)*(pi/6.0)*d_aer(n)**3
- enddo
- vt = sum(nnumb(1:nrd)*ddpi(1:nrd)*vdi(1:nrd))/sum(nnumb(1:nrd)*ddpi(1:nrd))
- else
- vt = 0.0
- endif
- vn_deposition_mean(region)%surf(i,j,mode) = vn_deposition_mean(region)%surf(i,j, mode) + vt
- vn_deposition(region,mode)%surf(i,j) = min(to_pascal*vt,ndp*dp) ! in Pa/timestep downwards
- if(okdebug) then
- if ( vt > tiny(vt) ) then
- vd_mean(mode,1) = vd_mean(mode,1) + vt
- vd_max(mode,1) = max(vd_max(mode,1) , vt)
- nvd(mode,1) = nvd(mode,1) + 1
- endif
- endif
- ! for mass:
- if(ntot > 1.0 .and. radius > tiny(radius) ) then ! you need some aerosol!
- vt = sum(nvolume(1:nrd)*ddpi(1:nrd)*vdi(1:nrd))/sum(nvolume(1:nrd)*ddpi(1:nrd))
- else
- vt = 0.0
- endif
- vm_deposition_mean(region)%surf(i,j, mode) = vm_deposition_mean(region)%surf(i,j, mode) + vt
- vm_deposition(region,mode)%surf(i,j) = min(to_pascal*vt,ndp*dp) ! in Pa/timestep downwards
- if(okdebug) then
- if ( vt > tiny(vt) ) then
- vd_mean(mode,2) = vd_mean(mode,2) + vt
- vd_max(mode,2) = max(vd_max(mode,2) , vt)
- nvd(mode,2) = nvd(mode,2) + 1
- endif
- endif !
- else
- vm_deposition(region,mode)%surf(i,j) = 0.0
- vn_deposition(region,mode)%surf(i,j) = 0.0
- endif RADENS
- end do M7MODES
-
- #endif /* M7 */
- enddo !i
- enddo !j
- !$OMP END PARALLEL
- if(okdebug) then
- do mode = 1, nmod
- call Par_reduce( r_mean(mode) , 'sum', r_mean_all(mode) , status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( nr(mode) , 'sum', nr_all(mode) , status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( r_max(mode) , 'max', r_max_all(mode) , status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( vd_mean(mode,1), 'sum', vd_mean_all(mode,1), status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( nvd(mode,1) , 'sum', nvd_all(mode,1) , status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( vd_max(mode,1) , 'max', vd_max_all(mode,1) , status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( vd_mean(mode,2), 'sum', vd_mean_all(mode,2), status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( nvd(mode,2) , 'sum', nvd_all(mode,2) , status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( vd_max(mode,2) , 'max', vd_max_all(mode,2) , status)
- IF_NOTOK_RETURN(status=1)
- if (isRoot) then
- if(nr_all(mode) > 0) then
- r_mean_all(mode) = r_mean_all(mode)*1e6/nr_all(mode)
- else
- r_mean_all(mode) = 0.
- end if
- if(nvd_all(mode,1) > 0) then
- vd_mean_all(mode,1) = 1e2*vd_mean_all(mode,1)/nvd_all(mode,1)
- else
- vd_mean_all(mode,1) = 0.
- end if
- if(nvd_all(mode,2) > 0) then
- vd_mean_all(mode,2) = 1e2*vd_mean_all(mode,2)/nvd_all(mode,2)
- else
- vd_mean_all(mode,2) = 0.
- end if
- print '(i6,i4,2f10.4,2f12.6,2f12.6)', 0, mode, r_mean_all(mode), 1e6*r_max_all(mode), &
- vd_mean_all(mode,1), 1e2*vd_max_all(mode,1), vd_mean_all(mode,2), 1e2*vd_max_all(mode,2)
- end if
- enddo
- write(gol,*) '________________________________________________________________________________' ; call goPr
- endif
- status=0
- END SUBROUTINE DEPOSITION_CALCV
- !EOC
- !------------------------------------------------------------------------------
- ! TM5 !
- !------------------------------------------------------------------------------
- !BOP
- !
- ! !IROUTINE: SEDIMENTATION_CALCV
- !
- ! !DESCRIPTION: calculate velocities
- !\\
- !\\
- ! !INTERFACE:
- !
- SUBROUTINE SEDIMENTATION_CALCV(region, status)
- !
- ! !USES:
- !
- use global_data, only : mass_dat, region_dat
- use meteodata, only : spm_dat, temper_dat, cc_dat
- use chem_param, only : sigma_lognormal, names, mode_start, mode_end
- use dims, only : at, bt, nsrce, tref, im, jm, lm, okdebug
- #ifdef with_m7
- use m7_data, only : rw_mode, dens_mode
- #endif
- use partools, only : par_reduce
- !
- ! !INPUT PARAMETERS:
- !
- integer, intent(in) :: region
- !
- ! !OUTPUT PARAMETERS:
- !
- integer, intent(out) :: status
- !
- ! !REVISION HISTORY:
- ! 2 Apr 2010 - P. Le Sager -
- ! 21 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
- !
- ! !REMARKS:
- ! (1) Called only if m7 used.
- !
- !EOP
- !------------------------------------------------------------------------------
- !BOC
- character(len=*), parameter :: rname = mname//'/Sedimentation_calcv'
-
- real, dimension(:,:,:), pointer :: p ! surface pressure (Pa)
- real, dimension(:,:,:), pointer :: t ! temperature (K)
- real, dimension(:,:,:), pointer :: cc ! cloud cover (0-1)
- real, dimension(:,:,:), pointer :: q ! humidity (kg/kg)
- real, dimension(:,:,:,:), pointer :: rm ! tracer array (kg)
- real :: pb ! pressure at bottom of box (Pa)
- real :: dt ! general timestep (s)
- real :: dp ! pressure difference layer
- integer :: i,j,l, mode, proc, itn, n, nglob
- real :: temp ! temperature
- real :: to_pascal
- real :: slinnfac
- real :: zvis, rho_air, radius, Dpg, vt
- real, dimension(nmod,2) :: vd_mean_all, vd_max_all
- real, dimension(nmod,2) :: vd_mean, vd_max
- integer, dimension(nmod,2) :: nvd, nvd_all
- real, dimension(nmod) :: r_mean_all, r_max_all
- real, dimension(nmod) :: r_mean, r_max
- integer, dimension(nmod) :: nr, nr_all
- real :: lnsigma, sigma
- integer :: i1, j1, i2, j2
- !________________________start_________________________________
- nullify(rm)
- nullify(p)
- nullify(cc)
- nullify(t)
- p => spm_dat (region)%data
- t => temper_dat(region)%data
- cc => cc_dat (region)%data
- rm => mass_dat (region)%rm
-
- dt = float(nsrce)/(2*tref(region)) ! timestep
- call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
- ! transfer sedimentation vel. from m/s to Pa/s (note define this as positive = falling)
- ! dp = -rho*g*dz
- ! rho is calculated from temperature and pressure....
- ! 7.24e16*p/T (#/cm3) (pV=nRT--> nR/V = p/T )
- ! #/cm3 ---> kg/m3 f = xmair*1e3/Avog
- ! Thus: rho (kg/m3) = 7.24e16*p/T * xmair*1e3/Avog
- ! and (dPa) = -rho*g*(vdep)*dt = -7.24e16*grav*xmair*1e3/Avog * (p/T) *dt
- n_sedimentation_mean(region) = n_sedimentation_mean(region) + 1
- if(okdebug.and.isRoot) then
- write(gol,*) '________________________________________________________________________________' ; call goPr
- write(gol,*) 'Statistics for the sedimentation routine:' ; call goPr
- write(gol,*) '________________________________________________________________________________' ; call goPr
- write(gol,*) 'level mode r_mean r_max(um) vd_n(cm/s) vd_max(cm/s) vd_m(cm/s) vd_mmax(cm/s) ' ; call goPr
- write(gol,*) '________________________________________________________________________________' ; call goPr
- endif
- #ifdef with_m7
- !$OMP PARALLEL &
- !$OMP default (none) &
- !$OMP shared (region, t, at, bt, p, dt, &
- !$OMP rm, lm, &
- !$OMP vn_sedimentation_mean, vn_sedimentation, vm_sedimentation_mean, vm_sedimentation, &
- !$OMP sigma_lognormal, mode_start, mode_end) &
- !$OMP shared (okdebug, vd_mean, vd_max, nvd, r_max, r_mean, nr) &
- !$OMP shared (rw_mode, dens_mode) &
- !$OMP private (i, j, l, temp, pb, dp, zvis, rho_air, &
- !$OMP to_pascal, mode, itn, radius, sigma, lnsigma, &
- !$OMP density, slinnfac, dpg, vt)
- LEVS: do l=1, lm(region)
- if(okdebug) then
- vd_mean = 0.0
- r_mean = 0.0
- vd_max = 0.0
- r_max = 0.0
- nvd = 0
- nr = 0
- endif
- do j=j1, j2
- do i=i1, i2
- if(l == 1) then
- temp = t(i,j,1) ! at surface to temp box
- else
- temp = 0.5*(t(i,j,l)+t(i,j,l-1)) ! interpolate to bottom of box
- endif
- pb = at(l) + bt(l)*p(i,j,1) ! pressure at bottom of box (Pa)
- dp = (at(l)-at(l+1)) + p(i,j,1)*(bt(l)-bt(l+1)) ! layer thickness
- zvis = 0.0000014963*temp*sqrt(temp)/(temp+120.) ! viscocity (kg/ms)
- rho_air = 7.24e16*pb/temp * xmair*1e3/Avog ! kg/m3
- to_pascal = m_to_pa*dt*pb/temp ! convert from m/s ---> Pa/timestep
- M7MODES: do mode = 1, nmod
- radius = rw_mode(region,mode)%d3(i,j,l)
- sigma = sigma_lognormal(mode)
- lnsigma = log(sigma)
- density = dens_mode(region,mode)%d3(i,j,l)
- slinnfac = exp(2.0*lnsigma*lnsigma)
- if(okdebug) then
- if(radius > tiny(radius)) then
- r_mean(mode) = r_mean(mode) + radius
- nr(mode) = nr(mode) + 1
- r_max(mode) = max(r_max(mode), radius)
- endif
- endif
- ! for number: take first mode (Seinfeld, 1986, pg 286)
- dpg = radius*2.0*exp(lnsigma*lnsigma) ! diameter in m
- vt = fall1(pb,Dpg,zvis,temp,rho_air,density)
- if(okdebug) then
- if ( vt > tiny(vt) ) then
- vd_mean(mode,1) = vd_mean(mode,1) + vt
- vd_max(mode,1) = max(vd_max(mode,1) , vt)
- nvd(mode,1) = nvd(mode,1) + 1
- endif
- endif
- vn_sedimentation(region,mode)%d3(i,j,l) = min(to_pascal*vt,ndp*dp) ! in Pa/timestep downwards
- if(l == 1) then
- vn_sedimentation_mean(region)%surf(i,j,mode) = &
- vn_sedimentation_mean(region)%surf(i,j,mode) + vt
- endif
- ! for mass: the third moment
- dpg = radius*2.0*exp(3*lnsigma*lnsigma) ! diameter in m
- vt = fall1(pb,Dpg,zvis,temp,rho_air,density)
- if(okdebug) then
- if ( vt > tiny(vt) ) then
- vd_mean(mode,2) = vd_mean(mode,2) + vt*slinnfac
- vd_max(mode,2) = max(vd_max(mode,2) , vt*slinnfac)
- nvd(mode,2) = nvd(mode,2) + 1
- endif
- endif
- vm_sedimentation(region,mode)%d3(i,j,l) = min(to_pascal*vt*slinnfac,ndp*dp) ! multiply with slinnfac
- if(l == 1) then
- vm_sedimentation_mean(region)%surf(i,j,mode) = &
- vm_sedimentation_mean(region)%surf(i,j,mode) + vt*slinnfac
- endif
- enddo M7MODES
- enddo ! i
- enddo ! j
- if(okdebug) then
- do mode = 1, nmod
- call Par_reduce( r_mean(mode) , 'sum', r_mean_all(mode) , status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( nr(mode) , 'sum', nr_all(mode) , status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( r_max(mode) , 'max', r_max_all(mode) , status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( vd_mean(mode,1), 'sum', vd_mean_all(mode,1), status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( nvd(mode,1) , 'sum', nvd_all(mode,1) , status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( vd_max(mode,1) , 'max', vd_max_all(mode,1) , status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( vd_mean(mode,2), 'sum', vd_mean_all(mode,2), status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( nvd(mode,2) , 'sum', nvd_all(mode,2) , status)
- IF_NOTOK_RETURN(status=1)
- call Par_reduce( vd_max(mode,2) , 'max', vd_max_all(mode,2) , status)
- IF_NOTOK_RETURN(status=1)
- if (isRoot) then
- if(nr_all(mode) > 0) then
- r_mean_all(mode) = r_mean_all(mode)*1e6/nr_all(mode)
- else
- r_mean_all(mode) = 0.
- end if
- if(nvd_all(mode,1) > 0) then
- vd_mean_all(mode,1) = 1e2*vd_mean_all(mode,1)/nvd_all(mode,1)
- else
- vd_mean_all(mode,1) = 0.
- end if
- if(nvd_all(mode,2) > 0) then
- vd_mean_all(mode,2) = 1e2*vd_mean_all(mode,2)/nvd_all(mode,2)
- else
- vd_mean_all(mode,2) = 0.
- end if
- print '(i6,i4,2f10.4,2f12.6,2f12.6)', l, mode, r_mean_all(mode), 1e6*r_max_all(mode), &
- vd_mean_all(mode,1), 1e2*vd_max_all(mode,1), vd_mean_all(mode,2), 1e2*vd_max_all(mode,2)
- end if
- enddo
- write(gol,*) '________________________________________________________________________________' ; call goPr
- endif
-
- enddo LEVS
- !$OMP END PARALLEL
-
- #endif /* M7 */
- status = 0
-
- END SUBROUTINE SEDIMENTATION_CALCV
- !EOC
- !------------------------------------------------------------------------------
- ! TM5 !
- !------------------------------------------------------------------------------
- !BOP
- !
- ! !IROUTINE: SEDIMENTATION_APPLY
- !
- ! !DESCRIPTION: Sedimentation calculation based on pre-calculated
- ! v_sedimentation.
- ! Based on dynamw routine, including the slopes.
- !\\
- !\\
- ! !INTERFACE:
- !
- SUBROUTINE SEDIMENTATION_APPLY( region, status )
- !
- ! !USES:
- !
- use global_data, only : mass_dat, region_dat
- use meteodata , only : spm_dat
- use chem_param, only : ra
- use dims, only : lm, at, bt, limits, sec_month, nsrce, tref, okdebug
- use chem_param, only : mode_nm, mode_tracers
- use partools, only : par_reduce, par_reduce_element
- #ifdef with_m7
- use emission_data, only : bb_lm
- #ifndef without_emission
- use emission_data, only : emis_mass, emis_number
- #endif
- #endif
- #ifdef with_budgets
- use emission_data, only : budemi_dat, sum_emission
- use ebischeme, only : buddep_dat
- #endif
- !
- ! !INPUT PARAMETERS:
- !
- integer, intent(in) :: region
- !
- ! !OUTPUT PARAMETERS:
- !
- integer, intent(out) :: status
- !
- ! !REVISION HISTORY:
- ! 19 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
- !
- ! !REMARKS:
- ! (1) effective only if m7 used...
- !
- !EOP
- !------------------------------------------------------------------------------
- !BOC
- character(len=*), parameter :: rname = mname//'/Sedimentation_Apply'
- real,dimension(:,:,:,:),pointer :: rm,rxm,rym,rzm
- real,dimension(:,:,:),pointer :: vsold
- real,dimension(:,: ),pointer :: vdold
- real,dimension(:,:,:),pointer :: p ! surface pressure
- real,dimension(:,:,:),allocatable :: f, pf, fx, fy, vs
- real,dimension(:,:,:),allocatable :: emit
- real,dimension(:,:),allocatable :: vd
- integer :: i, j, l, n, lmr, mode
- real, parameter :: one = 1.0
- real :: gamma, gam, l_gam
- real :: dp, dtime, month2dt
- real :: rmold, rmnew, rmplus, fdep, fsed
- integer,parameter :: iter_limit=200
- integer :: n_advz, iter
- integer :: nzone_v
- integer :: ls, le, ii, inmode
- real :: l_sum(3), g_sum(3)
- integer :: i1, j1, i2, j2, iflag, jflag, lflag
- !________________________start_________________________________
- ! Big if-condition over all routine
- ! start timing:
- call GO_Timer_Start( itim_appl, status )
- IF_NOTOK_RETURN(status=1)
-
- #ifdef with_m7
- ! Bounds
- call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
- lmr = lm(region)
-
- allocate( f ( i1:i2, j1:j2, lmr )) ! flux of tracer (kg)
- allocate(pf ( i1:i2, j1:j2, lmr )) ! rxz moment flux
- allocate(fx ( i1:i2, j1:j2, lmr )) ! rmx flux
- allocate(fy ( i1:i2, j1:j2, lmr )) ! rmy flux
- allocate(vs ( i1:i2, j1:j2, lmr ))
- allocate(vd ( i1:i2, j1:j2 ))
- allocate(emit( i1:i2, j1:j2, bb_lm))
- call sedimentation_calcv(region, status) ! calculate sedimentation....
- IF_NOTOK_RETURN(status=1)
- call deposition_calcv(region, status) ! calculate deposition.....
- IF_NOTOK_RETURN(status=1)
-
- nullify(rm)
- nullify(rxm)
- nullify(rym)
- nullify(rzm)
- nullify(p)
- p => spm_dat(region)%data
- rm => mass_dat(region)%rm
- rxm => mass_dat(region)%rxm
- rym => mass_dat(region)%rym
- rzm => mass_dat(region)%rzm
- if(okdebug) then
- write(gol,*) ' call sedimentation'; call goPr
- end if
-
- ! If requested, limit vertical slopes such that no non-negative tracer masses should occur
- ls = 1 ; le = lmr
- if (limits) then
- do n = 1, ubound (rzm, 4)
- do l = ls, le
- do j = j1, j2
- do i = i1, i2
- rzm(i,j,l,n) = max(min(rzm(i,j,l,n),rm(i,j,l,n)), -rm(i,j,l,n))
- end do
- end do
- end do
- end do
- endif
- ! determine timestep
- dtime=float(nsrce)/(2*tref(region))
- ! conversion to emission per timestep
- month2dt=dtime/sec_month
- ! =================
- ! Loop over tracers
- ! =================
- do mode =1,nmod
- do inmode=0,mode_nm(mode)
- n = mode_tracers(inmode,mode)
- !------------- reset
- n_advz=1
- nullify(vsold)
- nullify(vdold)
- if (inmode == 0) then ! number or mass tracer
- vsold => vn_sedimentation(region,mode)%d3
- vdold => vn_deposition(region,mode)%surf
- else
- vsold => vm_sedimentation(region,mode)%d3
- vdold => vm_deposition(region,mode)%surf
- endif
- !------------- find # iter needed for no CFL violation
- cfl: do
- vs(:,j1:j2,:) = vsold(:,j1:j2,:)/float(n_advz)
- vd(:,j1:j2) = vdold(:,j1:j2) /float(n_advz)
- advz: do iter=1,n_advz
- ! reset gamma
- l_gam = 0.
- do l= 1, lmr
- do j= j1, j2
- do i= i1, i2
- ! vs (Pa) always downwards
- ! calculate the flux at the bottom of box:
- ! note that we define this as negative (vs>0, f<0)
- ! pressure difference in layer dp (Pa)
- dp = (at(l)-at(l+1)) + p(i,j,1)*(bt(l)-bt(l+1)) ! positive..
- if(l /= 1) then
- gamma=-vs(i,j,l)/dp !always negative (according to negative cm dynamw)
- else
- gamma=-(vs(i,j,l)+vd(i,j))/dp !always negative (according to negative cm dynamw)
- endif
-
- ! replace 'one' with 0.99999 (NB/PLS)
- if (abs(gamma)>=0.9999999) then
- l_gam=max(l_gam,abs(gamma))
- ! exit advz ! commented for consistency with TM5
- end if
-
- enddo
- enddo
- enddo
- enddo advz
- call Par_REDUCE( l_gam, 'MAX', gam, status, all=.true.)
-
- ! if CFL violation increase iteration counter and re-start cfl loop
- ! but check if the number of iterations becomes too large
-
- if(abs(gam)>=0.9999999) then ! PLS: replace "one" with 0.9999999 to be consistent with above
- !Commented since "exit advz" is commented, and hence not meaningfull
- ! if(okdebug)then
- !
- ! iflag=min(i,i2)
- ! jflag=min(j,j2)
- ! lflag=min(l,lmr)
- !
- ! ! i-j-l information correct if from the processor where violation happened
- ! print *,' --- CFL violation: gamma=',gam,vs(iflag,jflag,lflag),' in (region,i,j,l,n)= ',region,iflag,jflag,lflag,n
- ! print*,' #iterations:', n_advz
- ! endif
- n_advz = n_advz + 1
- if ( n_advz > iter_limit ) then
- status=1
- IF_NOTOK_RETURN(status=1)
- end if
- cycle cfl
- else ! situation OK, no CFL: use this n_advz
- exit cfl
- endif
- enddo cfl
- !------------- Apply number of iterations to calculate new tracer distributions
- #ifdef with_budgets
- l_sum = 0.0
- #endif
- #ifndef without_emission
- if(inmode == 0) then
- emit(:,j1:j2,:) = 0.0
- do ii=1,mode_nm(mode) ! add up all number emissions in the mode...
- emit(:,j1:j2,:) = emit(:,j1:j2,:) + emis_number(region,mode)%d4(:,j1:j2,:,ii)*month2dt/float(n_advz)
- enddo
- else ! this is a 'mass' emission with index nmode
- emit(:,j1:j2,:) = emis_mass(region,mode)%d4(:,j1:j2,:,inmode)*month2dt/float(n_advz)
- endif
- #else
- emit = 0.0
- #endif
- ! do the iteration
- do iter=1,n_advz
- ! compute f, pf, fx and fy
- do l= 1, lmr
- do j= j1, j2
- do i= i1, i2
- ! vs (Pa) always downwards
- ! calculate the flux at the bottom of box:
- ! note that we define this as negative (vs>0, f<0)
- ! pressure difference in layer dp (Pa)
- dp = (at(l)-at(l+1)) + p(i,j,1)*(bt(l)-bt(l+1)) ! positive..
- if(l /= 1) then
- gamma=-vs(i,j,l)/dp !always negative (according to negative cm dynamw)
- else
- gamma=-(vs(i,j,l)+vd(i,j))/dp !always negative (according to negative cm dynamw)
- endif
- f(i,j,l) = gamma*(rm(i,j,l,n)-(one+gamma)*rzm(i,j,l,n)) !kg (neg.)
- pf(i,j,l) = -vs(i,j,l)*(gamma*gamma*rzm(i,j,l,n)-3.*f(i,j,l)) !neg.
- fx(i,j,l) = gamma*rxm(i,j,l,n) !kg (neg.)
- fy(i,j,l) = gamma*rym(i,j,l,n) !kg (neg.)
- ! - Cannot happen unless there is a bug (pls)
- !if (abs(gamma)>=one) then
- ! status=1
- ! IF_NOTOK_RETURN(status=1)
- !end if
-
- enddo
- enddo
- enddo
- ! calculate new tracer mass, and tracer mass slopes
- ! update rm, rzm, rxm and rym in interior layers of the column
- l = lmr
- do j = j1, j2
- do i = i1, i2
- dp = (at(l)-at(l+1)) + p(i,j,1)*(bt(l)-bt(l+1))
- rm (i,j,l,n)=rm(i,j,l,n) + f(i,j,l)
- rzm(i,j,l,n)=rzm(i,j,l,n)+ &
- ( pf(i,j,l) &
- -(-vs(i,j,l)) *rzm(i,j,l,n) &
- +3.*( ( -vs(i,j,l)) *rm (i,j,l,n) &
- -( f(i,j,l))*dp ))/dp
- if(limits) then
- rzm(i,j,l,n) = max(min(rzm(i,j,l,n), rm(i,j,l,n)), -rm(i,j,l,n))
- endif
- rxm(i,j,l,n)=rxm(i,j,l,n)+(fx(i,j,l))
- rym(i,j,l,n)=rym(i,j,l,n)+(fy(i,j,l))
- #ifdef with_budgets
- nzone_v=nzon_vg(l)
- buddep_m7_dat(region)%sed(i,j,nzone_v,sindex(n)) = &
- buddep_m7_dat(region)%sed(i,j,nzone_v,sindex(n)) - f(i,j,l)*1e3/ra(n) ! in mole
- ! Downward flux is negative. And it is defined at the bottom of the box. A positive flux
- ! is positive and would be an income for the respective grid cell. A minus sign takes care
- ! We want to define the sedimentation as a cost.
- #endif
- enddo
- enddo
-
- do l = lmr-1, 2, -1
- do j = j1, j2
- do i = i1, i2
- dp = (at(l)-at(l+1)) + p(i,j,1)*(bt(l)-bt(l+1))
- rmold = rm(i,j,l,n)
- if (l .le. bb_lm) then
- rmplus = rmold + f(i,j,l)-f(i,j,l+1) + emit(i,j,l)
- else
- rmplus = rmold + f(i,j,l)-f(i,j,l+1)
- endif
- rm(i,j,l,n) = rmplus
- rzm(i,j,l,n)=rzm(i,j,l,n)+ &
- ( pf(i,j,l)-pf(i,j,l+1) &
- -(vs(i,j,l+1)-vs(i,j,l)) *rzm(i,j,l,n) &
- +3.*( (-vs(i,j,l+1)-vs(i,j,l)) *rm (i,j,l,n) &
- -(f(i,j,l+1)+ f(i,j,l)) *dp ))/dp
- if(limits) then
- rzm(i,j,l,n) = max(min(rzm(i,j,l,n), rm(i,j,l,n)), -rm(i,j,l,n))
- endif
- rxm(i,j,l,n)=rxm(i,j,l,n)+(fx(i,j,l)-fx(i,j,l+1))
- rym(i,j,l,n)=rym(i,j,l,n)+(fy(i,j,l)-fy(i,j,l+1))
- #ifdef with_budgets
- nzone_v=nzon_vg(l)
- buddep_m7_dat(region)%sed(i,j,nzone_v,sindex(n)) = &
- buddep_m7_dat(region)%sed(i,j,nzone_v,sindex(n)) - (f(i,j,l)-f(i,j,l+1))*1e3/ra(n) ! in mole
- ! The sedimentation is calculated as 'income' again. With the minus sign, those are costs.
- #ifndef without_emission
- if ( l <= bb_lm ) then
- budemi_dat(region)%emi(i,j,nzone_v,n) = &
- budemi_dat(region)%emi(i,j,nzone_v,n) + emit(i,j,l)*1e3/ra(n) ! in mole
- end if
- #endif
- #endif
- enddo
- enddo
- enddo
-
- l = 1 !
- do j = j1, j2
- do i= i1, i2
- dp = (at(l)-at(l+1)) + p(i,j,1)*(bt(l)-bt(l+1))
- if(vd_in_deposition) then
- write(gol,*)' aply_sedimentation: vs in deposition disabled'; call goBug
- status=1
- IF_NOTOK_RETURN(status=1)
- end if
-
- !if(vd_in_deposition) then
- ! rm (i,j,l,n)=rm(i,j,l,n) - f(i,j,l+1)
- ! rzm(i,j,l,n)=rzm(i,j,l,n)+ &
- ! ( -pf(i,j,l+1) &
- ! -(vs(i,j,l+1)) *rzm(i,j,l,n) &
- ! +3.*( (-vs(i,j,l+1)) *rm (i,j,l,n) &
- ! -(f(i,j,l+1))*dp ))/dp
- ! if(limits) then
- ! rzm(i,j,l,n) = max(min(rzm(i,j,l,n), rm(i,j,l,n)), -rm(i,j,l,n))
- ! endif
- ! rxm(i,j,l,n)=rxm(i,j,l,n)+(-fx(i,j,l+1))
- ! rym(i,j,l,n)=rym(i,j,l,n)+(-fy(i,j,l+1))
- !else
- ! rm (i,j,l,n)=rm(i,j,l,n) + f(i,j,l)-f(i,j,l+1)
- ! rzm(i,j,l,n)=rzm(i,j,l,n)+ &
- ! ( pf(i,j,l)-pf(i,j,l+1) &
- ! -(vs(i,j,l+1)-vs(i,j,l)) *rzm(i,j,l,n) &
- ! +3.*( (-vs(i,j,l+1)-vs(i,j,l)) *rm (i,j,l,n) &
- ! -(f(i,j,l+1)+ f(i,j,l))*dp ))/dp
- ! if(limits) then
- ! rzm(i,j,l,n) = max(min(rzm(i,j,l,n), rm(i,j,l,n)), -rm(i,j,l,n))
- ! endif
- ! apply to rxm, rym the fluxes:
- rxm(i,j,l,n)=rxm(i,j,l,n)+(fx(i,j,l)-fx(i,j,l+1))
- rym(i,j,l,n)=rym(i,j,l,n)+(fy(i,j,l)-fy(i,j,l+1))
- ! for rm: apply emissions, sedimentation flux from above
- ! deposition and sedimentation at surface: Backward Eularian
- rmold = rm(i,j,l,n)
- rmplus = (rmold - f(i,j,l+1) + emit(i,j,l)) ! note f is negative !
- rmnew = rmplus/(1. + (vd(i,j) + vs(i,j,1))/dp)
- rm(i,j,l,n) = rmnew
- if(rmold > 1e-8) rzm(i,j,l,n) = rzm(i,j,l,n)*rmnew/rmold
- ! budget:
- #ifdef with_budgets
- if((vs(i,j,1) + vd(i,j)) > 1e-12) then
- fsed = -(rmplus-rmnew)*vs(i,j,1)/(vs(i,j,1) + vd(i,j)) ! is negative
- fdep = -(rmplus-rmnew)*vd(i,j) /(vs(i,j,1) + vd(i,j))
- else
- fsed = 0.0
- fdep = 0.0
- endif
-
- if(n == 1) then
- l_sum(1) = l_sum(1) + f(i,j,l+1) - fsed ! goes into sum_sedimentation
- l_sum(2) = l_sum(2) - fdep ! goes into sum_drydep
- #ifndef without_emission
- l_sum(3) = l_sum(3) + emit(i,j,1) ! goes into sum_emission
- #endif
- endif
- nzone_v=nzon_vg(l)
- buddep_m7_dat(region)%sed(i,j,nzone_v,sindex(n)) = &
- buddep_m7_dat(region)%sed(i,j,nzone_v,sindex(n)) - (fsed - f(i,j,l+1) )*1e3/ra(n) ! in mole
- ! The comment line says that fsed is negative. As we regard sedimentation as a cost, we define
- ! a positive sedimentation as a loss of material. A negative fsed is loss of material, so we
- ! need to have -fsed. The (upward) flux on the top of the grid cell is a cost as well.
- buddep_dat(region)%dry(i,j,n) = &
- buddep_dat(region)%dry(i,j,n) - fdep*1e3/ra(n) ! in mole
- #ifndef without_emission
- budemi_dat(region)%emi(i,j,1,n) = &
- budemi_dat(region)%emi(i,j,1,n) + emit(i,j,1)*1e3/ra(n) ! in mole
- #endif
- #endif /* BUDGETS */
-
- enddo !i
- enddo !j
- enddo ! iter !
- #ifdef with_budgets
- call PAR_REDUCE_ELEMENT( l_sum, 'SUM', g_sum, status )
- if(isRoot ) then
- sum_sedimentation(region) = sum_sedimentation(region) + g_sum(1)
- sum_drydep (region) = sum_drydep (region) + g_sum(2)
- #ifndef without_emission
- sum_emission (region) = sum_emission (region) + g_sum(3)
- #endif
- end if
- #endif
- enddo ! loop over tracers in mode
- enddo ! loop over modes
- deallocate( f)
- deallocate(pf)
- deallocate(fx)
- deallocate(fy)
- deallocate(vs)
- deallocate(vd)
- deallocate(emit)
- nullify(rm)
- nullify(rxm)
- nullify(rym)
- nullify(rzm)
- nullify(vsold)
- nullify(vdold)
- #endif /* M7 */
- ! end timing:
- call GO_Timer_End( itim_appl, status )
- IF_NOTOK_RETURN(status=1)
- status = 0
- END SUBROUTINE SEDIMENTATION_APPLY
- !EOC
- #ifdef with_m7
- !------------------------------------------------------------------------------
- ! TM5 !
- !------------------------------------------------------------------------------
- !BOP
- !
- ! !IROUTINE: FALL1
- !
- ! !DESCRIPTION: function to calculate the fall velocity from the particle
- ! diameter, as a function of density, temperature and pressure.
- !\\
- !\\
- ! !INTERFACE:
- !
- REAL FUNCTION FALL1( press, zmd, zvis, t, zdensair, densaer_p) result(vt)
- !
- ! !INPUT PARAMETERS:
- !
- real, intent(in) :: press ! pressure in Pa (or bar?)
- real, intent(in) :: zmd ! median radius of aerosol (m)
- real, intent(in) :: zvis ! viscosity (kg/(sm))
- real, intent(in) :: t ! temperature (K)
- real, intent(in) :: zdensair ! density air (kg/m3)
- real, intent(in) :: densaer_p ! density aerosol particles (kg/m3)
- !
- ! !REVISION HISTORY:
- ! 2 Apr 2010 - P. Le Sager -
- !
- ! !REMARKS:
- ! Called in Sedimentation_Apply, only if m7 used.
- !
- !EOP
- !------------------------------------------------------------------------------
- !BOC
- real :: zlair
- ! According to JEW, here is where too small value creates a problem (issue #317). Not sure
- ! what's going on, undeflow? -PLS
-
- ! ----------- start
- if (zmd > tiny(zmd)) then
- vt=2./9.*(densaer_p-zdensair) * grav/zvis*(zmd/2.)**2.
- zlair=0.066*(1.01325e5/press)*t/293.15*1e-6
- !--- With cunnigham slip- flow correction (S&P, Equation 8.34):
- vt = vt * (1.+ 1.257*zlair/zmd*2. + 0.4*zlair/zmd*2. * exp(-1.1/(zlair/zmd*2.)) )
- else
- vt = 0.0
- endif
- END FUNCTION FALL1
- !EOC
-
- #endif /* M7 */
- !------------------------------------------------------------------------------
- ! TM5 !
- !------------------------------------------------------------------------------
- !BOP
- !
- ! !IROUTINE: AEROSOL_RADIUS
- !
- ! !DESCRIPTION: function that calculates the median aerosol radius (m),
- ! given the total mass and number of a log-normal distribution.
- !\\
- !\\
- ! !INTERFACE:
- !
- REAL FUNCTION AEROSOL_RADIUS(mtot, ntot, sigma, rho_aer) result(radius)
- !
- ! !USES:
- !
- use Binas, only: Pi
- !
- ! !INPUT PARAMETERS:
- !
- real, intent(in) :: mtot ! total mass (kg)
- real, intent(in) :: ntot ! total number (#)
- real, intent(in) :: sigma ! the sigma of the log-normal aerosol size distribution
- real, intent(in) :: rho_aer ! the density of the aerosol (kg/m3)
- !
- ! !REVISION HISTORY:
- ! 2 Apr 2010 - P. Le Sager -
- !
- ! !REMARKS:
- !
- !EOP
- !------------------------------------------------------------------------------
- !BOC
- real :: lns
- if(mtot > tiny(mtot) .and. ntot > tiny(ntot)) then
- lns = alog(sigma)
- radius = (mtot/(rho_aer*4.0*pi/3.0 *ntot *exp((9./2.)*lns**2)))**(1./3.)
- else
- radius = 0.0
- endif
- END FUNCTION AEROSOL_RADIUS
- !EOC
- !------------------------------------------------------------------------------
- ! TM5 !
- !------------------------------------------------------------------------------
- !BOP
- !
- ! !IROUTINE: CALCULATE_RH
- !
- ! !DESCRIPTION: calculate the rh, with 100% rh assumption in cloudy part.
- ! In the cloud free part, the rh thus is smaller, and the water
- ! uptake by aerosols will be smaller.
- !\\
- !\\
- ! !INTERFACE:
- !
- SUBROUTINE CALCULATE_RH
- !
- ! !USES:
- !
- use chem_param, only : xmh2o
- use meteodata, only : phlb_dat
- use MeteoData, only : temper_dat, humid_dat, cc_dat
- use dims, only : nregions, im, jm ,lm
- !
- ! !REVISION HISTORY:
- ! 19 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
- !
- !EOP
- !------------------------------------------------------------------------------
- !BOC
- real, dimension(:,:,:), pointer :: phlb ! pressure at border (Pa)
- real, dimension(:,:,:), pointer :: t ! temperature (K)
- real, dimension(:,:,:), pointer :: q ! humidity (kg h2o / kg air)
- real, dimension(:,:,:), pointer :: cc ! cloud cover (0-1)
- real :: tr, wv, airn, h2on, rrh, s, ccs
- integer :: region, i,j,l, i1,i2,j1,j2
- do region = 1, nregions
- call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
- nullify(phlb)
- nullify(t)
- nullify(q)
- nullify(cc)
- phlb => phlb_dat(region)%data
- t => temper_dat(region)%data
- q => humid_dat(region)%data
- cc => cc_dat(region)%data
- do l=1, lm(region)
- do j=j1, j2
- do i=i1, i2
- tr = 1. - 373.15/t(i,j,l)
- wv=exp((((-.1299*tr-.6445)*tr-1.976)*tr+13.3185)*tr)
- airn = 7.24e16*0.5*(phlb(i,j,l) + phlb(i,j,l+1))/t(i,j,l) ! somethings seem redundent here!
- h2on = q(i,j,l)*airn*xmair/xmh2o ! leave it for readability!
- rrh = h2on*t(i,j,l)/(1013.25*wv*7.24e16)
- s = 0.01*max(0.0, min(rrh, 99.9 ) ) ! 0-0.999 scale!
- rha(region)%d3(i,j,l) = s
- ! scale relative humidity to cloudfree part
- ! assuming 100% rh in the cloudy part, but never smaller than 0.75!
- if (s > 0.90) then
- ccs = cc(i,j,l)
- if((1. - ccs) > tiny(ccs)) s = max(0.75, (s-ccs)/(1. - ccs))
- endif
- rh(region)%d3(i,j,l) = s
- enddo
- enddo
- enddo
- nullify(phlb)
- nullify(t)
- nullify(q)
- nullify(cc)
- enddo
- END SUBROUTINE CALCULATE_RH
- !EOC
- END MODULE SEDIMENTATION
|