PUMA
219
Portable University Model of the Atmosphere
|
00001 module pumamod 00002 00003 ! **************************************************************** 00004 ! * Puma Pre Processor * 00005 ! **************************************************************** 00006 ! * E. Kirk & T. Kunz & F. Lunkeit * 00007 ! * Meteorologisches Institut * 00008 ! * Universitaet Hamburg * 00009 ! * Bundesstrasse 55 * 00010 ! * 20146 HAMBURG * 00011 ! * 20-Apr-2009 GERMANY * 00012 ! **************************************************************** 00013 00014 ! **************************************************************** 00015 ! * Insert your own code for modification of initial data to: * 00016 ! * subroutine modify_orography * 00017 ! * subroutine modify_ground_temperature * 00018 ! **************************************************************** 00019 00020 ! **************************************************************** 00021 ! * PUMA in its default setup can run without initial data * 00022 ! * The default setup is an aqua planet with no orography and * 00023 ! * zonally symmetric forcing (newtonian cooling with Tr) * 00024 ! * The atmosphere starts at rest with no horizontal gradients * 00025 ! * * 00026 ! * This preprocessor program performs following tasks: * 00027 ! * 1) Prepare a realistic orography (T21 or T42) * 00028 ! * 2) Enable user modification of this orography * 00029 ! * 3) Enable user modification of the ground temperature field * 00030 ! * 4) Adjust vertical profiles of Restoration Temperature * 00031 ! * 5) Adjust the mean value of surface pressure * 00032 ! * 6) Build an initial Ps field adjusted to orography * 00033 ! * 7) Setup Yoden-profiles * 00034 ! * * 00035 ! * Inputfile: <Naaa_surf_0129.sra> with aaa=032,048,064, ... * 00036 ! * <Naaa_surf_0139.sra> : Ts anomalies * 00037 ! * Outputfiles: <Naaa_surf_0129.sra> : topography [m2/s2] * 00038 ! * <Naaa_surf_0134.sra> : Surface pressure [hPa] * 00039 ! * <Naaa_surf_0121.sra> : Constant part of Tr * 00040 ! * <Naaa_surf_0122.sra> : Variable part of Tr * 00041 ! * <Naaa_surf_0123.sra> : Damping time scales * 00042 ! * * 00043 ! * The outputfiles contain topography, surface pressure, * 00044 ! * the part of Tr, that is constant in time and the part pf Tr * 00045 ! * that can be modulated by an annual cycle. * 00046 ! * * 00047 ! * All files are written formatted, such avoiding the problems * 00048 ! * assigned to big endian and little endian machines * 00049 ! **************************************************************** 00050 00051 00052 ! **************************************************************** 00053 ! * The horizontal resolution of PUMA by the number of latitudes * 00054 ! * nlat is read from file "resolution_namelist" * 00055 ! **************************************************************** 00056 integer :: nlat = 32 00057 00058 ! example values: 32, 48, 64, 128, 192, 256, 512, 1024 00059 ! truncation: T21, T31, T42, T85, T127, T170, T341, T682 00060 00061 00062 ! ***************************************************************** 00063 ! * The number of sigma levels of PUMA are modified after reading * 00064 ! * file <resolution_namelist>. * 00065 ! ***************************************************************** 00066 integer :: nlev = 10 ! Levels 00067 00068 00069 ! *****************************************************************! 00070 ! * Grid related paramters, which are reset after reading the file ! 00071 ! * <resolution_namelist>. All parameters are initialized for the ! 00072 ! * T21 truncation ! 00073 ! *****************************************************************! 00074 integer :: nlon = 64 ! Longitudes = 2 * latitudes 00075 integer :: ntru = 21 ! (nlon-1) / 3 00076 integer :: nlpp = 32 ! Latitudes per process 00077 integer :: nhor = 2048 ! Horizontal part 00078 integer :: nlem = 9 ! Levels - 1 00079 integer :: nlep = 11 ! Levels + 1 00080 integer :: nlsq = 100 ! Levels squared 00081 integer :: ntp1 = 22 ! ntru + 1 00082 integer :: nrsp = 506 ! (ntru+1) * (ntru+2) 00083 integer :: ncsp = 253 ! nrsp / 2 00084 integer :: nspp = 506 ! nodes per process 00085 integer :: nesp = 506 ! number of extended modes 00086 integer :: nzom = 44 ! Number of zonal modes 00087 00088 integer :: nlah = 16 ! Half of latitudes 00089 integer :: nhpp = 16 ! Half latitudes per process 00090 00091 ! **************************************************************** 00092 ! * Don't touch the following parameter definitions ! * 00093 ! **************************************************************** 00094 00095 parameter(AKAP = 0.286) ! Kappa 00096 parameter(ALR = 0.0065) ! Lapse rate 00097 parameter(EZ = 1.632993161855452D0) ! ez = 1 / sqrt(3/8) 00098 parameter(GA = 9.81) ! Gravity 00099 parameter(GASCON = 287.0) ! Gas constant 00100 parameter(PI = 3.141592653589793D0) ! Pi 00101 parameter(TWOPI = PI + PI) ! 2 Pi 00102 parameter(PLARAD_EARTH = 6371000.0) ! Planet radius 00103 parameter(SID_DAY_EARTH= 86164.) ! Siderial day Earth 23h 56m 04s 00104 parameter(PNU = 0.02) ! Time filter 00105 parameter(PNU21 = 1.0 - 2.0*PNU) ! Time filter 2 00106 parameter(PSURF = 101100.0) ! Surface pressure [Pa] 00107 parameter(WW = 0.00007292) ! Rotation speed [1/sec] 00108 parameter(CV = PLARAD_EARTH * WW) ! cv 00109 parameter(CT = CV*CV/GASCON) ! ct 00110 parameter(OSCAR = CV*CV/GA) ! Scale Orography 00111 00112 00113 ! ************* 00114 ! * filenames * 00115 ! ************* 00116 character (256) :: resolution_namelist = "resolution_namelist" 00117 character (256) :: puma_namelist = "puma_namelist" 00118 character (256) :: ppp_puma_txt = "ppp-puma.txt" 00119 00120 ! ***************************************************************** 00121 ! * For multiruns the instance number is appended to the filename * 00122 ! * e.g.: puma_namelist_1 puma_diag_1 etc. for instance # 1 * 00123 ! ***************************************************************** 00124 00125 00126 00127 00128 00129 00130 00131 00132 00133 00134 ! ************************** 00135 ! * Global Integer Scalars * 00136 ! ************************** 00137 00138 integer :: kick = 1 ! kick > 1 initializes eddy generation 00139 integer :: mpstep = 0 ! PUMA 00140 integer :: nafter = 0 ! PUMA 00141 integer :: nwpd = 1 ! PUMA 00142 integer :: ncoeff = 0 ! number of modes to print 00143 integer :: ndel = 6 ! ndel 00144 integer :: ndiag = 12 ! write diagnostics interval 00145 integer :: nkits = 3 ! number of initial timesteps 00146 integer :: nlevt = 9 ! tropospheric levels (set_vertical_grid) 00147 00148 integer :: ngui = 0 ! PUMA variable 00149 integer :: nguidbg = 0 ! PUMA variable 00150 integer :: nqspec = 1 ! PLASIM variable 00151 integer :: nrun = 0 ! PUMA variable 00152 integer :: nstep = 0 ! current timestep 00153 integer :: nstop = 0 ! finishing timestep 00154 integer :: nsync = 0 ! PUMA variable 00155 integer :: ntspd = 24 ! number of timesteps per day 00156 integer :: ncu = 0 ! check unit (debug output) 00157 integer :: noro = 0 ! 1: read orography 00158 ! 2: orography is computed (sine wave) 00159 ! 3: orography is computed (gauss) 00160 00161 integer :: norox = 0 ! x-wavenumber of idealized orography 00162 integer :: nreverse = 0 ! t-gradient reversal in stratosphere; 0:no 1:yes 00163 integer :: ncorrect = 0 ! correct tr due to orography (0:no, 1:yes) 00164 integer :: nsym = 0 ! produces total symmetric initial conditions 00165 00166 integer :: nsrv = 1 ! 1: write gridpoint fields for diagnostics 00167 integer :: lon1oro = 0 ! Define rectangle for anomaly 00168 integer :: lon2oro = 0 ! 00169 integer :: lat1oro = 0 ! 00170 integer :: lat2oro = 0 ! 00171 integer :: ntgr = 0 ! 1: read ground temperature 00172 integer :: lon1tgr = 0 ! Define rectangle for anomaly 00173 integer :: lon2tgr = 0 ! 00174 integer :: lat1tgr = 0 ! 00175 integer :: lat2tgr = 0 ! 00176 integer :: nstrato = 0 ! 1: Torben's stratosphere forcing 00177 integer :: nsponge = 0 ! Switch for sponge layer 00178 integer :: nhelsua = 0 ! 1: Set up Held & Suarez T_R field 00179 ! instead of original PUMA T_R field 00180 ! 2: Set up Held & Suarez T_R field 00181 ! instead of original PUMA T_R field 00182 ! AND use latitudinally varying 00183 ! heating timescale in PUMA (H&Z(94)), 00184 ! irrelevant for PumaPreProcessor (ppp) 00185 ! 3: Use latitudinally varying 00186 ! heating timescale in PUMA (H&Z(94)), 00187 ! irrelevant for PumaPreProcessor (ppp) 00188 integer :: ntestgp = 0 ! switch 0/1 produce a second set of restoration 00189 ! restoration temperatures and damping time scales 00190 integer :: nvg = 0 ! type of vertical grid 00191 ! 0 = linear 00192 ! 1 = Scinocca & Haynes 00193 ! 2 = Polvani & Kushner 00194 00195 integer :: nyoden = 0 ! > 0 Read yoden profile t0(:) and dt(:) 00196 integer :: npackgp = 1 ! used in PUMA 00197 integer :: npacksp = 1 ! used in PUMA 00198 integer :: noutput = 0 ! used in PUMA 00199 integer :: noutsrv = 0 ! used in PUMA 00200 00201 00202 ! These three predifined Yoden profiles may be selected by setting 00203 ! NYODEN= 1, 3 or 5 and nlev=20 00204 00205 real :: t0yod1(20) = (/224.14,213.91,211.36,212.95,217.56 00206 ,224.07,231.24,237.73,243.54,248.87 00207 ,253.41,257.83,261.72,265.60,268.96 00208 ,272.33,275.36,278.34,281.06,283.74/) 00209 real :: dtyod1(20) = (/ 0.00, 0.00, 2.00, 9.19, 19.13 00210 , 28.26, 34.91, 40.37, 45.10, 49.19 00211 , 52.05, 54.69, 56.20, 57.70, 58.31 00212 , 58.91, 59.26, 59.56, 59.76, 59.94/) 00213 real :: t0yod3(20) = (/265.14,254.91,246.36,240.95,237.56 00214 ,234.65,235.24,237.73,243.54,248.87 00215 ,253.41,257.83,261.72,265.60,268.96 00216 ,272.33,275.36,278.34,281.06,283.74/) 00217 real :: dtyod3(20) = (/ 0.00, -3.05,-20.32,-26.19,-28.13 00218 , 28.26, 34.91, 40.37, 45.10, 49.19 00219 , 52.05, 54.69, 56.20, 57.70, 58.31 00220 , 58.91, 59.26, 59.56, 59.76, 59.94/) 00221 real :: t0yod5(20) = (/305.00,298.00,292.00,286.00,280.00 00222 ,274.00,268.00,261.00,256.54,254.87 00223 ,253.41,257.83,261.72,265.60,268.96 00224 ,272.33,275.36,278.34,281.06,283.74/) 00225 real :: dtyod5(20) = (/ 0.00, -3.05,-21.32,-27.19,-29.13 00226 ,-32.26,-34.91,-40.37,-45.10,-49.19 00227 , 52.05, 54.69, 56.20, 57.70, 58.31 00228 , 58.91, 59.26, 59.56, 59.76, 59.94/) 00229 real :: t0yod7(20) = (/265.14,254.91,246.36,240.95,237.56 00230 ,234.65,235.24,237.73,243.54,248.87 00231 ,253.41,257.83,261.72,265.60,268.96 00232 ,272.33,275.36,278.34,281.06,283.74/) 00233 real :: dtyod7(20) = (/ 0.00,-25.05,-64.32,-58.19,-22.13 00234 , 28.26, 34.91, 40.37, 45.10, 49.19 00235 , 52.05, 54.69, 56.20, 57.70, 58.31 00236 , 58.91, 59.26, 59.56, 59.76, 60.00/) 00237 real :: t0yod8(20) = (/265.14,254.91,246.36,240.95,237.56 00238 ,234.65,235.24,237.73,243.54,248.87 00239 ,253.41,257.83,261.72,265.60,268.96 00240 ,272.33,275.36,278.34,281.06,283.74/) 00241 real :: dtyod8(20) = (/ 0.00,-25.05,-64.32,-58.19,-22.13 00242 , 18.26, 24.91, 30.37, 35.10, 39.19 00243 , 42.05, 44.69, 46.20, 47.70, 48.31 00244 , 48.91, 49.26, 49.56, 49.76, 50.00/) 00245 real :: t0yod9(20) = (/265.14,254.91,246.36,240.95,237.56 00246 ,234.65,235.24,237.73,243.54,248.87 00247 ,253.41,257.83,261.72,265.60,268.96 00248 ,272.33,275.36,278.34,281.06,283.74/) 00249 real :: dtyod9(20) = (/ 0.00, 0.00, 0.00, 0.00, 0.00 00250 , 28.26, 34.91, 40.37, 45.10, 49.19 00251 , 52.05, 54.69, 56.20, 57.70, 58.31 00252 , 58.91, 59.26, 59.56, 59.76, 60.00/) 00253 00254 integer :: nfls = 1 ! =1: lower stratospheric forcing is applied, 00255 ! see parameters flsp0, flsdp, flsamp and 00256 ! flsoff below 00257 00258 ! *********************** 00259 ! * Global Real Scalars * 00260 ! *********************** 00261 00262 real :: delt ! 2 pi / ntspd timestep interval 00263 real :: delt2 ! 2 * delt 00264 ! 00265 ! namelist parameter for yoden setup 00266 ! (for arrays to and dt see namelist arrays below) 00267 00268 real :: dtep = 60.0 ! delta T equator <-> pole [K] 00269 real :: dtns = 0.0 ! delta T north <-> south [K] 00270 real :: dtrop = 12000.0 ! Tropopause height [m] 00271 real :: dttrp = 2.0 ! Tropopause smoothing [K] 00272 real :: dtzz = 10.0 ! delta(Theta)/H additional lapserate in 00273 real :: syncstr= 0.0 ! PUMA variable 00274 ! Held & Suarez T_R field 00275 real :: ttp = 200.0 ! Tropopause temperature in 00276 ! Held & Suarez T_R field 00277 real :: plavor= EZ ! planetary vorticity 00278 real :: rotspd = 1.0 ! rotation speed 1.0 = normal Earth rotation 00279 real :: sigmax= 6.0e-7 ! sigma for top half level 00280 real :: tdiss = 0.25 ! diffusion time scale [days] 00281 real :: tac = 0. ! length of annual cycle [days] (0 = no cycle) 00282 real :: pac = 0. ! phase of the annual cycle [days] 00283 real :: tgr = 288.0 ! Ground Temperature in mean profile [K] 00284 real :: oroano= 0.0 ! Orography anomaly in [gpm] 00285 real :: tgrano= 0.0 ! Ground temperature anomaly in [K] 00286 !! 00287 real :: alrs = -0.0000! stratospheric lapse rate [K/m] 00288 real :: horo = 0.0 ! height of the idealized orography [m] 00289 real :: orofac= 1.0 ! factor to scale the orograpy 00290 real :: ttropo= 250.0 ! temp. at tropopause 00291 !! 00292 real :: dorox = 0.0 ! lon. base point for gauss mountain [dec] 00293 real :: doroy = 0.0 ! lat. base point for gauss mountain [dec] 00294 real :: doroxs = 0.0 ! gauss mountain scale in lon.-dir. [dec] 00295 real :: doroys = 0.0 ! gauss mountain scale in lat.-dir. [dec] 00296 00297 real :: tauta = 40.0 ! heating timescale far from surface [days] 00298 real :: tauts = 4.0 ! heating timescale close to surface [days] 00299 real :: sid_day= SID_DAY_EARTH ! siderial day [sec] 00300 00301 00302 00303 real :: zsigb = 0.7 ! sigma_b for Held&Suarez frict. and heat. 00304 ! time scale 00305 00306 00307 00308 ! * parameter for stratospheric forcing * 00309 00310 real :: alrpv = 0.002 ! Vertical lapse rate of stratospheric 00311 ! polar vortex forcing restoration 00312 ! temperature field. It corresponds to 00313 ! 'gamma' in Polvani & Kushner (2002). 00314 ! But alrpv is in [K/m], thus, 00315 ! alrpv=0.002 corresponds to 'gamma=2' 00316 ! in P&K (2002). 00317 real :: radpv = 50. ! Radius of stratospheric polar vortex 00318 ! forcing [deg latitude] 00319 real :: edgepv = 10. ! Width of edge of stratospheric polar 00320 ! vortex forcing [deg latitude]. 00321 ! If edgepv=0., then no polar vortex is 00322 ! set up. 00323 real :: pmaxpv = 10000. ! Lower boundary of stratospheric polar 00324 ! vortex forcing, max. pressure [Pa]. 00325 ! If pmaxpv=0. then pmaxpv is set to the 00326 ! pressure at tropopause height, specified 00327 ! by dtrop, according to the US standard 00328 ! atmosphere (USSA) vertical profile, used 00329 ! for contruction of the restoration 00330 ! temperature field. With the standard 00331 ! setting (dtrop=11000m, ALR=0.0065K/m, 00332 ! tgr=288.15K) this gives pmaxpv=22632Pa. 00333 ! ++++NOTE: pmaxpv should be within the 00334 ! second USSA layer, that is the interval 00335 ! from 54749Pa to 22632Pa (in case of 00336 ! standard parameter setting).++++ 00337 00338 real :: flsp0 = 10000. ! pressure of max. lower stratospheric forcing 00339 ! field [Pa] 00340 real :: flsdp = 9000. ! half of vertical extension of lower 00341 ! stratospheric forcing field [Pa] 00342 real :: flsamp = 15. ! amplitude of lower stratospheric forcing 00343 ! field [K] 00344 real :: flsoff = -5. ! offset of lower stratospheric forcing 00345 ! field [K] 00346 00347 00348 ! ******************* 00349 ! * Namelist Arrays * 00350 ! ******************* 00351 ! workaround for older fortran versions, where allocatable arrays 00352 ! are not allowed in namelists 00353 00354 00355 integer, parameter :: MAXLEV = 100 00356 integer, parameter :: MAXSELZW = 42 00357 integer, parameter :: MAXSELSP = ((MAXSELZW+1) * (MAXSELZW+2)) / 2 00358 integer :: nselect(0:MAXSELZW) = 1 ! NSELECT can be used up tp T42 00359 integer :: nspecsel(MAXSELSP) = 1 00360 integer :: ndl(MAXLEV) = 0 00361 real :: restim(MAXLEV) = 15.0 00362 real :: sigmah(MAXLEV) = 0.0 00363 real :: t0k(MAXLEV) = 250.0 00364 real :: t0(MAXLEV) = 250.0 00365 real :: tfrc(MAXLEV) = 0.0 00366 real :: dt(MAXLEV) = 0.0 00367 00368 ! ************************** 00369 ! * Global Spectral Arrays * 00370 ! ************************** 00371 00372 real, allocatable :: sor(:) ! Spectral Orography 00373 real, allocatable :: ssp(:) ! Spectral surface pressure 00374 real, allocatable :: stg(:) ! Spectral ground temperature 00375 real, allocatable :: sep(:) ! Spectral equator-pole gradient 00376 real, allocatable :: sns(:) ! Spectral north-south gradient 00377 real, allocatable :: spnorm(:) ! ECHAM -> PUMA normalization factors 00378 real, allocatable :: sr1(:,:) ! Constant part of Tr 00379 real, allocatable :: sr2(:,:) ! Variable part of Tr 00380 00381 ! *************************** 00382 ! * Global Gridpoint Arrays * 00383 ! *************************** 00384 00385 real, allocatable :: gor(:,:) ! Orography 00386 real, allocatable :: gsp(:,:) ! Surface pressure 00387 real, allocatable :: gtg(:,:) ! Ground temperature 00388 real, allocatable :: gan(:,:) ! Ground temperature anomaly 00389 real, allocatable :: gep(:,:) ! Equator-pole gradient 00390 real, allocatable :: gns(:,:) ! North-south gradient 00391 real, allocatable :: gtc(:,:,:) ! Restoration Temperature 00392 real, allocatable :: gtv(:,:,:) ! Restoration Temperature NS mode 00393 real, allocatable :: gtdamp(:,:,:)! Reciprocal of damping time scale for T 00394 real, allocatable :: gaf(:,:,:) ! Anomaly factors 00395 real, allocatable :: gra(:) ! Gradient factors 00396 00397 ! ******************* 00398 ! * Latitude Arrays * 00399 ! ******************* 00400 00401 character (3), allocatable :: chlat(:) ! label for latitudes 00402 00403 real (kind=8), allocatable :: sid(:) ! sin(phi) 00404 real (kind=8), allocatable :: gwd(:) ! Gaussian weight 00405 real (kind=8), allocatable :: csq(:) ! cos(phi)^2 00406 real (kind=8), allocatable :: dla(:) ! phi 00407 00408 00409 ! **************** 00410 ! * Level Arrays * 00411 ! **************** 00412 00413 real, allocatable :: t0d(:) ! vertical t0k gradient 00414 real, allocatable :: dsigma(:) 00415 real, allocatable :: rdsig(:) 00416 real, allocatable :: sigma(:) 00417 real, allocatable :: tkp(:) 00418 00419 ! ********************** 00420 ! * Dummy declarations * 00421 ! ********************** 00422 00423 real :: gp(2) 00424 real :: sp(2) 00425 real :: gpj(2) 00426 real :: gu(2,2) 00427 real :: gv(2,2) 00428 real :: sd(2,2) 00429 real :: st(2,2) 00430 real :: sq(2,2) 00431 real :: sz(2,2) 00432 real :: gd(2,2) 00433 real :: gq(2,2) 00434 real :: gt(2,2) 00435 real :: gz(2,2) 00436 00437 end module pumamod 00438 00439 program ppp 00440 00441 ! open file ppp-puma interface information 00442 if (mypid == NROOT) then 00443 open(95,file="ppp-puma.txt",form='formatted') 00444 endif 00445 00446 call resolution 00447 call prolog 00448 call gridpoint 00449 00450 ! close file ppp-puma interface information 00451 if (mypid == NROOT) then 00452 close(95) 00453 endif 00454 00455 stop 00456 end 00457 00458 ! ****************************** 00459 ! * SUBROUTINE ALLOCATE_ARRAYS * 00460 ! ****************************** 00461 00462 subroutine allocate_arrays 00463 use pumamod 00464 00465 !--- Global Spectral Arrays 00466 allocate(sor(nesp)) ; sor(:) = 0.0 ! Spectral Orography 00467 allocate(ssp(nesp)) ; ssp(:) = 0.0 ! Spectral surface pressure 00468 allocate(stg(nesp)) ; stg(:) = 0.0 ! Spectral ground temperature 00469 allocate(sep(nesp)) ; sep(:) = 0.0 ! Spectral equator-pole gradient 00470 allocate(sns(nesp)) ; sns(:) = 0.0 ! Spectral north-south gradient 00471 allocate(spnorm(nesp)) ; spnorm(:) = 0.0 ! ECHAM -> PUMA normalization 00472 allocate(sr1(nesp,nlev)) ; sr1(:,:) = 0.0 ! Constant part of Tr 00473 allocate(sr2(nesp,nlev)) ; sr2(:,:) = 0.0 ! Variable part of Tr 00474 00475 !--- Global Gridpoint Arrays 00476 allocate(gor(nlon,nlat)) ; gor(:,:) = 0.0 ! Orography 00477 allocate(gsp(nlon,nlat)) ; gsp(:,:) = 0.0 ! Surface pressure 00478 allocate(gtg(nlon,nlat)) ; gtg(:,:) = 0.0 ! Ground temperature 00479 allocate(gan(nlon,nlat)) ; gan(:,:) = 0.0 ! Ground temperature anomaly 00480 allocate(gep(nlon,nlat)) ; gep(:,:) = 0.0 ! Equator-pole gradient 00481 allocate(gns(nlon,nlat)) ; gns(:,:) = 0.0 ! North-south gradient 00482 allocate(gtc(nlon,nlat,nlev)) ; gtc(:,:,:) = 0.0 ! Restoration Temperature 00483 allocate(gtv(nlon,nlat,nlev)) ; gtv(:,:,:) = 0.0 ! Rest. Temperature NS mode 00484 allocate(gtdamp(nlon,nlat,nlev)); gtdamp(:,:,:) = 0.0 ! Reciprocal of damping time scale for T 00485 allocate(gaf(nlon,nlat,nlev)) ; gaf(:,:,:) = 0.0 ! Anomaly factors 00486 00487 !--- Latitude Arrays 00488 allocate(chlat(nlat)) ; chlat(:) = " " ! label for latitudes 00489 allocate(sid(nlat)) ; sid(:) = 0.0 ! sin(phi) 00490 allocate(gwd(nlat)) ; gwd(:) = 0.0 ! Gaussian weight 00491 allocate(csq(nlat)) ; csq(:) = 0.0 ! cos(phi)^2 00492 allocate(dla(nlat)) ; dla(:) = 0.0 ! phi 00493 00494 !--- Level Arrays 00495 allocate(gra(nlev)) ; gra(:) = 0.0 ! Gradient factors 00496 allocate(t0d(nlev)) ; t0d(:) = 0.0 ! vertical t0k gradient 00497 allocate(dsigma(nlev)) ; dsigma(:) = 0.0 00498 allocate(rdsig(nlev)) ; rdsig(:) = 0.0 00499 allocate(sigma(nlev)) ; sigma(:) = 0.0 00500 allocate(tkp(nlev)) ; tkp(:) = 0.0 00501 00502 return 00503 end subroutine allocate_arrays 00504 00505 ! =========================== 00506 ! SUBROUTINE MODIFY_OROGRAPHY 00507 ! =========================== 00508 00509 subroutine modify_orography(por) 00510 use pumamod 00511 real :: por(nlon,nlat) 00512 00513 ! Array <por> contains the orography on a Gaussian grid 00514 ! the units are that of a geopotential [m2/s2] (gpm * g) 00515 ! You may modify the orography here with your own code 00516 ! The new orography is spectrally fitted after this routine 00517 ! A gridpoint representation is written in service format 00518 ! to file <puma_oro_tnn.srv> with nn = spectral truncation. 00519 00520 if (noro == 2) call mkoro(por) 00521 if (noro == 3) call mkorog(por) 00522 00523 ! Rectangular anomaly 00524 00525 ! if (oroano /= 0.0 .and. lat1oro > 0 .and. lat2oro <= nlat & 00526 ! .and. lon1oro > 0 .and. lon2oro <= nlon & 00527 ! .and. lat1oro < lat2oro .and. lon1oro < lon2oro) then 00528 ! do jlat = lat1oro , lat2oro 00529 ! do jlon = lon1oro , lon2oro 00530 ! por(jlon,jlat) = por(jlon,jlat) + oroano * GA 00531 ! if (por(jlon,jlat) < 0.0) por(jlon,jlat) = 0.0 00532 ! enddo 00533 ! enddo 00534 ! endif 00535 00536 ! Elliptic anomaly 00537 00538 if (oroano /= 0.0 .and. lat1oro > 0 .and. lat2oro <= nlat & 00539 .and. lon1oro > 0 .and. lon2oro <= nlon & 00540 .and. lat1oro < lat2oro .and. lon1oro < lon2oro) then 00541 x0 = (lon1oro + lon2oro) * 0.5 00542 y0 = (lat1oro + lat2oro) * 0.5 00543 xf = PI / (lon2oro - lon1oro) 00544 yf = PI / (lat2oro - lat1oro) 00545 do jlat = lat1oro , lat2oro 00546 yb = (jlat - y0) * yf 00547 do jlon = lon1oro , lon2oro 00548 xa = (jlon - x0) * xf 00549 cx = cos(xa) 00550 cy = cos(yb) 00551 if (cx > 0.0 .and. cy > 0.0) then 00552 por(jlon,jlat) = por(jlon,jlat) + oroano * GA * cx * cy 00553 endif 00554 if (por(jlon,jlat) < 0.0) por(jlon,jlat) = 0.0 00555 enddo 00556 enddo 00557 endif 00558 00559 return 00560 end 00561 00562 ! ==================================== 00563 ! SUBROUTINE MODIFY_GROUND_TEMPERATURE 00564 ! ==================================== 00565 00566 subroutine modify_ground_temperature(ptgr) 00567 use pumamod 00568 real :: ptgr(nlon,nlat) 00569 00570 ! Array <ptgr> contains the ground temperature on a Gaussian grid. 00571 ! The units are [K] 00572 ! You may modify the ground temperature here with your own code. 00573 ! The new ground temperature is used to construct the temperature 00574 ! profile of the restoration temperature on each grid point. 00575 ! A gridpoint representation is written in service format 00576 ! to file <puma_gtgr_tnn.srv> with nn = spectral truncation. 00577 00578 if (tgrano /= 0.0 .and. lat1tgr > 0 .and. lat2tgr <= nlat & 00579 .and. lon1tgr > 0 .and. lon2tgr <= nlon & 00580 .and. lat1tgr < lat2tgr .and. lon1tgr < lon2tgr) then 00581 do jlat = lat1tgr , lat2tgr 00582 do jlon = lon1tgr , lon2tgr 00583 gan(jlon,jlat) = gan(jlon,jlat) + tgrano 00584 ptgr(jlon,jlat) = ptgr(jlon,jlat) + tgrano 00585 if (ptgr(jlon,jlat) < 0.0) ptgr(jlon,jlat) = 0.0 00586 enddo 00587 enddo 00588 endif 00589 00590 return 00591 end 00592 00593 00594 ! ================ 00595 ! SUBROUTINE MKORO 00596 ! ================ 00597 00598 subroutine mkoro(por) 00599 use pumamod 00600 ! 00601 real por(nlon,nlat) 00602 ! 00603 zscale=horo*GA*0.5 00604 ! 00605 por(:,:)=0. 00606 ! 00607 do jlat=1,nlat/2 00608 zlat=dla(jlat) 00609 zfacy=(sin(2.*zlat))**2 00610 do jlon=1,nlon 00611 if(norox > 0) then 00612 zfacx=(1.+cos(norox*real(jlon)*TWOPI/real(nlon))) 00613 else 00614 zfacx=1. 00615 endif 00616 por(jlon,jlat)=zscale*zfacx*zfacy 00617 enddo 00618 enddo 00619 ! 00620 if(nsym == 1) then 00621 do jlat=1,nlat/2 00622 j2=nlat+1-jlat 00623 por(:,j2)=por(:,jlat) 00624 enddo 00625 endif 00626 ! 00627 return 00628 end 00629 00630 ! ================= 00631 ! SUBROUTINE MKOROG 00632 ! ================= 00633 00634 subroutine mkorog(por) 00635 use pumamod 00636 ! 00637 real por(nlon,nlat) 00638 ! 00639 zscale=horo*GA 00640 ! 00641 zlon0=dorox*PI/180. 00642 zlat0=doroy*PI/180. 00643 zlons=(180./(doroxs*PI))**2 00644 zlats=(180./(doroys*PI))**2 00645 ! 00646 do jlat=1,nlat 00647 zlat=dla(jlat) 00648 !! zcos2=cos(zlat)**2 00649 zcos2=1. 00650 zdlat2=(zlat-zlat0)**2 00651 do jlon=1,nlon 00652 zlon=TWOPI*real(jlon-1)/real(nlon) 00653 zdlon=abs(zlon-zlon0) 00654 if(zdlon > PI) zdlon=TWOPI-zdlon 00655 zdlon2=zdlon**2 00656 por(jlon,jlat)=zscale*EXP(-zlons*zcos2*zdlon2-zlats*zdlat2) 00657 enddo 00658 enddo 00659 ! 00660 if(nsym == 1 .and. zlat0 > 0.) then 00661 do jlat=1,nlat/2 00662 j2=nlat+1-jlat 00663 por(:,j2)=por(:,jlat) 00664 enddo 00665 elseif(nsym == 1 .and. zlat0 < 0.) then 00666 do jlat=1,nlat/2 00667 j2=nlat+1-jlat 00668 por(:,jlat)=por(:,j2) 00669 enddo 00670 endif 00671 ! 00672 return 00673 end 00674 00675 ! ================= 00676 ! SUBROUTINE PROLOG 00677 ! ================= 00678 00679 subroutine prolog 00680 use pumamod 00681 00682 00683 00684 call allocate_arrays 00685 00686 call printparameter 00687 call inigau(nlat,sid,gwd) 00688 call inilat 00689 call legpri 00690 call readnl 00691 call initpm 00692 call legini(nlat,nlpp,nesp,nlev,plavor,sid,gwd) 00693 call initfd 00694 00695 00696 if (mypid == NROOT) then 00697 call ppp_write_i('NLAT',1,nlat) 00698 call ppp_write_i('NLEV',1,nlev) 00699 call ppp_write_i('NHELSUA',1,nhelsua) 00700 call ppp_write_r('SIGMH',NLEV,sigmah) 00701 endif 00702 00703 return 00704 end 00705 00706 ! ================= 00707 ! SUBROUTINE INITFD 00708 ! ================= 00709 00710 subroutine initfd 00711 use pumamod 00712 00713 dimension zrmean(nlev) 00714 00715 zfmode0 = sqrt(2.0) 00716 zfmode1 = 1.0 / sqrt(6.0) 00717 zfmode2 = -2.0 / 3.0 * sqrt(0.4) 00718 00719 stg(1) = zfmode0 * tgr ! Ground temperature [K] 00720 sns(3) = zfmode1 * dtns ! North-South gradient [K] 00721 sep(5) = zfmode2 * dtep ! Equator-Pole gradient [K] 00722 00723 ! Find sigma at dtrop 00724 00725 zttrop = tgr - dtrop * ALR 00726 ztps = (zttrop/tgr)**(GA/(ALR*GASCON)) 00727 00728 ! The North-South and Equator-Pole gradients are defined on z=0. 00729 ! gra() modifies the gradient from full at z=0 to zero at tropopause 00730 ! PUMA aquaplanet compatibility mode (sine function used) 00731 00732 do jlev = 1 , nlev 00733 gra(jlev) = sin(0.5 * PI * (sigma(jlev) - ztps) / (1.0-ztps)) 00734 if (gra(jlev) < 0.0) gra(jlev) = 0.0 00735 enddo 00736 00737 return 00738 end 00739 00740 ! ========================== 00741 ! SUBROUTINE ANOMALY_FACTORS 00742 ! ========================== 00743 00744 subroutine anomaly_factors 00745 use pumamod 00746 00747 do jlat = 1 , nlat 00748 do jlon = 1 , nlon 00749 00750 ! Find sigma at dtrop 00751 00752 zttrop = tgr - dtrop * ALR 00753 ztps = (zttrop/gtg(jlon,jlat))**(GA/(ALR*GASCON)) 00754 00755 ! The North-South and Equator-Pole gradients are defined on z=0. 00756 ! gaf() modifies the gradient from full at z=0 to zero at tropopause 00757 ! PUMA aquaplanet compatibility mode (sine function used) 00758 00759 if(nreverse == 0) then 00760 do jlev = 1 , nlev 00761 gaf(jlon,jlat,jlev) = sin(0.5 * PI * (sigma(jlev) - ztps) / (1.0-ztps)) 00762 if (gaf(jlon,jlat,jlev) < 0.0) gaf(jlon,jlat,jlev) = 0.0 00763 enddo 00764 else 00765 do jlev = 1 , nlev 00766 gaf(jlon,jlat,jlev) = sin(0.5 * PI * (sigma(jlev) - ztps) / (1.0-ztps)) 00767 if (sigma(jlev) < ztps) & 00768 & gaf(jlon,jlat,jlev) = sin(PI*(sigma(jlev)-ztps)/(ztps-sigma(1))) 00769 enddo 00770 endif 00771 00772 enddo 00773 enddo 00774 00775 return 00776 end 00777 00778 00779 ! ======================== 00780 ! SUBROUTINE READ_GAN_GRID 00781 ! ======================== 00782 00783 subroutine read_gan_grid(kread) 00784 use pumamod 00785 00786 logical :: lexist 00787 integer :: ihead(8) 00788 character(20) :: ynumber 00789 character(256) :: yfilename 00790 00791 ! Read temperature anomalies for PUMA 00792 ! Use formatted Service style 00793 00794 kread = 0 00795 00796 if (nlat < 1000) then 00797 write(ynumber,'(I3.3)') nlat 00798 else 00799 write(ynumber,'(I4.4)') nlat 00800 endif 00801 00802 yfilename = "N" // trim(adjustl(ynumber)) // "_surf_0139.sra" 00803 inquire(file=yfilename,exist=lexist) 00804 if (lexist) then 00805 write(*,*) ' Reading anomaly temperature from file <',trim(yfilename),'>' 00806 open (65,file=yfilename,form='formatted') 00807 read (65,*) ihead(:) 00808 read (65,*) gan(:,:) 00809 close(65) 00810 kread = 1 00811 else 00812 write(*,*) ' No anomaly temperature file' 00813 endif 00814 return 00815 end subroutine read_gan_grid 00816 00817 00818 ! ======================== 00819 ! SUBROUTINE READ_ORO_GRID 00820 ! ======================== 00821 00822 subroutine read_oro_grid(kread) 00823 use pumamod 00824 00825 logical :: lexist 00826 integer :: ihead(8) 00827 character(20) :: ynumber 00828 character(256) :: yfilename 00829 00830 ! Read orography for PUMA 00831 ! Use formatted Service style 00832 00833 kread = 0 00834 00835 if (nlat < 1000) then 00836 write(ynumber,'(I3.3)') nlat 00837 else 00838 write(ynumber,'(I4.4)') nlat 00839 endif 00840 00841 yfilename = "N" // trim(adjustl(ynumber)) // "_surf_0129.sra" 00842 inquire(file=yfilename,exist=lexist) 00843 if (lexist) then 00844 write(*,*) ' Reading orography from file <',trim(yfilename),'>' 00845 open (65,file=yfilename,form='formatted') 00846 read (65,*) ihead(:) 00847 read (65,*) gor(:,:) 00848 close(65) 00849 kread = 1 00850 else 00851 gor(:,:) = 0.0 00852 write(*,*) ' No orography file - starting with zero orography' 00853 endif 00854 return 00855 end subroutine read_oro_grid 00856 00857 00858 ! ==================== 00859 ! SUBROUTINE WRITE_ORO 00860 ! ==================== 00861 00862 subroutine write_oro 00863 use pumamod 00864 00865 dimension itime(8) 00866 dimension ihead(8) 00867 00868 character(20) :: ynumber 00869 character(256) :: yfilename 00870 00871 call date_and_time(values=itime) 00872 00873 ! Write orography for PUMA 00874 ! Use formatted Service style 00875 00876 if (nlat < 1000) then 00877 write(ynumber,'(I3.3)') nlat 00878 else 00879 write(ynumber,'(I4.4)') nlat 00880 endif 00881 00882 yfilename = "N" // trim(adjustl(ynumber)) // "_surf_0129.sra" 00883 open(60,file=yfilename,form='formatted') 00884 ihead(1) = 129 ! code for orography 00885 ihead(2) = 0 ! level 00886 ihead(3) = itime(1) * 10000 + itime(2) * 100 + itime(3) ! YYYYMMDD 00887 ihead(4) = itime(5) * 100 + itime(6) ! HHMM 00888 ihead(5) = nlon ! 1. dimension 00889 ihead(6) = nlat ! 2. dimension 00890 ihead(7) = 1 00891 ihead(8) = 0 00892 00893 write (60,'(8I10)') ihead(:) 00894 write (60,'(8F10.3)') gor(:,:) 00895 00896 close(60) 00897 00898 return 00899 end subroutine write_oro 00900 00901 00902 ! =================== 00903 ! SUBROUTINE WRITE_PS 00904 ! =================== 00905 00906 subroutine write_ps 00907 use pumamod 00908 00909 dimension itime(8) 00910 dimension ihead(8) 00911 00912 character(20) :: ynumber 00913 character(256) :: yfilename 00914 00915 real :: zpres(nlon,nlat) 00916 00917 call date_and_time(values=itime) 00918 00919 ! Write surface pressure for PUMA 00920 ! Use formatted Service style 00921 00922 if (nlat < 1000) then 00923 write(ynumber,'(I3.3)') nlat 00924 else 00925 write(ynumber,'(I4.4)') nlat 00926 endif 00927 yfilename = "N" // trim(adjustl(ynumber)) // "_surf_0134.sra" 00928 open(60,file=yfilename,form='formatted') 00929 ihead(1) = 134 ! code for surface pressure [hPa] 00930 ihead(2) = 0 ! level 00931 ihead(3) = itime(1) * 10000 + itime(2) * 100 + itime(3) ! YYYYMMDD 00932 ihead(4) = itime(5) * 100 + itime(6) ! HHMM 00933 ihead(5) = nlon ! 1. dimension 00934 ihead(6) = nlat ! 2. dimension 00935 ihead(7) = 1 00936 ihead(8) = 0 00937 00938 zpres(:,:) = 0.01 * PSURF * exp(gsp(:,:)) ! Store as [hPa] 00939 00940 write (60,'(8I10)') ihead(:) 00941 write (60,'(8F10.4)') zpres(:,:) 00942 00943 close(60) 00944 00945 return 00946 end subroutine write_ps 00947 00948 00949 ! ==================== 00950 ! SUBROUTINE WRITE_GTC 00951 ! ==================== 00952 00953 subroutine write_gtc 00954 use pumamod 00955 00956 dimension itime(8) 00957 dimension ihead(8) 00958 00959 character(20) :: ynumber 00960 character(256) :: yfilename 00961 00962 call date_and_time(values=itime) 00963 00964 ! Write constant part of Tr 00965 ! Use formatted Service style 00966 00967 if (nlat < 1000) then 00968 write(ynumber,'(I3.3)') nlat 00969 else 00970 write(ynumber,'(I4.4)') nlat 00971 endif 00972 yfilename = "N" // trim(adjustl(ynumber)) // "_surf_0121.sra" 00973 00974 open(60,file=yfilename,form='formatted') 00975 ihead(1) = 121 ! code for Tr const 00976 ihead(2) = 0 ! level 00977 ihead(3) = itime(1) * 10000 + itime(2) * 100 + itime(3) ! YYYYMMDD 00978 ihead(4) = itime(5) * 100 + itime(6) ! HHMM 00979 ihead(5) = nlon ! 1. dimension 00980 ihead(6) = nlat ! 2. dimension 00981 ihead(7) = 1 00982 ihead(8) = 0 00983 00984 do jlev = 1 , nlev 00985 ihead(2) = jlev 00986 write (60,'(8I10)') ihead(:) 00987 write (60,'(8F10.4)') gtc(:,:,jlev) 00988 enddo 00989 00990 close(60) 00991 00992 return 00993 end subroutine write_gtc 00994 00995 00996 00997 ! ==================== 00998 ! SUBROUTINE WRITE_GTV 00999 ! ==================== 01000 01001 subroutine write_gtv 01002 use pumamod 01003 01004 dimension itime(8) 01005 dimension ihead(8) 01006 01007 character(20) :: ynumber 01008 character(256) :: yfilename 01009 01010 call date_and_time(values=itime) 01011 01012 ! Write variable part of Tr 01013 ! Use formatted Service style 01014 01015 if (nlat < 1000) then 01016 write(ynumber,'(I3.3)') nlat 01017 else 01018 write(ynumber,'(I4.4)') nlat 01019 endif 01020 yfilename = "N" // trim(adjustl(ynumber)) // "_surf_0122.sra" 01021 open(60,file=yfilename,form='formatted') 01022 ihead(1) = 122 ! code for Tr variable 01023 ihead(2) = 0 ! level 01024 ihead(3) = itime(1) * 10000 + itime(2) * 100 + itime(3) ! YYYYMMDD 01025 ihead(4) = itime(5) * 100 + itime(6) ! HHMM 01026 ihead(5) = nlon ! 1. dimension 01027 ihead(6) = nlat ! 2. dimension 01028 ihead(7) = 1 01029 ihead(8) = 0 01030 01031 do jlev = 1 , nlev 01032 ihead(2) = jlev 01033 write (60,'(8I10)') ihead(:) 01034 write (60,'(8F10.4)') gtv(:,:,jlev) 01035 enddo 01036 01037 close(60) 01038 01039 return 01040 end subroutine write_gtv 01041 01042 01043 ! ======================== 01044 ! SUBROUTINE WRITE_VARGP2D 01045 ! ======================== 01046 01047 subroutine write_vargp2D(zgp,kcode) 01048 use pumamod 01049 01050 dimension itime(8) 01051 dimension ihead(8) 01052 01053 character(20) :: ynumber 01054 character(256) :: yfilename 01055 real :: zgp(nlon,nlat) 01056 01057 01058 call date_and_time(values=itime) 01059 01060 ! produce file name to be written 01061 if (NLAT < 1000) then 01062 write(yfilename,'("N",I3.3,"_surf_",I4.4,".sra")') NLAT,kcode 01063 else 01064 write(yfilename,'("N",I4.4,"_surf_",I4.4,".sra")') NLAT,kcode 01065 endif 01066 01067 01068 01069 open(60,file=yfilename,form='formatted') 01070 ihead(1) = kcode ! code for reciprocal of damping time scale 01071 ihead(2) = 0 ! level 01072 ihead(3) = itime(1) * 10000 + itime(2) * 100 + itime(3) ! YYYYMMDD 01073 ihead(4) = itime(5) * 100 + itime(6) ! HHMM 01074 ihead(5) = nlon ! 1. dimension 01075 ihead(6) = nlat ! 2. dimension 01076 ihead(7) = 1 01077 ihead(8) = 0 01078 01079 select case(kcode) 01080 case(129,134) 01081 ihead(2) = 0 01082 write (60,'(8I10)') ihead(:) 01083 write (60,'(8(X,E16.10))') zgp(:,:) 01084 end select 01085 01086 close(60) 01087 01088 return 01089 end subroutine write_vargp2D 01090 01091 ! ======================== 01092 ! SUBROUTINE WRITE_VARGP3D 01093 ! ======================== 01094 01095 subroutine write_vargp3D(zgp,kcode,klev) 01096 use pumamod 01097 01098 dimension itime(8) 01099 dimension ihead(8) 01100 01101 character(20) :: ynumber 01102 character(256) :: yfilename 01103 real :: zgp(nlon,nlat,klev) 01104 01105 01106 call date_and_time(values=itime) 01107 01108 ! produce file name to be written 01109 if (NLAT < 1000) then 01110 write(yfilename,'("N",I3.3,"_surf_",I4.4,".sra")') NLAT,kcode 01111 else 01112 write(yfilename,'("N",I4.4,"_surf_",I4.4,".sra")') NLAT,kcode 01113 endif 01114 01115 01116 01117 open(60,file=yfilename,form='formatted') 01118 ihead(1) = kcode ! code for reciprocal of damping time scale 01119 ihead(2) = 0 ! level 01120 ihead(3) = itime(1) * 10000 + itime(2) * 100 + itime(3) ! YYYYMMDD 01121 ihead(4) = itime(5) * 100 + itime(6) ! HHMM 01122 ihead(5) = nlon ! 1. dimension 01123 ihead(6) = nlat ! 2. dimension 01124 ihead(7) = 1 01125 ihead(8) = 0 01126 01127 select case(kcode) 01128 case(121,122,123,124,125,126) 01129 do jlev = 1 , klev 01130 ihead(2) = jlev 01131 write (60,'(8I10)') ihead(:) 01132 write (60,'(8(X,E16.10))') zgp(:,:,jlev) 01133 enddo 01134 end select 01135 01136 close(60) 01137 01138 return 01139 end subroutine write_vargp3D 01140 01141 01142 ! ==================== 01143 ! SUBROUTINE GRIDPOINT 01144 ! ==================== 01145 01146 subroutine gridpoint 01147 use pumamod 01148 !! 01149 dimension ihead(8) 01150 dimension zprof(nlev) 01151 dimension zzprof(nlon,nlat,nlev) 01152 character(256) :: yfilename,yfohead,yfodata,ymessage 01153 logical :: exist 01154 01155 ! Read orography 01156 01157 gor(:,:) = 0.0 01158 if (noro > 0) then 01159 call read_oro_grid(iread) 01160 endif 01161 01162 ! Read ground anomaly temperature 01163 01164 call read_gan_grid(iread) 01165 01166 call sp2fc(sns,gns) 01167 call sp2fc(sep,gep) 01168 call sp2fc(stg,gtg) 01169 01170 call alt2reg(gns,1) 01171 call alt2reg(gep,1) 01172 call alt2reg(gtg,1) 01173 01174 01175 call fc2gp(gns,nlon,nlat) 01176 call fc2gp(gep,nlon,nlat) 01177 call fc2gp(gtg,nlon,nlat) 01178 01179 gtg(:,:) = gtg(:,:) + gan(:,:) 01180 01181 call modify_orography(gor) ! User interface 01182 01183 if (nyoden /= 0) then 01184 call yoden 01185 else 01186 ! compute ground temperature on orography surface 01187 01188 gtg(:,:) = gtg(:,:) - ALR * gor(:,:) / GA ! [gpm] 01189 01190 call modify_ground_temperature(gtg) ! User interface 01191 01192 call anomaly_factors ! Compute factors for NS & EP 01193 01194 ! Compute vertical profile for each column 01195 01196 do jlat = 1 , nlat 01197 do jlon = 1 , nlon 01198 call tprofile(gtg(jlon,jlat),zprof,gor(jlon,jlat)/GA) 01199 gtc(jlon,jlat,:) = zprof(:) 01200 enddo 01201 enddo 01202 01203 ! Modify Restoration Temperature with EP mode 01204 01205 do jlev = 1 , nlev 01206 gtc(:,:,jlev) = gtc(:,:,jlev) + gaf(:,:,jlev) * gep(:,:) 01207 enddo 01208 01209 ! Compute vertical profile for each column including variable NS mode 01210 01211 do jlev = 1 , nlev 01212 gtv(:,:,jlev) = gaf(:,:,jlev) * gns(:,:) 01213 enddo 01214 01215 endif ! (nyoden == 1) 01216 01217 ! Initialize surface pressure (LnPs) 01218 01219 do jlat = 1 , nlat 01220 do jlon = 1 , nlon 01221 gsp(jlon,jlat) = -gor(jlon,jlat) / (GASCON*tgr) 01222 enddo 01223 enddo 01224 01225 ! if (nhelsua == 1 .or. nhelsua == 2) then 01226 if (nhelsua > 0) then 01227 call heldsuarez 01228 gor(:,:) = 0.0 01229 gsp(:,:) = 0.0 01230 endif 01231 01232 01233 if (nstrato == 1) then 01234 call setzt2 ! Torben's forcing initialisation 01235 endif 01236 01237 call write_oro 01238 call write_ps 01239 call write_gtc 01240 call write_gtv 01241 call write_vargp3D(gtdamp,123,nlev) 01242 if (ntestgp == 1) then 01243 call write_vargp3D(gtc,124,nlev) 01244 call write_vargp3D(gtv,125,nlev) 01245 call write_vargp3D(gtdamp,126,nlev) 01246 endif 01247 01248 call printprofile 01249 01250 return 01251 end 01252 01253 ! ===================== 01254 ! SUBROUTINE HELDSUAREZ 01255 ! ===================== 01256 01257 subroutine heldsuarez 01258 use pumamod 01259 01260 ! Set up the restoration temperature field according to that given 01261 ! in Held & Suarez (1994, Bul. Amer. Meteor. Soc.). 01262 ! Only difference: There is an offset of 1./3. added to the sine of 01263 ! latitude. The reason is that the namelist parameter TGR still 01264 ! represents the global mean of surface restoration temperature. 01265 ! 01266 ! ==> Set TGR=295. in order to get exactly the same restoration 01267 ! temperature field as in Held & Suarez (1994). 01268 ! 01269 ! ==> DTNS in H&S (1994) is the equator-pole difference while 01270 ! PUMA uses DTNS for pole-pole difference. Therefore we use 01271 ! 0.5 * dtns in this subroutine. 01272 01273 01274 ! Produce restoration temperature 01275 01276 real :: zp0,z3 01277 real :: zdtc,zdtv,zsip 01278 01279 zp0 = 100000. 01280 z3 = 1.0 / 3.0 01281 if (nhelsua == 1 .or. nhelsua == 2) then 01282 do jlev=1,nlev 01283 do jlat=1,nlat 01284 zsip = sigma(jlev)*PSURF/zp0 01285 zdtc = dtep * (sid(jlat)**2-z3) + dtzz * log(zsip) * csq(jlat) 01286 zdtv = zdtc - 0.5 * dtns * sid(jlat) 01287 gtc(:,jlat,jlev) = max(ttp, (tgr - zdtc) * zsip**AKAP) 01288 gtv(:,jlat,jlev) = max(ttp, (tgr - zdtv) * zsip**AKAP) 01289 enddo 01290 enddo 01291 gtv(:,:,:) = gtv(:,:,:) - gtc(:,:,:) 01292 endif 01293 01294 ! Produce reciprocal of damping time scale for T [1/sec] 01295 01296 ! tauta = 1.0 / (TWOPI * tauta) 01297 ! tauts = 1.0 / (TWOPI * tauts) 01298 01299 rtauta_dim = 1.0 /(tauta*sid_day) 01300 rtauts_dim = 1.0 /(tauts*sid_day) 01301 if (nhelsua == 2 .or. nhelsua == 3) then 01302 do jlev=1,nlev 01303 if (sigma(jlev) > zsigb) then 01304 do jlat = 1,nlat 01305 gtdamp(1:nlon,jlat,jlev) = rtauta_dim & 01306 & + (rtauts_dim - rtauta_dim) * ((sigma(jlev) - zsigb) / (1. - zsigb)) & 01307 & * (1. - sid(jlat)**2)**2 01308 enddo 01309 else 01310 gtdamp(:,:,jlev) = rtauta_dim 01311 endif 01312 enddo 01313 endif 01314 01315 return 01316 end 01317 01318 ! ===================== 01319 ! SUBROUTINE RESOLUTION 01320 ! ===================== 01321 01322 subroutine resolution 01323 use pumamod 01324 logical :: lex 01325 namelist /res/ nlat, nlev 01326 01327 nlat = 32 01328 nlev = 10 01329 01330 inquire(file=resolution_namelist,exist=lex) 01331 if (.not. lex) then 01332 resolution_namelist = trim(resolution_namelist) // "_00" 01333 inquire(file=resolution_namelist,exist=lex) 01334 endif 01335 01336 if (lex) then 01337 open(14,file=resolution_namelist) 01338 read(14,res) 01339 close(14) 01340 endif 01341 01342 nlem = nlev - 1 01343 nlep = nlev + 1 01344 nlsq = nlev * nlev 01345 01346 nlon = nlat + nlat ! Longitudes 01347 nlah = nlat / 2 01348 nlpp = nlat 01349 nhpp = nlah 01350 nhor = nlon * nlpp 01351 01352 ntru = (nlon - 1) / 3 01353 ntp1 = ntru + 1 01354 nzom = ntp1 + ntp1 01355 nrsp = (ntru + 1) * (ntru + 2) 01356 ncsp = nrsp / 2 01357 nspp = nrsp 01358 nesp = nspp 01359 01360 return 01361 end 01362 01363 ! ================= 01364 ! SUBROUTINE READNL 01365 ! ================= 01366 01367 subroutine readnl 01368 use pumamod 01369 01370 ! This namelist must be identical to namelist inp in puma.f90 01371 01372 namelist /inp/ & 01373 alpha , alrpv , alrs , disp & 01374 , dorox , doroxs , doroy , doroys , dt , dtep & 01375 , dtns , dtrop , dttrp , dtzz , dvdiff , edgepv & 01376 , epsync & 01377 , flsp0 , flsdp , flsamp , flsoff , horo , kick & 01378 , lat1oro , lat1tgr , lat2oro , lat2tgr & 01379 , lon1oro , lon1tgr , lon2oro , lon2tgr & 01380 , mpstep & 01381 , nafter , ncoeff , ncorrect, ncu , ndel , ndiag & 01382 , ndl , nextout , nfls , ngui , nguidbg & 01383 , nhelsua, nsync & 01384 , ntestgp , nkits & 01385 , nlevt , nmonths , noro , norox , noutput , noutsrv & 01386 , npackgp , npacksp , nreverse& 01387 , nruido , nrun , nselect , nspecsel, nsponge , nsrv & 01388 , nstep , nstop , nstrato , ntgr , nsym , ntspd & 01389 , nvg , nwpd , nwspini , nyears , nyoden & 01390 , oroano , orofac & 01391 , pac , pmaxpv , pspon & 01392 , radpv , restim , rotspd & 01393 , sigmah , sigmax , sponk & 01394 , t0 , t0k , tac , tauta , tauts & 01395 , tdiss , tfrc , tgr , tgrano , ttp & 01396 , nenergy , nentropy, ndheat 01397 01398 nselect(:) = 1 01399 nspecsel(:) = 1 01400 ndl(:) = 0 01401 restim(:) = 15.0 01402 sigmah(:) = 0.0 01403 tfrc(1:nlev) = (/ (0.0,i=1,nlem), 1.0 /) 01404 t0k(:) = 250.0 01405 t0(:) = 250.0 01406 dt(:) = 0.0 01407 01408 open(13,file='ppp_namelist') 01409 read (13,inp) 01410 01411 ! Use predefined Yoden profile ? 01412 01413 if (nlev == 20 .and. nyoden > 0) then 01414 ! noro = 0 ! Don't read orography 01415 ! norox = 2 ! Make idealized orography 01416 ! horo = 500.0 ! Height of idealized orography 01417 alrs = -0.001 ! Stratospheric lapse rate 01418 nreverse = 0 ! No T-gradient reversal at tropopause 01419 ncorrect = 0 ! No T-correction due to orography 01420 idim = min(20,nlev) 01421 if (nyoden == 1) then 01422 t0(1:idim) = t0yod1(1:idim) 01423 dt(1:idim) = dtyod1(1:idim) 01424 else if (nyoden == 3) then 01425 t0(1:idim) = t0yod3(1:idim) 01426 dt(1:idim) = dtyod3(1:idim) 01427 else if (nyoden == 5) then 01428 t0(1:idim) = t0yod5(1:idim) 01429 dt(1:idim) = dtyod5(1:idim) 01430 else if (nyoden == 7) then 01431 t0(1:idim) = t0yod7(1:idim) 01432 dt(1:idim) = dtyod7(1:idim) 01433 else if (nyoden == 8) then 01434 t0(1:idim) = t0yod8(1:idim) 01435 dt(1:idim) = dtyod8(1:idim) 01436 else if (nyoden == 9) then 01437 t0(1:idim) = t0yod9(1:idim) 01438 dt(1:idim) = dtyod9(1:idim) 01439 endif 01440 endif 01441 01442 close(13) 01443 write(*,inp) 01444 01445 return 01446 end 01447 01448 ! ===================== 01449 ! * SET VERTICAL GRID * 01450 ! ===================== 01451 01452 subroutine set_vertical_grid 01453 01454 use pumamod 01455 01456 if (sigmah(nlev) /= 0.0) return ! Already read in from namelist INP 01457 01458 if (nvg == 1) then ! Scinocca & Haynes sigma levels 01459 01460 if (nlevt >= nlev) then ! Security check for 'nlevt' 01461 write (*,*) '*** ERROR *** nlevt >= nlev' 01462 write (*,*) 'Number of levels (nlev): ',nlev 01463 write (*,*) 'Number of tropospheric levels (nlevt): ',nlevt 01464 endif 01465 01466 ! troposphere: linear spacing in sigma 01467 ! stratosphere: linear spacing in log(sigma) 01468 ! after (see their Appendix): 01469 ! Scinocca, J. F. and P. H. Haynes (1998): Dynamical forcing of 01470 ! stratospheric planetary waves by tropospheric baroclinic eddies. 01471 ! J. Atmos. Sci., 55 (14), 2361-2392 01472 01473 ! Here, zsigtran is set to sigma at dtrop (tropopause height for 01474 ! construction of restoration temperature field). If tgr=288.15K, 01475 ! ALR=0.0065K/km and dtrop=11.km, then zsigtran=0.223 (=0.1 in 01476 ! Scinocca and Haynes (1998)). 01477 ! A smoothing of the transition between linear and logarithmic 01478 ! spacing, as noted in Scinocca and Haynes (1998), is not yet 01479 ! implemented. 01480 01481 zsigtran = (1. - ALR * dtrop / tgr)**(GA/(GASCON*ALR)) 01482 zsigmin = 1. - (1. - zsigtran) / real(nlevt) 01483 01484 do jlev=1,nlev 01485 if (jlev == 1) then 01486 sigmah(jlev) = 0.000001 01487 sigmah(jlev) = sigmax 01488 elseif (jlev > 1 .and. jlev < nlev - nlevt) then 01489 sigmah(jlev) = exp((log(sigmax) - log(zsigtran)) & 01490 & / real(nlev - nlevt - 1) * real(nlev - nlevt - jlev) 01491 + log(zsigtran)) 01492 elseif (jlev >= nlev - nlevt .and. jlev < nlev - 1) then 01493 sigmah(jlev) = (zsigtran - zsigmin) / real(nlevt - 1) 01494 * real(nlev - 1 - jlev) + zsigmin 01495 elseif (jlev == nlev - 1) then 01496 sigmah(jlev) = zsigmin 01497 elseif (jlev == nlev) then 01498 sigmah(jlev) = 1. 01499 endif 01500 enddo 01501 return 01502 endif ! (nvg == 1) 01503 01504 if (nvg == 2) then ! Polvani & Kushner sigma levels 01505 inl = int(real(nlev)/(1.0 - sigmax**(1.0/5.0))) 01506 do jlev=1,nlev 01507 sigmah(jlev) = (real(jlev + inl - nlev) / real(inl))**5 01508 enddo 01509 return 01510 endif ! (nvg == 2) 01511 01512 ! Default: equidistant sigma levels 01513 01514 if (nvg == 0) then 01515 do jlev = 1 , nlev 01516 sigmah(jlev) = real(jlev) / real(nlev) 01517 enddo 01518 endif ! (nvg == 0) 01519 01520 return 01521 end 01522 01523 ! ================= 01524 ! SUBROUTINE INITPM 01525 ! ================= 01526 01527 subroutine initpm 01528 use pumamod 01529 01530 real (kind=8) radea,zakk,zzakk 01531 radea = PLARAD_EARTH ! Planet radius in high precision 01532 plavor = EZ * rotspd ! Planetary vorticity 01533 01534 ! ************************************************************* 01535 ! * carries out all initialisation of model prior to running. * 01536 ! * major sections identified with comments. * 01537 ! * this s/r sets the model parameters and all resolution * 01538 ! * dependent quantities. * 01539 ! ************************************************************* 01540 01541 ! ********************* 01542 ! * set vertical grid * 01543 ! ********************* 01544 01545 call set_vertical_grid 01546 01547 dsigma(1 ) = sigmah(1) 01548 dsigma(2:nlev) = sigmah(2:nlev) - sigmah(1:NLEM) 01549 01550 rdsig(:) = 0.5 / dsigma(:) 01551 01552 sigma(1 ) = 0.5 * sigmah(1) 01553 sigma(2:nlev) = 0.5 * (sigmah(1:NLEM) + sigmah(2:nlev)) 01554 01555 ! annual cycle period and phase in timesteps 01556 01557 if (tac > 0.0) tac = TWOPI / (ntspd * tac) 01558 pac = pac * ntspd 01559 01560 ! compute internal diffusion parameter 01561 01562 jdelh = ndel/2 01563 if (tdiss > 0.0) then 01564 zakk = WW*(radea**ndel)/(TWOPI*tdiss*((ntru*(ntru+1.))**jdelh)) 01565 else 01566 zakk = 0.0 01567 endif 01568 zzakk = zakk / (WW*(radea**ndel)) 01569 01570 ! set coefficients which depend on wavenumber 01571 01572 zrsq2 = 1.0 / sqrt(2.0) 01573 01574 jr=-1 01575 do jm=0,ntru 01576 do jn=jm,ntru 01577 jr=jr+2 01578 ji=jr+1 01579 spnorm(jr)=zrsq2 01580 spnorm(ji)=zrsq2 01581 enddo 01582 zrsq2=-zrsq2 01583 enddo 01584 01585 return 01586 end 01587 01588 subroutine printparameter 01589 use pumamod 01590 01591 print 8000 01592 print 8050 01593 print 8000 01594 print 8010,nlev 01595 print 8020,ntru 01596 print 8030,nlat 01597 print 8040,nlon 01598 print 8000 01599 print 8120 01600 return 01601 8000 format(' *****************************************') 01602 8010 format(' * nlev = ',i6,' Number of levels *') 01603 8020 format(' * ntru = ',i6,' Triangular truncation *') 01604 8030 format(' * nlat = ',i6,' Number of latitudes *') 01605 8040 format(' * nlon = ',i6,' Number of longitues *') 01606 8050 format(' * PPP - Puma Pre Processor *') 01607 8120 format(/) 01608 end 01609 01610 01611 ! =================== 01612 ! SUBROUTINE GPROFILE 01613 ! =================== 01614 subroutine gprofile(ptgr,prgrad,pgpm) 01615 use pumamod 01616 01617 ! ************************************************************* 01618 ! * Set up the restoration temperature profiles for gradient * 01619 ! * modes DTNS - mode[0,1] and DTEP - mode[0,2] * 01620 ! * The lapse rate of ALR K/m is assumed under the tropopause * 01621 ! * and zero above. The tropopause is defined by <dtrop>. * 01622 ! * The profile is a sine wave with 0 at tropopause sigma and * 01623 ! * 1 at sigma = 1. * 01624 ! ************************************************************* 01625 01626 dimension prgrad(nlev) 01627 01628 ztpheight = dtrop - pgpm ! Tropopause height over ground 01629 ztptemp = tgr - ALR * dtrop ! Tropopause temperature 01630 ztps = (ztptemp/ptgr)**(GA/(ALR*GASCON)) ! Tropoause sigma 01631 01632 do jlev = 1 , nlev 01633 prgrad(jlev) = sin(0.5*PI*(sigma(jlev)-ztps)/(1.0-ztps)) 01634 if (sigma(jlev) < ztps) prgrad(jlev) = 0.0 01635 enddo 01636 01637 return 01638 end 01639 01640 ! =================== 01641 ! SUBROUTINE TPROFILE 01642 ! =================== 01643 subroutine tprofile(ptgr,prof,pgpm) 01644 use pumamod 01645 01646 ! ************************************************************* 01647 ! * Set up the restoration temperature profile for one column * 01648 ! * The temperature at sigma = 1 is <ptgr>, entered in kelvin * 01649 ! * The lapse rate of ALR K/m is assumed under the tropopause * 01650 ! * and zero above. The tropopause is defined by <ztpheight>. * 01651 ! * The smoothing ot the tropopause depends on <dttrp>. * 01652 ! ************************************************************* 01653 01654 dimension prof(nlev) ! Resulting temperature profile [K] 01655 01656 zsigprev = 1.0 ! sigma value 01657 ztprev = ptgr ! Temperature [K] 01658 zzprev = 0.0 ! Height [m] 01659 ztpheight = dtrop - pgpm ! Tropopause height over ground 01660 ztptemp = tgr - ALR * dtrop ! Tropopause temperature 01661 zalr = (ptgr - ztptemp) / ztpheight 01662 01663 do jlev = nlev , 1 , -1 ! from bottom to top of atmosphere 01664 zlogsig = GASCON / GA * log(zsigprev / sigma(jlev)) 01665 zzp = zzprev + ztprev * zlogsig 01666 ztp=ztptemp+sqrt((.5*zalr*(zzp-ztpheight))**2+dttrp**2) 01667 ztp=ztp-.5*zalr*(zzp-ztpheight) 01668 ztpm=.5*(ztprev+ztp) 01669 01670 zzpp = zzprev + ztpm * zlogsig 01671 ztpp=ztptemp+sqrt((.5*zalr*(zzpp-ztpheight))**2+dttrp**2) 01672 ztpp=ztpp-.5*zalr*(zzpp-ztpheight) 01673 01674 prof(jlev)=ztpp 01675 zzprev=zzprev + 0.5 * (ztpp+ztprev) * zlogsig 01676 ztprev=ztpp 01677 zsigprev=sigma(jlev) 01678 enddo 01679 return 01680 end 01681 01682 ! ====================== 01683 ! SUBROUTINE ppp_write_i 01684 ! ====================== 01685 01686 subroutine ppp_write_i(yvarname,nvals,ivals) 01687 use pumamod 01688 01689 character(*) :: yvarname 01690 integer :: nvals 01691 integer :: ivals(nvals) 01692 01693 if (mypid == NROOT) then 01694 write(95,'("[",A,"]")') trim(yvarname) 01695 write(95,'(I4)') nvals 01696 write(95,'(I6)') ivals(:) 01697 endif 01698 return 01699 end 01700 01701 ! ====================== 01702 ! SUBROUTINE ppp_write_r 01703 ! ====================== 01704 01705 subroutine ppp_write_r(yvarname,nvals,pvals) 01706 use pumamod 01707 01708 character(*) :: yvarname 01709 integer :: nvals 01710 real :: pvals(nvals) 01711 01712 if (mypid == NROOT) then 01713 write(95,'("[",A,"]")') trim(yvarname) 01714 write(95,'(I4)') nvals 01715 write(95,'(E14.8)') pvals(:) 01716 endif 01717 return 01718 end 01719 01720 ! ================ 01721 ! SUBROUTINE yoden 01722 ! ================ 01723 01724 subroutine yoden 01725 use pumamod 01726 ! 01727 do jlev=1,nlev 01728 do jlat=1,nlat/2 01729 zlat=dla(jlat) 01730 ztres=t0(jlev)+dt(jlev)/2.*(cos(2.*zlat)-1./3.) 01731 do jlon=1,nlon 01732 gtc(jlon,jlat,jlev)=ztres 01733 enddo 01734 enddo 01735 enddo 01736 ! 01737 do jlat=1,nlat/2 01738 j2=nlat+1-jlat 01739 gtc(:,j2,:)=gtc(:,jlat,:) 01740 enddo 01741 01742 write (*,*) ' Computed Yoden profile',nyoden 01743 ! 01744 return 01745 end 01746 ! 01747 ! ======================= 01748 ! SUBROUTINE PRINTPROFILE 01749 ! ======================= 01750 01751 subroutine printprofile 01752 use pumamod 01753 01754 ! ********************************** 01755 ! * write out vertical information * 01756 ! ********************************** 01757 01758 dimension ztr(nlev+1) 01759 01760 ztr(nlev+1) = tgr 01761 01762 write(*,9001) 01763 write(*,9002) 01764 write(*,9003) 01765 write(*,9002) 01766 01767 do jlev=1,nlev 01768 ztr(jlev) = sum(gtc(:,:,jlev)) / (nlon * nlat) 01769 enddo 01770 01771 do jlev=1,nlev 01772 write(*,9004) jlev,sigma(jlev),ztr(jlev),ztr(jlev+1)-ztr(jlev),gra(jlev) 01773 enddo 01774 01775 write(*,9002) 01776 write(*,9001) 01777 return 01778 9001 format(/) 01779 9002 format(1x,45('*')) 01780 9003 format(' * Lv * Sigma Restor-T Delta-T Vfact *') 01781 9004 format(' *',i3,' * ',4f9.3,' *') 01782 end 01783 01784 ! ===================== 01785 ! * SUBROUTINE LEGPRI * 01786 ! ===================== 01787 01788 subroutine legpri 01789 use pumamod 01790 01791 write (*,231) 01792 write (*,232) 01793 write (*,233) 01794 write (*,232) 01795 do 14 jlat = 1 , nlat 01796 zalat = dla(jlat)*180.0/PI 01797 write (*,234) jlat,zalat,csq(jlat),gwd(jlat) 01798 14 continue 01799 write (*,232) 01800 write (*,231) 01801 return 01802 231 format(/) 01803 232 format(1x,36('*')) 01804 233 format(' * No * Lat * csq weight *') 01805 234 format(' *',i3,' *',f6.1,' *',2f10.4,' *') 01806 end 01807 01808 01809 ! ================= 01810 ! SUBROUTINE INILAT 01811 ! ================= 01812 01813 subroutine inilat 01814 use pumamod 01815 character(1) :: ch 01816 01817 ch = 'N' 01818 do jlat = 1 , nlat 01819 csq(jlat) = 1.0 - sid(jlat) * sid(jlat) 01820 dla(jlat) = asin(sid(jlat)) 01821 enddo 01822 do jlat = 1 , nlat/2 01823 ideg = nint(180.0/PI * asin(sid(jlat))) 01824 write(chlat(jlat),'(i2,a1)') ideg,'N' 01825 write(chlat(nlat+1-jlat),'(i2,a1)') ideg,'S' 01826 enddo 01827 return 01828 end 01829 01830 01831 ! ================= 01832 ! SUBROUTINE SETZT2 01833 ! ================= 01834 subroutine setzt2 01835 use pumamod 01836 01837 ! US standard atmosphere (1976): 01838 parameter(INL = 7) ! number of defined layers 01839 dimension zzus(0:INL) ! height of interfaces between layers 01840 dimension zlus(INL) ! temperature lapse rates of layers 01841 dimension zpus(0:INL) ! pressure at interfaces between layers 01842 dimension ztus(0:INL) ! temperature at interfaces between layers 01843 01844 dimension ztrs(nlev) ! Mean profile 01845 dimension ztpv(nlev) ! Vertical profile of stratospheric polar 01846 ! vortex forcing 01847 dimension zdtep(nlat) 01848 dimension zdtns(nlat) 01849 dimension zff(nlev) 01850 dimension zfw(nlat,nlev) 01851 dimension zfsph(nlat,nlev) 01852 dimension zqc(nlat,nlev) 01853 dimension zphi(nlat) 01854 dimension zgr1(nlon,nlat,nlev) 01855 dimension zgr2(nlon,nlat,nlev) 01856 dimension zfls(nlat,nlev) 01857 01858 real :: zp 01859 real :: zsigtp 01860 real :: pref 01861 real :: zpmaxsph 01862 01863 sr1(:,:) = 0.0 ! NESP,nlev 01864 sr2(:,:) = 0.0 ! NESP,nlev 01865 01866 ! 1. Mean vertical profile (MVP), approx. US standard atmosphere 01867 01868 zzus(0) = 0. 01869 zzus(1) = dtrop ! US standard atmosphere: zzus(1) = 11000. 01870 zzus(2) = 20000. 01871 zzus(3) = 32000. 01872 zzus(4) = 47000. 01873 zzus(5) = 51000. 01874 zzus(6) = 71000. 01875 zzus(7) = 84852. 01876 zlus(1) = ALR ! US standard atmosphere: zlus(1) = 0.0065 01877 zlus(2) = 0.0 01878 zlus(3) = -0.001 01879 zlus(4) = -0.0028 01880 zlus(5) = 0.0 01881 zlus(6) = 0.0028 01882 zlus(7) = 0.002 01883 01884 ! calculation of pressure and temperature at layer interfaces 01885 01886 zpus(0) = PSURF ! US standard atmosphere: zpus(0) = 1013.25 hPa 01887 ztus(0) = tgr ! US standard atmosphere: ztus(0) = 288.15 K 01888 01889 do ji=1,INL 01890 ztus(ji) = ztus(ji-1) - zlus(ji) * (zzus(ji) - zzus(ji-1)) 01891 if (zlus(ji) == 0.) then 01892 zpus(ji) = zpus(ji-1) * exp(-GA * (zzus(ji) - zzus(ji-1)) & 01893 & / (GASCON * ztus(ji-1))) 01894 else 01895 zpus(ji) = zpus(ji-1) & 01896 & * (ztus(ji) / ztus(ji-1))**(GA/(GASCON*zlus(ji))) 01897 endif 01898 enddo 01899 01900 ! calculation of temperature on given sigma full levels, sigma(1:nlev) 01901 do jlev=nlev,1,-1 01902 zp = sigma(jlev)*PSURF 01903 if (zp <= zpus(0) .and. zp > zpus(1)) then 01904 ztrs(jlev) = ztus(0) * (zp / zpus(0))**(GASCON*zlus(1)/GA) 01905 elseif (zp <= zpus(1) .and. zp > zpus(2)) then 01906 ztrs(jlev) = ztus(1) * (zp / zpus(1))**(GASCON*zlus(2)/GA) 01907 elseif (zp <= zpus(2) .and. zp > zpus(3)) then 01908 ztrs(jlev) = ztus(2) * (zp / zpus(2))**(GASCON*zlus(3)/GA) 01909 elseif (zp <= zpus(3) .and. zp > zpus(4)) then 01910 ztrs(jlev) = ztus(3) * (zp / zpus(3))**(GASCON*zlus(4)/GA) 01911 elseif (zp <= zpus(4) .and. zp > zpus(5)) then 01912 ztrs(jlev) = ztus(4) * (zp / zpus(4))**(GASCON*zlus(5)/GA) 01913 elseif (zp <= zpus(5) .and. zp > zpus(6)) then 01914 ztrs(jlev) = ztus(5) * (zp / zpus(5))**(GASCON*zlus(6)/GA) 01915 elseif (zp <= zpus(6) .and. zp > zpus(7)) then 01916 ztrs(jlev) = ztus(6) * (zp / zpus(6))**(GASCON*zlus(7)/GA) 01917 else 01918 ztrs(jlev) = ztus(7) 01919 endif 01920 enddo 01921 01922 ! 2. Symmetric equator-pole forcing mode (DTEP) and 01923 ! 3. Asymmetric Npole-Spole forcing mode (DTNS) 01924 01925 ! sid(nlat) is sine of latitude, taking into account the nonequally 01926 ! spaced Gaussian latitudes. 01927 do jlat=1,nlat 01928 zdtep(jlat) = -dtep * (sid(jlat)**2 - 1./3.) 01929 zdtns(jlat) = dtns * sid(jlat) / 2. 01930 enddo 01931 01932 ! 4. Factor modulating the DTEP and DTNS modes (f) 01933 01934 zsigtp = zpus(1)/zpus(0) ! sigma at tropopause 01935 zff(:) = 0. 01936 do jlev=1,nlev 01937 if (sigma(jlev) > zsigtp) then 01938 zff(jlev) = sin(0.5*PI * (sigma(jlev) - zsigtp) & 01939 & / (1. - zsigtp)) 01940 endif 01941 enddo 01942 01943 ! 5. Vertical profile of stratospheric polar vortex forcing 01944 01945 ztpv(:) = 0. 01946 if (pmaxpv == 0.) then 01947 do jlev=1,nlev 01948 if (sigma(jlev) <= zsigtp) then 01949 ztpv(jlev) = ztus(1) * (sigma(jlev)*PSURF / zpus(1)) & 01950 & **(GASCON*alrpv/GA) 01951 endif 01952 enddo 01953 elseif (pmaxpv > 0.) then 01954 do jlev=1,nlev 01955 if (sigma(jlev) <= pmaxpv/PSURF) then 01956 ztpv(jlev) = ztus(1) * (sigma(jlev)*PSURF / pmaxpv) & 01957 & **(GASCON*alrpv/GA) 01958 else 01959 ztpv(jlev) = ztus(1) 01960 endif 01961 enddo 01962 endif 01963 01964 ! 6. Factor confining the stratosph. polar vortex to high latitudes 01965 01966 zphi(:) = dla(:) * 180. / PI 01967 zfw(:,:) = 0. 01968 if (edgepv > 0.) then 01969 do jlev=1,nlev 01970 if (sigma(jlev) <= pmaxpv/PSURF) then 01971 do jlat=1,nlat 01972 zfw(jlat,jlev) = & 01973 & 0.5 * (1. - tanh((radpv - zphi(jlat)) / edgepv)) 01974 enddo 01975 endif 01976 enddo 01977 endif 01978 01979 ! 7. Lower stratospheric forcing 01980 01981 zfls(:,:) = 0. 01982 if (nfls == 1) then 01983 do jlev=1,nlev 01984 zp =sigma(jlev) * PSURF 01985 do jlat=1,nlat 01986 if (zp > flsp0-flsdp .and. zp < flsp0+flsdp) then 01987 zfls(jlat,jlev) = cos(0.5 * PI * (zp - flsp0) / flsdp)& 01988 & * (flsoff - flsamp * cos(2. * zphi(jlat) * PI / 180.)) 01989 endif 01990 enddo 01991 enddo 01992 endif 01993 01994 ! construct restoration temperature field 01995 01996 do jlev=1,nlev 01997 do jlat=1,nlat 01998 zgr1(:,jlat,jlev) = ((1. - zfw(jlat,jlev)) * ztrs(jlev) & 01999 & + zfw(jlat,jlev) * ztpv(jlev) + zff(jlev) * zdtep(jlat) & 02000 & + (1. - zfw(jlat,jlev)) * zfls(jlat,jlev) - t0k(jlev)) / CT 02001 zgr2(:,jlat,jlev) = (zff(jlev) * zdtns(jlat)) / CT 02002 enddo 02003 enddo 02004 02005 do jlev = 1 , nlev 02006 gtc(:,:,jlev) = t0k(jlev) + CT * zgr1(:,:,jlev) 02007 gtv(:,:,jlev) = CT * zgr2(:,:,jlev) 02008 enddo 02009 02010 ! ---------- test output to control T_r field ---------- 02011 open(112,file='tr_test.srv',form='unformatted') 02012 do jlev=1,nlev 02013 ip = int(sigma(jlev) * PSURF * 1000.) 02014 write(112) 121, ip, 0000, 00, nlon, nlat, 0, 0 02015 write(112) t0k(jlev) + (zgr1(:,:,jlev) + zgr2(:,:,jlev)) * CT 02016 enddo 02017 close(112) 02018 ! ---------- test output to control T_r field ---------- 02019 02020 print *,'**************************************************' 02021 print *,'* Restoration Temperature set up for aqua planet *' 02022 print *,'* including stratosphere and polar vortex *' 02023 print *,'**************************************************' 02024 return 02025 end