| 1 | subroutine cellmass(infid,latlength,lonlength,altlength,timelength,lmdflag, & |
|---|
| 2 | miss_val,deltalon,deltalat,latrad,plev,ps,grav,rayon, & |
|---|
| 3 | dmass ) |
|---|
| 4 | |
|---|
| 5 | implicit none |
|---|
| 6 | |
|---|
| 7 | include "netcdf.inc" ! NetCDF definitions |
|---|
| 8 | |
|---|
| 9 | ! arguments |
|---|
| 10 | integer infid ! NetCDF input file ID |
|---|
| 11 | integer lonlength ! # of grid points along longitude |
|---|
| 12 | integer latlength ! # of grid points along latitude |
|---|
| 13 | integer altlength ! # of grid point along altitude (of input datasets) |
|---|
| 14 | integer timelength ! # of points along time |
|---|
| 15 | logical lmdflag ! true=LMD, false=CAM |
|---|
| 16 | real :: miss_val ! missing value |
|---|
| 17 | real :: deltalat,deltalon ! lat and lon intervals in radians |
|---|
| 18 | real,dimension(latlength) :: latrad ! latitudes in radians |
|---|
| 19 | real,dimension(altlength) :: plev ! Pressure levels (Pa) |
|---|
| 20 | real,dimension(lonlength,latlength,timelength),intent(in) :: ps ! surface pressure |
|---|
| 21 | real,dimension(lonlength,latlength,altlength,timelength),intent(in) :: grav,rayon |
|---|
| 22 | real,dimension(lonlength,latlength,altlength,timelength),intent(out) :: dmass |
|---|
| 23 | |
|---|
| 24 | !local |
|---|
| 25 | character (len=64) :: text ! to store some text |
|---|
| 26 | real,dimension(:),allocatable :: aps,bps ! hybrid vertical coordinates |
|---|
| 27 | real,dimension(:,:,:,:),allocatable :: press ! GCM atmospheric pressure |
|---|
| 28 | real,dimension(:),allocatable :: pp ! Pressure levels (Pa) |
|---|
| 29 | real,dimension(:,:,:,:),allocatable :: deltap ! pressure thickness of each layer (Pa) |
|---|
| 30 | integer ierr,ierr1,ierr2 ! NetCDF routines return codes |
|---|
| 31 | integer i,j,ilon,ilat,ilev,itim ! for loops |
|---|
| 32 | real :: tmpp ! temporary pressure |
|---|
| 33 | real :: p0 ! GCM reference pressure |
|---|
| 34 | integer tmpvarid |
|---|
| 35 | |
|---|
| 36 | include "planet.h" |
|---|
| 37 | |
|---|
| 38 | !=============================================================================== |
|---|
| 39 | ! 2.2.1 Pressure intervals |
|---|
| 40 | !=============================================================================== |
|---|
| 41 | allocate(deltap(lonlength,latlength,altlength,timelength)) |
|---|
| 42 | allocate(press(lonlength,latlength,altlength,timelength)) |
|---|
| 43 | allocate(pp(altlength)) |
|---|
| 44 | |
|---|
| 45 | if(lmdflag) then ! LMD vs CAM |
|---|
| 46 | text="pres" |
|---|
| 47 | call get_var4d(infid,lonlength,latlength,altlength,timelength,text,press,miss_val,ierr1,ierr2) |
|---|
| 48 | if (ierr1.ne.NF_NOERR) then |
|---|
| 49 | ! assume we are using _P files |
|---|
| 50 | do itim=1,timelength |
|---|
| 51 | do ilon=1,lonlength |
|---|
| 52 | do ilat=1,latlength |
|---|
| 53 | press(ilon,ilat,:,itim) = plev |
|---|
| 54 | enddo |
|---|
| 55 | enddo |
|---|
| 56 | enddo |
|---|
| 57 | else |
|---|
| 58 | if (ierr2.ne.NF_NOERR) stop "Error: Failed reading pres" |
|---|
| 59 | endif |
|---|
| 60 | |
|---|
| 61 | else ! LMD vs CAM |
|---|
| 62 | ierr=NF_INQ_VARID(infid,"P0",tmpvarid) |
|---|
| 63 | if (ierr.ne.NF_NOERR) then |
|---|
| 64 | write(*,*) "Failed to get P0 ID, used psref=",psref |
|---|
| 65 | p0=psref |
|---|
| 66 | else |
|---|
| 67 | ierr=NF_GET_VAR_REAL(infid,tmpvarid,p0) |
|---|
| 68 | if (ierr.ne.NF_NOERR) then |
|---|
| 69 | write(*,*) "Failed reading reference pressure, used psref=",psref |
|---|
| 70 | p0=psref |
|---|
| 71 | endif |
|---|
| 72 | endif |
|---|
| 73 | ! hybrid coordinate aps/hyam |
|---|
| 74 | text="hyam" |
|---|
| 75 | ierr=NF_INQ_VARID(infid,text,tmpvarid) |
|---|
| 76 | if (ierr.ne.NF_NOERR) then |
|---|
| 77 | stop "Error: Could not find aps/hyam coordinates" |
|---|
| 78 | else |
|---|
| 79 | allocate(aps(altlength)) |
|---|
| 80 | ierr=NF_GET_VAR_REAL(infid,tmpvarid,aps) |
|---|
| 81 | if (ierr.ne.NF_NOERR) then |
|---|
| 82 | stop "Error: Failed reading aps/hyam" |
|---|
| 83 | endif |
|---|
| 84 | call reverselev(altlength,aps) |
|---|
| 85 | endif |
|---|
| 86 | |
|---|
| 87 | ! hybrid coordinate hybm |
|---|
| 88 | text="hybm" |
|---|
| 89 | ierr=NF_INQ_VARID(infid,text,tmpvarid) |
|---|
| 90 | if (ierr.ne.NF_NOERR) then |
|---|
| 91 | stop "Error: Failed to get bps/hybm ID" |
|---|
| 92 | else |
|---|
| 93 | allocate(bps(altlength)) |
|---|
| 94 | ierr=NF_GET_VAR_REAL(infid,tmpvarid,bps) |
|---|
| 95 | if (ierr.ne.NF_NOERR) then |
|---|
| 96 | stop "Error: Failed reading bps/hybm" |
|---|
| 97 | endif |
|---|
| 98 | call reverselev(altlength,bps) |
|---|
| 99 | endif |
|---|
| 100 | |
|---|
| 101 | aps=aps*p0 |
|---|
| 102 | |
|---|
| 103 | do itim=1,timelength |
|---|
| 104 | do ilev=1,altlength |
|---|
| 105 | do ilat=1,latlength |
|---|
| 106 | do ilon=1,lonlength |
|---|
| 107 | press(ilon,ilat,ilev,itim)=aps(ilev)+bps(ilev)*ps(ilon,ilat,itim) |
|---|
| 108 | enddo |
|---|
| 109 | enddo |
|---|
| 110 | enddo |
|---|
| 111 | enddo |
|---|
| 112 | |
|---|
| 113 | endif ! LMD vs CAM |
|---|
| 114 | |
|---|
| 115 | do itim=1,timelength |
|---|
| 116 | |
|---|
| 117 | do ilon=1,lonlength |
|---|
| 118 | do ilat=1,latlength |
|---|
| 119 | tmpp=ps(ilon,ilat,itim) |
|---|
| 120 | pp=press(ilon,ilat,:,itim) |
|---|
| 121 | if (tmpp.ge.pp(1)) then |
|---|
| 122 | deltap(ilon,ilat,1,itim)= tmpp - exp((log(pp(1))+log(pp(2)))/2.) ! initialization, rectified with ps below |
|---|
| 123 | else |
|---|
| 124 | deltap(ilon,ilat,1,itim)= miss_val |
|---|
| 125 | endif |
|---|
| 126 | do ilev=2,altlength-1 |
|---|
| 127 | deltap(ilon,ilat,ilev,itim)= exp((log(pp(ilev-1))+log(pp(ilev)))/2.)-& |
|---|
| 128 | exp((log(pp(ilev))+log(pp(ilev+1)))/2.) |
|---|
| 129 | enddo |
|---|
| 130 | deltap(ilon,ilat,altlength,itim)=exp((log(pp(altlength-1))+log(pp(altlength)))/2.) |
|---|
| 131 | enddo |
|---|
| 132 | enddo |
|---|
| 133 | |
|---|
| 134 | do ilon=1,lonlength |
|---|
| 135 | do ilat=1,latlength |
|---|
| 136 | tmpp=ps(ilon,ilat,itim) |
|---|
| 137 | pp=press(ilon,ilat,:,itim) |
|---|
| 138 | do ilev=altlength,2,-1 |
|---|
| 139 | if ((pp(ilev).le.tmpp).and.(pp(ilev-1).gt.tmpp)) then |
|---|
| 140 | deltap(ilon,ilat,ilev,itim)= tmpp - & |
|---|
| 141 | exp((log(pp(ilev))+log(pp(ilev+1)))/2.) |
|---|
| 142 | elseif (pp(ilev).gt.tmpp) then |
|---|
| 143 | deltap(ilon,ilat,ilev,itim)=miss_val |
|---|
| 144 | endif |
|---|
| 145 | enddo |
|---|
| 146 | enddo |
|---|
| 147 | enddo |
|---|
| 148 | |
|---|
| 149 | enddo ! timelength |
|---|
| 150 | |
|---|
| 151 | !=============================================================================== |
|---|
| 152 | ! 2.2.2 Mass in cells |
|---|
| 153 | !=============================================================================== |
|---|
| 154 | |
|---|
| 155 | do itim=1,timelength |
|---|
| 156 | |
|---|
| 157 | do ilon=1,lonlength |
|---|
| 158 | do ilat=1,latlength |
|---|
| 159 | do ilev=1,altlength |
|---|
| 160 | if ((deltap(ilon,ilat,ilev,itim).ne.miss_val) & |
|---|
| 161 | .and. (rayon(ilon,ilat,ilev,itim).ne.miss_val) & |
|---|
| 162 | .and. (grav(ilon,ilat,ilev,itim).ne.miss_val)) then |
|---|
| 163 | dmass(ilon,ilat,ilev,itim) = & |
|---|
| 164 | rayon(ilon,ilat,ilev,itim)*cos(latrad(ilat))*deltalon & |
|---|
| 165 | * rayon(ilon,ilat,ilev,itim)*deltalat & |
|---|
| 166 | * deltap(ilon,ilat,ilev,itim)/grav(ilon,ilat,ilev,itim) |
|---|
| 167 | else |
|---|
| 168 | dmass(ilon,ilat,ilev,itim) = miss_val |
|---|
| 169 | endif |
|---|
| 170 | enddo |
|---|
| 171 | enddo |
|---|
| 172 | enddo |
|---|
| 173 | |
|---|
| 174 | enddo ! timelength |
|---|
| 175 | |
|---|
| 176 | end subroutine cellmass |
|---|