PUMA
219
Portable University Model of the Atmosphere
|
00001 module pumamod 00002 00003 !*********************************************! 00004 ! Portable University Model of the Atmosphere ! 00005 !*********************************************! 00006 ! Version: 17.0 16-Feb-2011 ! 00007 !*********************************************! 00008 ! Klaus Fraedrich ! 00009 ! Frank Lunkeit - Edilbert Kirk ! 00010 ! Frank Sielmann - Torben Kunz ! 00011 ! Hartmut Borth ! 00012 !*********************************************! 00013 ! Meteorologisches Institut ! 00014 ! KlimaCampus - Universitaet Hamburg ! 00015 !*********************************************! 00016 ! http://www.mi.uni-hamburg.de/puma ! 00017 !*********************************************! 00018 00019 !**************************************************************! 00020 ! The number of processes for processing on parallel machines ! 00021 ! NLAT/2 must be dividable by <npro>. npro can be set by the ! 00022 ! option -n <npro> when calling the puma executable ! 00023 ! This option is only available if the code is compiled with ! 00024 ! an mpi compiler. ! 00025 !**************************************************************! 00026 integer :: npro = 1 00027 00028 !**************************************************************! 00029 ! The horizontal resolution of PUMA is set by defining the ! 00030 ! number of latitudes <nlev> with the 1st. command line ! 00031 ! parameter and the number of levels with the 2nd. command ! 00032 ! parameter. A typical call for T42 is: ! 00033 ! puma.x 64 10 ! 00034 ! which sets nlat=64 and nlev=10 ! 00035 !**************************************************************! 00036 integer :: nlat = 32 00037 00038 !example values: 32, 48, 64, 128, 192, 256, 512, 1024 00039 !truncation: T21, T31, T42, T85, T127, T170, T341, T682 00040 00041 integer :: nlev = 10 00042 00043 !*****************************************************! 00044 ! Grid related paramters, which are computed from the ! 00045 ! command line arguments <nlat> and <nlev> ! 00046 ! Preset values are for T21 (nlat=32) and nlev=10 ! 00047 ! ****************************************************! 00048 00049 integer :: nlem = 9 ! Levels - 1 00050 integer :: nlep = 11 ! Levels + 1 00051 integer :: nlsq = 100 ! Levels squared 00052 00053 integer :: nlon = 64 ! Longitudes = 2 * latitudes 00054 integer :: nlah = 16 ! Half of latitudes 00055 integer :: ntru = 21 ! (nlon-1) / 3 00056 integer :: ntp1 = 22 ! ntru + 1 00057 integer :: nzom = 44 ! Number of zonal modes 00058 integer :: nrsp = 506 ! (ntru+1) * (ntru+2) 00059 integer :: ncsp = 253 ! nrsp / 2 00060 integer :: nspp = 506 ! nodes per process 00061 integer :: nesp = 506 ! number of extended modes 00062 00063 integer :: nlpp = 32 ! Latitudes per process 00064 integer :: nhpp = 16 ! Half latitudes per process 00065 integer :: nhor = 2048 ! Horizontal part 00066 integer :: nugp = 2048 ! Horizontal total 00067 integer :: npgp = 1024 ! Horizontal total packed words 00068 00069 integer :: nud = 6 ! I/O unit for diagnostic output 00070 00071 !***********! 00072 ! filenames ! 00073 !***********! 00074 character (256) :: puma_namelist = "puma_namelist" 00075 character (256) :: puma_output = "puma_output" 00076 character (256) :: puma_diag = "puma_diag" 00077 character (256) :: puma_restart = "puma_restart" 00078 character (256) :: puma_status = "puma_status" 00079 character (256) :: efficiency_dat = "efficiency.dat" 00080 character (256) :: ppp_puma_txt = "ppp-puma.txt" 00081 character (256) :: puma_sp_init = "puma_sp_init" 00082 00083 ! ***************************************************************** 00084 ! * For multiruns the instance number is appended to the filename * 00085 ! * e.g.: puma_namelist_1 puma_diag_1 etc. for instance # 1 * 00086 ! ***************************************************************** 00087 00088 ! **************************************************************** 00089 ! * Don't touch the following parameter definitions ! * 00090 ! **************************************************************** 00091 integer, parameter :: PUMA = 0 ! Model ID 00092 integer, parameter :: PLASIM = 1 ! Model ID 00093 00094 parameter(NROOT = 0) ! Master node 00095 00096 parameter(PI = 3.141592653589793D0) ! Pi 00097 parameter(TWOPI = PI + PI) ! 2 Pi 00098 00099 parameter(AKAP_EARTH = 0.286 ) ! Kappa Earth 00100 parameter(AKAP_MARS = 0.2273) ! Kappa Mars 00101 parameter(ALR_EARTH = 0.0065) ! Lapse rate Earth 00102 parameter(ALR_MARS = 0.0025) ! Lapse rate Mars 00103 parameter(GA_EARTH = 9.81) ! Gravity Earth 00104 parameter(GA_MARS = 3.74) ! Gravity Mars 00105 parameter(GASCON_EARTH = 287.0) ! Gas constant for dry air on Earth 00106 parameter(GASCON_MARS = 188.9) ! Gas constant for dry air on Mars 00107 parameter(PSURF_EARTH = 101100.0) ! Mean Surface pressure [Pa] on Earth 00108 ! Trenberth 1981, J. Geoph. Res., Vol.86, 5238-5246 00109 parameter(PLARAD_EARTH = 6371000.0) ! Earth radius 00110 parameter(PLARAD_MARS = 3397000.0) ! Mars radius 00111 parameter(SID_DAY_EARTH= 86164.) ! Siderial day Earth 23h 56m 04s 00112 parameter(SID_DAY_MARS = 88642.) ! Siderial day Mars 24h 37m 22s 00113 00114 parameter(WW_EARTH = TWOPI/SID_DAY_EARTH) ! reciprocal of time scale 00115 ! on Earth [1/sec] 00116 parameter(WW_MARS = TWOPI/SID_DAY_MARS) ! reciprocal of time scale 00117 ! on Mars [1/sec] 00118 00119 parameter(CV_EARTH = PLARAD_EARTH * WW_EARTH) ! Velocity scale on Earth [m/s] 00120 parameter(CV_MARS = PLARAD_MARS * WW_MARS) ! Velocity scale on Mars [m/s] 00121 00122 parameter(CT_EARTH = CV_EARTH*CV_EARTH/GASCON_EARTH) !Temperature scale [K] 00123 ! on Earth 00124 parameter(CT_MARS = CV_MARS*CV_MARS/GASCON_MARS) !Temperature scale [K] 00125 ! on Mars 00126 00127 parameter(PNU = 0.02) ! Time filter 00128 parameter(PNU21 = 1.0 - 2.0*PNU) ! Time filter 2 00129 00130 ! ***************************************************************** 00131 ! * EZ: Factor to multiply the spherical harmonic Y_(1,0) to get * 00132 ! * the non-dimensional planetary vorticity 2 sin(phi). In PUMA * 00133 ! * Y_(1,0) = sqrt(3/2)*sin(phi) (normalization factor 1/sqrt(2)).* 00134 ! * The time scale must be given by Tscale = 1/Omega * 00135 ! ***************************************************************** 00136 parameter(EZ = 1.632993161855452D0) ! ez = 1 / sqrt(3/8) 00137 00138 00139 ! ************************************************************** 00140 ! * Planetary parameters & Scales * 00141 ! * ----------------------------- * 00142 ! * The Puma model is formulated in non-dimensional form with * 00143 ! * the planetary radius as length scale and the reciprocal of * 00144 ! * the planetary rotation rate as time scale. The temperature * 00145 ! * scale is given by the geopotential scale divided by the * 00146 ! * gas constant. * 00147 ! * For the time scale the length of the siderial day is used * 00148 ! * as basic unit * 00149 ! * The parameters are initialized for Earth settings. They * 00150 ! * may be modified by the namelist file <puma_namelist> * 00151 ! * * 00152 ! * The scales are derived internal quantities * 00153 ! ************************************************************** 00154 real :: sid_day = SID_DAY_EARTH ! Length of sideral day [sec] on Earth 00155 real :: plarad = PLARAD_EARTH ! Planetary radius [m] on Earth 00156 real :: gascon = GASCON_EARTH ! Dry air gas consant [J/K kg] on Earth 00157 real :: akap = AKAP_EARTH ! Kappa [] on Earth 00158 real :: alr = ALR_EARTH ! average lapse rate [K/km] on Earth 00159 real :: ga = GA_EARTH ! Gravity [m/sec*sec] on Earth 00160 real :: psurf = PSURF_EARTH ! Mean surface pressure for EARTH [Pa] 00161 00162 real :: ww = WW_EARTH ! reciprocal of time scale [1/sec] (Omega) 00163 real :: cv = CV_EARTH ! velocity scale [m/sec] on Earth 00164 real :: ct = CT_EARTH ! temperature scale [K] on Earth 00165 00166 ! ************************** 00167 ! * Global Integer Scalars * 00168 ! ************************** 00169 00170 logical :: lrestart = .false. ! Existing "puma_restart" sets to .true. 00171 logical :: lselect = .false. ! true: disable some zonal waves 00172 logical :: lspecsel = .false. ! true: disable some spectral modes 00173 00174 integer :: model = PUMA 00175 00176 integer :: kick = 1 ! kick > 0 initializes eddy generation 00177 integer :: nafter = 0 ! write data interval 0: controlled by nwpd 00178 integer :: nwpd = 1 ! number of writes per day 00179 integer :: ncoeff = 0 ! number of modes to print 00180 integer :: ndel = 6 ! ndel 00181 integer :: ndiag = 12 ! write diagnostics interval 00182 integer :: ngui = 0 ! activate Graphical User Interface 00183 integer :: nkits = 3 ! number of initial timesteps 00184 integer :: nlevt = 9 ! tropospheric levels (set_vertical_grid) 00185 integer :: noutput = 1 ! global switch for output on (1) or off (0) 00186 integer :: nwspini = 1 ! write sp_init after initialization 00187 integer :: nrun = 0 ! if (nstop == 0) nstop = nstep + nrun 00188 integer :: nstep1 = 0 ! start step (for cpu statistics) 00189 integer :: nstep = -1 ! current timestep step 0: 01-Jan-0001 00:00 00190 integer :: nstop = 0 ! finishing timestep 00191 integer :: ntspd = 0 ! number of timesteps per day 0 = auto 00192 integer :: mpstep = 0 ! minutes per step 0 = automatic 00193 integer :: ncu = 0 ! check unit (debug output) 00194 integer :: nwrioro = 1 ! controls output of orography 00195 integer :: nextout = 0 ! 1: extended output (entropy production) 00196 integer :: nruido = 0 ! 1: global constant, temporal noise 00197 ! 2: spatio-temporal noise 00198 ! 3: spatio-temporal equator symmetric 00199 integer :: nseedlen = 0 ! length of random seed (set by lib call) 00200 integer :: nmonths = 0 ! Simulation time (1 month = 30 days) 00201 integer :: nyears = 1 ! simulation time (1 year = 360 days) 00202 integer :: nsponge = 0 ! 1: Create sponge layer 00203 integer :: nhelsua = 0 ! 1: Set up Held & Suarez T_R field 00204 ! instead of original PUMA T_R field 00205 ! 2: Set up Held & Suarez T_R field 00206 ! instead of original PUMA T_R field 00207 ! AND use latitudinally varying 00208 ! heating timescale in PUMA (H&Z(94)), 00209 ! irrelevant for PumaPreProcessor (ppp) 00210 ! 3: Use latitudinally varying 00211 ! heating timescale in PUMA (H&Z(94)), 00212 ! irrelevant for PumaPreProcessor (ppp) 00213 integer :: ndiagp = 0 ! 0/1 switch for grid point diabatic heating 00214 integer :: nconv = 0 ! 0/1 switch for convecive heating 00215 integer :: nvg = 0 ! type of vertical grid 00216 ! 0 = linear 00217 ! 1 = Scinocca & Haynes 00218 ! 2 = Polvani & Kushner 00219 integer :: nenergy = 0 ! energy diagnostics (on/off 1/0) 00220 integer :: nentropy= 0 ! entropy diagnostics (on/off 1/0) 00221 integer :: ndheat = 0 ! energy recycling (on/off 1/0) 00222 00223 integer :: nradcv = 0 ! use two restoration fields 00224 00225 00226 00227 ! *********************** 00228 ! * Global Real Scalars * 00229 ! *********************** 00230 00231 real :: alpha = 1.0 ! Williams filter factor 00232 real :: alrs = 0.0 ! stratospheric lapse rate [K/m] 00233 real :: delt ! 2 pi / ntspd timestep interval 00234 real :: delt2 ! 2 * delt 00235 real :: dtep = 60.0 ! delta T equator <-> pole [K] 00236 real :: dtns = -70.0 ! delta T north <-> south [K] 00237 real :: dtrop = 12000.0 ! Tropopause height [m] 00238 real :: dttrp = 2.0 ! Tropopause smoothing [K] 00239 real :: dtzz = 10.0 ! delta(Theta)/H additional lapserate in 00240 ! Held & Suarez T_R field 00241 real :: orofac = 1.0 ! factor to scale the orograpy 00242 real :: plavor = EZ ! planetary vorticity 00243 real :: psmean = PSURF_EARTH ! Mean of Ps on Earth 00244 real :: rotspd = 1.0 ! rotation speed 1.0 = normal Earth rotation 00245 real :: sigmax = 6.0e-7 ! sigma for top half level 00246 real :: tdiss = 0.25 ! diffusion time scale [days] 00247 real :: tac = 360.0 ! length of annual cycle [days] (0 = no cycle) 00248 real :: pac = 0.0 ! phase of the annual cycle [days] 00249 real :: tgr = 288.0 ! Ground Temperature in mean profile [K] 00250 real :: dvdiff = 0.0 ! vertical diffusion coefficient [m2/s] 00251 ! ! dvdiff =0. means no vertical diffusion 00252 real :: disp = 0.0 ! noise dispersion 00253 real :: tauta = 40.0 ! heating timescale far from surface 00254 real :: tauts = 4.0 ! heating timescale close to surface 00255 real :: pspon = 50. ! apply sponge layer where p < pspon 00256 ! ! pressure [Pa] 00257 real :: sponk = 0.5 ! max. damping coefficient for sponge layer, 00258 ! ! unit: [1/day] 00259 00260 ! ************************** 00261 ! * Global Spectral Arrays * 00262 ! ************************** 00263 00264 real, allocatable :: sd(:,:) ! Spectral Divergence 00265 real, allocatable :: sdd(:,:) ! Difference between instances 00266 real, allocatable :: st(:,:) ! Spectral Temperature 00267 real, allocatable :: std(:,:) ! Difference between instances 00268 real, allocatable :: st1(:,:) ! Spectral Temperature at t-1 (for NEXTOUT == 1) 00269 real, allocatable :: st2(:,:) ! Spectral Temperature at t-2 (for NEXTOUT == 1) 00270 real, allocatable :: sz(:,:) ! Spectral Vorticity 00271 real, allocatable :: szd(:,:) ! Difference between instances 00272 real, allocatable :: sp(:) ! Spectral Pressure (ln Ps) 00273 real, allocatable :: spd(:) ! Difference between instances 00274 real, allocatable :: sq(:,:) ! For compatibility with PlaSim 00275 real, allocatable :: sp1(:) ! Spectral Pressure at t-1 (for NEXTOUT == 1) 00276 real, allocatable :: sp2(:) ! Spectral Pressure at t-2 (for NEXTOUT == 1) 00277 real, allocatable :: so(:) ! Spectral Orography 00278 real, allocatable :: sr1(:,:) ! Spectral Restoration Temperature 00279 real, allocatable :: sr2(:,:) ! Spectral Restoration Temperature 00280 00281 real, allocatable :: sdp(:,:) ! Spectral Divergence Partial 00282 real, allocatable :: stp(:,:) ! Spectral Temperature Partial 00283 real, allocatable :: szp(:,:) ! Spectral Vorticity Partial 00284 real, allocatable :: spp(:) ! Spectral Pressure Partial 00285 real, allocatable :: sop(:) ! Spectral Orography Partial 00286 real, allocatable :: srp1(:,:)! Spectral Restoration Partial 00287 real, allocatable :: srp2(:,:)! Spectral Restoration Partial 00288 00289 real, allocatable :: sdt(:,:) ! Spectral Divergence Tendency 00290 real, allocatable :: stt(:,:) ! Spectral Temperature Tendency 00291 real, allocatable :: szt(:,:) ! Spectral Vorticity Tendency 00292 real, allocatable :: spt(:) ! Spectral Pressure Tendency 00293 00294 real, allocatable :: sdm(:,:) ! Spectral Divergence Minus 00295 real, allocatable :: stm(:,:) ! Spectral Temperature Minus 00296 real, allocatable :: szm(:,:) ! Spectral Vorticity Minus 00297 real, allocatable :: spm(:) ! Spectral Pressure Minus 00298 00299 real, allocatable :: sak(:) ! Hyper diffusion 00300 real, allocatable :: srcn(:) ! 1.0 / (n * (n+1)) 00301 real, allocatable :: span(:) ! Pressure for diagnostics 00302 real, allocatable :: spnorm(:)! Factors for output normalization 00303 00304 integer, allocatable :: nindex(:) ! Holds wavenumber 00305 integer, allocatable :: nscatsp(:) ! Used for reduce_scatter op 00306 integer, allocatable :: nselzw(:) ! Enable/disable selected zonal waves 00307 integer, allocatable :: nselsp(:) ! Enable/disable slected spectral modes 00308 00309 ! *************************** 00310 ! * Global Gridpoint Arrays * 00311 ! *************************** 00312 00313 real, allocatable :: gd(:,:) ! Divergence 00314 real, allocatable :: gt(:,:) ! Temperature 00315 real, allocatable :: gz(:,:) ! Vorticity 00316 real, allocatable :: gu(:,:) ! u * cos(phi) 00317 real, allocatable :: gv(:,:) ! v * sin(phi) 00318 real, allocatable :: gp(:) ! Ln(Ps) 00319 real, allocatable :: gq(:,:) ! For compatibilty with PlaSim 00320 real, allocatable :: gfu(:,:) ! Term Fu in Primitive Equations 00321 real, allocatable :: gfv(:,:) ! Term Fv in Primitive Equations 00322 real, allocatable :: gut(:,:) ! Term u * T 00323 real, allocatable :: gvt(:,:) ! Term v * T 00324 real, allocatable :: gke(:,:) ! Kinetic energy u * u + v * v 00325 real, allocatable :: gpj(:) ! d(Ln(Ps)) / d(mu) 00326 real, allocatable :: rcsq(:) ! 1 / cos2(phi) 00327 real, allocatable :: ruido(:,:,:)! noise (nlon,nlat,nlev) 00328 real, allocatable :: ruidop(:,:) ! noise partial (nhor,nlev) 00329 real, allocatable :: gtdamp(:,:) ! 3D reciprocal damping times [1/sec] 00330 ! for relaxation in grid point space 00331 ! for radiative restoration temperature 00332 ! (e.g. for Held&Suarez) 00333 real, allocatable :: gr1(:,:) ! constant radiative restoration time scale 00334 real, allocatable :: gr2(:,:) ! variable radiative restoration time scale 00335 real, allocatable :: gtdampc(:,:)! the same as gtdamp, but for convective 00336 ! restoration temperature 00337 real, allocatable :: gr1c(:,:) ! constant convective restoration time scale 00338 real, allocatable :: gr2c(:,:) ! variable convective restoration time scale 00339 00340 ! ********************* 00341 ! * Diagnostic Arrays * 00342 ! ********************* 00343 00344 integer, allocatable :: ndil(:) ! Set diagnostics level 00345 00346 real, allocatable :: csu(:,:) ! Cross section u [m/s] 00347 real, allocatable :: csv(:,:) ! Cross section v [m/s] 00348 real, allocatable :: cst(:,:) ! Cross section T [Celsius] 00349 00350 real,allocatable :: denergy(:,:) ! energy diagnostics 00351 real,allocatable :: dentropy(:,:) ! entropy diagnostics 00352 00353 ! ******************* 00354 ! * Latitude Arrays * 00355 ! ******************* 00356 00357 character (3),allocatable :: chlat(:) ! label for latitudes 00358 real (kind=8),allocatable :: sid(:) ! sin(phi) 00359 real (kind=8),allocatable :: gwd(:) ! Gaussian weight (phi) 00360 real,allocatable :: csq(:) ! cos2(phi) 00361 real,allocatable :: rcs(:) ! 1/cos(phi) 00362 00363 ! **************** 00364 ! * Level Arrays * 00365 ! **************** 00366 00367 real, allocatable :: t0(:) ! reference temperature 00368 real, allocatable :: t0d(:) ! vertical t0 gradient 00369 real, allocatable :: taur(:) ! tau R [days] 00370 real, allocatable :: tauf(:) ! tau F [days] 00371 real, allocatable :: damp(:) ! 1.0 / (2 Pi * taur) 00372 real, allocatable :: fric(:) ! 1.0 / (2 Pi * tauf ) 00373 00374 real, allocatable :: bm1(:,:,:) 00375 real, allocatable :: dsigma(:) 00376 real, allocatable :: rdsig(:) 00377 real, allocatable :: sigma(:) ! full level sigma 00378 real, allocatable :: sigmh(:) ! half level sigma 00379 real, allocatable :: tkp(:) 00380 real, allocatable :: c(:,:) 00381 real, allocatable :: xlphi(:,:) ! matrix Lphi (g) 00382 real, allocatable :: xlt(:,:) ! matrix LT (tau) 00383 00384 ! ****************** 00385 ! * Parallel Stuff * 00386 ! ****************** 00387 00388 integer :: myworld = 0 ! MPI variable 00389 integer :: mpinfo = 0 ! MPI variable 00390 integer :: mypid = 0 ! My Process Id 00391 real :: tmstart = 0.0 ! CPU time at start 00392 real :: tmstop = 0.0 ! CPU time at stop 00393 character(80), allocatable :: ympname(:) ! Processor name 00394 00395 00396 ! ********************** 00397 ! * Multirun variables * 00398 ! ********************** 00399 00400 integer :: mrworld = 0 ! MPI communication 00401 integer :: mrinfo = 0 ! MPI info 00402 integer :: mrpid = -1 ! MPI instance id 00403 integer :: mrnum = 0 ! MPI number of instances 00404 integer :: mintru = 0 ! Lowest resolution of all instances 00405 integer :: mrdim = 0 ! Exchange dimension (min. NRSP) 00406 integer :: nsync = 0 ! Synchronization on or off 00407 integer, allocatable :: mrtru(:) ! Truncations of members 00408 00409 real :: syncstr = 0.0 ! Coupling strength (0 .. 1) 00410 real :: synctime = 0.0 ! Coupling time [days] 00411 00412 ! ****************************************** 00413 ! * GUI (Graphical User Interface for X11) * 00414 ! ****************************************** 00415 00416 parameter (NPARCS = 10) ! Number of GUI parameters 00417 integer :: nguidbg = 0 ! Flag for GUI debug output 00418 integer :: nshutdown = 0 ! Flag for shutdown request 00419 integer :: ndatim(6) = -1 ! Date & time array 00420 real(kind=4) :: parc(NPARCS) ! Values of GUI parameters 00421 real(kind=4) :: crap(NPARCS) ! Backup of parc(NPARCS) 00422 logical :: ldtep = .FALSE. ! DTEP changed by GUI 00423 logical :: ldtns = .FALSE. ! DTNS changed by GUI 00424 character(len=32) :: yplanet = "Earth" 00425 00426 ! *************** 00427 ! * Random seed * 00428 ! *************** 00429 00430 integer :: seed(8) = 0 ! settable in namelist 00431 integer, allocatable :: meed(:) ! machine dependent seed 00432 real :: ganext = 0.0! y part of gaussian noise 00433 00434 end module pumamod 00435 00436 !***************! 00437 ! MODULE RADMOD ! 00438 !***************! 00439 00440 module radmod ! Dummy declaration for compatibility 00441 use pumamod ! with PLASIM (needed in guimod) 00442 end module radmod 00443 00444 00445 ! ***************** ! 00446 ! * MODULE PPPMOD * ! 00447 ! ***************** ! 00448 00449 module prepmod 00450 integer :: num_ppp = 0 00451 integer :: nlat_ppp = 0 00452 integer :: nlev_ppp = 0 00453 00454 type ppp_type 00455 character (80) :: name ! name of variable or array 00456 logical :: isint ! .true. for integer 00457 integer :: n ! length of vector (1 for scalar) 00458 integer, pointer :: pint ! pointer to integer value or array 00459 real , pointer :: preal ! pointer to real value or array 00460 end type ppp_type 00461 00462 type(ppp_type) :: ppp_tab(30) 00463 00464 interface 00465 subroutine ppp_def_int(pname,nvar,ndim) 00466 character (*) :: pname 00467 integer, target :: nvar 00468 integer :: ndim 00469 end subroutine ppp_def_int 00470 subroutine ppp_def_real(pname,rvar,ndim) 00471 character (*) :: pname 00472 real , target :: rvar(*) 00473 integer :: ndim 00474 end subroutine ppp_def_real 00475 end interface 00476 00477 end module prepmod 00478 00479 00480 ! ********************* 00481 ! * PROGRAM PUMA_MAIN * 00482 ! ********************* 00483 00484 program puma_main 00485 use pumamod 00486 00487 ! *********** 00488 ! * History * 00489 ! *********** 00490 00491 ! 1972 - W. Bourke: 00492 ! An efficient one-level primitive equation spectral model 00493 ! Mon. Weath. Rev., 100, pp. 683-689 00494 00495 ! 1975 - B.J. Hoskins and A.J. Simmons: 00496 ! A multi-layer spectral model and the semi-implicit method 00497 ! Qart. J. R. Met. Soc., 101, pp. 637-655 00498 00499 ! 1993 - I.N. James and J.P. Dodd: 00500 ! A Simplified Global Circulation Model 00501 ! Users' Manual, Dept. of Meteorology, University of Reading 00502 00503 ! 1998 - Klaus Fraedrich, Edilbert Kirk, Frank Lunkeit 00504 ! Portable University Model of the Atmosphere 00505 ! DKRZ Technical Report No. 16 00506 00507 ! 2009 - PUMA Version 16.0 00508 ! http://www.mi.uni-hamburg.de/puma 00509 00510 ! ****************** 00511 ! * Recent Changes * 00512 ! ****************** 00513 00514 ! 10-Jun-2002 - Puma Workshop - Documentation of subroutine SPECTRAL 00515 ! 04-Jul-2002 - Frank Lunkeit - Annual cycle 00516 ! 08-Jul-2002 - Edilbert Kirk - Factor for rotation speed 00517 ! 25-Sep-2002 - Puma Workshop - Documentation of subroutine CALCGP 00518 ! 11-Nov-2002 - Edilbert Kirk - Add Orography to output file 00519 ! 26-Feb-2003 - Edilbert Kirk - Read preprocessed initial file 00520 ! 07-Sep-2004 - Edilbert Kirk - Graphical User Interface 00521 ! 23-Aug-2006 - Torben Kunz - Held & Suarez forcing 00522 ! 23-Aug-2006 - Torben Kunz - new spacing schemes of sigma levels 00523 ! 23-Aug-2006 - Edilbert Kirk - individual selection of zonal waves 00524 ! 23-Aug-2006 - Edilbert Kirk - optimized Legendre trasnformation module 00525 ! 19-Feb-2007 - Edilbert Kirk - new flexible restart I/O 00526 ! 15-Sep-2009 - Edilbert Kirk - static arrays replaced by allocatable 00527 ! 15-Sep-2009 - Frank Lunkeit - diagnostics for entropy production 00528 ! 27-Sep-2010 - Edilbert Kirk - cleaned up ruido routines 00529 00530 call mpstart 00531 call setfilenames 00532 call opendiag 00533 call read_resolution 00534 call resolution 00535 if (mrnum == 2) then 00536 call mrdimensions 00537 endif 00538 call allocate_arrays 00539 call prolog 00540 call master 00541 call epilog 00542 call guistop 00543 call mpstop 00544 stop 00545 end program puma_main 00546 00547 00548 ! *************************** 00549 ! * SUBROUTINE SETFILENAMES * 00550 ! *************************** 00551 00552 subroutine setfilenames 00553 use pumamod 00554 00555 character (3) :: mrext 00556 00557 if (mrpid < 0) return ! no multirun 00558 00559 write(mrext,'("_",i2.2)') mrpid 00560 00561 puma_namelist = trim(puma_namelist ) // mrext 00562 puma_output = trim(puma_output ) // mrext 00563 puma_diag = trim(puma_diag ) // mrext 00564 puma_restart = trim(puma_restart ) // mrext 00565 puma_status = trim(puma_status ) // mrext 00566 efficiency_dat = trim(efficiency_dat ) // mrext 00567 ppp_puma_txt = trim(ppp_puma_txt ) // mrext 00568 puma_sp_init = trim(puma_sp_init ) // mrext 00569 00570 return 00571 end 00572 00573 00574 ! *********************** 00575 ! * SUBROUTINE OPENDIAG * 00576 ! *********************** 00577 00578 subroutine opendiag 00579 use pumamod 00580 00581 if (mypid == NROOT) then 00582 open(nud,file=puma_diag) 00583 endif 00584 00585 return 00586 end 00587 00588 00589 ! ****************************** 00590 ! * SUBROUTINE ALLOCATE_ARRAYS * 00591 ! ****************************** 00592 00593 subroutine allocate_arrays 00594 use pumamod 00595 00596 allocate(sd(nesp,nlev)) ; sd(:,:) = 0.0 ! Spectral Divergence 00597 allocate(st(nesp,nlev)) ; st(:,:) = 0.0 ! Spectral Temperature 00598 allocate(sz(nesp,nlev)) ; sz(:,:) = 0.0 ! Spectral Vorticity 00599 allocate(sp(nesp)) ; sp(:) = 0.0 ! Spectral Pressure (ln Ps) 00600 allocate(so(nesp)) ; so(:) = 0.0 ! Spectral Orography 00601 allocate(sr1(nesp,nlev)) ; sr1(:,:) = 0.0 ! Spectral Restoration Temperature 00602 allocate(sr2(nesp,nlev)) ; sr2(:,:) = 0.0 ! Spectral Restoration Temperature 00603 allocate(sdp(nspp,nlev)) ; sdp(:,:) = 0.0 ! Spectral Divergence Partial 00604 allocate(stp(nspp,nlev)) ; stp(:,:) = 0.0 ! Spectral Temperature Partial 00605 allocate(szp(nspp,nlev)) ; szp(:,:) = 0.0 ! Spectral Vorticity Partial 00606 allocate(spp(nspp)) ; spp(:) = 0.0 ! Spectral Pressure Partial 00607 allocate(sop(nspp)) ; sop(:) = 0.0 ! Spectral Orography Partial 00608 allocate(srp1(nspp,nlev)) ; srp1(:,:)= 0.0 ! Spectral Restoration Partial 00609 allocate(srp2(nspp,nlev)) ; srp2(:,:)= 0.0 ! Spectral Restoration Partial 00610 allocate(sdt(nspp,nlev)) ; sdt(:,:) = 0.0 ! Spectral Divergence Tendency 00611 allocate(stt(nspp,nlev)) ; stt(:,:) = 0.0 ! Spectral Temperature Tendency 00612 allocate(szt(nspp,nlev)) ; szt(:,:) = 0.0 ! Spectral Vorticity Tendency 00613 allocate(spt(nspp)) ; spt(:) = 0.0 ! Spectral Pressure Tendency 00614 allocate(sdm(nspp,nlev)) ; sdm(:,:) = 0.0 ! Spectral Divergence Minus 00615 allocate(stm(nspp,nlev)) ; stm(:,:) = 0.0 ! Spectral Temperature Minus 00616 allocate(szm(nspp,nlev)) ; szm(:,:) = 0.0 ! Spectral Vorticity Minus 00617 allocate(spm(nspp)) ; spm(:) = 0.0 ! Spectral Pressure Minus 00618 allocate(sak(nesp)) ; sak(:) = 0.0 ! Hyper diffusion 00619 allocate(srcn(nesp)) ; srcn(:) = 0.0 ! 1.0 / (n * (n+1)) 00620 allocate(span(nesp)) ; span(:) = 0.0 ! Pressure for diagnostics 00621 allocate(spnorm(nesp)) ; spnorm(:)= 0.0 ! Factors for output normalization 00622 00623 allocate(nindex(nesp)) ; nindex(:) = ntru ! Holds wavenumber 00624 allocate(nscatsp(npro)) ; nscatsp(:) = nspp ! Used for reduce_scatter op 00625 allocate(nselzw(0:ntru)) ; nselzw(:) = 1 ! Enable selected zonal waves 00626 allocate(nselsp(ncsp)) ; nselsp(:) = 1 ! Enable slected spectral modes 00627 00628 allocate(gd(nhor,nlev)) ; gd(:,:) = 0.0 ! Divergence 00629 allocate(gt(nhor,nlev)) ; gt(:,:) = 0.0 ! Temperature 00630 allocate(gz(nhor,nlev)) ; gz(:,:) = 0.0 ! Vorticity 00631 allocate(gu(nhor,nlev)) ; gu(:,:) = 0.0 ! u * cos(phi) 00632 allocate(gv(nhor,nlev)) ; gv(:,:) = 0.0 ! v * sin(phi) 00633 allocate(gp(nhor)) ; gp(:) = 0.0 ! Ln(Ps) 00634 allocate(gfu(nhor,nlev)) ; gfu(:,:) = 0.0 ! Term Fu in Primitive Equations 00635 allocate(gfv(nhor,nlev)) ; gfv(:,:) = 0.0 ! Term Fv in Primitive Equations 00636 allocate(gut(nhor,nlev)) ; gut(:,:) = 0.0 ! Term u * T 00637 allocate(gvt(nhor,nlev)) ; gvt(:,:) = 0.0 ! Term v * T 00638 allocate(gke(nhor,nlev)) ; gke(:,:) = 0.0 ! Kinetic energy u * u + v * v 00639 allocate(gpj(nhor)) ; gpj(:) = 0.0 ! d(Ln(Ps)) / d(mu) 00640 00641 00642 allocate(rcsq(nhor)) ; rcsq(:) = 0.0 ! 1 / cos2(phi) 00643 00644 allocate(ndil(nlev)) ; ndil(:) = 0 00645 allocate(csu(nlat,nlev)) ; csu(:,:) = 0.0 00646 allocate(csv(nlat,nlev)) ; csv(:,:) = 0.0 00647 allocate(cst(nlat,nlev)) ; cst(:,:) = 0.0 00648 00649 allocate(chlat(nlat)) ; chlat(:) = ' ' 00650 allocate(sid(nlat)) ; sid(:) = 0.0 ! sin(phi) 00651 allocate(gwd(nlat)) ; gwd(:) = 0.0 ! Gaussian weight (phi) 00652 allocate(csq(nlat)) ; csq(:) = 0.0 ! cos2(phi) 00653 allocate(rcs(nlat)) ; rcs(:) = 0.0 ! 1/cos(phi) 00654 00655 allocate(t0(nlev)) ; t0(:) = 250.0 ! reference temperature 00656 allocate(t0d(nlev)) ; t0d(:) = 0.0 ! vertical t0 gradient 00657 allocate(taur(nlev)) ; taur(:) = 0.0 ! tau R [days] 00658 allocate(tauf(nlev)) ; tauf(:) = 0.0 ! tau F [days] 00659 allocate(damp(nlev)) ; damp(:) = 0.0 ! 1.0 / (2 Pi * taur) 00660 allocate(fric(nlev)) ; fric(:) = 0.0 ! 1.0 / (2 Pi * tauf ) 00661 allocate(dsigma(nlev)) ; dsigma(:) = 0.0 00662 allocate(rdsig(nlev)) ; rdsig(:) = 0.0 00663 allocate(sigma(nlev)) ; sigma(:) = 0.0 00664 allocate(sigmh(nlev)) ; sigmh(:) = 0.0 00665 allocate(tkp(nlev)) ; tkp(:) = 0.0 00666 allocate(c(nlev,nlev)) ; c(:,:) = 0.0 00667 allocate(xlphi(nlev,nlev)) ; xlphi(:,:) = 0.0 ! matrix Lphi (g) 00668 allocate(xlt(nlev,nlev)) ; xlt(:,:) = 0.0 ! matrix LT (tau) 00669 allocate(bm1(nlev,nlev,0:NTRU)) ; bm1(:,:,:) = 0.0 00670 00671 if (mrnum == 2) then 00672 allocate(sdd(nesp,nlev)) ; sdd(:,:) = 0.0 00673 allocate(std(nesp,nlev)) ; std(:,:) = 0.0 00674 allocate(szd(nesp,nlev)) ; szd(:,:) = 0.0 00675 allocate(spd(nesp )) ; spd(: ) = 0.0 00676 endif 00677 00678 return 00679 end subroutine allocate_arrays 00680 00681 00682 ! ================= 00683 ! SUBROUTINE PROLOG 00684 ! ================= 00685 00686 subroutine prolog 00687 use pumamod 00688 00689 character( 8) :: cpuma = 'PUMA-II ' 00690 character(80) :: pumaversion = '16.0 (27-Sep-2010)' 00691 real :: zsig(nlon*nlat) 00692 00693 if (mypid == NROOT) then 00694 call cpu_time(tmstart) 00695 write(nud,'(/," ****************************************************")') 00696 write(nud,'(" * PUMA ",a43," *")') trim(pumaversion) 00697 write(nud,'(" ****************************************************")') 00698 if (mrnum == 0) then 00699 write(nud,'(" * NTRU =",i4," NLEV =",i4," NLON = ",i4," NLAT =",i4," *")') & 00700 NTRU,NLEV,NLON,NLAT 00701 else 00702 do jpid = 1 , mrnum 00703 write(nud,'(" * PID =",i4," NTRU =",i4," NLEV = ",i4," *")') & 00704 jpid-1,mrtru(jpid),NLEV 00705 enddo 00706 endif 00707 write(nud,'(" ****************************************************")') 00708 if (NPRO > 1) then 00709 write(nud,'(/," ****************************************************")') 00710 do jpro = 1 , NPRO 00711 write(nud,'(" * CPU",i4,1x,a40," *")') jpro-1,ympname(jpro) 00712 enddo 00713 write(nud,'(" ****************************************************")') 00714 endif 00715 call restart_ini(lrestart,puma_restart) 00716 call inigau(NLAT,sid,gwd) 00717 call inilat 00718 call legpri 00719 call readnl 00720 call ppp_interface 00721 call initpm 00722 call initsi 00723 call altlat(csq,NLAT) ! csq -> alternating grid 00724 if (ngui > 0) call guistart 00725 if (nrun == 0 .and. nstop > 0) nrun = nstop-nstep 00726 if (nrun == 0) nrun = ntspd * (nyears * 360 + nmonths * 30) 00727 call initrandom ! set random seed 00728 endif ! (mypid == NROOT) 00729 00730 call mpbci(nruido) 00731 call initruido ! allocate ruido arrays 00732 00733 00734 if (nshutdown > 0) return ! If something went wrong in the init routines 00735 00736 ! *********************** 00737 ! * broadcast & scatter * 00738 ! *********************** 00739 00740 call mpscdn(sid,NHPP) ! real (kind=8) 00741 call mpscdn(gwd,NHPP) ! real (kind=8) 00742 call mpscrn(csq,NLPP) 00743 00744 do jlat = 1 , NLPP 00745 rcsq(1+(jlat-1)*NLON:jlat*NLON) = 1.0 / csq(jlat) 00746 enddo 00747 00748 ! broadcast integer 00749 00750 call mpbci(kick ) ! add noise for kick > 0 00751 call mpbci(nafter ) ! write data interval [steps] 00752 call mpbci(nwpd ) ! write data interval [writes per day] 00753 call mpbci(ncoeff ) ! number of modes to print 00754 call mpbci(ndel ) ! ndel 00755 call mpbci(noutput ) ! global output switch 00756 call mpbci(ndiag ) ! write diagnostics interval 00757 call mpbci(ngui ) ! GUI on (1) or off (0) 00758 call mpbci(nkits ) ! number of initial timesteps 00759 call mpbci(nlevt ) ! tropospheric levels 00760 call mpbci(nrun ) ! if (nstop == 0) nstop = nstep + nrun 00761 call mpbci(nstep ) ! current timestep 00762 call mpbci(nstop ) ! finishing timestep 00763 call mpbci(ntspd ) ! number of timesteps per day 00764 call mpbci(mpstep ) ! minutes per step 00765 call mpbci(nyears ) ! simulation time 00766 call mpbci(nmonths ) ! simulation time 00767 call mpbci(nextout ) ! write extended output 00768 call mpbci(nsponge) ! Switch for sponge layer 00769 call mpbci(nhelsua) ! Held & Suarez forcing 00770 call mpbci(ndiagp) ! 0/1 switch for new grid point diabatic heating 00771 call mpbci(nconv) ! 0/1 switch for convective heating 00772 call mpbci(nvg ) ! Type of vertical grid 00773 call mpbci(nenergy) ! energy diagnostics 00774 call mpbci(nentropy) ! entropy diagnostics 00775 call mpbci(ndheat) ! energy recycling 00776 call mpbci(nradcv) ! use two restoration fields 00777 00778 ! broadcast logical 00779 00780 call mpbcl(lrestart) ! true: read restart file, false: initial run 00781 call mpbcl(lselect ) ! true: disable some zonal waves 00782 call mpbcl(lspecsel) ! true: disable some spectral modes 00783 00784 ! broadcast real 00785 00786 call mpbcr(ww ) 00787 call mpbcr(v_scl ) 00788 call mpbcr(ct ) 00789 00790 call mpbcr(sid_day ) 00791 call mpbcr(plarad ) 00792 call mpbcr(gascon ) 00793 call mpbcr(akap ) 00794 call mpbcr(alr ) 00795 call mpbcr(ga ) 00796 call mpbcr(psurf ) 00797 call mpbcr(alpha ) ! Williams factor for time filter 00798 call mpbcr(dtep ) ! equator-pole temperature difference 00799 call mpbcr(dtns ) 00800 call mpbcr(dtrop ) 00801 call mpbcr(dttrp ) 00802 call mpbcr(tdiss ) 00803 call mpbcr(tac ) 00804 call mpbcr(pac ) 00805 call mpbcr(plavor ) 00806 call mpbcr(rotspd ) 00807 call mpbcr(sigmax ) ! sigma of top half level 00808 call mpbcr(tgr ) 00809 call mpbcr(dvdiff ) 00810 call mpbcr(disp ) 00811 call mpbcr(tauta ) 00812 call mpbcr(tauts ) 00813 call mpbcr(pspon ) 00814 call mpbcr(sponk ) 00815 00816 ! broadcast integer arrays 00817 00818 call mpbcin(ndil ,NLEV) 00819 call mpbcin(nselzw,NTP1) 00820 00821 ! broadcast real arrays 00822 00823 call mpbcrn(damp ,NLEV) 00824 call mpbcrn(dsigma,NLEV) 00825 call mpbcrn(fric ,NLEV) 00826 call mpbcrn(rdsig ,NLEV) 00827 call mpbcrn(taur ,NLEV) 00828 call mpbcrn(sigma ,NLEV) 00829 call mpbcrn(sigmh ,NLEV) 00830 call mpbcrn(t0 ,NLEV) 00831 call mpbcrn(t0d ,NLEV) 00832 call mpbcrn(tauf ,NLEV) 00833 call mpbcrn(tkp ,NLEV) 00834 00835 call mpbcrn(c ,NLSQ) 00836 call mpbcrn(xlphi ,NLSQ) 00837 call mpbcrn(xlt ,NLSQ) 00838 00839 ! scatter integer arrays 00840 00841 call mpscin(nindex,NSPP) 00842 call mpscrn(srcn ,NSPP) 00843 call mpscrn(sak ,NSPP) 00844 00845 call legini(nlat,nlpp,nesp,nlev,plavor,sid,gwd) 00846 00847 if (lrestart) then 00848 call read_atmos_restart 00849 if (mypid == NROOT) then 00850 if (kick > 10) call noise(kick-10) 00851 endif 00852 else 00853 call initfd 00854 endif 00855 00856 if (mypid == NROOT) then 00857 call printseed ! either namelist, clock initialized or from restart file 00858 endif 00859 00860 ! broadcast spectral arrays 00861 00862 call mpbcrn(sp,NESP) 00863 call mpbcrn(sd,NESP*NLEV) 00864 call mpbcrn(st,NESP*NLEV) 00865 call mpbcrn(sz,NESP*NLEV) 00866 00867 ! scatter spectral arrays 00868 00869 call mpscsp(sd,sdp,NLEV) 00870 call mpscsp(st,stp,NLEV) 00871 call mpscsp(sz,szp,NLEV) 00872 call mpscsp(sr1,srp1,NLEV) 00873 call mpscsp(sr2,srp2,NLEV) 00874 call mpscsp(sp,spp,1) 00875 call mpscsp(so,sop,1) 00876 00877 ! scatter gridpoint arrays 00878 00879 if (nruido > 0) call mpscgp(ruido,ruidop,NLEV) 00880 00881 ! 00882 ! initialize energy and entropy diagnostics 00883 ! 00884 if(nenergy > 0) then 00885 allocate(denergy(NHOR,9)) 00886 denergy(:,:)=0. 00887 endif 00888 if(nentropy > 0) then 00889 allocate(dentropy(NHOR,9)) 00890 dentropy(:,:)=0. 00891 endif 00892 if(ndheat > 1 .and. mypid == NROOT) then 00893 open(9,file=efficiency_dat,form='formatted') 00894 endif 00895 ! 00896 ! write first service record containing sigma coordinates 00897 ! 00898 if (mypid == NROOT) then 00899 if (noutput > 0) then 00900 istep = nstep 00901 if (istep > 0) istep = istep + nafter ! next write after restart 00902 open(40,file=puma_output,form='unformatted') 00903 call ntomin(istep,imin,ihour,iday,imonth,iyear) 00904 zsig(1:nlev) = sigmh(:) 00905 zsig(nlev+1:) = 0.0 00906 write(40) 333,0,iyear*10000+imonth*100+iday,0,nlon,nlat,nlev,ntru 00907 write(40) zsig 00908 endif ! (noutput > 0) 00909 endif ! (mypid == NROOT) 00910 return 00911 end subroutine prolog 00912 00913 00914 !===================! 00915 ! SUBROUTINE MASTER ! 00916 !================== ! 00917 00918 subroutine master 00919 use pumamod 00920 00921 if (nshutdown > 0) return ! if something went wrong in prolog already 00922 00923 ! *************************** 00924 ! * short initial timesteps * 00925 ! *************************** 00926 00927 ikits = nkits 00928 do jkits = 1 , ikits 00929 delt = (TWOPI/ntspd) / (2**nkits) 00930 delt2 = delt + delt 00931 call gridpoint 00932 call makebm 00933 call spectral 00934 nkits = nkits - 1 00935 enddo 00936 00937 delt = TWOPI/ntspd 00938 delt2 = delt + delt 00939 call makebm 00940 00941 nstep1 = nstep ! remember 1.st timestep 00942 00943 do jstep = 1 , nrun 00944 nstep = nstep + 1 00945 call ntomin(nstep,ndatim(5),ndatim(4),ndatim(3),ndatim(2),ndatim(1)) 00946 00947 ! ************************************************************ 00948 ! * calculation of non-linear quantities in grid point space * 00949 ! ************************************************************ 00950 00951 call gridpoint 00952 00953 if (mypid == NROOT) then 00954 if (mod(nstep,nafter) == 0 .and. noutput > 0) call outsp 00955 if (mod(nstep,ndiag ) == 0 .or. ngui > 0) call diag 00956 if (ncu > 0) call checkunit 00957 endif 00958 if (ngui > 0) call guistep_puma 00959 00960 ! ****************************** 00961 ! * adiabatic part of timestep * 00962 ! ****************************** 00963 00964 call spectral 00965 if (mod(nstep,nafter) == 0 .and. noutput > 0) call outgp 00966 if (nshutdown > 0) return 00967 enddo 00968 return 00969 end subroutine master 00970 00971 00972 ! ================= 00973 ! SUBROUTINE EPILOG 00974 ! ================= 00975 00976 subroutine epilog 00977 use pumamod 00978 real (kind=8) :: zut,zst 00979 integer (kind=8) :: imem,ipr,ipf,isw,idr,idw 00980 00981 if (mypid == NROOT) close(40) ! close output file 00982 00983 ! write restart file 00984 00985 if (mypid == NROOT) then 00986 call restart_prepare(puma_status) 00987 sp(1) = psmean ! save psmean 00988 call put_restart_integer('nstep' ,nstep ) 00989 call put_restart_integer('nlat' ,NLAT ) 00990 call put_restart_integer('nlon' ,NLON ) 00991 call put_restart_integer('nlev' ,NLEV ) 00992 call put_restart_integer('nrsp' ,NRSP ) 00993 00994 ! Save current random number generator seed 00995 00996 call random_seed(get=meed) 00997 call put_restart_array('seed',meed,nseedlen,1,1) 00998 call put_restart_array('ganext',ganext,1,1,1) 00999 01000 call put_restart_array('sz' ,sz ,NRSP,NESP,NLEV) 01001 call put_restart_array('sd' ,sd ,NRSP,NESP,NLEV) 01002 call put_restart_array('st' ,st ,NRSP,NESP,NLEV) 01003 call put_restart_array('sr1',sr1,NRSP,NESP,NLEV) 01004 call put_restart_array('sr2',sr2,NRSP,NESP,NLEV) 01005 call put_restart_array('sp' ,sp ,NRSP,NESP, 1) 01006 call put_restart_array('so' ,so ,NRSP,NESP, 1) 01007 if (nruido > 0) then 01008 call put_restart_array('ruido',ruido,nugp,nugp,nlev) 01009 endif 01010 endif 01011 01012 call mpputsp('szm',szm,NSPP,NLEV) 01013 call mpputsp('sdm',sdm,NSPP,NLEV) 01014 call mpputsp('stm',stm,NSPP,NLEV) 01015 call mpputsp('spm',spm,NSPP, 1) 01016 01017 ! write gridpoint arrays 01018 01019 if (allocated(gr1)) then 01020 call mpputgp('gr1',gr1,nhor,nlev) 01021 endif 01022 if (allocated(gr2)) then 01023 call mpputgp('gr2',gr2,nhor,nlev) 01024 endif 01025 if (allocated(gtdamp)) then 01026 call mpputgp('gtdamp',gtdamp,nhor,nlev) 01027 endif 01028 01029 if (allocated(gr1c)) then 01030 call mpputgp('gr1c',gr1c,nhor,nlev) 01031 endif 01032 if (allocated(gr2c)) then 01033 call mpputgp('gr2c',gr2c,nhor,nlev) 01034 endif 01035 if (allocated(gtdampc)) then 01036 call mpputgp('gtdampc',gtdampc,nhor,nlev) 01037 endif 01038 01039 if (mypid == NROOT) then 01040 ! Get resource stats from function resources in file pumax.c 01041 ires = nresources(zut,zst,imem,ipr,ipf,isw,idr,idw) 01042 call cpu_time(tmstop) 01043 tmrun = tmstop - tmstart 01044 if (nstep > nstep1) then 01045 zspy = tmrun * 360.0 * real(ntspd) / (nstep - nstep1) ! sec / siy 01046 zypd = (24.0 * 3600.0 / zspy) ! siy / day 01047 write(nud,'(/,"****************************************")') 01048 if (zut > 0.0) & 01049 write(nud, '("* User time : ", f10.3," sec *")') zut 01050 if (zst > 0.0) & 01051 write(nud, '("* System time : ", f10.3," sec *")') zst 01052 if (zut + zst > 0.0) tmrun = zut + zst 01053 write(nud, '("* Total CPU time : ", f10.3," sec *")') tmrun 01054 if (imem > 0) & 01055 write(nud, '("* Memory usage : ", f10.3," MB *")') imem * 0.000001 01056 if (ipr > 0) & 01057 write(nud, '("* Page reclaims : ", i6," pages *")') ipr 01058 if (ipf > 0) & 01059 write(nud, '("* Page faults : ", i6," pages *")') ipf 01060 if (isw > 0) & 01061 write(nud, '("* Page swaps : ", i6," pages *")') isw 01062 if (idr > 0) & 01063 write(nud, '("* Disk read : ", i6," blocks *")') idr 01064 if (idw > 0) & 01065 write(nud, '("* Disk write : ", i6," blocks *")') idw 01066 write(nud,'("****************************************")') 01067 if (zspy < 600.0) then 01068 write(nud,'("* Seconds per sim year: ",i6,9x,"*")') nint(zspy) 01069 else if (zspy < 900000.0) then 01070 write(nud,'("* Minutes per sim year ",i6,9x,"*")') nint(zspy/60.0) 01071 else 01072 write(nud,'("* Days per sim year: ",i6,5x,"*")') nint(zspy/86400.0) 01073 endif 01074 write(nud,'("* Sim years per day :",i7,9x,"*")') nint(zypd) 01075 write(nud,'("****************************************")') 01076 endif 01077 endif 01078 01079 return 01080 end subroutine epilog 01081 01082 ! ============================= 01083 ! SUBROUTINE READ_ATMOS_RESTART 01084 ! ============================= 01085 01086 subroutine read_atmos_restart 01087 use pumamod 01088 01089 integer :: k = 0 01090 01091 ! read scalars and full spectral arrays 01092 01093 if (mypid == NROOT) then 01094 call get_restart_integer('nstep',nstep) 01095 call get_restart_array('seed',meed,nseedlen,1,1) 01096 call get_restart_array('ganext',ganext,1,1,1) 01097 call get_restart_array('sz' ,sz ,NRSP,NESP,NLEV) 01098 call get_restart_array('sd' ,sd ,NRSP,NESP,NLEV) 01099 call get_restart_array('st' ,st ,NRSP,NESP,NLEV) 01100 call get_restart_array('sr1',sr1,NRSP,NESP,NLEV) 01101 call get_restart_array('sr2',sr2,NRSP,NESP,NLEV) 01102 call get_restart_array('sp' ,sp ,NRSP,NESP, 1) 01103 call get_restart_array('so' ,so ,NRSP,NESP, 1) 01104 if (nruido > 0) then 01105 call get_restart_array('ruido',ruido,nugp,nugp,nlev) 01106 endif 01107 psmean = sp(1) 01108 sp(1) = 0.0 01109 call random_seed(put=meed) 01110 endif 01111 01112 call mpbci(nstep) ! broadcast current timestep 01113 call mpbcr(psmean) ! broadcast mean surface pressure 01114 01115 ! read and scatter spectral arrays 01116 01117 call mpgetsp('szm',szm,NSPP,NLEV) 01118 call mpgetsp('sdm',sdm,NSPP,NLEV) 01119 call mpgetsp('stm',stm,NSPP,NLEV) 01120 call mpgetsp('spm',spm,NSPP, 1) 01121 01122 ! allocate, read and scatter gridpoint arrays 01123 01124 if (mypid == NROOT) call varseek('gr1',ktmp) 01125 call mpbci(ktmp) 01126 if (ktmp > 0) then 01127 allocate(gr1(nhor,nlev)) 01128 call mpgetgp('gr1',gr1,nhor,nlev) 01129 endif 01130 if (mypid == NROOT) call varseek('gr2',ktmp) 01131 call mpbci(ktmp) 01132 if (ktmp > 0) then 01133 allocate(gr2(nhor,nlev)) 01134 call mpgetgp('gr2',gr2,nhor,nlev) 01135 endif 01136 if (mypid == NROOT) call varseek('gtdamp',ktmp) 01137 call mpbci(ktmp) 01138 if (ktmp > 0) then 01139 allocate(gtdamp(nhor,nlev)) 01140 call mpgetgp('gtdamp',gtdamp,nhor,nlev) 01141 endif 01142 if (mypid == NROOT) call varseek('gr1c',ktmp) 01143 call mpbci(ktmp) 01144 if (ktmp > 0) then 01145 allocate(gr1c(nhor,nlev)) 01146 call mpgetgp('gr1c',gr1c,nhor,nlev) 01147 endif 01148 if (mypid == NROOT) call varseek('gr2c',ktmp) 01149 call mpbci(ktmp) 01150 if (ktmp > 0) then 01151 allocate(gr2c(nhor,nlev)) 01152 call mpgetgp('gr2c',gr2c,nhor,nlev) 01153 endif 01154 if (mypid == NROOT) call varseek('gtdampc',ktmp) 01155 call mpbci(ktmp) 01156 if (ktmp > 0) then 01157 allocate(gtdampc(nhor,nlev)) 01158 call mpgetgp('gtdampc',gtdampc,nhor,nlev) 01159 endif 01160 01161 return 01162 end subroutine read_atmos_restart 01163 01164 ! ================= 01165 ! SUBROUTINE INITFD 01166 ! ================= 01167 01168 subroutine initfd 01169 use pumamod 01170 01171 if (nkits < 1) nkits = 1 01172 01173 ! Look for start data and read them if there 01174 01175 call read_surf(129,so, 1,iread1) 01176 call read_surf(134,sp, 1,iread2) 01177 call read_surf(121,sr1,NLEV,iread3) 01178 call read_surf(122,sr2,NLEV,iread4) 01179 call read_vargp(123,NLEV,iread123) 01180 if (mypid == NROOT .and. iread123 == 0) then 01181 if (nhelsua > 1) then 01182 write(nud,*) "*** ERROR no *_surf_0123.sra file for Held&Suarez" 01183 stop 01184 endif 01185 endif 01186 01187 if (ndiagp > 0) then 01188 call read_vargp(121,NLEV,iread121) 01189 call read_vargp(122,NLEV,iread122) 01190 if (.not. allocated(gtdamp)) then 01191 call read_vargp(123,NLEV,iread123) 01192 endif 01193 if (mypid == NROOT) then 01194 if (iread121==0 .or. iread122==0 .or. iread123==0) then 01195 write(nud,*) "*** ERROR not all fields (121,122,123) for grid point heating found" 01196 stop 01197 endif 01198 endif 01199 endif 01200 01201 if (nconv > 0) then 01202 call read_vargp(124,NLEV,iread124) 01203 call read_vargp(125,NLEV,iread125) 01204 call read_vargp(126,NLEV,iread126) 01205 if (mypid == NROOT) then 01206 if (iread124==0 .or. iread125==0 .or. iread126==0) then 01207 write(nud,*) "*** ERROR not all fields (124,125,126) for convective heating found" 01208 stop 01209 endif 01210 endif 01211 endif 01212 01213 if (mypid == NROOT) then 01214 if (iread1==0 .or. iread2==0 .or. iread3==0 .or. iread4==0) then 01215 call setzt ! setup for aqua-planet 01216 else 01217 psmean = psurf * exp(spnorm(1) * sp(1)) 01218 sp(1) = 0.0 01219 so(:) = so(:) / (cv * cv) ! descale from [m2/s2] 01220 sr1(:,:) = sr1(:,:) / ct ! descale from [K] 01221 sr2(:,:) = sr2(:,:) / ct ! descale from [K] 01222 sr1(1,:) = sr1(1,:) - t0(:) * sqrt(2.0) ! subtract profile 01223 write(nud,'(a,f8.2,a)') ' Mean of Ps = ',0.01*psmean, '[hPa]' 01224 endif 01225 endif 01226 01227 ! Add initial noise if wanted 01228 01229 if (mypid == NROOT) then 01230 call printprofile 01231 if (kick > 10) then 01232 call noise(kick-10) 01233 else 01234 call noise(kick) 01235 endif 01236 endif ! (mypid == NROOT) 01237 01238 call mpscsp(sp,spm,1) 01239 if (mypid == NROOT) then 01240 st(1,:) = sr1(1,:) 01241 stm(1,:) = sr1(1,:) 01242 sz(3,:) = plavor 01243 szm(3,:) = plavor 01244 endif 01245 return 01246 end 01247 01248 01249 ! ========================== 01250 ! SUBROUTINE READ_RESOLUTION 01251 ! ========================== 01252 01253 subroutine read_resolution 01254 use pumamod 01255 01256 character (80) :: ylat 01257 character (80) :: ylev 01258 01259 if (mypid == NROOT) then 01260 call get_command_argument(1,ylat) 01261 call get_command_argument(2,ylev) 01262 read(ylat,*) nlat 01263 read(ylev,*) nlev 01264 endif 01265 01266 call mpbci(nlat) 01267 call mpbci(nlev) 01268 return 01269 end 01270 01271 01272 ! ===================== 01273 ! SUBROUTINE RESOLUTION 01274 ! ===================== 01275 01276 subroutine resolution 01277 use pumamod 01278 01279 nlem = nlev - 1 01280 nlep = nlev + 1 01281 nlsq = nlev * nlev 01282 01283 nlon = nlat + nlat ! Longitudes 01284 nlah = nlat / 2 01285 nlpp = nlat / npro 01286 nhpp = nlah / npro 01287 nhor = nlon * nlpp 01288 nugp = nlon * nlat 01289 npgp = nugp / 2 01290 01291 ntru = (nlon - 1) / 3 01292 ntp1 = ntru + 1 01293 nzom = ntp1 + ntp1 01294 nrsp = (ntru + 1) * (ntru + 2) 01295 ncsp = nrsp / 2 01296 nspp = (nrsp + npro - 1) / npro 01297 nesp = nspp * npro 01298 01299 return 01300 end 01301 01302 01303 ! ================= 01304 ! SUBROUTINE READNL 01305 ! ================= 01306 01307 subroutine readnl 01308 use pumamod 01309 01310 ! This workaround is necessaray, because allocatable arrays are 01311 ! not allowed in namelists for FORTRAN versions < F2003 01312 01313 integer, parameter :: MAXLEV = 100 01314 integer, parameter :: MAXSELZW = 42 01315 integer, parameter :: MAXSELSP = ((MAXSELZW+1) * (MAXSELZW+2)) / 2 01316 integer :: nselect(0:MAXSELZW) = 1 ! NSELECT can be used up tp T42 01317 integer :: nspecsel(MAXSELSP) = 1 ! Default setting: all modes active 01318 integer :: ndl(MAXLEV) = 0 ! Diagnostics off 01319 real :: restim(MAXLEV) = 0.0 ! Tau R 01320 real :: sigmah(MAXLEV) = 0.0 ! Half level sigma 01321 real :: t0k(MAXLEV) = 250.0 ! Reference temperature 01322 real :: tfrc(MAXLEV) = 0.0 ! Tau F 01323 01324 namelist /inp/ & 01325 akap , alpha , alr , alrs , disp , dtep & 01326 , dtns , dtrop , dttrp , dtzz , dvdiff & 01327 , ga , gascon & 01328 , kick , mpstep , nafter , ncoeff , nconv , ncu & 01329 , ndel , ndheat , ndiag , ndiagp , ndl , nenergy & 01330 , nentropy, nextout , ngui , nguidbg , nhelsua , nkits & 01331 , nlevt , nmonths , noutput , nradcv , nruido , nrun & 01332 , nselect , nspecsel, nsponge , nstep , nstop , nsync & 01333 , ntspd , nvg , nwpd , nwspini , nyears & 01334 , orofac , pac , plarad , pspon , psurf , restim & 01335 , rotspd , seed , sid_day , sigmah , sigmax , sponk & 01336 , syncstr , synctime, t0k & 01337 , tac , tauta , tauts , tdiss , tfrc , tgr 01338 01339 open(13,file=puma_namelist,iostat=ios) 01340 if (ios == 0) then 01341 read (13,inp) 01342 close(13) 01343 endif 01344 01345 !--- modify basic scales according to namelist 01346 ww = TWOPI/sid_day ! reciprocal of time scale 1/Omega 01347 cv = plarad*ww ! velocity scale (velocity at the equator) 01348 ct = cv*cv/gascon ! temperature scale from hydrostatic equation 01349 if (ntspd == 0) ntspd = (24 * nlat) / 32 ! automatic 01350 if (mpstep > 0) ntspd = 1440 / mpstep 01351 mpstep = 1440 / ntspd 01352 nafter = ntspd ! daily output 01353 if (nwpd > 0 .and. nwpd <= ntspd) then 01354 nafter = ntspd / nwpd 01355 endif 01356 if (ndiag < 1) ndiag = ntspd * 10 ! every 10th. day 01357 01358 if (synctime > 0.0) syncstr = 1.0 / (TWOPI * synctime) 01359 01360 write(nud,inp) 01361 01362 itru = ntru 01363 if (itru > MAXSELZW) itru = MAXSELZW 01364 icsp = ncsp 01365 if (icsp > MAXSELSP) icsp = MAXSELSP 01366 ilev = nlev 01367 if (ilev > MAXLEV) ilev = MAXLEV 01368 01369 nselzw(0:itru) = nselect(0:itru) ! Copy values to allocated array 01370 nselsp(1:icsp) = nspecsel(1:icsp) 01371 ndil(1:ilev) = ndl(1:ilev) 01372 taur(1:ilev) = restim(1:ilev) 01373 tauf(1:ilev) = tfrc(1:ilev) 01374 sigmh(1:ilev) = sigmah(1:ilev) 01375 t0(1:ilev) = t0k(1:ilev) 01376 01377 return 01378 end 01379 01380 01381 ! ====================== 01382 ! SUBROUTINE PPP_DEF_INT 01383 ! ====================== 01384 01385 subroutine ppp_def_int(pname,nvar,ndim) 01386 use prepmod 01387 01388 character (*) :: pname 01389 integer,target :: nvar 01390 01391 num_ppp = num_ppp + 1 01392 ppp_tab(num_ppp)%name = '[' // trim(pname) // ']' 01393 ppp_tab(num_ppp)%isint = .true. 01394 ppp_tab(num_ppp)%n = ndim 01395 ppp_tab(num_ppp)%pint => nvar 01396 ppp_tab(num_ppp)%preal => null() 01397 return 01398 end subroutine ppp_def_int 01399 01400 01401 ! ======================= 01402 ! SUBROUTINE PPP_DEF_REAL 01403 ! ======================= 01404 01405 subroutine ppp_def_real(pname,rvar,ndim) 01406 use prepmod 01407 character (*) :: pname 01408 real ,target :: rvar 01409 01410 num_ppp = num_ppp + 1 01411 ppp_tab(num_ppp)%name = '[' // trim(pname) // ']' 01412 ppp_tab(num_ppp)%isint = .false. 01413 ppp_tab(num_ppp)%n = ndim 01414 ppp_tab(num_ppp)%pint => null() 01415 ppp_tab(num_ppp)%preal => rvar 01416 return 01417 end subroutine ppp_def_real 01418 01419 01420 subroutine ppp_read_i(a,ndim,nread) 01421 integer :: a(ndim) 01422 integer :: n 01423 01424 nread = 0 01425 read (15,*) n 01426 if (n < 1 .or. n > ndim) return 01427 read (15,*) a(1:n) 01428 nread = n 01429 return 01430 end 01431 01432 01433 subroutine ppp_read_r(a,ndim,nread) 01434 real :: a(ndim) 01435 integer :: n 01436 01437 nread = 0 01438 read (15,*) n 01439 if (n < 1 .or. n > ndim) return 01440 read (15,*) a(1:n) 01441 nread = n 01442 return 01443 end 01444 01445 01446 ! ======================== 01447 ! SUBROUTINE PPP_INTERFACE 01448 ! ======================== 01449 01450 subroutine ppp_interface 01451 use pumamod 01452 use prepmod 01453 logical :: lexist 01454 integer :: iostat 01455 integer :: n 01456 integer :: ivar 01457 character (80) :: yname 01458 01459 inquire(file=ppp_puma_txt,exist=lexist) 01460 if (.not. lexist) return 01461 01462 call ppp_def_int('NLAT',nlat_ppp,1) 01463 call ppp_def_int('NLEV',nlev_ppp,1) 01464 01465 call ppp_def_real('SIGMH',sigmh,nlev) 01466 01467 write(nud,*) "*******************************" 01468 write(nud,*) "* Reading file <",trim(ppp_puma_txt),"> *" 01469 write(nud,*) "*******************************" 01470 open (15,file=ppp_puma_txt) 01471 read (15,'(A)',iostat=iostat) yname 01472 do while (trim(yname) /= '[END]' .and. iostat == 0) 01473 do j = 1 , num_ppp 01474 if (trim(yname) == ppp_tab(j)%name) then 01475 if (ppp_tab(j)%isint) then 01476 call ppp_read_i(ppp_tab(j)%pint,ppp_tab(j)%n,iread) 01477 if (iread == 0) then 01478 write(nud,*) "*** ERROR reading ",trim(yname)," from ",trim(ppp_puma_txt) 01479 stop 01480 else if (iread == 1) then 01481 write(nud,'("* ",A," = ",I10," *")') yname(1:15),ppp_tab(j)%pint 01482 else 01483 write(nud,'("* ",A," :",I5," items *")') yname(1:15),iread 01484 endif 01485 else 01486 call ppp_read_r(ppp_tab(j)%preal,ppp_tab(j)%n,iread) 01487 if (iread == 0) then 01488 write(nud,*) "*** ERROR reading ",trim(yname)," from ",trim(ppp_puma_txt) 01489 stop 01490 else if (iread == 1) then 01491 write(nud,'("* ",A," = ",G10.4," *")') yname(1:15),ppp_tab(j)%preal 01492 else 01493 write(nud,'("* ",A," :",I5," items *")') yname(1:15),iread 01494 endif 01495 endif 01496 exit 01497 endif 01498 enddo 01499 read (15,'(A)',iostat=iostat) yname 01500 enddo 01501 if (nlat_ppp /= 0 .and. nlat_ppp /= nlat) then 01502 write(nud,*) "*** ERROR *** ERROR *** ERROR *** ERROR ***" 01503 write(nud,*) "# of latitudes mismatch in preprocessor PPP and PUMA" 01504 write(nud,*) "NLAT in PPP : ",nlat_ppp," <",trim(ppp_puma_txt),">" 01505 write(nud,*) "NLAT in PUMA : ",nlat 01506 write(nud,*) "Aborting ..." 01507 stop 01508 endif 01509 if (nlev_ppp /= 0 .and. nlev_ppp /= nlev) then 01510 write(nud,*) "*** ERROR *** ERROR *** ERROR *** ERROR ***" 01511 write(nud,*) "# of levels mismatch in preprocessor PPP and PUMA" 01512 write(nud,*) "NLEV in PPP : ",nlev_ppp," <",trim(ppp_puma_txt),">" 01513 write(nud,*) "NLEV in PUMA : ",nlev 01514 write(nud,*) "Aborting ..." 01515 stop 01516 endif 01517 write(nud,*) "*******************************" 01518 01519 return 01520 end subroutine ppp_interface 01521 01522 01523 ! ============================= 01524 ! SUBROUTINE SELECT_ZONAL_WAVES 01525 ! ============================= 01526 01527 subroutine select_zonal_waves 01528 use pumamod 01529 01530 if (sum(nselzw(:)) /= NTP1) then ! some wavenumbers disabled 01531 lselect = .true. 01532 endif 01533 return 01534 end 01535 01536 ! ================================ 01537 ! SUBROUTINE SELECT_SPECTRAL_MODES 01538 ! ================================ 01539 01540 subroutine select_spectral_modes 01541 use pumamod 01542 01543 if (sum(nselsp(:)) /= NCSP) then ! some modes disabled 01544 lspecsel = .true. 01545 endif 01546 return 01547 end 01548 01549 ! ===================== 01550 ! * SET VERTICAL GRID * 01551 ! ===================== 01552 01553 subroutine set_vertical_grid 01554 01555 use pumamod 01556 01557 if (sigmh(NLEV) /= 0.0) return ! Already read in from namelist INP 01558 01559 if (nvg == 1) then ! Scinocca & Haynes sigma levels 01560 01561 if (nlevt >= NLEV) then ! Security check for 'nlevt' 01562 write(nud,*) '*** ERROR *** nlevt >= NLEV' 01563 write(nud,*) 'Number of levels (NLEV): ',NLEV 01564 write(nud,*) 'Number of tropospheric levels (nlevt): ',nlevt 01565 endif 01566 01567 ! troposphere: linear spacing in sigma 01568 ! stratosphere: linear spacing in log(sigma) 01569 ! after (see their Appendix): 01570 ! Scinocca, J. F. and P. H. Haynes (1998): Dynamical forcing of 01571 ! stratospheric planetary waves by tropospheric baroclinic eddies. 01572 ! J. Atmos. Sci., 55 (14), 2361-2392 01573 01574 ! Here, zsigtran is set to sigma at dtrop (tropopause height for 01575 ! construction of restoration temperature field). If tgr=288.15K, 01576 ! ALR=0.0065K/km and dtrop=11.km, then zsigtran=0.223 (=0.1 in 01577 ! Scinocca and Haynes (1998)). 01578 ! A smoothing of the transition between linear and logarithmic 01579 ! spacing, as noted in Scinocca and Haynes (1998), is not yet 01580 ! implemented. 01581 01582 zsigtran = (1. - alr * dtrop / tgr)**(ga/(gascon*alr)) 01583 zsigmin = 1. - (1. - zsigtran) / real(nlevt) 01584 01585 do jlev=1,NLEV 01586 if (jlev == 1) then 01587 sigmh(jlev) = SIGMAX 01588 elseif (jlev > 1 .and. jlev < NLEV - nlevt) then 01589 sigmh(jlev) = exp((log(SIGMAX) - log(zsigtran)) & 01590 & / real(NLEV - nlevt - 1) * real(NLEV - nlevt - jlev) 01591 + log(zsigtran)) 01592 elseif (jlev >= NLEV - nlevt .and. jlev < NLEV - 1) then 01593 sigmh(jlev) = (zsigtran - zsigmin) / real(nlevt - 1) 01594 * real(NLEV - 1 - jlev) + zsigmin 01595 elseif (jlev == NLEV - 1) then 01596 sigmh(jlev) = zsigmin 01597 elseif (jlev == NLEV) then 01598 sigmh(jlev) = 1. 01599 endif 01600 enddo 01601 return ! case nvg == 1 finished 01602 else if (nvg == 2) then ! Polvani & Kushner sigma levels 01603 inl = int(real(NLEV)/(1.0 - sigmax**(1.0/5.0))) 01604 do jlev=1,NLEV 01605 sigmh(jlev) = (real(jlev + inl - NLEV) / real(inl))**5 01606 enddo 01607 return 01608 01609 ! Default (nvg == 0) : equidistant sigma levels 01610 01611 else 01612 do jlev = 1 , NLEV 01613 sigmh(jlev) = real(jlev) / real(NLEV) 01614 enddo 01615 endif 01616 01617 return 01618 end 01619 01620 01621 ! ================= 01622 ! SUBROUTINE INITPM 01623 ! ================= 01624 01625 subroutine initpm 01626 use pumamod 01627 01628 real (kind=8) :: radea,zakk,zzakk 01629 real :: zsigb ! sigma_b for Held & Suarez frictional 01630 ! and heating timescales 01631 01632 radea = plarad ! Planet radius in high precision 01633 plavor = EZ * rotspd ! Planetary vorticity 01634 01635 ! ************************************************************* 01636 ! * carries out all initialisation of model prior to running. * 01637 ! * major sections identified with comments. * 01638 ! * this s/r sets the model parameters and all resolution * 01639 ! * dependent quantities. * 01640 ! ************************************************************* 01641 01642 if (lrestart) nkits=0 01643 01644 ! **************************************************** 01645 ! * Check for enabling / disabling zonal wavenumbers * 01646 ! **************************************************** 01647 01648 call select_zonal_waves 01649 if (npro == 1) call select_spectral_modes 01650 01651 ! ********************* 01652 ! * set vertical grid * 01653 ! ********************* 01654 01655 call set_vertical_grid 01656 01657 dsigma(1 ) = sigmh(1) 01658 dsigma(2:NLEV) = sigmh(2:NLEV) - sigmh(1:NLEM) 01659 01660 rdsig(:) = 0.5 / dsigma(:) 01661 01662 sigma(1 ) = 0.5 * sigmh(1) 01663 sigma(2:NLEV) = 0.5 * (sigmh(1:NLEM) + sigmh(2:NLEV)) 01664 01665 ! Initialize profile of tau R if not set in namelist 01666 01667 if (taur(NLEV) == 0.0) then 01668 do jlev = 1 , NLEV 01669 taur(jlev) = 158.0 / PI * atan(1.0 - sigma(jlev)) 01670 if (taur(jlev) > 30.0) taur(jlev) = 30.0 01671 enddo 01672 endif 01673 01674 ! Initialize profile of tau F if not set in namelist 01675 01676 if (tauf(NLEV) == 0.0) then 01677 do jlev = 1 , NLEV 01678 if (sigma(jlev) > 0.8) then 01679 tauf(jlev) = exp(10.0 * (1.0 - sigma(jlev))) / 2.718 01680 endif 01681 enddo 01682 endif 01683 01684 ! Compute 1.0 / (2 Pi * tau) for efficient use in calculations 01685 ! A day is 2 Pi in non dimensional units using omega as scaling 01686 01687 where (taur(:) > 0.0) 01688 damp(:) = 1.0 / (TWOPI * taur(:)) 01689 endwhere 01690 01691 where (tauf(:) > 0.0) 01692 fric(:) = 1.0 / (TWOPI * tauf(:)) 01693 endwhere 01694 01695 if (nsponge == 1) call sponge 01696 01697 01698 ! annual cycle period and phase in timesteps 01699 01700 if (tac > 0.0) tac = TWOPI / (ntspd * tac) 01701 pac = pac * ntspd 01702 01703 ! compute internal diffusion parameter 01704 01705 jdelh = ndel/2 01706 if (tdiss > 0.0) then 01707 zakk = ww*(radea**ndel)/(TWOPI*tdiss*((NTRU*(NTRU+1.))**jdelh)) 01708 else 01709 zakk = 0.0 01710 endif 01711 zzakk = zakk / (ww*(radea**ndel)) 01712 01713 ! set coefficients which depend on wavenumber 01714 01715 zrsq2 = 1.0 / sqrt(2.0) 01716 01717 jr =-1 01718 jw = 0 01719 do jm=0,NTRU 01720 do jn=jm,NTRU 01721 jr=jr+2 01722 ji=jr+1 01723 jw=jw+1 01724 nindex(jr)=jn 01725 nindex(ji)=jn 01726 spnorm(jr)=zrsq2 01727 spnorm(ji)=zrsq2 01728 zsq = jn * (jn+1) 01729 if (jn > 0) then 01730 srcn(jr) = 1.0 / zsq 01731 srcn(ji) = srcn(jr) 01732 endif 01733 sak(jr) = -zzakk * zsq**jdelh 01734 sak(ji) = sak(jr) 01735 enddo 01736 zrsq2=-zrsq2 01737 enddo 01738 01739 ! finally make temperatures dimensionless 01740 01741 dtns = dtns / ct 01742 dtep = dtep / ct 01743 ! dttrp = dttrp / ct 01744 t0(:) = t0(:) / ct 01745 01746 ! print out 01747 01748 write(nud,8120) 01749 write(nud,8000) 01750 write(nud,8010) NLEV 01751 write(nud,8020) NTRU 01752 write(nud,8030) NLAT 01753 write(nud,8040) NLON 01754 if (zakk == 0.0) then 01755 write(nud,8060) 01756 else 01757 write(nud,8070) ndel 01758 write(nud,8080) 01759 write(nud,8090) zakk,ndel 01760 write(nud,8100) tdiss 01761 endif 01762 write(nud,8110) PNU 01763 write(nud,8000) 01764 write(nud,8120) 01765 return 01766 01767 8000 format('*****************************************************') 01768 8010 format('* NLEV = ',i6,' Number of levels *') 01769 8020 format('* NTRU = ',i6,' Triangular truncation *') 01770 8030 format('* NLAT = ',i6,' Number of latitudes *') 01771 8040 format('* NLON = ',i6,' Number of longitues *') 01772 8060 format('* No lateral dissipation *') 01773 8070 format('* ndel = ',i6,' Lateral dissipation *') 01774 8080 format('* on vorticity, divergence and temperature *') 01775 8090 format('* with diffusion coefficient = ',e13.4,' m**',i1,'/s *') 01776 8100 format('* e-folding time for smallest scale is ',f7.3,' days *') 01777 8110 format('* Robert time filter with parameter PNU =',f8.3,' *') 01778 8120 format(/) 01779 end 01780 01781 01782 ! ================= 01783 ! SUBROUTINE MAKEBM 01784 ! ================= 01785 01786 subroutine makebm 01787 use pumamod 01788 01789 zdeltsq = delt * delt 01790 01791 do jlev1 = 1 , NLEV 01792 do jlev2 = 1 , NLEV 01793 zaq = zdeltsq * (t0(jlev1) * dsigma(jlev2)& 01794 & + dot_product(xlphi(:,jlev1),xlt(jlev2,:))) 01795 bm1(jlev2,jlev1,1:NTRU) = zaq 01796 enddo 01797 enddo 01798 01799 do jn=1,NTRU 01800 do jlev = 1 , NLEV 01801 bm1(jlev,jlev,jn) = bm1(jlev,jlev,jn) + 1.0 / (jn*(jn+1)) 01802 enddo 01803 call minvers(bm1(1,1,jn),NLEV) 01804 enddo 01805 return 01806 end 01807 01808 ! ================= 01809 ! SUBROUTINE INITSI 01810 ! ================= 01811 01812 subroutine initsi 01813 use pumamod 01814 01815 ! ********************************************** 01816 ! * Initialisation of the Semi Implicit scheme * 01817 ! ********************************************** 01818 01819 dimension zalp(NLEV),zh(NLEV) 01820 dimension ztautk(NLEV,NLEV) 01821 dimension ztaudt(NLEV,NLEV) 01822 01823 tkp(:) = akap * t0(:) 01824 t0d(1:NLEM) = t0(2:NLEV) - t0(1:NLEM) 01825 01826 zalp(2:NLEV) = log(sigmh(2:NLEV)) - log(sigmh(1:NLEM)) 01827 01828 xlphi(:,:) = 0.0 01829 xlphi(1,1) = 1.0 01830 do jlev = 2 , NLEV 01831 xlphi(jlev,jlev) = 1.0 - zalp(jlev)*sigmh(jlev-1)/dsigma(jlev) 01832 xlphi(jlev,1:jlev-1) = zalp(jlev) 01833 enddo 01834 01835 do jlev = 1 , NLEV 01836 c(jlev,:) = xlphi(:,jlev) * (dsigma(jlev) / dsigma(:)) 01837 enddo 01838 01839 ! *********************** tkp(i) = t0(i) * AKAP 01840 ! * matrix xlt - part 1 * 01841 ! *********************** 01842 01843 do jlev = 1 , NLEV 01844 ztautk(:,jlev) = tkp(jlev) * c(:,jlev) 01845 enddo 01846 01847 ! ********************* dsigma(i) = sigmh(i) - sigmh(i-1) 01848 ! * matrix xlt part 2 * rdsig (i) = 0.5 / dsigma(i) 01849 ! ********************* 01850 01851 ztaudt(1,1) = 0.5 * t0d(1) * (sigmh(1) - 1.0) 01852 ztaudt(2:NLEV,1) = 0.5 * t0d(1) * dsigma(2:NLEV) 01853 01854 do j= 2 , NLEV 01855 do i = 1 , j-1 01856 ztaudt(i,j) = dsigma(i) * rdsig(j) & 01857 * (t0d(j-1) * (sigmh(j-1)-1.0) + t0d(j) * (sigmh(j)-1.0)) 01858 enddo 01859 ztaudt(j,j) = 0.5 & 01860 * (t0d(j-1) * sigmh(j-1) + t0d(j) * (sigmh(j)-1.0)) 01861 do i = j+1 , NLEV 01862 ztaudt(i,j) = dsigma(i) * rdsig(j) & 01863 * (t0d(j-1) * sigmh(j-1) + t0d(j) * sigmh(j) ) 01864 enddo 01865 enddo 01866 01867 xlt(:,:) = ztautk(:,:) + ztaudt(:,:) 01868 01869 ! xlt finished 01870 01871 zfctr=0.001*cv*cv/ga 01872 do jlev=1,NLEV 01873 zh(jlev) = dot_product(xlphi(:,jlev),t0(:)) * zfctr 01874 enddo 01875 01876 ! ********************************** 01877 ! * write out vertical information * 01878 ! ********************************** 01879 01880 ilev = min(NLEV,5) 01881 write(nud,9001) 01882 write(nud,9002) 01883 write(nud,9003) 01884 write(nud,9002) 01885 do jlev=1,NLEV 01886 write(nud,9004) jlev,sigma(jlev),t0(jlev)*ct,zh(jlev) 01887 enddo 01888 write(nud,9002) 01889 write(nud,9001) 01890 01891 ! matrix c 01892 01893 write(nud,9012) 01894 write(nud,9013) 'c',(jlev,jlev=1,ilev) 01895 write(nud,9012) 01896 do jlev=1,NLEV 01897 write(nud,9014) jlev,(c(i,jlev),i=1,ilev) 01898 enddo 01899 write(nud,9012) 01900 write(nud,9001) 01901 01902 ! matrix xlphi 01903 01904 write(nud,9012) 01905 write(nud,9013) 'xlphi',(jlev,jlev=1,ilev) 01906 write(nud,9012) 01907 do jlev=1,NLEV 01908 write(nud,9014) jlev,(xlphi(i,jlev),i=1,ilev) 01909 enddo 01910 write(nud,9012) 01911 write(nud,9001) 01912 return 01913 9001 format(/) 01914 9002 format(33('*')) 01915 9003 format('* Lv * Sigma Basic-T Height *') 01916 9004 format('*',i3,' * ',3f8.3,' *') 01917 9012 format(69('*')) 01918 9013 format('* Lv * ',a5,i7,4i12,' *') 01919 9014 format('*',i3,' * ',5f12.8,' *') 01920 end 01921 01922 ! ===================== 01923 ! SUBROUTINE INITRANDOM 01924 ! ===================== 01925 01926 subroutine initrandom 01927 use pumamod 01928 integer :: i, clock 01929 01930 ! Set random number generator seed 01931 01932 call random_seed(size=nseedlen) 01933 allocate(meed(nseedlen)) 01934 01935 ! Take seed from namelist parameter 'SEED' ? 01936 01937 if (seed(1) /= 0) then 01938 meed(:) = 0 01939 i = nseedlen 01940 if (i > 8) i = 8 01941 meed(1:i) = seed(1:i) 01942 else 01943 call system_clock(count=clock) 01944 meed(:) = clock + 37 * (/(i,i=1,nseedlen)/) 01945 endif 01946 call random_seed(put=meed) 01947 return 01948 end 01949 01950 ! ==================== 01951 ! SUBROUTINE PRINTSEED 01952 ! ==================== 01953 01954 subroutine printseed 01955 use pumamod 01956 integer :: i 01957 01958 write (nud,9020) 01959 write (nud,9010) 01960 do i = 1 , nseedlen 01961 write (nud,9000) i,meed(i) 01962 enddo 01963 write (nud,9010) 01964 write (nud,9020) 01965 return 01966 9000 format('* seed(',i1,') = ',i10,' *') 01967 9010 format('************************') 01968 9020 format(/) 01969 end 01970 01971 ! ==================== 01972 ! SUBROUTINE INITRUIDO 01973 ! ==================== 01974 01975 subroutine initruido 01976 use pumamod 01977 if (nruido > 0) then 01978 allocate(ruido(nlon,nlat,nlev)) 01979 allocate(ruidop(nhor,nlev)) 01980 ruido = 77 01981 ruidop = 88 01982 endif 01983 return 01984 end 01985 01986 ! ==================== 01987 ! SUBROUTINE STEPRUIDO 01988 ! ==================== 01989 01990 subroutine stepruido 01991 use pumamod 01992 real :: zr 01993 integer :: need(8) 01994 01995 if (mypid == NROOT) then 01996 if (nruido == 1) then 01997 zr = disp*gasdev() 01998 ruido(:,:,:) = zr 01999 elseif (nruido == 2) then 02000 do jlev=1,NLEV 02001 do jlat=1,NLAT 02002 do jlon=1,NLON 02003 ruido(jlon,jlat,jlev) = disp*gasdev() 02004 enddo 02005 enddo 02006 enddo 02007 elseif (nruido == 3) then 02008 do jlev=1,NLEV 02009 do jlat=1,NLAT,2 02010 do jlon=1,NLON 02011 ruido(jlon,jlat ,jlev) = disp*gasdev() 02012 ruido(jlon,jlat+1,jlev) = ruido(jlon,jlat,jlev) 02013 enddo 02014 enddo 02015 enddo 02016 endif 02017 endif ! (mypid == NROOT) 02018 02019 call mpscgp(ruido,ruidop,NLEV) 02020 call random_seed(get=need) 02021 return 02022 end 02023 02024 ! ================== 02025 ! SUBROUTINE MINVERS 02026 ! ================== 02027 02028 subroutine minvers(a,n) 02029 dimension a(n,n),b(n,n),indx(n) 02030 02031 b = 0.0 02032 do j = 1 , n 02033 b(j,j) = 1.0 02034 enddo 02035 call ludcmp(a,n,indx) 02036 do j = 1 , n 02037 call lubksb(a,n,indx,b(1,j)) 02038 enddo 02039 a = b 02040 return 02041 end 02042 02043 ! ================= 02044 ! SUBROUTINE LUBKSB 02045 ! ================= 02046 02047 subroutine lubksb(a,n,indx,b) 02048 dimension a(n,n),b(n),indx(n) 02049 k = 0 02050 do i = 1 , n 02051 l = indx(i) 02052 sum = b(l) 02053 b(l) = b(i) 02054 if (k > 0) then 02055 do j = k , i-1 02056 sum = sum - a(i,j) * b(j) 02057 enddo 02058 else if (sum /= 0.0) then 02059 k = i 02060 endif 02061 b(i) = sum 02062 enddo 02063 02064 do i = n , 1 , -1 02065 sum = b(i) 02066 do j = i+1 , n 02067 sum = sum - a(i,j) * b(j) 02068 enddo 02069 b(i) = sum / a(i,i) 02070 enddo 02071 return 02072 end 02073 02074 ! ================= 02075 ! SUBROUTINE LUDCMP 02076 ! ================= 02077 02078 subroutine ludcmp(a,n,indx) 02079 dimension a(n,n),indx(n),vv(n) 02080 02081 d = 1.0 02082 vv = 1.0 / maxval(abs(a),2) 02083 02084 do 19 j = 1 , n 02085 do i = 2 , j-1 02086 a(i,j) = a(i,j) - dot_product(a(i,1:i-1),a(1:i-1,j)) 02087 enddo 02088 aamax = 0.0 02089 do i = j , n 02090 if (j > 1) & 02091 & a(i,j) = a(i,j) - dot_product(a(i,1:j-1),a(1:j-1,j)) 02092 dum = vv(i) * abs(a(i,j)) 02093 if (dum .ge. aamax) then 02094 imax = i 02095 aamax = dum 02096 endif 02097 enddo 02098 if (j .ne. imax) then 02099 do 17 k = 1 , n 02100 dum = a(imax,k) 02101 a(imax,k) = a(j,k) 02102 a(j,k) = dum 02103 17 continue 02104 d = -d 02105 vv(imax) = vv(j) 02106 endif 02107 indx(j) = imax 02108 if (a(j,j) == 0.0) a(j,j) = tiny(a(j,j)) 02109 if (j < n) a(j+1:n,j) = a(j+1:n,j) / a(j,j) 02110 19 continue 02111 return 02112 end 02113 02114 ! ============================= 02115 ! SUBROUTINE FILTER_ZONAL_WAVES 02116 ! ============================= 02117 02118 subroutine filter_zonal_waves(pfc) 02119 use pumamod 02120 dimension pfc(2,NLON/2,NLPP) 02121 02122 do jlat = 1 , NLPP 02123 pfc(1,1:NTP1,jlat) = pfc(1,1:NTP1,jlat) * nselzw(:) 02124 pfc(2,1:NTP1,jlat) = pfc(2,1:NTP1,jlat) * nselzw(:) 02125 enddo 02126 02127 return 02128 end 02129 02130 02131 ! ================================ 02132 ! SUBROUTINE FILTER_SPECTRAL_MODES 02133 ! ================================ 02134 02135 subroutine filter_spectral_modes 02136 use pumamod 02137 02138 j = 0 02139 k = -1 02140 do m = 0 , NTRU 02141 do n = m , NTRU 02142 k = k + 2 02143 j = j + 1 02144 if (nselsp(j) == 0) then 02145 spp(k:k+1 ) = 0.0 02146 sdp(k:k+1,:) = 0.0 02147 stp(k:k+1,:) = 0.0 02148 spt(k:k+1 ) = 0.0 02149 sdt(k:k+1,:) = 0.0 02150 stt(k:k+1,:) = 0.0 02151 spm(k:k+1 ) = 0.0 02152 sdm(k:k+1,:) = 0.0 02153 stm(k:k+1,:) = 0.0 02154 srp1(k:k+1,:) = 0.0 02155 srp2(k:k+1,:) = 0.0 02156 if (n < NTRU) then 02157 szp(k+2:k+3,:) = 0.0 02158 szt(k+2:k+3,:) = 0.0 02159 szm(k+2:k+3,:) = 0.0 02160 endif 02161 endif 02162 enddo 02163 enddo 02164 02165 return 02166 end 02167 02168 02169 ! ================ 02170 ! SUBROUTINE NOISE 02171 ! ================ 02172 02173 subroutine noise(kickval) 02174 use pumamod 02175 02176 ! kickval = -1 : read ln(ps) from puma_sp_init 02177 ! kickval = 0 : model runs zonally symmetric with no eddies 02178 ! kickval = 1 : add white noise to ln(Ps) asymmetric hemispheres 02179 ! kickval = 2 : add white noise to ln(Ps) symmetric to the equator 02180 ! kickval = 3 : force mode(1,2) of ln(Ps) allowing reproducable runs 02181 ! kickval = 4 : add white noise to symmetric zonal wavenumbers 7 of ln(Ps) 02182 02183 integer :: kickval 02184 integer :: jsp, jsp1, jn, jm 02185 integer :: jr, ji, ins 02186 real :: zr, zi, zscale, zrand 02187 02188 zscale = 0.000001 ! amplitude of noise 02189 zr = 0.01 ! kickval=3 value for mode(1,2) real 02190 zi = 0.005 ! kickval=3 value for mode(1,2) imag 02191 02192 select case (kickval) 02193 case (-1) 02194 open(71, file=puma_sp_init,form='unformatted',iostat=iostat) 02195 if (iostat /= 0) then 02196 write(nud,*) ' *** kick=-1: needs file <',trim(puma_sp_init),'> ***' 02197 stop 02198 endif 02199 read(71,iostat=iostat) sp(:) 02200 if (iostat /= 0) then 02201 write(nud,*) ' *** error reading file <',trim(puma_sp_init),'> ***' 02202 stop 02203 endif 02204 close(71) 02205 write(nud,*) 'initial ln(ps) field read from <',trim(puma_sp_init),'>' 02206 return 02207 case (0) ! do nothing 02208 case (1) 02209 jsp1=2*NTP1+1 02210 do jsp=jsp1,NRSP 02211 call random_number(zrand) 02212 if (mrpid > 0) zrand = zrand + mrpid * 0.01 02213 sp(jsp)=sp(jsp)+zscale*(zrand-0.5) 02214 enddo 02215 write(nud,*) 'white noise added' 02216 case (2) 02217 jr=2*NTP1-1 02218 do jm=1,NTRU 02219 do jn=jm,NTRU 02220 jr=jr+2 02221 ji=jr+1 02222 if (mod(jn+jm,2) == 0) then 02223 call random_number(zrand) 02224 if (mrpid > 0) zrand = zrand + mrpid * 0.01 02225 sp(jr)=sp(jr)+zscale*(zrand-0.5) 02226 sp(ji)=sp(ji)+zscale*(zrand-0.5) 02227 endif 02228 enddo 02229 enddo 02230 write(nud,*) 'symmetric white noise added' 02231 case (3) 02232 sp(2*NTP1+3) = sp(2*NTP1+3) + zr 02233 sp(2*NTP1+4) = sp(2*NTP1+4) + zi 02234 write(nud,*) 'mode(1,2) of ln(Ps) set to (',sp(2*NTP1+3),',',sp(2*NTP1+4),')' 02235 case (4) 02236 jr=2*NTP1-1 02237 do jm=1,NTRU 02238 do jn=jm,NTRU 02239 jr=jr+2 02240 ji=jr+1 02241 if (mod(jn+jm,2) == 0 .and. jm == 7) then 02242 call random_number(zrand) 02243 sp(jr)=sp(jr)+zscale*(zrand-0.5) 02244 sp(ji)=sp(ji)+zscale*(zrand-0.5) 02245 endif 02246 enddo 02247 enddo 02248 write(nud,*) 'symmetric zonal wavenumbers 7 of ln(Ps) perturbed', & 02249 & 'with white noise.' 02250 case default 02251 write(nud,*) 'Value ',kickval ,' for kickval not implemented.' 02252 stop 02253 end select 02254 02255 if (nwspini == 1) then 02256 open(71, file=puma_sp_init, form='unformatted') 02257 write(71) sp(:) 02258 close(71) 02259 endif 02260 02261 return 02262 end 02263 02264 ! ================ 02265 ! SUBROUTINE SETZT 02266 ! ================ 02267 subroutine setzt 02268 use pumamod 02269 02270 ! ************************************************************* 02271 ! * Set up the restoration temperature fields sr1 and sr2 * 02272 ! * for aqua planet conditions. * 02273 ! * The temperature at sigma = 1 is <tgr>, entered in kelvin. * 02274 ! * The lapse rate of ALR K/m is assumed under the tropopause * 02275 ! * and zero above. The tropopause is defined by <dtrop>. * 02276 ! * The smoothing ot the tropopause depends on <dttrp>. * 02277 ! ************************************************************* 02278 02279 dimension ztrs(NLEV) ! Mean profile 02280 dimension zfac(NLEV) 02281 02282 sr1(:,:) = 0.0 ! NESP,NLEV 02283 sr2(:,:) = 0.0 ! NESP,NLEV 02284 02285 ! Temperatures in [K] 02286 02287 zsigprev = 1.0 ! sigma value 02288 ztprev = tgr ! Temperature [K] 02289 zzprev = 0.0 ! Height [m] 02290 02291 do jlev = NLEV , 1 , -1 ! from bottom to top of atmosphere 02292 zzp=zzprev+(gascon*ztprev/ga)*log(zsigprev/sigma(jlev)) 02293 ztp=tgr-dtrop*alr ! temperature at tropopause 02294 ztp=ztp+sqrt((.5*alr*(zzp-dtrop))**2+dttrp**2) 02295 ztp=ztp-.5*alr*(zzp-dtrop) 02296 ztpm=.5*(ztprev+ztp) 02297 zzpp=zzprev+(gascon*ztpm/ga)*log(zsigprev/sigma(jlev)) 02298 ztpp=tgr-dtrop*alr 02299 ztpp=ztpp+sqrt((.5*alr*(zzpp-dtrop))**2+dttrp**2) 02300 ztpp=ztpp-.5*alr*(zzpp-dtrop) 02301 ztrs(jlev)=ztpp 02302 zzprev=zzprev+(.5*(ztpp+ztprev)*gascon/ga)*log(zsigprev/sigma(jlev)) 02303 ztprev=ztpp 02304 zsigprev=sigma(jlev) 02305 enddo 02306 02307 do jlev=1,NLEV 02308 ztrs(jlev)=ztrs(jlev)/ct 02309 enddo 02310 02311 !****************************************************************** 02312 ! loop to set array zfac - this controls temperature gradients as a 02313 ! function of sigma in tres. it is a sine wave from one at 02314 ! sigma = 1 to zero at stps (sigma at the tropopause) . 02315 !****************************************************************** 02316 ! first find sigma at dtrop 02317 ! 02318 zttrop=tgr-dtrop*alr 02319 ztps=(zttrop/tgr)**(ga/(alr*gascon)) 02320 ! 02321 ! now the latitudinal variation in tres is set up ( this being in terms 02322 ! of a deviation from t0 which is usually constant with height) 02323 ! 02324 zsqrt2 = sqrt(2.0) 02325 zsqrt04 = sqrt(0.4) 02326 zsqrt6 = sqrt(6.0) 02327 do 2100 jlev=1,NLEV 02328 zfac(jlev)=sin(0.5*PI*(sigma(jlev)-ztps)/(1.-ztps)) 02329 if (zfac(jlev).lt.0.0) zfac(jlev)=0.0 02330 sr1(1,jlev)=zsqrt2*(ztrs(jlev)-t0(jlev)) 02331 sr2(3,jlev)=(1./zsqrt6)*dtns*zfac(jlev) 02332 sr1(5,jlev)=-2./3.*zsqrt04*dtep*zfac(jlev) 02333 2100 continue 02334 write(nud,*) '**************************************************' 02335 write(nud,*) '* Restoration Temperature set up for aqua planet *' 02336 write(nud,*) '**************************************************' 02337 return 02338 end 02339 02340 ! ======================= 02341 ! SUBROUTINE PRINTPROFILE 02342 ! ======================= 02343 02344 subroutine printprofile 02345 use pumamod 02346 02347 ! ********************************** 02348 ! * write out vertical information * 02349 ! ********************************** 02350 02351 write(nud,9001) 02352 write(nud,9002) 02353 write(nud,9003) 02354 write(nud,9002) 02355 02356 do jlev=1,NLEV 02357 zt = (sr1(1,jlev)/sqrt(2.0) + t0(jlev)) * ct 02358 if (tauf(jlev) > 0.1) then 02359 write(nud,9004) jlev,sigma(jlev),zt,taur(jlev),tauf(jlev) 02360 else 02361 write(nud,9005) jlev,sigma(jlev),zt,taur(jlev) 02362 endif 02363 enddo 02364 02365 write(nud,9002) 02366 write(nud,9001) 02367 return 02368 9001 format(/) 02369 9002 format(36('*')) 02370 9003 format('* Lv * Sigma Restor-T tauR tauF *') 02371 9004 format('*',i3,' * ',f8.3,f9.3,2f5.1,' *') 02372 9005 format('*',i3,' * ',f8.3,f9.3,f5.1,' - *') 02373 end 02374 02375 02376 ! ==================== 02377 ! SUBROUTINE READ_SURF 02378 ! ==================== 02379 02380 subroutine read_surf(kcode,psp,klev,kread) 02381 use pumamod 02382 02383 logical :: lexist 02384 integer :: kread 02385 integer :: ihead(8) 02386 character(len=256) :: yfilename 02387 real :: psp(NESP,klev) 02388 real :: zgp(NUGP,klev) 02389 real :: zpp(NHOR,klev) 02390 02391 kread = 0 02392 if (mypid == NROOT) then 02393 if (NLAT < 1000) then 02394 write(yfilename,'("N",I3.3,"_surf_",I4.4,".sra")') NLAT,kcode 02395 else 02396 write(yfilename,'("N",I4.4,"_surf_",I4.4,".sra")') NLAT,kcode 02397 endif 02398 inquire(file=yfilename,exist=lexist) 02399 endif 02400 call mpbcl(lexist) 02401 if (.not. lexist) return 02402 02403 if (mypid == NROOT) then 02404 open(65,file=yfilename,form='formatted') 02405 write(nud,*) 'Reading file <',trim(yfilename),'>' 02406 do jlev = 1 , klev 02407 read (65,*) ihead(:) 02408 read (65,*) zgp(:,jlev) 02409 enddo 02410 close(65) 02411 if (kcode == 134) then 02412 write(nud,*) "Converting Ps to LnPs" 02413 zscale = log(100.0) - log(psurf) ! Input [hPa] / PSURF [Pa] 02414 zgp(:,:) = log(zgp(:,:)) + zscale 02415 endif 02416 call reg2alt(zgp,klev) 02417 endif ! (mypid == NROOT) 02418 call mpscgp(zgp,zpp,klev) 02419 call gp2fc(zpp,NLON,NLPP*klev) 02420 do jlev = 1 , klev 02421 call fc2sp(zpp(1,jlev),psp(1,jlev)) 02422 enddo 02423 call mpsum(psp,klev) 02424 kread = 1 02425 return 02426 end subroutine read_surf 02427 02428 02429 02430 ! ===================== 02431 ! SUBROUTINE READ_VARGP 02432 ! ===================== 02433 02434 subroutine read_vargp(kcode,klev,kread) 02435 use pumamod 02436 02437 logical :: lexist 02438 integer :: ihead(8) 02439 character(len=256) :: yfilename 02440 real :: zgp(NUGP,klev) 02441 02442 kread = 0 02443 if (mypid == NROOT) then 02444 if (NLAT < 1000) then 02445 write(yfilename,'("N",I3.3,"_surf_",I4.4,".sra")') NLAT,kcode 02446 else 02447 write(yfilename,'("N",I4.4,"_surf_",I4.4,".sra")') NLAT,kcode 02448 endif 02449 inquire(file=yfilename,exist=lexist) 02450 endif 02451 call mpbcl(lexist) 02452 if (.not. lexist) then 02453 if (mypid == NROOT) then 02454 write(nud,*) 'File <',trim(yfilename),'> not found' 02455 endif 02456 return 02457 endif 02458 02459 if (mypid == NROOT) then 02460 open(65,file=yfilename,form='formatted') 02461 write(nud,*) 'Reading file <',trim(yfilename),'>' 02462 do jlev = 1 , klev 02463 read (65,*) ihead(:) 02464 read (65,*) zgp(:,jlev) 02465 enddo 02466 close(65) 02467 call reg2alt(zgp,klev) 02468 endif ! (mypid == NROOT) 02469 02470 select case(kcode) 02471 case(121) 02472 !--- non-dimensionalize and shift const radiative rest. temp. 02473 if (mypid == NROOT) then 02474 zgp(:,:) = zgp(:,:)/ct 02475 do jhor = 1,nugp 02476 zgp(jhor,:) = zgp(jhor,:) - t0(:) 02477 enddo 02478 endif 02479 allocate(gr1(nhor,klev)) 02480 if (mypid == NROOT) then 02481 write(nud,*) 'Field gr1 allocated' 02482 endif 02483 call mpscgp(zgp,gr1,klev) 02484 case(122) 02485 !--- non-dimensionalize variable. radiative rest. temp. 02486 if (mypid == NROOT) then 02487 zgp(:,:) = zgp(:,:)/ct 02488 endif 02489 allocate(gr2(nhor,klev)) 02490 if (mypid == NROOT) then 02491 write(nud,*) 'Field gr2 allocated' 02492 endif 02493 call mpscgp(zgp,gr2,klev) 02494 case(123) 02495 !--- non-dimensionalize radiative relaxation time scale 02496 if (mypid == NROOT) then 02497 zgp(:,:) = zgp(:,:)/ww 02498 endif 02499 allocate(gtdamp(nhor,klev)) 02500 if (mypid == NROOT) then 02501 write(nud,*) 'Field gtdamp allocated' 02502 endif 02503 call mpscgp(zgp,gtdamp,klev) 02504 case(124) 02505 !--- non-dimensionalize and shift const. convective rest. temp. 02506 if (mypid == NROOT) then 02507 zgp(:,:) = zgp(:,:)/ct 02508 do jhor = 1,nugp 02509 zgp(jhor,:) = zgp(jhor,:) - t0(:) 02510 enddo 02511 endif 02512 allocate(gr1c(nhor,klev)) 02513 if (mypid == NROOT) then 02514 write(nud,*) 'Field gr1c allocated' 02515 endif 02516 call mpscgp(zgp,gr1c,klev) 02517 case(125) 02518 !--- non-dimensionalize variable. convective rest. temp. 02519 if (mypid == NROOT) then 02520 zgp(:,:) = zgp(:,:)/ct 02521 endif 02522 allocate(gr2c(nhor,klev)) 02523 if (mypid == NROOT) then 02524 write(nud,*) 'Field gr2c allocated' 02525 endif 02526 call mpscgp(zgp,gr2c,klev) 02527 case(126) 02528 !--- non-dimensionalize convective relaxation time scale 02529 if (mypid == NROOT) then 02530 zgp(:,:) = zgp(:,:)/ww 02531 endif 02532 allocate(gtdampc(nhor,klev)) 02533 if (mypid == NROOT) then 02534 write(nud,*) 'Field gtdampc allocated' 02535 endif 02536 call mpscgp(zgp,gtdampc,klev) 02537 end select 02538 kread = 1 02539 return 02540 end subroutine read_vargp 02541 02542 ! =============== 02543 ! SUBROUTINE DIAG 02544 ! =============== 02545 02546 subroutine diag 02547 use pumamod 02548 if (noutput > 0 .and. mod(nstep,ndiag) == 0) then 02549 if (ncoeff > 0) call prisp 02550 call xsect 02551 endif 02552 call energy 02553 return 02554 end 02555 02556 ! ================ 02557 ! SUBROUTINE PRISP 02558 ! ================ 02559 02560 subroutine prisp 02561 use pumamod 02562 02563 character(30) :: title 02564 02565 scale = 100.0 02566 title = 'Vorticity [10-2]' 02567 do 100 jlev=1,NLEV 02568 if (ndil(jlev).ne.0) call wrspam(sz(1,jlev),jlev,title,scale) 02569 100 continue 02570 02571 title = 'Divergence [10-2]' 02572 do 200 jlev=1,NLEV 02573 if (ndil(jlev).ne.0) call wrspam(sd(1,jlev),jlev,title,scale) 02574 200 continue 02575 02576 scale = 1000.0 02577 title = 'Temperature [10-3]' 02578 do 300 jlev=1,NLEV 02579 if (ndil(jlev).ne.0) call wrspam(st(1,jlev),jlev,title,scale) 02580 300 continue 02581 02582 title = 'Pressure [10-3]' 02583 call wrspam(sp,0,title,scale) 02584 02585 return 02586 end 02587 02588 ! ==================== 02589 ! SUBROUTINE POWERSPEC 02590 ! ==================== 02591 02592 subroutine powerspec(pf,pspec) 02593 use pumamod 02594 real :: pf(2,NCSP) 02595 real :: pspec(NTP1) 02596 02597 do j = 1 , NTP1 02598 pspec(j) = 0.5 * (pf(1,j) * pf(1,j) + pf(2,j) * pf(2,j)) 02599 enddo 02600 02601 j = NTP1 + 1 02602 do m = 2 , NTP1 02603 do l = m , NTP1 02604 pspec(l) = pspec(l) + pf(1,j) * pf(1,j) + pf(2,j) * pf(2,j) 02605 j = j + 1 02606 enddo 02607 enddo 02608 return 02609 end 02610 02611 ! ===================== 02612 ! SUBROUTINE POWERPRINT 02613 ! ===================== 02614 02615 subroutine powerprint(text,pspec) 02616 use pumamod 02617 character(3) :: text 02618 real :: pspec(NTP1) 02619 02620 zmax = maxval(pspec(:)) 02621 if (zmax <= 1.0e-20) return 02622 zsca = 10 ** (4 - int(log10(zmax))) 02623 write(nud,1000) text,(int(pspec(j)*zsca),j=2,13) 02624 return 02625 1000 format('* Power(',a3,') ',i8,11i5,' *') 02626 end 02627 02628 02629 02630 02631 ! ============== 02632 ! FUNCTION RMSSP 02633 ! ============== 02634 02635 function rmssp(pf) 02636 use pumamod 02637 real pf(NESP,NLEV) 02638 02639 zsum = 0.0 02640 do jlev = 1 , NLEV 02641 zsum = zsum + dsigma(jlev)& 02642 & * (dot_product(pf(1:NZOM,jlev),pf(1:NZOM,jlev)) * 0.5& 02643 & + dot_product(pf(NZOM+1:NRSP,jlev),pf(NZOM+1:NRSP,jlev))) 02644 enddo 02645 rmssp = zsum 02646 return 02647 end 02648 02649 ! ================= 02650 ! SUBROUTINE ENERGY 02651 ! ================= 02652 02653 subroutine energy 02654 use pumamod 02655 02656 parameter (idim=5) ! Number of scalars for GUI timeseries 02657 02658 ! calculates various global diagnostic quantities 02659 ! remove planetary vorticity so sz contains relative vorticity 02660 02661 real :: spec(NTP1) 02662 real (kind=4) ziso(idim) 02663 02664 sz(3,:) = sz(3,:) - plavor 02665 02666 ! *********************************************** 02667 ! calculate means - zpsitot rms vorticity 02668 ! zchitot rms divergence 02669 ! ztmptot rms temperature 02670 ! ztotp ie+pe potential energy 02671 ! zamsp mean surface pressure 02672 ! *********************************************** 02673 02674 zsqrt2 = sqrt(2.0) 02675 zamsp = 1.0 + span(1) / zsqrt2 02676 zst = dot_product(dsigma(:),st(1,:)) / zsqrt2 02677 ztout1 = dot_product(dsigma(:),t0(:)) 02678 02679 ztout2 = 0.0 02680 zst2b = 0.0 02681 ztoti = 0.0 02682 do jlev = 1 , NLEV 02683 ztout2 = ztout2 + dsigma(jlev) * t0(jlev) * t0(jlev) 02684 zst2b = zst2b + dsigma(jlev) * t0(jlev) * st(1,jlev) 02685 ztoti = ztoti + dsigma(jlev)& 02686 & * (dot_product(span(1:NZOM),st(1:NZOM,jlev)) * 0.5& 02687 & + dot_product(span(NZOM+1:NRSP),st(NZOM+1:NRSP,jlev))) 02688 enddo 02689 02690 ztotp = dot_product(span(1:NZOM),so(1:NZOM)) * 0.5& 02691 & + dot_product(span(NZOM+1:NRSP),so(NZOM+1:NRSP))& 02692 & + so(1)/zsqrt2 + (zamsp*ztout1+ztoti+zst) / akap 02693 02694 zpsitot = sqrt(rmssp(sz)) 02695 zchitot = sqrt(rmssp(sd)) 02696 ztmptot = sqrt(rmssp(st)+ztout2+zst2b*zsqrt2) 02697 02698 ziso(1) = ct * (spnorm(1) * st(1,NLEV) + t0(NLEV)) - 273.16 ! T(NLEV) [C] 02699 ziso(2) = ww * zchitot * 1.0e6 02700 ziso(3) = ztmptot 02701 ziso(4) = ztotp 02702 ziso(5) = sz(3,2) 02703 call guiput("SCALAR" // char(0) ,ziso,idim,1,1) 02704 02705 ! restore sz to absolute vorticity 02706 02707 sz(3,:) = sz(3,:) + plavor 02708 02709 if (mod(nstep,ndiag) /= 0) return ! was called for GUI only 02710 write(nud,9001) 02711 write(nud,9002) nstep,zpsitot,zchitot,ztmptot,ztotp,zamsp 02712 write(nud,9002) 02713 write(nud,9011) (j,j=1,12) 02714 write(nud,9012) 02715 call powerspec(span,spec) 02716 call powerprint('Pre',spec) 02717 call powerspec(sz(1,NLEV),spec) 02718 call powerprint('Vor',spec) 02719 call powerspec(sd(1,NLEV),spec) 02720 call powerprint('Div',spec) 02721 call powerspec(st(1,NLEV),spec) 02722 call powerprint('Tem',spec) 02723 return 02724 9001 format(/, 02725 ' nstep rms z rms d rms t & & pe+ie msp') 02726 9002 format(i10,4x,4g12.5,g15.8) 02727 !9009 format('*',75(' '),' *') 02728 !9010 format('* Power(',a,') ',7e9.2,' *') 02729 9011 format('* Wavenumber ',i8,11i5,' *') 02730 9012 format('',78('*')) 02731 end 02732 02733 ! ================= 02734 ! SUBROUTINE NTOMIN 02735 ! ================= 02736 02737 subroutine ntomin(kstep,imin,ihou,iday,imon,iyea) 02738 use pumamod 02739 istep = kstep ! day [0-29] month [0-11] 02740 if (istep .lt. 0) istep = 0 ! min [0-59] hour [0-23] 02741 imin = mod(istep,ntspd) * 1440 / ntspd ! minutes of current day 02742 ihou = imin / 60 ! hours of current day 02743 imin = imin - ihou * 60 ! minutes of current hour 02744 iday = istep / ntspd ! days in this run 02745 imon = iday / 30 ! months in this run 02746 iday = iday - imon * 30 ! days of current month 02747 iyea = imon / 12 ! years in this run 02748 imon = imon - iyea * 12 ! month of current year 02749 iday = iday + 1 02750 imon = imon + 1 02751 iyea = iyea + 1 02752 return 02753 end 02754 02755 ! ================= 02756 ! SUBROUTINE NTODAT 02757 ! ================= 02758 02759 subroutine ntodat(istep,datch) 02760 character(18) :: datch 02761 character(3) :: mona(12) 02762 data mona /'Jan','Feb','Mar','Apr','May','Jun',& 02763 & 'Jul','Aug','Sep','Oct','Nov','Dec'/ 02764 call ntomin(istep,imin,ihou,iday,imon,iyea) 02765 write(datch,20030) iday,mona(imon),iyea,ihou,imin 02766 20030 format(i2,'-',a3,'-',i4.4,2x,i2,':',i2.2) 02767 end 02768 02769 02770 ! ================= 02771 ! SUBROUTINE WRSPAM 02772 ! ================= 02773 02774 subroutine wrspam(ps,klev,title,scale) 02775 use pumamod 02776 ! 02777 dimension ps(NRSP) 02778 character(30) :: title 02779 character(18) :: datch 02780 02781 ! cab(i)=real(scale*sqrt(ps(i+i-1)*ps(i+i-1)+ps(i+i)*ps(i+i))) 02782 02783 call ntodat(nstep,datch) 02784 write(nud,'(1x)') 02785 write(nud,20000) 02786 write(nud,20030) datch,title,klev 02787 write(nud,20000) 02788 write(nud,20020) (i,i=0,9) 02789 write(nud,20000) 02790 write(nud,20100) (cab(i),i=1,10) 02791 write(nud,20200) (cab(i),i=NTRU+2,NTRU+10) 02792 write(nud,20300) (cab(i),i=2*NTRU+2,2*NTRU+9) 02793 write(nud,20400) (cab(i),i=3*NTRU+1,3*NTRU+7) 02794 write(nud,20000) 02795 write(nud,'(1x)') 02796 02797 20000 format(78('*')) 02798 20020 format('* n * ',10i7,' *') 02799 20030 format('* * ',a18,2x,a30,' Level ',i2,11x,'*') 02800 20100 format('* 0 *',f8.2,9f7.2,' *') 02801 20200 format('* 1 *',8x,9f7.2,' *') 02802 20300 format('* 2 *',15x,8f7.2,' *') 02803 20400 format('* 3 *',22x,7f7.2,' *') 02804 contains 02805 function cab(i) 02806 cab = scale * sqrt(ps(i+i-1)*ps(i+i-1)+ps(i+i)*ps(i+i)) 02807 end function cab 02808 end 02809 02810 ! =============== 02811 ! SUBROUTINE WRZS 02812 ! =============== 02813 02814 subroutine wrzs(zs,title,scale) 02815 use pumamod 02816 ! 02817 dimension zs(NLAT,NLEV) 02818 character(30) :: title 02819 character(18) :: datch 02820 02821 ip = NLAT / 16 02822 ia = ip/2 02823 ib = ia + 7 * ip 02824 id = NLAT + 1 - ia 02825 ic = id - 7 * ip 02826 02827 call ntodat(nstep,datch) 02828 write(nud,'(1x)') 02829 write(nud,20000) 02830 write(nud,20030) datch,title 02831 write(nud,20000) 02832 write(nud,20020) (chlat(i),i=ia,ib,ip),(chlat(j),j=ic,id,ip) 02833 write(nud,20000) 02834 do 200 jlev = 1 , NLEV 02835 write(nud,20100) jlev,((int(zs(i,jlev)*scale)),i=ia,ib,ip),& 02836 & ((int(zs(j,jlev)*scale)),j=ic,id,ip),jlev 02837 200 continue 02838 write(nud,20000) 02839 write(nud,'(1x)') 02840 02841 20000 format(78('*')) 02842 20020 format('* Lv * ',16(1x,a3),' * Lv *') 02843 20030 format('* * ',a18,2x,a30,20x,'*') 02844 20100 format('* ',i2,' * ',16i4,' * ',i2,' *') 02845 end 02846 02847 ! ================ 02848 ! SUBROUTINE XSECT 02849 ! ================ 02850 02851 subroutine xsect 02852 use pumamod 02853 character(30) :: title 02854 02855 scale = 10.0 02856 title = 'Zonal Wind [0.1 m/s]' 02857 call wrzs(csu,title,scale) 02858 title = 'Meridional Wind [0.1 m/s]' 02859 call wrzs(csv,title,scale) 02860 scale = 1.0 02861 title = 'Temperature [C]' 02862 call wrzs(cst,title,scale) 02863 return 02864 end 02865 02866 ! ================== 02867 ! SUBROUTINE WRITESP 02868 ! ================== 02869 02870 subroutine writesp(kunit,pf,kcode,klev,pscale,poff) 02871 use pumamod 02872 real :: pf(NRSP) 02873 real :: zf(NRSP) 02874 integer :: ihead(8) 02875 02876 call ntomin(nstep,nmin,nhour,nday,nmonth,nyear) 02877 02878 ihead(1) = kcode 02879 ihead(2) = klev 02880 ihead(3) = nday + 100 * nmonth + 10000 * nyear 02881 ihead(4) = nmin + 100 * nhour 02882 ihead(5) = NRSP 02883 ihead(6) = 1 02884 ihead(7) = 1 02885 ihead(8) = 0 02886 02887 ! normalize ECHAM compatible and scale to physical dimensions 02888 02889 zf(:) = pf(:) * spnorm(1:NRSP) * pscale 02890 zf(1) = zf(1) + poff ! Add offset if necessary 02891 write(kunit) ihead 02892 write(kunit) zf 02893 02894 return 02895 end 02896 02897 ! ================== 02898 ! SUBROUTINE WRITEGP 02899 ! ================== 02900 02901 subroutine writegp(kunit,pf,kcode,klev) 02902 use pumamod 02903 real :: pf(NHOR) 02904 real :: zf(NUGP) 02905 integer :: ihead(8) 02906 02907 call mpgagp(zf,pf,1) 02908 02909 if (mypid == NROOT) then 02910 call alt2reg(zf,1) 02911 call ntomin(nstep,nmin,nhour,nday,nmonth,nyear) 02912 02913 ihead(1) = kcode 02914 ihead(2) = klev 02915 ihead(3) = nday + 100 * nmonth + 10000 * nyear 02916 ihead(4) = nmin + 100 * nhour 02917 ihead(5) = NLON 02918 ihead(6) = NLAT 02919 ihead(7) = 1 02920 ihead(8) = 0 02921 02922 write(kunit) ihead 02923 write(kunit) zf 02924 endif 02925 02926 return 02927 end 02928 02929 02930 ! ================ 02931 ! SUBROUTINE OUTSP 02932 ! ================ 02933 02934 subroutine outsp 02935 use pumamod 02936 real zsr(NESP) 02937 02938 if (nwrioro == 1) then 02939 call writesp(40,so,129,0,cv*cv,0.0) 02940 nwrioro = 0 02941 endif 02942 02943 if (nextout == 1) then 02944 call writesp(40,sp2,40,0,1.0,log(psmean)) 02945 call writesp(40,sp1,41,0,1.0,log(psmean)) 02946 do jlev = 1,NLEV 02947 call writesp(40,st2(1,jlev),42,jlev,ct,t0(jlev)*ct) 02948 enddo 02949 do jlev = 1,NLEV 02950 call writesp(40,st1(1,jlev),43,jlev,ct,t0(jlev)*ct) 02951 enddo 02952 endif 02953 02954 ! ************ 02955 ! * pressure * 02956 ! ************ 02957 02958 call writesp(40,sp,152,0,1.0,log(psmean)) 02959 02960 ! *************** 02961 ! * temperature * 02962 ! *************** 02963 02964 do jlev = 1 , NLEV 02965 call writesp(40,st(1,jlev),130,jlev,ct,t0(jlev)*ct) 02966 enddo 02967 02968 ! ******************** 02969 ! * res. temperature * 02970 ! ******************** 02971 02972 zampl = cos((real(nstep)-pac)*tac) 02973 do jlev = 1 , NLEV 02974 zsr(:)=sr1(:,jlev)+sr2(:,jlev)*zampl 02975 call writesp(40,zsr,154,jlev,ct,t0(jlev)*ct) 02976 enddo 02977 02978 ! ************** 02979 ! * divergence * 02980 ! ************** 02981 02982 do jlev = 1 , NLEV 02983 call writesp(40,sd(1,jlev),155,jlev,ww,0.0) 02984 enddo 02985 02986 ! ************* 02987 ! * vorticity * 02988 ! ************* 02989 02990 do jlev = 1 , NLEV 02991 zsave = sz(3,jlev) 02992 sz(3,jlev) = sz(3,jlev) - plavor 02993 call writesp(40,sz(1,jlev),138,jlev,ww,0.0) 02994 sz(3,jlev) = zsave 02995 enddo 02996 02997 return 02998 end 02999 03000 ! ================ 03001 ! SUBROUTINE OUTGP 03002 ! ================ 03003 03004 subroutine outgp 03005 use pumamod 03006 real zhelp(NHOR) 03007 ! 03008 ! energy diagnostics 03009 ! 03010 if(nenergy > 0) then 03011 do je=1,9 03012 jcode=300+je 03013 zhelp(:)=denergy(:,je) 03014 call writegp(40,zhelp,jcode,0) 03015 enddo 03016 endif 03017 if(nentropy > 0) then 03018 do je=1,9 03019 jcode=310+je 03020 zhelp(:)=dentropy(:,je) 03021 call writegp(40,zhelp,jcode,0) 03022 enddo 03023 endif 03024 ! 03025 return 03026 end 03027 03028 03029 ! ==================== 03030 ! SUBROUTINE CHECKUNIT 03031 ! ==================== 03032 03033 subroutine checkunit 03034 use pumamod 03035 03036 write(ncu,1000) nstep,'sp( 1 )',sp(1),sp(1)*spnorm(1)+log(psmean) 03037 write(ncu,1000) nstep,'st( 1,1)',st(1,1),st(1,1)*spnorm(1)*ct+t0(1)*ct 03038 write(ncu,1000) nstep,'sd( 1,1)',sd(1,1),sd(1,1)*spnorm(1)*ww 03039 write(ncu,1000) nstep,'sz( 1,1)',sz(1,1),sz(1,1)*spnorm(1)*ww 03040 03041 write(ncu,1000) nstep,'st( 1,NLEV)',st(1,NLEV),st(1,NLEV)*spnorm(1)*ct+t0(5)*ct 03042 write(ncu,1000) nstep,'sd( 1,NLEV)',sd(1,NLEV),sd(1,NLEV)*spnorm(1)*ww 03043 write(ncu,1000) nstep,'sz( 1,NLEV)',sz(1,NLEV),sz(1,NLEV)*spnorm(1)*ww 03044 03045 if (100 < NRSP) then 03046 write(ncu,1000) nstep,'sp(100 )',sp(100),sp(100)*spnorm(100) 03047 write(ncu,1000) nstep,'st(100,NLEV)',st(100,NLEV),st(100,NLEV)*spnorm(100)*ct 03048 write(ncu,1000) nstep,'sd(100,NLEV)',sd(100,NLEV),sd(100,NLEV)*spnorm(100)*ww 03049 write(ncu,1000) nstep,'sz(100,NLEV)',sz(100,NLEV),sz(100,NLEV)*spnorm(100)*ww 03050 endif 03051 03052 return 03053 1000 format(i5,1x,a,1x,2f14.7) 03054 end 03055 03056 03057 ! ===================== 03058 ! * SUBROUTINE LEGPRI * 03059 ! ===================== 03060 03061 subroutine legpri 03062 use pumamod 03063 03064 write(nud,231) 03065 write(nud,232) 03066 write(nud,233) 03067 write(nud,232) 03068 do 14 jlat = 1 , NLAT 03069 zalat = asin(sid(jlat))*180.0/PI 03070 write(nud,234) jlat,zalat,csq(jlat),gwd(jlat) 03071 14 continue 03072 write(nud,232) 03073 write(nud,231) 03074 return 03075 231 format(/) 03076 232 format(37('*')) 03077 233 format('* No * Lat * csq weight *') 03078 234 format('*',i4,' *',f6.1,' *',2f10.4,' *') 03079 end 03080 03081 03082 ! ================= 03083 ! SUBROUTINE INILAT 03084 ! ================= 03085 03086 subroutine inilat 03087 use pumamod 03088 real (kind=8) :: zcsq 03089 03090 do jlat = 1 , NLAT 03091 zcsq = 1.0 - sid(jlat) * sid(jlat) 03092 csq(jlat) = zcsq 03093 rcs(jlat) = 1.0 / sqrt(zcsq) 03094 enddo 03095 do jlat = 1 , NLAT/2 03096 ideg = nint(180.0/PI * asin(sid(jlat))) 03097 write(chlat(jlat),'(i2,a1)') ideg,'N' 03098 write(chlat(NLAT+1-jlat),'(i2,a1)') ideg,'S' 03099 enddo 03100 return 03101 end 03102 03103 03104 ! ==================== 03105 ! SUBROUTINE GRIDPOINT 03106 ! ==================== 03107 03108 subroutine gridpoint 03109 use pumamod 03110 03111 real gtn(NLON,NLPP,NLEV) 03112 real gvpp(NHOR) 03113 real gpmt(NLON,NLPP) 03114 real sdf(NESP,NLEV) 03115 real stf(NESP,NLEV) 03116 real szf(NESP,NLEV) 03117 real spf(NESP) 03118 real zgp(NLON,NLAT) 03119 real zgpp(NHOR) 03120 real (kind=4) :: zcs(NLAT,NLEV) 03121 real (kind=4) :: zsp(NRSP) 03122 03123 do jlev = 1 , NLEV 03124 call sp2fc(sd(1,jlev),gd(1,jlev)) 03125 call sp2fc(st(1,jlev),gt(1,jlev)) 03126 call sp2fc(sz(1,jlev),gz(1,jlev)) 03127 enddo 03128 03129 call sp2fc(sp,gp) ! LnPs 03130 call sp2fcdmu(sp,gpj) ! d(lnps) / d(mu) 03131 ! divergence, vorticity -> u*cos(phi), v*cos(phi) 03132 do jlev = 1 , NLEV 03133 call dv2uv(sd(1,jlev),sz(1,jlev),gu(1,jlev),gv(1,jlev)) 03134 enddo 03135 if (lselect) then 03136 call filter_zonal_waves(gp) 03137 call filter_zonal_waves(gpj) 03138 do jlev = 1 , NLEV 03139 call filter_zonal_waves(gu(1,jlev)) 03140 call filter_zonal_waves(gv(1,jlev)) 03141 call filter_zonal_waves(gd(1,jlev)) 03142 call filter_zonal_waves(gt(1,jlev)) 03143 call filter_zonal_waves(gz(1,jlev)) 03144 enddo 03145 endif 03146 03147 if (ngui > 0 .or. mod(nstep,ndiag) == 0) then 03148 do jlev = 1 , NLEV 03149 do jlat = 1 , NLPP 03150 sec = cv / sqrt(csq(jlat)) 03151 csu(jlat,jlev) = gu(1+(jlat-1)*NLON,jlev) * sec 03152 csv(jlat,jlev) = gv(1+(jlat-1)*NLON,jlev) * sec 03153 cst(jlat,jlev) =(gt(1+(jlat-1)*NLON,jlev) + t0(jlev))*ct-273.16 03154 enddo 03155 enddo 03156 endif 03157 03158 do jlat = 1 , NLPP 03159 do jlon = 1 , NLON-1 , 2 03160 gpmt(jlon ,jlat) = -gp(jlon+1+(jlat-1)*NLON) * ((jlon-1)/2) 03161 gpmt(jlon+1,jlat) = gp(jlon +(jlat-1)*NLON) * ((jlon-1)/2) 03162 end do 03163 end do 03164 03165 call fc2gp(gu ,NLON,NLPP*NLEV) 03166 call fc2gp(gv ,NLON,NLPP*NLEV) 03167 call fc2gp(gt ,NLON,NLPP*NLEV) 03168 call fc2gp(gd ,NLON,NLPP*NLEV) 03169 call fc2gp(gz ,NLON,NLPP*NLEV) 03170 call fc2gp(gpj,NLON,NLPP) 03171 call fc2gp(gpmt,NLON,NLPP) 03172 03173 call calcgp(gtn,gpmt,gvpp) 03174 03175 gut(:,:) = gu(:,:) * gt(:,:) 03176 gvt(:,:) = gv(:,:) * gt(:,:) 03177 gke(:,:) = gu(:,:) * gu(:,:) + gv(:,:) * gv(:,:) 03178 03179 call gp2fc(gtn ,NLON,NLPP*NLEV) 03180 call gp2fc(gut ,NLON,NLPP*NLEV) 03181 call gp2fc(gvt ,NLON,NLPP*NLEV) 03182 call gp2fc(gfv ,NLON,NLPP*NLEV) 03183 call gp2fc(gfu ,NLON,NLPP*NLEV) 03184 call gp2fc(gke ,NLON,NLPP*NLEV) 03185 call gp2fc(gvpp,NLON,NLPP ) 03186 03187 call fc2sp(gvpp,spf) 03188 03189 if (lselect) then 03190 call filter_zonal_waves(gvpp) 03191 do jlev = 1 , NLEV 03192 call filter_zonal_waves(gtn(1,1,jlev)) 03193 call filter_zonal_waves(gut(1,jlev)) 03194 call filter_zonal_waves(gvt(1,jlev)) 03195 call filter_zonal_waves(gfv(1,jlev)) 03196 call filter_zonal_waves(gfu(1,jlev)) 03197 call filter_zonal_waves(gke(1,jlev)) 03198 enddo 03199 endif 03200 03201 do jlev = 1 , NLEV 03202 call mktend(sdf(1,jlev),stf(1,jlev),szf(1,jlev),gtn(1,1,jlev),& 03203 gfu(1,jlev),gfv(1,jlev),gke(1,jlev),gut(1,jlev),gvt(1,jlev)) 03204 enddo 03205 03206 if (nruido > 0) call stepruido 03207 call mpsumsc(spf,spt,1) 03208 call mpsumsc(stf,stt,NLEV) 03209 call mpsumsc(sdf,sdt,NLEV) 03210 call mpsumsc(szf,szt,NLEV) 03211 03212 if (ngui > 0 .or. mod(nstep,ndiag) == 0) then 03213 call fc2gp(gp,NLON,NLPP) 03214 zgpp(:) = exp(gp) ! LnPs -> Ps 03215 call mpgagp(zgp,zgpp,1) ! zgp = Ps (full grid) 03216 if (ngui > 0) then 03217 call guips(zgp,psmean) 03218 call guigv("GU" // char(0),gu) 03219 call guigv("GV" // char(0),gv) 03220 call guigt(gt) 03221 endif 03222 zgpp(:) = zgpp(:) - 1.0 ! Mean(LnPs) = 0 <-> Mean(Ps) = 1 03223 call gp2fc(zgpp,NLON,NLPP) 03224 call fc2sp(zgpp,span) 03225 03226 call mpsum(span,1) ! span = Ps spectral 03227 call mpgacs(csu) 03228 call mpgacs(csv) 03229 call mpgacs(cst) 03230 if (mypid == NROOT) then 03231 call altcs(csu) 03232 call altcs(csv) 03233 call altcs(cst) 03234 if (ngui > 0) then 03235 zcs(:,:) = csu(:,:) 03236 call guiput("CSU" // char(0) ,zcs ,NLAT,NLEV,1) 03237 zcs(:,:) = csv(:,:) 03238 call guiput("CSV" // char(0) ,zcs ,NLAT,NLEV,1) 03239 zcs(:,:) = cst(:,:) 03240 call guiput("CST" // char(0) ,zcs ,NLAT,NLEV,1) 03241 zsp(:) = span(1:NRSP) 03242 call guiput("SPAN" // char(0) ,zsp ,NCSP,-NTP1,1) 03243 endif 03244 endif 03245 endif 03246 return 03247 end 03248 03249 ! ================= 03250 ! SUBROUTINE CALCGP 03251 ! ================= 03252 subroutine calcgp(gtn,gpm,gvp) 03253 03254 use pumamod 03255 03256 ! Comments by Torben Kunz and Guido Schroeder 03257 03258 ! Compute nonlinear tendencies in grid point space. 03259 ! Hoskins and Simmons 1975 (Q.J.R.Meteorol.Soc.,101,637-655) (HS75) 03260 03261 ! For terms calculated in this routine, see HS75, eqs. (8)-(10) and 03262 ! appendix I: 03263 ! - script Fu, Fv as contributions to script D: gl. arrays gfu, gfv 03264 ! - script T: returned as gtn 03265 ! - script P: returned as gvp 03266 03267 03268 ! parameters (in) 03269 ! --------------- 03270 03271 ! gpm -- d(ln(ps)) / d(lambda) 03272 03273 ! parameters (out) 03274 ! --------------- 03275 03276 ! gtn -- temperature tendency 03277 ! gvp -- vertical integral of (u,v) * grad(ln(ps)) 03278 03279 ! global arrays variable in time 03280 ! ------------------------------ 03281 03282 ! gfu, gfv -- terms Fu, Fv in primitive equations, 03283 ! see HS75 (eqs. (1), (2)) 03284 ! gu, gv -- components u, v of horizontal velocity vector 03285 ! gd -- divergence D 03286 ! gz -- absolute vorticity 03287 ! gt -- temperature deviation T' 03288 03289 ! global arrays constant in time 03290 ! ------------------------------ 03291 03292 ! t0d -- reference temperature difference between two adjacent 03293 ! full levels 03294 ! tkp -- reference temperature times kappa (global parameter AKAP) 03295 ! rdsig -- 1 / (2 * dsigma) 03296 ! rcsq -- 1 / (1 - mu^2) 03297 03298 ! notations used in subsequent comments 03299 ! ------------------------------------- 03300 03301 ! aINTb(A)dsigma :<=> the integral of A over the interval [a,b] 03302 ! with respect to sigma 03303 03304 real gtn(NHOR,NLEV) 03305 real gpm(NHOR) , gvp(NHOR) 03306 real zsdotp(NHOR,NLEM),zsumd(NHOR),zsumvp(NHOR),zsumvpm(NHOR) 03307 real ztpta(NHOR),ztptb(NHOR) 03308 real zvgpg(NHOR,NLEV) 03309 real gtd(NHOR,NLEM) 03310 real gud(NHOR,NLEM) 03311 real gvd(NHOR,NLEM) 03312 03313 ! 1. 03314 ! 1.1 zvgpg: (u,v) * grad(ln(ps)) 03315 03316 do jlev = 1 , NLEV 03317 zvgpg(:,jlev) = rcsq * (gu(:,jlev)*gpm(:)+gv(:,jlev)*gpj(:)) 03318 enddo 03319 03320 ! 1.2 Calculate vertical integral of A = D + (u,v) * grad(ln(ps)), 03321 ! separated into divergence and ln(ps) advection. 03322 ! zsumd : 0INT1(D)dsigma 03323 ! gvp : 0INT1[(u,v) * grad ln(ps)]dsigma 03324 ! zsdotp : 0INTsigma(A)dsigma 03325 03326 zsumd = dsigma(1) * gd(:,1) 03327 gvp = dsigma(1) * zvgpg(:,1) 03328 zsdotp(:,1) = zsumd + gvp 03329 03330 do jlev = 2 , NLEM 03331 zsumd = zsumd + dsigma(jlev) * gd(:,jlev) 03332 gvp = gvp + dsigma(jlev) * zvgpg(:,jlev) 03333 zsdotp(:,jlev) = zsumd + gvp 03334 enddo 03335 03336 zsumd = zsumd + dsigma(NLEV) * gd(:,NLEV) 03337 gvp = gvp + dsigma(NLEV) * zvgpg(:,NLEV) 03338 03339 ! 2. Calculate vertical velocity and vertical advection terms 03340 ! on half levels. 03341 03342 do jlev = 1 , NLEM 03343 zsdotp(:,jlev) = (sigmh(jlev) * (zsumd+gvp) - zsdotp(:,jlev)) 03344 enddo 03345 03346 gtd(:,:) = zsdotp(:,:) * (gt(:,2:NLEV) - gt(:,1:NLEM)) 03347 gud(:,:) = zsdotp(:,:) * (gu(:,2:NLEV) - gu(:,1:NLEM)) 03348 gvd(:,:) = zsdotp(:,:) * (gv(:,2:NLEV) - gv(:,1:NLEM)) 03349 03350 ! 3. Calculate nonlinear contributions to temperature tendency and 03351 ! nonlinear terms Fu, Fv as used in vorticity and 03352 ! divergence equation. 03353 03354 ! 3.1 top level: 03355 03356 ! 3.1.1 zsumvp: 0INTsigma[(u,v) * grad(ln(ps))]dsigma 03357 03358 zsumvp = zvgpg(:,1) * dsigma(1) 03359 03360 ! 3.1.2 Calculation of gtn, gfv and gfu as for inner levels (3.2), 03361 ! but somewhat simplified: 03362 ! a) For the top level the following equation holds in the 03363 ! discretized form: (1/sigma)*0INTsigma(A)dsigma == A 03364 ! (HS75, second equation following eq. (7)). Therefore, 03365 ! (3.2.3) simplifies to -kappa*T' * D and (3.2.4) vanishes. 03366 ! b) Vertical advection terms (gtd, gud, gvd (see section 2) 03367 ! and vertical T0 advection (3.2.6)) vanish at upper 03368 ! boundary (sigma == 0). 03369 03370 gtn(:,1) = (1.0-akap) * gt(:,1) * gd(:,1) - rdsig(1) * (gtd(:,1) & 03371 + t0d(1) * (sigmh(1)*gvp-zsumvp)) 03372 03373 gfv(:,1) = - gu(:,1)*gz(:,1) - gpj(:)*gt(:,1) - rdsig(1)*gvd(:,1) 03374 gfu(:,1) = gv(:,1)*gz(:,1) - gpm(:)*gt(:,1) - rdsig(1)*gud(:,1) 03375 03376 ! 3.2 inner levels: 03377 03378 do jlev = 2 , NLEM 03379 03380 ! 3.2.1 ztpta: (1/sigma)*0INTsigma(A-D)dsigma 03381 ! ztptb: (1/sigma)*0INTsigma(A)dsigma 03382 ! Matrix c contains factors for discretized integration, see 03383 ! HS75 (second equation following eq. (7)). 03384 03385 ztpta = c(1,jlev) * zvgpg(:,1) 03386 ztptb = c(1,jlev) * (zvgpg(:,1) + gd(:,1)) 03387 03388 do jlej = 2 , jlev 03389 ztpta = ztpta + c(jlej,jlev) * zvgpg(:,jlej) 03390 ztptb = ztptb + c(jlej,jlev) * (zvgpg(:,jlej) + gd(:,jlej)) 03391 enddo 03392 03393 zsumvpm = zsumvp 03394 zsumvp = zsumvp + zvgpg(:,jlev) * dsigma(jlev) 03395 03396 ! 3.2.2 D * T' 03397 03398 gtn(:,jlev) = gt(:,jlev) * gd(:,jlev) 03399 03400 ! 3.2.3 kappa*T' * 03401 ! [(u,v)*grad(ln(ps)) - (1/sigma)*0INTsigma(A)dsigma] 03402 03403 gtn(:,jlev) = gtn(:,jlev) & 03404 & + akap * gt(:,jlev) * (zvgpg(:,jlev) - ztptb) 03405 03406 ! 3.2.4 kappa*T0 * 03407 ! [(u,v)*grad(ln(ps)) - (1/sigma)*0INTsigma(A-D)dsigma] 03408 03409 gtn(:,jlev) = gtn(:,jlev) & 03410 & + tkp(jlev) * (zvgpg(:,jlev) - ztpta) 03411 03412 ! 3.2.5 Calculate vertical T' advection on full levels by 03413 ! averaging two half level advection terms (gtd, calculated 03414 ! in section 2). 03415 03416 ! and 03417 03418 ! 3.2.6 Calculate vertical T0 advection on full levels by 03419 ! averaging two half level advection terms. 03420 03421 gtn(:,jlev) = gtn(:,jlev) & 03422 & - rdsig(jlev) * (gtd(:,jlev) + gtd(:,jlev-1) & 03423 & +(sigmh(jlev) * gvp - zsumvp) * t0d(jlev) & 03424 & +(sigmh(jlev-1) * gvp - zsumvpm) * t0d(jlev-1)) 03425 03426 ! 3.2.7 terms Fv, Fu, see HS75 (equations following eq. (5)); 03427 ! vertical advection terms interpolated to full levels by 03428 ! averaging two half level advection terms. 03429 03430 gfv(:,jlev) = - gu(:,jlev)*gz(:,jlev) - gpj(:)*gt(:,jlev) & 03431 & - rdsig(jlev)*(gvd(:,jlev) + gvd(:,jlev-1)) 03432 03433 gfu(:,jlev) = gv(:,jlev)*gz(:,jlev) - gpm(:)*gt(:,jlev) & 03434 & - rdsig(jlev)*(gud(:,jlev) + gud(:,jlev-1)) 03435 enddo 03436 03437 ! 3.3 bottom level 03438 03439 ! 3.3.1 ztpta, ztptb: see 3.2.1 03440 03441 ztpta = c(1,NLEV) * zvgpg(:,1) 03442 ztptb = c(1,NLEV) * (zvgpg(:,1) + gd(:,1)) 03443 03444 do jlej = 2 , NLEV 03445 ztpta = ztpta + c(jlej,NLEV) * zvgpg(:,jlej) 03446 ztptb = ztptb + c(jlej,NLEV) * (zvgpg(:,jlej) + gd(:,jlej)) 03447 enddo 03448 03449 ! 3.3.2 Calculation of gtn, gfv and gfu as for inner levels (3.2), 03450 ! but somewhat simplified: 03451 ! Vertical advection terms (gtd, gud, gvd (see section 2) and 03452 ! vertical T0 advection (3.2.6)) vanish at 03453 ! lower boundary (sigma == 1). 03454 03455 gtn(:,NLEV) = gt(:,NLEV) * gd(:,NLEV) & 03456 & + akap*gt(:,NLEV)*(zvgpg(:,NLEV)-ztptb) & 03457 & + tkp(NLEV)*(zvgpg(:,NLEV)-ztpta) & 03458 & - rdsig(NLEV) * (gtd(:,NLEM) & 03459 & + t0d(NLEM)*(sigmh(NLEM)*gvp-zsumvp)) 03460 03461 gfv(:,NLEV) = -gu(:,NLEV) * gz(:,NLEV) - gpj(:) * gt(:,NLEV) & 03462 & - rdsig(NLEV) * gvd(:,NLEM) 03463 gfu(:,NLEV) = gv(:,NLEV) * gz(:,NLEV) - gpm(:) * gt(:,NLEV) & 03464 & - rdsig(NLEV) * gud(:,NLEM) 03465 03466 ! 3.3.3 Add gaussian noise to T (controlled by nruido) 03467 03468 if (nruido > 0) gtn(:,:) = gtn(:,:) + ruidop(:,:) 03469 03470 return 03471 end 03472 03473 ! =================== 03474 ! SUBROUTINE SPECTRAL 03475 ! =================== 03476 03477 subroutine spectral 03478 use pumamod 03479 03480 !* Add adiabatic and diabatic tendencies - perform leapfrog 03481 03482 ! The adiabatic tendencies are added using the semi implicit scheme 03483 ! Hoskins and Simmons 1975 (Q.J.R.Meteorol.Soc.,101,637-655) (HS75) 03484 ! To compare the code directly with HS75 the following notes might 03485 ! be helpful (in addition to the comments below): 03486 03487 ! Name rule for global arrays <abc>: 03488 ! a : representation (s=spectral, g=grid, z=local) 03489 ! b : variable (p=ln(ps), d=divergence, z=vorticity, t=temperature) 03490 ! c : modifier (m=previous timestep, p=present timestep, t=tendency) 03491 03492 ! global arrays variable in time 03493 ! ------------------------------ 03494 03495 ! spt - pressure tendency HS75 (10) 03496 ! sdt - divergence tendency HS75 ( 8) 03497 ! szt - vorticity tendency 03498 ! stt - temperature tendency HS75 ( 9) 03499 03500 ! spm - pressure at previous timestep 03501 ! sdm - divergence at previous timestep 03502 ! szm - vorticity at previous timestep 03503 ! stm - temperature at previous timestep 03504 03505 ! spp - pressure at present timestep 03506 ! sdp - divergence at present timestep 03507 ! szp - vorticity at present timestep 03508 ! stp - temperature at present timestep 03509 03510 ! global arrays constant in time 03511 ! ------------------------------ 03512 03513 ! sak(NSPP) - = hyper diffusion 03514 ! sop(NSPP) - g* = orography as geopotential 03515 ! srp1(NSPP,NLEV) - Tr = radiative equilibrium temperature (annual mean) 03516 ! srp2(NSPP,NLEV) - Tr = radiative equilibrium temperature (annual cycle) 03517 ! nindex(NSPP) - n = total wavenumber n for spectral modes 03518 ! srcn(NSPP) - 1/Cn = 1.0 / (n * (n+1)) 03519 ! damp(NLEV) 1/tau R = time constant for newtonian cooling 03520 ! fric(NLEV) 1/tau F = time constant for Rayleigh friction 03521 03522 real zpm(NSPP) ! new spm 03523 real zdm(NSPP,NLEV) ! new sdm 03524 real zzm(NSPP,NLEV) ! new szm 03525 real ztm(NSPP,NLEV) ! new stm 03526 real zwp(NSPP) ! timefilter delta pm 03527 real zwd(NSPP,NLEV) ! timefilter delta sd 03528 real zwz(NSPP,NLEV) ! timefilter delta sz 03529 real zwt(NSPP,NLEV) ! timefilter delta st 03530 real zsrp(NSPP) ! restoring temperature (mean + annual cycle) 03531 03532 real zgt(NSPP,NLEV) ! work array 03533 03534 real,allocatable :: zstte(:,:,:) ! temp. tendencies for energy diag. 03535 real,allocatable :: zszte(:,:,:) ! vort. tendencies for energy recycling 03536 real,allocatable :: zsdte(:,:,:) ! div. tendencies for energy recycling 03537 real,allocatable :: zdps(:) ! surf pressure for energy diag 03538 real,allocatable :: zsp(:) ! surf pressure spectral 03539 real,allocatable :: zspf(:) ! surf pressure spectral 03540 real,allocatable :: zspt(:) ! surf pressure tendency 03541 03542 real,allocatable :: zst(:,:) ! temperature for entropy diagnostics 03543 real,allocatable :: zstt(:,:) ! tem. tendencies for entropy diag. 03544 real,allocatable :: ztgp(:,:) ! 03545 real,allocatable :: zdtgp(:,:) ! 03546 real,allocatable :: zsum1(:) 03547 real,allocatable :: zgw(:) 03548 03549 ! 0. Special code for experiments with mode filtering 03550 03551 if (lspecsel) call filter_spectral_modes 03552 03553 ! 1. Initialize local arrays 03554 03555 zpm(:) = spp(:) 03556 zdm(:,:) = sdp(:,:) 03557 zzm(:,:) = szp(:,:) 03558 ztm(:,:) = stp(:,:) 03559 ! 03560 ! allocate diagnostic arrays if needed 03561 ! 03562 if(nenergy > 0 .or. nentropy > 0) then 03563 allocate(zstte(NSPP,NLEV,3)) 03564 endif 03565 if(ndheat > 0) then 03566 allocate(zszte(NSPP,NLEV,2)) 03567 allocate(zsdte(NSPP,NLEV,2)) 03568 endif 03569 ! 03570 ! allocate and compute surface pressure if needed 03571 ! 03572 if(nenergy > 0 .or. nentropy > 0 .or. ndheat > 0) then 03573 allocate(zspt(NSPP)) 03574 allocate(zsp(NSPP)) 03575 endif 03576 03577 ! 2. Calculate divergence on timelevel t (sdt) HS75 (17) 03578 ! which will replace the divergence tendency sdt 03579 ! (semi implicit scheme) 03580 03581 ! The vertical scheme has being changed to the ECMWF scheme 03582 ! (see e.g. Simmons and Burridge 1981, Mon.Wea.Rev.,109,758-766). 03583 ! in this scheme, matrix xlphi (g) differs from that in HS75. 03584 03585 ! z0 : reference temperature To 03586 ! zq : 1.0 / Cn 03587 ! zt : xlphi * script T - To * script P 03588 ! zm : xlphi * T + To * ln(Ps)(t-dt) 03589 03590 ! (note that phi is needed in HS75 (17) and, therefore, 03591 ! the surface geopotential phi* [sop] is added 03592 03593 do jlev=1,NLEV 03594 z0 = t0(jlev) 03595 do jsp=1,NSPP 03596 zq = srcn(jsp) ! 1.0 / (n * (n + 1)) 03597 zt = dot_product(xlphi(:,jlev),stt(jsp,:)) - z0 * spt(jsp) 03598 zm = dot_product(xlphi(:,jlev),stm(jsp,:)) + z0 * spm(jsp) 03599 za = sdt(jsp,jlev) * zq 03600 zb = sdm(jsp,jlev) * zq 03601 zgt(jsp,jlev) = zb + delt * (za + zm + sop(jsp) + zt * delt) 03602 enddo 03603 enddo 03604 03605 ! bm1 is the invers of matrix (1/cn I+B dt**2) (lhs HS75 (17)) 03606 03607 do jlev = 1 , NLEV 03608 do jsp = 1 , NSPP 03609 jn = nindex(jsp) ! total wavenumber n 03610 sdt(jsp,jlev) = dot_product(zgt(jsp,:),bm1(:,jlev,jn)) 03611 enddo 03612 enddo 03613 03614 ! 3. Calculate surface pressure tendency -ln(ps) HS75 (15) 03615 03616 do jlev = 1 , NLEV 03617 spt(:) = spt(:) + dsigma(jlev) * sdt(:,jlev) 03618 enddo 03619 03620 ! 4. Calculate temperature tendency HS75 (14) 03621 03622 do jlev = 1 , NLEV 03623 do jsp = 1 , NSPP 03624 stt(jsp,jlev)=stt(jsp,jlev)-dot_product(xlt(:,jlev),sdt(jsp,:)) 03625 enddo 03626 enddo 03627 03628 ! 5. Add tendencies 03629 03630 spp(:) = spm(:) - delt2 * spt(:) ! spt = -ln(ps) tendency 03631 sdp(:,:) = 2.0 * sdt(:,:) - sdm(:,:) ! sdt = sdm + delt * tend. 03632 szp(:,:) = delt2 * szt(:,:) + szm(:,:) ! vorticity 03633 stp(:,:) = delt2 * stt(:,:) + stm(:,:) ! temperature 03634 03635 if(nenergy > 0) then 03636 zspt(:)=-spt(:) 03637 call mkenerdiag(stm,stt,spm,zspt,denergy(:,1)) 03638 endif 03639 if(nentropy > 0) then 03640 call mkentrodiag(stm,stt,spm,dentropy(:,1)) 03641 endif 03642 03643 ! 6. Calculate newtonian cooling, friction and biharmonic diffusion 03644 ! (srp - stp) * damp = (Tr' -T') / tau R = newtonian cooling 03645 ! srp1 = annual mean component 03646 ! srp2 = annual cycle component 03647 ! sak = diffusion 03648 ! fric = friction 03649 ! zampl = annual cycle 03650 03651 zampl = cos((real(nstep)-pac)*tac) 03652 03653 if (nhelsua == 0 .or. nhelsua == 1) then 03654 do jlev=1,NLEV 03655 zsrp(:)=srp1(:,jlev)+srp2(:,jlev)*zampl 03656 sdt(:,jlev) = sdp(:,jlev) * (sak(1:NSPP) - fric(jlev)) 03657 szt(:,jlev) = szp(:,jlev) * (sak(1:NSPP) - fric(jlev)) 03658 stt(:,jlev) = (zsrp(:) - stp(:,jlev)) * damp(jlev) & 03659 & + stp(:,jlev) * sak(1:NSPP) 03660 if(nenergy > 0) then 03661 zstte(:,jlev,2)=(zsrp(:)-stp(:,jlev))*damp(jlev) 03662 zstte(:,jlev,3)=stp(:,jlev)*sak(1:NSPP) 03663 endif 03664 if(ndheat > 0) then 03665 zsdte(:,jlev,1) = -sdp(:,jlev) * fric(jlev) 03666 zszte(:,jlev,1) = -szp(:,jlev) * fric(jlev) 03667 zsdte(:,jlev,2) = sdp(:,jlev) * sak(1:NSPP) 03668 zszte(:,jlev,2) = szp(:,jlev) * sak(1:NSPP) 03669 endif 03670 enddo 03671 elseif (nhelsua == 2 .or. nhelsua == 3 .or. ndiagp > 0) then 03672 if (ndiagp == 0) then 03673 call heatgp(zampl) ! stt(:,:) = Newtonian cooling 03674 else 03675 call diagp(zampl) ! stt(:,:) = Newtonian cooling 03676 endif 03677 if(nenergy > 0) then 03678 zstte(:,:,2)=stt(:,:) 03679 endif 03680 do jlev=1,NLEV 03681 sdt(:,jlev) = sdp(:,jlev) * (sak(1:NSPP) - fric(jlev)) 03682 szt(:,jlev) = szp(:,jlev) * (sak(1:NSPP) - fric(jlev)) 03683 stt(:,jlev) = stt(:,jlev) + stp(:,jlev) * sak(1:NSPP) 03684 if(nenergy > 0) then 03685 zstte(:,jlev,3)=stp(:,jlev)*sak(1:NSPP) 03686 endif 03687 if(ndheat > 0) then 03688 zsdte(:,jlev,1) = -sdp(:,jlev) * fric(jlev) 03689 zszte(:,jlev,1) = -szp(:,jlev) * fric(jlev) 03690 zsdte(:,jlev,2) = sdp(:,jlev) * sak(1:NSPP) 03691 zszte(:,jlev,2) = szp(:,jlev) * sak(1:NSPP) 03692 endif 03693 enddo 03694 endif 03695 03696 ! Conserve ln(ps) by forcing mode(0,0) to zero 03697 ! Correct vorticity by canceling the friction and diffusion 03698 ! applied to planetary vorticity 03699 ! Only root node processes the first NSPP modes 03700 03701 if(nenergy > 0) then 03702 zspt(:)=0. 03703 call mkenerdiag(stp,zstte(:,:,2),spp,zspt,denergy(:,2)) 03704 call mkenerdiag(stp,zstte(:,:,3),spp,zspt,denergy(:,3)) 03705 endif 03706 if(nentropy > 0) then 03707 call mkentrodiag(stp,zstte(:,:,2),spp,dentropy(:,2)) 03708 call mkentrodiag(stp,zstte(:,:,3),spp,dentropy(:,3)) 03709 endif 03710 if(nenergy > 0 .or. nentropy > 0 .or. ndheat > 0) then 03711 zsp(:)=spp(:) 03712 zstte(:,:,1)=stt(:,:) 03713 endif 03714 03715 if (mypid == NROOT) then 03716 spp(1) = 0.0 03717 spp(2) = 0.0 03718 szt(3,:) = szt(3,:) + plavor * (fric(:) - sak(3)) 03719 if(ndheat > 0) then 03720 zszte(3,:,1) = zszte(3,:,1) + plavor * fric(:) 03721 zszte(3,:,2) = zszte(3,:,2) - plavor * sak(3) 03722 endif 03723 endif 03724 ! 03725 ! 6b) call for vertical diffusion 03726 ! 03727 03728 if(dvdiff > 0.) call vdiff(stp,szp,sdp,stt,szt,sdt) 03729 03730 ! 03731 ! recycle kin energy dissipation 03732 ! 03733 03734 if(ndheat > 0) then 03735 call mkdheat(zszte(:,:,1),zszte(:,:,2) & 03736 & ,zsdte(:,:,1),zsdte(:,:,2),zsp) 03737 endif 03738 03739 03740 if(nenergy > 0 .or. nentropy > 0) then 03741 zstte(:,:,1)=stt(:,:)-zstte(:,:,1) 03742 endif 03743 if(nenergy > 0) then 03744 call mkenerdiag(stp,zstte(:,:,1),zsp,zspt,denergy(:,4)) 03745 endif 03746 if(nentropy > 0) then 03747 zstte(:,:,1)=stt(:,:)-zstte(:,:,1) 03748 call mkentrodiag(stp,zstte(:,:,1),zsp,dentropy(:,4)) 03749 endif 03750 if(nenergy > 0 .or. nentropy > 0) then 03751 zstte(:,:,1)=0. 03752 zspt(:)=(spp(:)-zsp(:))/delt2 03753 endif 03754 if(nenergy > 0) then 03755 call mkenerdiag(stp,zstte(:,:,1),zsp,zspt,denergy(:,8)) 03756 endif 03757 if(nentropy > 0) then 03758 call mkentrodiag(stp,zstte(:,:,1),zsp,dentropy(:,8)) 03759 endif 03760 03761 ! 03762 ! diagnostics of efficiency 03763 ! 03764 03765 if(ndheat > 1) then 03766 zcp=gascon/akap 03767 allocate(zst(NESP,NLEV)) 03768 allocate(zstt(NESP,NLEV)) 03769 allocate(zspf(NESP)) 03770 allocate(ztgp(NHOR,NLEV)) 03771 allocate(zdtgp(NHOR,NLEV)) 03772 allocate(zdps(NHOR)) 03773 allocate(zsum1(4)) 03774 allocate(zgw(NHOR)) 03775 jhor=0 03776 do jlat=1,NHPP 03777 do jlon=1,NLON*2 03778 jhor=jhor+1 03779 zgw(jhor)=gwd(jlat) 03780 enddo 03781 enddo 03782 call mpgallsp(zst,stp,NLEV) 03783 call mpgallsp(zstt,stt,NLEV) 03784 call mpgallsp(zspf,zsp,1) 03785 do jlev = 1 , NLEV 03786 call sp2fc(zst(1,jlev),ztgp(1,jlev)) 03787 call sp2fc(zstt(1,jlev),zdtgp(1,jlev)) 03788 enddo 03789 call sp2fc(zspf,zdps) 03790 call fc2gp(ztgp,NLON,NLPP*NLEV) 03791 call fc2gp(zdtgp,NLON,NLPP*NLEV) 03792 call fc2gp(zdps,NLON,NLPP) 03793 zdps(:)=psurf*exp(zdps(:)) 03794 zsum1(:)=0. 03795 do jlev=1,NLEV 03796 ztgp(:,jlev)=ct*(ztgp(:,jlev)+t0(jlev)) 03797 zdtgp(:,jlev)=ct*ww*zdtgp(:,jlev) 03798 zsum1(1)=zsum1(1)+SUM(zdtgp(:,jlev)*zgw(:) & 03799 & *zcp*zdps(:)/ga*dsigma(jlev) & 03800 & ,mask=(zdtgp(:,jlev) >= 0.)) 03801 zsum1(2)=zsum1(2)+SUM(zdtgp(:,jlev)*zgw(:) & 03802 & *zcp*zdps(:)/ga*dsigma(jlev) & 03803 & ,mask=(zdtgp(:,jlev) < 0.)) 03804 zsum1(3)=zsum1(3)+SUM(zdtgp(:,jlev)/ztgp(:,jlev)*zgw(:) & 03805 & *zcp*zdps(:)/ga*dsigma(jlev) & 03806 & ,mask=(zdtgp(:,jlev) >= 0.)) 03807 zsum1(4)=zsum1(4)+SUM(zdtgp(:,jlev)/ztgp(:,jlev)*zgw(:) & 03808 & *zcp*zdps(:)/ga*dsigma(jlev) & 03809 & ,mask=(zdtgp(:,jlev) < 0.)) 03810 enddo 03811 zsum3=SUM(zgw(:)) 03812 call mpsumbcr(zsum1,4) 03813 call mpsumbcr(zsum3,1) 03814 zsum1(:)=zsum1(:)/zsum3 03815 if(mypid == NROOT) then 03816 ztp=zsum1(1)/zsum1(3) 03817 zztm=zsum1(2)/zsum1(4) 03818 write(9,*) zsum1(:),zsum1(1)/zsum1(3),zsum1(2)/zsum1(4) & 03819 & ,(ztp-zztm)/ztp 03820 endif 03821 deallocate(zst) 03822 deallocate(zstt) 03823 deallocate(zspf) 03824 deallocate(ztgp) 03825 deallocate(zdps) 03826 deallocate(zdtgp) 03827 deallocate(zsum1) 03828 deallocate(zgw) 03829 endif 03830 03831 ! 7. Add newtonian cooling, friction and diffusion tendencies 03832 03833 sdp(:,:) = sdp(:,:) + delt2 * sdt(:,:) 03834 szp(:,:) = szp(:,:) + delt2 * szt(:,:) 03835 stp(:,:) = stp(:,:) + delt2 * stt(:,:) 03836 03837 ! 11. Coupling for synchronization runs 03838 03839 if (mrnum == 2 .and. nsync > 0) then 03840 call mrdiff(stp,std,NESP,NLEV) 03841 call mrdiff(sdp,sdd,NESP,NLEV) 03842 call mrdiff(szp,szd,NESP,NLEV) 03843 call mrdiff(spp,spd,NESP, 1) 03844 stp(:,:) = stp(:,:) + syncstr * std(:,:) 03845 sdp(:,:) = sdp(:,:) + syncstr * sdd(:,:) 03846 szp(:,:) = szp(:,:) + syncstr * szd(:,:) 03847 spp(: ) = spp(: ) + syncstr * spd(: ) 03848 03849 endif 03850 03851 ! 8. Apply Robert Asselin time filter (not for short initial timesteps) 03852 ! d(t) = pnu * f(t-1) + pnu * f(t+1) - 2 * pnu * f(t) 03853 03854 if (nkits == 0) then 03855 zwp(:) = pnu * (spm(:) + spp(:) - 2.0 * zpm(:) ) 03856 zwd(:,:) = pnu * (sdm(:,:) + sdp(:,:) - 2.0 * zdm(:,:)) 03857 zwz(:,:) = pnu * (szm(:,:) + szp(:,:) - 2.0 * zzm(:,:)) 03858 zwt(:,:) = pnu * (stm(:,:) + stp(:,:) - 2.0 * ztm(:,:)) 03859 03860 ! Add Robert-Asselin-Williams filter value to f(t) 03861 03862 spm(:) = zpm(:) + alpha * zwp(:) 03863 sdm(:,:) = zdm(:,:) + alpha * zwd(:,:) 03864 szm(:,:) = zzm(:,:) + alpha * zwz(:,:) 03865 stm(:,:) = ztm(:,:) + alpha * zwt(:,:) 03866 03867 ! Add filter value to f(t+1) 03868 03869 spp(:) = spp(:) - (1.0 - alpha) * zwp(:) 03870 sdp(:,:) = sdp(:,:) - (1.0 - alpha) * zwd(:,:) 03871 szp(:,:) = szp(:,:) - (1.0 - alpha) * zwz(:,:) 03872 stp(:,:) = stp(:,:) - (1.0 - alpha) * zwt(:,:) 03873 endif 03874 03875 if (nenergy > 0 .or. nentropy > 0) then 03876 zstte(:,:,1)=(stm(:,:)-ztm(:,:))/delt2 03877 zspt(:)=(spm(:)-zpm(:))/delt2 03878 endif 03879 if(nenergy > 0) then 03880 call mkenerdiag(ztm,zstte(:,:,1),zpm,zspt,denergy(:,9)) 03881 endif 03882 if (nentropy > 0) then 03883 call mkentrodiag(ztm,zstte(:,:,1),zpm,dentropy(:,9)) 03884 endif 03885 03886 ! 9. Save spectral arrays for extended output 03887 03888 if (nextout == 1 .and. mypid == NROOT) then 03889 if (mod(nstep,nafter) == nafter - 2) then 03890 if (.not. allocated(st2)) allocate(st2(nesp,nlev)) 03891 st2(:,:) = st(:,:) 03892 if (.not. allocated(sp2)) allocate(sp2(nesp)) 03893 sp2(:) = sp(:) 03894 endif 03895 if (mod(nstep,nafter) == nafter - 1) then 03896 if (.not. allocated(st1)) allocate(st1(nesp,nlev)) 03897 st1(:,:) = st(:,:) 03898 if (.not. allocated(sp1)) allocate(sp1(nesp)) 03899 sp1(:) = sp(:) 03900 endif 03901 endif 03902 03903 ! 10. Gather spectral modes from all processes 03904 03905 call mpgallsp(sp,spp, 1) 03906 call mpgallsp(sd,sdp,NLEV) 03907 call mpgallsp(sz,szp,NLEV) 03908 call mpgallsp(st,stp,NLEV) 03909 03910 if(nenergy > 0 .or. nentropy > 0) then 03911 deallocate(zstte) 03912 endif 03913 if(ndheat > 0) then 03914 deallocate(zszte) 03915 deallocate(zsdte) 03916 endif 03917 if(nenergy > 0 .or. nentropy > 0 .or. ndheat > 0) then 03918 deallocate(zsp) 03919 deallocate(zspt) 03920 endif 03921 03922 return 03923 end 03924 03925 subroutine mrcheck(f) 03926 use pumamod 03927 real :: f(*) 03928 write (nud,'(/,i3,8f8.4)') 0,f(1:16:2) 03929 write (nud,'( i3,8f8.4)') 8,f(17:32:2) 03930 write (nud,'( i3,8f8.4)') 16,f(33:48:2) 03931 write (nud,'( i3,8f8.4)') 24,f(49:64:2) 03932 write (nud,'( i3,8f8.4)') 32,f(65:80:2) 03933 return 03934 end 03935 03936 03937 ! ================ 03938 ! SUBROUTINE DIAGP 03939 ! ================ 03940 03941 subroutine diagp(zampl) 03942 use pumamod 03943 03944 real :: zstf(NESP,NLEV) 03945 real :: zgr12(NHOR,NLEV) 03946 real :: zgtt(NHOR,NLEV) 03947 real :: gr12(NHOR,NLEV) 03948 real :: gr12c(NHOR,NLEV) 03949 03950 03951 real :: gdtmp(NHOR) 03952 03953 real :: zampl 03954 03955 !--- transform temperature and divergence to grid point space 03956 call mpgallsp(st,stp,NLEV) 03957 if (nconv > 0) then 03958 call mpgallsp(sd,sdp,NLEV) 03959 endif 03960 do jlev=1,NLEV 03961 call sp2fc(st(1,jlev) ,gt(1,jlev) ) 03962 if (nconv > 0) then 03963 call sp2fc(sd(1,jlev) ,gd(1,jlev) ) 03964 endif 03965 enddo 03966 call fc2gp(gt ,NLON,NLPP*NLEV) 03967 if (nconv > 0) then 03968 call fc2gp(gd ,NLON,NLPP*NLEV) 03969 endif 03970 03971 03972 !--- radiative temperature tendencies 03973 gr12(:,:) = gr1(:,:) + gr2(:,:)*zampl 03974 zgtt(:,:) = (gr12(:,:) - gt(:,:))*gtdamp(:,:) 03975 03976 !--- add convective temperature tendencies 03977 if (nconv > 0) then 03978 gdtmp(:) = gd(:,nlev) 03979 do jlev = 1,nlev 03980 where (gdtmp < 0.0) 03981 gr12c(:,jlev) = gr1c(:,jlev) + gr2c(:,jlev)*zampl 03982 zgtt(:,jlev) = zgtt(:,jlev) + (gr12c(:,jlev) - gt(:,jlev))*gtdampc(:,jlev) 03983 endwhere 03984 enddo 03985 endif 03986 03987 !--- transform temperature tendencies to spectral space 03988 call gp2fc(zgtt ,NLON,NLPP*NLEV) 03989 do jlev=1,NLEV 03990 call fc2sp(zgtt(1,jlev),zstf(1,jlev)) 03991 enddo 03992 call mpsumsc(zstf,stt,NLEV) 03993 03994 return 03995 end subroutine diagp 03996 03997 ! ================= 03998 ! SUBROUTINE HEATGP 03999 ! ================= 04000 04001 subroutine heatgp(zampl) 04002 use pumamod 04003 04004 real :: zsr12(NESP,NLEV) 04005 real :: zsrp12(NSPP,NLEV) 04006 real :: zstf(NESP,NLEV) 04007 real :: zgr12(NHOR,NLEV) 04008 real :: zgtt(NHOR,NLEV) 04009 04010 real :: zampl 04011 04012 zsrp12(:,:)=srp1(:,:)+srp2(:,:)*zampl 04013 call mpgallsp(zsr12,zsrp12,NLEV) 04014 call mpgallsp(st,stp,NLEV) 04015 do jlev=1,NLEV 04016 call sp2fc(zsr12(1,jlev),zgr12(1,jlev)) 04017 call sp2fc(st(1,jlev) ,gt(1,jlev) ) 04018 enddo 04019 call fc2gp(zgr12,NLON,NLPP*NLEV) 04020 call fc2gp(gt ,NLON,NLPP*NLEV) 04021 04022 ! Newtonian cooling 04023 04024 zgtt(:,:) = (zgr12(:,:) - gt(:,:)) * gtdamp(:,:) 04025 04026 call gp2fc(zgtt ,NLON,NLPP*NLEV) 04027 do jlev=1,NLEV 04028 call fc2sp(zgtt(1,jlev),zstf(1,jlev)) 04029 enddo 04030 call mpsumsc(zstf,stt,NLEV) 04031 04032 return 04033 end 04034 04035 ! ================ 04036 ! SUBROUTINE VDIFF 04037 ! ================ 04038 04039 subroutine vdiff(pt,pz,pd,ptt,pzt,pdt) 04040 use pumamod 04041 ! 04042 parameter(ztref=250.) 04043 real pt(NSPP,NLEV),pz(NSPP,NLEV),pd(NSPP,NLEV) 04044 real ptt(NSPP,NLEV),pzt(NSPP,NLEV),pdt(NSPP,NLEV) 04045 real ztn(NSPP,NLEV),zzn(NSPP,NLEV),zdn(NSPP,NLEV) 04046 real zebs(NLEM) 04047 real zskap(NLEV),zskaph(NLEV) 04048 real zkdiff(NLEM) 04049 ! 04050 zdelt=delt2/ww 04051 zkonst1=ga*zdelt/gascon 04052 zkonst2=zkonst1*ga/gascon 04053 ! 04054 zskap(:)=sigma(:)**akap 04055 zskaph(:)=sigmh(:)**akap 04056 ! 04057 ! 1) modified diffusion coefficents 04058 ! 04059 do jlev=1,NLEM 04060 jlp=jlev+1 04061 zkdiff(jlev)=zkonst2*sigmh(jlev)*sigmh(jlev)/(ztref*ztref) & 04062 & *dvdiff/(sigma(jlp)-sigma(jlev)) 04063 enddo 04064 ! 04065 ! 2. semi implicit scheme 04066 ! 04067 ! 2a momentum 04068 ! 04069 ! top layer elimination 04070 ! 04071 zebs(1)=zkdiff(1)/(dsigma(1)+zkdiff(1)) 04072 zdn(:,1)=dsigma(1)*pd(:,1)/(dsigma(1)+zkdiff(1)) 04073 zzn(:,1)=dsigma(1)*pz(:,1)/(dsigma(1)+zkdiff(1)) 04074 ! 04075 ! middle layer elimination 04076 ! 04077 do jlev=2,NLEM 04078 jlem=jlev-1 04079 zebs(jlev)=zkdiff(jlev)/(dsigma(jlev)+zkdiff(jlev) & 04080 & +zkdiff(jlem)*(1.-zebs(jlem))) 04081 zdn(:,jlev)=(pd(:,jlev)*dsigma(jlev)+zkdiff(jlem)*zdn(:,jlem)) & 04082 & /(dsigma(jlev)+zkdiff(jlev) & 04083 & +zkdiff(jlem)*(1.-zebs(jlem))) 04084 zzn(:,jlev)=(pz(:,jlev)*dsigma(jlev)+zkdiff(jlem)*zzn(:,jlem)) & 04085 & /(dsigma(jlev)+zkdiff(jlev) & 04086 & +zkdiff(jlem)*(1.-zebs(jlem))) 04087 enddo 04088 ! 04089 ! bottom layer elimination 04090 ! 04091 zdn(:,NLEV)=(pd(:,NLEV)*dsigma(NLEV)+zkdiff(NLEM)*zdn(:,NLEM)) & 04092 & /(dsigma(NLEV)+zkdiff(NLEM)*(1.-zebs(NLEM))) 04093 zzn(:,NLEV)=(pz(:,NLEV)*dsigma(NLEV)+zkdiff(NLEM)*zzn(:,NLEM)) & 04094 & /(dsigma(NLEV)+zkdiff(NLEM)*(1.-zebs(NLEM))) 04095 ! 04096 ! back-substitution 04097 ! 04098 do jlev=NLEM,1,-1 04099 jlep=jlev+1 04100 zdn(:,jlev)=zdn(:,jlev)+zebs(jlev)*zdn(:,jlep) 04101 zzn(:,jlev)=zzn(:,jlev)+zebs(jlev)*zzn(:,jlep) 04102 enddo 04103 ! 04104 ! tendencies 04105 ! 04106 pdt(:,1:NLEV)=pdt(:,1:NLEV)+(zdn(:,1:NLEV)-pd(:,1:NLEV))/delt2 04107 pzt(:,1:NLEV)=pzt(:,1:NLEV)+(zzn(:,1:NLEV)-pz(:,1:NLEV))/delt2 04108 ! 04109 ! 2c potential temperature 04110 ! 04111 do jlev=1,NLEM 04112 zkdiff(jlev)=zkdiff(jlev)*zskaph(jlev) 04113 enddo 04114 ! 04115 ! semi implicit scheme 04116 ! 04117 ! top layer elimination 04118 ! 04119 zebs(1)=zkdiff(1)/(dsigma(1)+zkdiff(1)/zskap(1)) 04120 ztn(:,1)=dsigma(1)*pt(:,1)/(dsigma(1)+zkdiff(1)/zskap(1)) 04121 ! 04122 ! middle layer elimination 04123 ! 04124 do jlev=2,NLEM 04125 jlem=jlev-1 04126 zebs(jlev)=zkdiff(jlev)/(dsigma(jlev)+(zkdiff(jlev) & 04127 & +zkdiff(jlem)*(1.-zebs(jlem)/zskap(jlem)))/zskap(jlev)) 04128 ztn(:,jlev)=(pt(:,jlev)*dsigma(jlev) & 04129 & +zkdiff(jlem)/zskap(jlem)*ztn(:,jlem)) & 04130 & /(dsigma(jlev)+(zkdiff(jlev) & 04131 & +zkdiff(jlem)*(1.-zebs(jlem)/zskap(jlem))) & 04132 & /zskap(jlev)) 04133 enddo 04134 ! 04135 ! bottom layer elimination 04136 ! 04137 ztn(:,NLEV)=(pt(:,NLEV)*dsigma(NLEV) & 04138 & +zkdiff(NLEM)*ztn(:,NLEM)/zskap(NLEM)) & 04139 & /(dsigma(NLEV)+zkdiff(NLEM)/zskap(NLEV) & 04140 & *(1.-zebs(NLEM)/zskap(NLEM))) 04141 ! 04142 ! back-substitution 04143 ! 04144 do jlev=NLEM,1,-1 04145 jlep=jlev+1 04146 ztn(:,jlev)=ztn(:,jlev)+zebs(jlev)*ztn(:,jlep)/zskap(jlep) 04147 enddo 04148 ! 04149 ! tendencies 04150 ! 04151 ptt(:,1:NLEV)=ptt(:,1:NLEV)+(ztn(:,1:NLEV)-pt(:,1:NLEV))/delt2 04152 ! 04153 return 04154 end subroutine vdiff 04155 04156 ! ================= 04157 ! SUBROUTINE GASDEV 04158 ! ================= 04159 04160 ! Gaussian noise generator with zero mean and unit variance. 04161 04162 real function gasdev() 04163 use pumamod 04164 implicit none 04165 real :: fr, vx, vy, ra 04166 04167 if (ganext == 0.0) then 04168 ra = 2.0 04169 do while (ra >= 1.0 .or. ra < 1.0e-20) 04170 call random_number(vx) 04171 call random_number(vy) 04172 vx = 2.0 * vx - 1.0 04173 vy = 2.0 * vy - 1.0 04174 ra = vx * vx + vy * vy 04175 enddo 04176 fr = sqrt(-2.0 * log(ra) / ra) 04177 gasdev = vx * fr 04178 ganext = vy * fr 04179 else 04180 gasdev = ganext 04181 ganext = 0.0 04182 endif 04183 04184 return 04185 end 04186 04187 ! ================= 04188 ! SUBROUTINE SPONGE 04189 ! ================= 04190 04191 subroutine sponge 04192 use pumamod 04193 04194 real :: zp 04195 04196 ! This introduces a simple sponge layer to the highest model levels 04197 ! by applying Rayleigh friction there, according to 04198 ! Polvani & Kushner (2002, GRL), see their appendix. 04199 04200 write(nud,*) 04201 write(nud,9991) 04202 write(nud,9997) 04203 write(nud,9991) 04204 write(nud,9996) 04205 write(nud,9991) 04206 do jlev=1,NLEV 04207 zp = sigma(jlev)*psurf 04208 if (zp < pspon) then 04209 fric(jlev) = (sponk * ((pspon - zp) / pspon)**2) / TWOPI 04210 endif 04211 04212 ! some output 04213 if (zp > pspon) then 04214 if (fric(jlev) == 0) then 04215 write(nud,9992) jlev 04216 else 04217 write(nud,9993) jlev, fric(jlev)*TWOPI 04218 endif 04219 else 04220 if (fric(jlev) == 0) then 04221 write(nud,9994) jlev 04222 else 04223 write(nud,9995) jlev, fric(jlev)*TWOPI 04224 endif 04225 endif 04226 enddo 04227 write(nud,9991) 04228 write(nud,*) 04229 return 04230 9991 format(33('*')) 04231 9992 format('*',i4,' * ',7('-'),' * *') 04232 9993 format('*',i4,' * ',f7.4,' * *') 04233 9994 format('*',i4,' * ',7('-'),' *',' SPONGE *') 04234 9995 format('*',i4,' * ',f7.4,' *',' SPONGE *') 04235 9996 format('* Lv * [1/day] * *') 04236 9997 format('* Rayleigh damping coefficients *') 04237 end 04238 04239 04240 ! ===================== 04241 ! SUBROUTINE MKENERDIAG 04242 ! ===================== 04243 04244 subroutine mkenerdiag(pst,pstt,psp,pspt,penergy) 04245 use pumamod 04246 ! 04247 real :: pst(NSPP,NLEV),pstt(NSPP,NLEV) 04248 real :: psp(NSPP),pspt(NSPP) 04249 real :: penergy(NHOR) 04250 ! 04251 real :: zsttf(NESP,NLEV),zstf(NESP,NLEV) 04252 real :: zsptf(NESP),zspf(NESP) 04253 real :: zgtt(NHOR,NLEV),zgt(NHOR,NLEV) 04254 real :: zgps(NHOR),zgpst(NHOR) 04255 real :: ztm(NHOR) 04256 ! 04257 zcp=gascon/akap 04258 zdelt=delt2/ww 04259 ! 04260 call mpgallsp(zsttf,pstt,NLEV) 04261 call mpgallsp(zstf,pst,NLEV) 04262 call mpgallsp(zsptf,pspt,1) 04263 call mpgallsp(zspf,psp,1) 04264 04265 do jlev=1,NLEV 04266 call sp2fc(zsttf(:,jlev),zgtt(:,jlev)) 04267 call sp2fc(zstf(:,jlev),zgt(:,jlev)) 04268 enddo 04269 call sp2fc(zsptf,zgpst) 04270 call sp2fc(zspf,zgps) 04271 call fc2gp(zgtt,NLON,NLPP*NLEV) 04272 call fc2gp(zgt,NLON,NLPP*NLEV) 04273 call fc2gp(zgps,NLON,NLPP) 04274 call fc2gp(zgpst,NLON,NLPP) 04275 zgpst(:)=psurf*(exp(zgps(:)+delt2*zgpst(:))-exp(zgps(:)))/zdelt 04276 zgps(:)=psurf*exp(zgps(:))+zdelt*zgpst(:) 04277 zgtt(:,:)=ct*ww*zgtt(:,:) 04278 do jlev=1,NLEV 04279 zgt(:,jlev)=ct*(zgt(:,jlev)+t0(jlev)) 04280 enddo 04281 ! 04282 ztm(:)=0. 04283 penergy(:)=0. 04284 do jlev=1,NLEV 04285 ztm(:)=ztm(:)+zgt(:,jlev)*dsigma(jlev) 04286 penergy(:)=penergy(:)+zgtt(:,jlev)*dsigma(jlev) 04287 enddo 04288 penergy(:)=ztm(:)*zcp*zgpst(:)/ga & 04289 & +penergy(:)*zcp*zgps(:)/ga 04290 ! 04291 return 04292 end 04293 04294 ! ====================== 04295 ! SUBROUTINE MKENTRODIAG 04296 ! ====================== 04297 04298 subroutine mkentrodiag(pst,pstt,psp,pentropy) 04299 use pumamod 04300 ! 04301 real :: pst(NSPP,NLEV),pstt(NSPP,NLEV) 04302 real :: psp(NSPP) 04303 real :: pentropy(NHOR) 04304 ! 04305 real :: zsttf(NESP,NLEV),zstf(NESP,NLEV) 04306 real :: zspf(NESP) 04307 real :: zgtt(NHOR,NLEV),zgt(NHOR,NLEV) 04308 real :: zgps(NHOR) 04309 ! 04310 zcp=gascon/akap 04311 ! 04312 call mpgallsp(zsttf,pstt,NLEV) 04313 call mpgallsp(zstf,pst,NLEV) 04314 call mpgallsp(zspf,psp,1) 04315 04316 do jlev=1,NLEV 04317 call sp2fc(zsttf(:,jlev),zgtt(:,jlev)) 04318 call sp2fc(zstf(:,jlev),zgt(:,jlev)) 04319 enddo 04320 call sp2fc(zspf,zgps) 04321 call fc2gp(zgtt,NLON,NLPP*NLEV) 04322 call fc2gp(zgt,NLON,NLPP*NLEV) 04323 call fc2gp(zgps,NLON,NLPP) 04324 zgps(:)=psurf*exp(zgps(:)) 04325 zgtt(:,:)=ct*ww*zgtt(:,:) 04326 do jlev=1,NLEV 04327 zgt(:,jlev)=ct*(zgt(:,jlev)+t0(jlev)) 04328 enddo 04329 ! 04330 pentropy(:)=0. 04331 do jlev=1,NLEV 04332 pentropy(:)=pentropy(:)+zgtt(:,jlev)*dsigma(jlev)/zgt(:,jlev) 04333 enddo 04334 pentropy(:)=pentropy(:)*zcp*zgps(:)/ga 04335 ! 04336 return 04337 end 04338 04339 ! ================== 04340 ! SUBROUTINE MKDHEAT 04341 ! ================== 04342 04343 subroutine mkdheat(zszt1,zszt2,zsdt1,zsdt2,zsp) 04344 use pumamod 04345 ! 04346 ! 'recycle' kin. energy loss by heating the environment 04347 ! 04348 ! zszt1/zsdt1 : vorticity/divergence tendency due to friction 04349 ! zszt2/zsdt2 : vorticity/divergence tendency fue to diffusion 04350 ! zp : surface pressure 04351 ! 04352 real zszt1(NSPP,NLEV),zszt2(NSPP,NLEV) 04353 real zsdt1(NSPP,NLEV),zsdt2(NSPP,NLEV) 04354 real zsp(NSPP) 04355 real zp(NHOR) 04356 ! 04357 real zsd(NESP,NLEV),zsz(NESP,NLEV) 04358 real zspf(NESP),zspt(NSPP) 04359 real zsdp(NSPP,NLEV),zszp(NSPP,NLEV) 04360 real zu(NHOR,NLEV),zun(NHOR,NLEV),zdu1(NHOR,NLEV),zdu2(NHOR,NLEV) 04361 real zv(NHOR,NLEV),zvn(NHOR,NLEV),zdv1(NHOR,NLEV),zdv2(NHOR,NLEV) 04362 real zdtdt1(NHOR,NLEV),zdtdt2(NHOR,NLEV),zdtdt3(NHOR,NLEV) 04363 ! 04364 real zdtdt(NHOR,NLEV),zdekin(NHOR,NLEV) 04365 ! 04366 real zsde(NSPP,NLEV),zsdef(NESP,NLEV) 04367 real zstt(NSPP,NLEV),zstf(NESP,NLEV) 04368 real zstt1(NSPP,NLEV),zstf1(NESP,NLEV),zstt3(NSPP,NLEV) 04369 real zstt2(NSPP,NLEV),zstf2(NESP,NLEV),zstf3(NESP,NLEV) 04370 ! 04371 ! some constants 04372 ! 04373 zdelt=delt2/ww ! timestep in s 04374 zcp=gascon/akap ! heat capacity 04375 ! 04376 ! 'recycle' friction 04377 ! 04378 ! a) gather the 'partial' field of z and d, and make u and v 04379 ! at old time level 04380 ! 04381 zsdp(:,:)=sdp(:,:) 04382 zszp(:,:)=szp(:,:) 04383 call mpgallsp(zsd,zsdp,NLEV) 04384 call mpgallsp(zsz,zszp,NLEV) 04385 do jlev = 1 , NLEV 04386 call dv2uv(zsd(1,jlev),zsz(1,jlev),zu(1,jlev),zv(1,jlev)) 04387 enddo 04388 call fc2gp(zu,NLON,NLPP*NLEV) 04389 call fc2gp(zv,NLON,NLPP*NLEV) 04390 ! 04391 ! b) add fricton tendencies and create new u and v 04392 ! 04393 zsdp(:,:)=sdp(:,:)+zsdt1(:,:)*delt2 04394 zszp(:,:)=szp(:,:)+zszt1(:,:)*delt2 04395 call mpgallsp(zsd,zsdp,NLEV) 04396 call mpgallsp(zsz,zszp,NLEV) 04397 do jlev = 1 , NLEV 04398 call dv2uv(zsd(1,jlev),zsz(1,jlev),zun(1,jlev),zvn(1,jlev)) 04399 enddo 04400 call fc2gp(zun,NLON,NLPP*NLEV) 04401 call fc2gp(zvn,NLON,NLPP*NLEV) 04402 ! 04403 ! c) compute temperature tendency 04404 ! 04405 do jlev=1,NLEV 04406 zu(:,jlev)=cv*zu(:,jlev)*SQRT(rcsq(:)) 04407 zv(:,jlev)=cv*zv(:,jlev)*SQRT(rcsq(:)) 04408 zun(:,jlev)=cv*zun(:,jlev)*SQRT(rcsq(:)) 04409 zvn(:,jlev)=cv*zvn(:,jlev)*SQRT(rcsq(:)) 04410 zdu1(:,jlev)=zun(:,jlev)-zu(:,jlev) 04411 zdv1(:,jlev)=zvn(:,jlev)-zv(:,jlev) 04412 zdtdt1(:,jlev)=-(zun(:,jlev)*zun(:,jlev) & 04413 & -zu(:,jlev)*zu(:,jlev) & 04414 & +zvn(:,jlev)*zvn(:,jlev) & 04415 & -zv(:,jlev)*zv(:,jlev))*0.5/zdelt/zcp 04416 enddo 04417 04418 ! 04419 ! 'recycle' momentum diffusion 04420 ! 04421 ! a) add tendencies and create new u and v and get surface pressure 04422 ! 04423 ! 04424 zsdp(:,:)=sdp(:,:)+zsdt2(:,:)*delt2 04425 zszp(:,:)=szp(:,:)+zszt2(:,:)*delt2 04426 call mpgallsp(zsd,zsdp,NLEV) 04427 call mpgallsp(zsz,zszp,NLEV) 04428 call mpgallsp(zspf,zsp,1) 04429 do jlev = 1 , NLEV 04430 call dv2uv(zsd(1,jlev),zsz(1,jlev),zun(1,jlev),zvn(1,jlev)) 04431 enddo 04432 call fc2gp(zun,NLON,NLPP*NLEV) 04433 call fc2gp(zvn,NLON,NLPP*NLEV) 04434 call sp2fc(zspf,zp) 04435 call fc2gp(zp,NLON,NLPP) 04436 zp(:)=psurf*exp(zp(:)) 04437 ! 04438 ! b) compute loss of kinetic energy 04439 ! (note: only the global average change of kin. e. is 'lost' 04440 ! the other changes are just diffusion) 04441 ! 04442 do jlev = 1 , NLEV 04443 zun(:,jlev)=cv*zun(:,jlev)*SQRT(rcsq(:)) 04444 zvn(:,jlev)=cv*zvn(:,jlev)*SQRT(rcsq(:)) 04445 zdu2(:,jlev)=zun(:,jlev)-zu(:,jlev) 04446 zdv2(:,jlev)=zvn(:,jlev)-zv(:,jlev) 04447 zdekin(:,jlev)=(zun(:,jlev)*zun(:,jlev) & 04448 & -zu(:,jlev)*zu(:,jlev) & 04449 & +zvn(:,jlev)*zvn(:,jlev) & 04450 & -zv(:,jlev)*zv(:,jlev))*0.5/zdelt & 04451 & *zp(:)/ga*dsigma(jlev) 04452 enddo 04453 ! 04454 ! c) get the global average and transform it back 04455 ! 04456 call gp2fc(zdekin,NLON,NLPP*NLEV) 04457 do jlev=1,NLEV 04458 call fc2sp(zdekin(:,jlev),zsdef(:,jlev)) 04459 enddo 04460 call mpsumsc(zsdef,zsde,NLEV) 04461 call mpgallsp(zsdef,zsde,NLEV) 04462 zsdef(2:NESP,:)=0. 04463 do jlev = 1 , NLEV 04464 call sp2fc(zsdef(1,jlev),zdekin(1,jlev)) 04465 enddo 04466 call fc2gp(zdekin,NLON,NLPP*NLEV) 04467 ! 04468 ! d) compute temperature tendency 04469 ! 04470 do jlev=1,NLEV 04471 zdtdt2(:,jlev)=-zdekin(:,jlev)*ga/zp(:)/dsigma(jlev)/zcp 04472 zdtdt3(:,jlev)=-(zdu1(:,jlev)*zdu2(:,jlev) & 04473 & +zdv1(:,jlev)*zdv2(:,jlev))/zdelt/zcp 04474 enddo 04475 ! 04476 zdtdt1(:,:)=zdtdt1(:,:)/ct/ww 04477 zdtdt2(:,:)=zdtdt2(:,:)/ct/ww 04478 zdtdt3(:,:)=zdtdt3(:,:)/ct/ww 04479 ! 04480 call gp2fc(zdtdt1,NLON,NLPP*NLEV) 04481 call gp2fc(zdtdt2,NLON,NLPP*NLEV) 04482 call gp2fc(zdtdt3,NLON,NLPP*NLEV) 04483 do jlev=1,NLEV 04484 call fc2sp(zdtdt1(:,jlev),zstf1(:,jlev)) 04485 call fc2sp(zdtdt2(:,jlev),zstf2(:,jlev)) 04486 call fc2sp(zdtdt3(:,jlev),zstf3(:,jlev)) 04487 enddo 04488 call mpsumsc(zstf1,zstt1,NLEV) 04489 call mpsumsc(zstf2,zstt2,NLEV) 04490 call mpsumsc(zstf3,zstt3,NLEV) 04491 ! 04492 ! add the temprature tendencies 04493 ! 04494 stt(:,:)=stt(:,:)+zstt1(:,:)+zstt2(:,:)+zstt3(:,:) 04495 ! 04496 ! energy diagnostics 04497 ! 04498 if(nenergy > 0) then 04499 zspt(:)=0. 04500 call mkenerdiag(stp,zstt1,zsp,zspt,denergy(:,5)) 04501 call mkenerdiag(stp,zstt2,zsp,zspt,denergy(:,6)) 04502 call mkenerdiag(stp,zstt3,zsp,zspt,denergy(:,7)) 04503 endif 04504 if(nentropy > 0) then 04505 call mkentrodiag(stp,zstt1,zsp,dentropy(:,5)) 04506 call mkentrodiag(stp,zstt2,zsp,dentropy(:,6)) 04507 call mkentrodiag(stp,zstt3,zsp,dentropy(:,7)) 04508 endif 04509 04510 ! 04511 return 04512 end subroutine mkdheat 04513 04514 ! ================= 04515 ! SUBROUTINE MKEKIN 04516 ! ================= 04517 04518 subroutine mkekin(zszp,zsdp,zp,zekin) 04519 use pumamod 04520 ! 04521 real zszp(NSPP,NLEV),zsdp(NSPP,NLEV) 04522 real zp(NHOR),zekin(NHOR) 04523 ! 04524 real zsd(NESP,NLEV),zsz(NESP,NLEV) 04525 real zu(NHOR,NLEV),zv(NHOR,NLEV) 04526 ! 04527 ! some constants 04528 ! 04529 zdelt=delt2/ww ! timestep in s 04530 zcp=gascon/akap ! heat capacity 04531 ! 04532 call mpgallsp(zsd,zsdp,NLEV) 04533 call mpgallsp(zsz,zszp,NLEV) 04534 do jlev = 1 , NLEV 04535 call dv2uv(zsd(1,jlev),zsz(1,jlev),zu(1,jlev),zv(1,jlev)) 04536 enddo 04537 call fc2gp(zu,NLON,NLPP*NLEV) 04538 call fc2gp(zv,NLON,NLPP*NLEV) 04539 ! 04540 zekin(:)=0. 04541 do jlev = 1 , NLEV 04542 zu(:,jlev)=cv*zu(:,jlev)*SQRT(rcsq(:)) 04543 zv(:,jlev)=cv*zv(:,jlev)*SQRT(rcsq(:)) 04544 zekin(:)=(zu(:,jlev)*zu(:,jlev)+zv(:,jlev)*zv(:,jlev))*0.5 & 04545 & *zp(:)/ga*dsigma(jlev)+zekin(:) 04546 enddo 04547 ! 04548 return 04549 end 04550 subroutine mkekin2(zszp,zsdp,zspp,zekin) 04551 use pumamod 04552 ! 04553 real zszp(NSPP,NLEV),zsdp(NSPP,NLEV),zspp(NSPP) 04554 real zp(NHOR),zekin(NHOR) 04555 ! 04556 real zsd(NESP,NLEV),zsz(NESP,NLEV),zsp(NESP) 04557 real zu(NHOR,NLEV),zv(NHOR,NLEV) 04558 ! 04559 ! some constants 04560 ! 04561 zdelt=delt2/ww ! timestep in s 04562 zcp=gascon/akap ! heat capacity 04563 ! 04564 call mpgallsp(zsd,zsdp,NLEV) 04565 call mpgallsp(zsz,zszp,NLEV) 04566 call mpgallsp(zsp,zspp,NLEV) 04567 do jlev = 1 , NLEV 04568 call dv2uv(zsd(1,jlev),zsz(1,jlev),zu(1,jlev),zv(1,jlev)) 04569 enddo 04570 call sp2fc(zsp,zp) 04571 call fc2gp(zu,NLON,NLPP*NLEV) 04572 call fc2gp(zv,NLON,NLPP*NLEV) 04573 call fc2gp(zp,NLON,NLPP) 04574 ! 04575 zp(:)=psurf*exp(zp(:)) 04576 zekin(:)=0. 04577 do jlev = 1 , NLEV 04578 zu(:,jlev)=cv*zu(:,jlev)*SQRT(rcsq(:)) 04579 zv(:,jlev)=cv*zv(:,jlev)*SQRT(rcsq(:)) 04580 zekin(:)=(zu(:,jlev)*zu(:,jlev)+zv(:,jlev)*zv(:,jlev))*0.5 & 04581 & *zp(:)/ga*dsigma(jlev)+zekin(:) 04582 enddo 04583 ! 04584 return 04585 end 04586 04587 04588 ! ================= 04589 ! SUBROUTINE MKEPOT 04590 ! ================= 04591 04592 subroutine mkepot(zstp,zp,zepot) 04593 use pumamod 04594 ! 04595 real zstp(NSPP,NLEV) 04596 real zp(NHOR),zepot(NHOR) 04597 ! 04598 real zst(NESP,NLEV) 04599 real zt(NHOR,NLEV) 04600 ! 04601 ! some constants 04602 ! 04603 zdelt=delt2/ww ! timestep in s 04604 zcp=gascon/akap ! heat capacity 04605 ! 04606 call mpgallsp(zst,zstp,NLEV) 04607 do jlev = 1 , NLEV 04608 call sp2fc(zst(1,jlev),zt(1,jlev)) 04609 enddo 04610 call fc2gp(zt,NLON,NLPP*NLEV) 04611 ! 04612 zepot(:)=0. 04613 do jlev = 1 , NLEV 04614 zt(:,jlev)=ct*(zt(:,jlev)+t0(jlev)) 04615 zepot(:)=zt(:,jlev)*zcp & 04616 & *zp(:)/ga*dsigma(jlev)+zepot(:) 04617 enddo 04618 ! 04619 return 04620 end 04621 subroutine mkepot2(zstp,zspp,zepot) 04622 use pumamod 04623 ! 04624 real zstp(NSPP,NLEV),zspp(NSPP) 04625 real zp(NHOR),zepot(NHOR) 04626 ! 04627 real zst(NESP,NLEV),zsp(NESP) 04628 real zt(NHOR,NLEV) 04629 ! 04630 ! some constants 04631 ! 04632 zdelt=delt2/ww ! timestep in s 04633 zcp=gascon/akap ! heat capacity 04634 ! 04635 call mpgallsp(zst,zstp,NLEV) 04636 call mpgallsp(zsp,zspp,1) 04637 do jlev = 1 , NLEV 04638 call sp2fc(zst(1,jlev),zt(1,jlev)) 04639 enddo 04640 call sp2fc(zsp,zp) 04641 call fc2gp(zt,NLON,NLPP*NLEV) 04642 call fc2gp(zp,NLON,NLPP) 04643 ! 04644 zp(:)=psurf*exp(zp(:)) 04645 zepot(:)=0. 04646 do jlev = 1 , NLEV 04647 zt(:,jlev)=ct*(zt(:,jlev)+t0(jlev)) 04648 zepot(:)=zt(:,jlev)*zcp & 04649 & *zp(:)/ga*dsigma(jlev)+zepot(:) 04650 enddo 04651 ! 04652 return 04653 end 04654