[2541] | 1 | module check_fields_mod |
---|
| 2 | |
---|
| 3 | real,parameter :: default_temp_min=50. ! minimum reasonable temperature (K) |
---|
| 4 | real,parameter :: default_temp_max=350. ! maximum reasonable temperature (K) |
---|
| 5 | |
---|
| 6 | real,parameter :: default_wind_max=500. ! maximum reasonable wind magnitude (m/s) |
---|
| 7 | |
---|
| 8 | real,parameter :: default_ps_min=80. ! minimum reasonable surface pressure (Pa) |
---|
| 9 | real,parameter :: default_ps_max=2000. ! maximum reasonable surface pressure (Pa) |
---|
| 10 | |
---|
| 11 | contains |
---|
| 12 | |
---|
[2570] | 13 | subroutine check_physics_fields(message,temp,u,v,pplev,q) |
---|
[2541] | 14 | use dimphy, only: klon, klev |
---|
[2570] | 15 | use tracer_mod, only: nqmx |
---|
[2541] | 16 | implicit none |
---|
[2570] | 17 | character(len=*),intent(in):: message ! text message for outputs |
---|
[2541] | 18 | real,intent(in) :: temp(klon,klev) |
---|
| 19 | real,intent(in) :: u(klon,klev) ! zonal wind (m/s) |
---|
| 20 | real,intent(in) :: v(klon,klev) ! meridional wind (m/s) |
---|
| 21 | real,intent(in) :: pplev(klon,klev+1) ! pressure at level interfaces (Pa) |
---|
[2570] | 22 | real,intent(in) :: q(klon,klev,nqmx) ! tracer mixing ratio (.../kg_air) |
---|
[2541] | 23 | |
---|
| 24 | character(len=50) :: name="check_physics_fields" |
---|
[2570] | 25 | logical :: ok_t,ok_w,ok_ps,ok_q |
---|
[2541] | 26 | |
---|
| 27 | ! 1. Initialisations |
---|
[2570] | 28 | ok_q=.true. |
---|
[2541] | 29 | |
---|
| 30 | ! 2. Check temperature, winds and surface pressure |
---|
[2570] | 31 | call check_temperature(message,temp,ok_t) |
---|
| 32 | call check_winds(message,u,v,ok_w) |
---|
| 33 | call check_ps(message,pplev(:,1),ok_ps) |
---|
| 34 | if (nqmx>=1) then |
---|
| 35 | call check_tracers(message,q,ok_q) |
---|
| 36 | endif |
---|
[2541] | 37 | |
---|
[2570] | 38 | if ((.not.ok_t).or.(.not.ok_w).or.(.not.ok_ps).or.(.not.ok_q)) then |
---|
[2541] | 39 | ! Something is wrong, might as well stop here |
---|
| 40 | call abort_physic(trim(name),trim(message)//" Invalid field values",1) |
---|
| 41 | endif |
---|
| 42 | |
---|
| 43 | end subroutine check_physics_fields |
---|
| 44 | |
---|
| 45 | |
---|
[2570] | 46 | subroutine check_temperature(message,temp,ok,temp_min,temp_max) |
---|
[2541] | 47 | use dimphy, only: klon, klev |
---|
| 48 | implicit none |
---|
[2570] | 49 | character(len=*),intent(in):: message ! text message for outputs |
---|
[2541] | 50 | real,intent(in) :: temp(klon,klev) |
---|
| 51 | logical,intent(out) :: ok ! returns .true. if everything OK, .false. otherwise |
---|
| 52 | real,intent(in),optional :: temp_min ! user provided acceptable minimum |
---|
| 53 | real,intent(in),optional :: temp_max ! user provided acceptable maximum |
---|
| 54 | |
---|
| 55 | character(len=50) :: name="check_temperature" |
---|
| 56 | real :: tmin,tmax |
---|
| 57 | integer :: i,k |
---|
| 58 | |
---|
| 59 | ! 0. Check optional inputs |
---|
| 60 | if (present(temp_min)) then |
---|
| 61 | tmin=temp_min |
---|
| 62 | else |
---|
| 63 | tmin=default_temp_min |
---|
| 64 | endif |
---|
| 65 | |
---|
| 66 | if (present(temp_max)) then |
---|
| 67 | tmax=temp_max |
---|
| 68 | else |
---|
| 69 | tmax=default_temp_max |
---|
| 70 | endif |
---|
| 71 | |
---|
| 72 | ! 1. initializations |
---|
| 73 | ok=.true. |
---|
| 74 | |
---|
| 75 | ! 2. do the checking |
---|
| 76 | do i=1,klon |
---|
| 77 | do k=1,klev |
---|
| 78 | ! look for NaN |
---|
| 79 | if (temp(i,k).ne.temp(i,k)) then |
---|
| 80 | ok=.false. |
---|
[2570] | 81 | write(*,*)trim(message)//" "//trim(name)//" temp(i,k)=",temp(i,k),& |
---|
| 82 | " for i=",i," k=",k |
---|
[2541] | 83 | endif |
---|
| 84 | ! check for temperatures too low |
---|
| 85 | if (temp(i,k).lt.tmin) then |
---|
| 86 | ok=.false. |
---|
[2570] | 87 | write(*,*)trim(message)//" "//trim(name)//" temp(i,k)=",temp(i,k),& |
---|
| 88 | " for i=",i," k=",k," <",tmin |
---|
[2541] | 89 | endif |
---|
| 90 | ! check for temperatures too high |
---|
| 91 | if (temp(i,k).gt.tmax) then |
---|
| 92 | ok=.false. |
---|
[2570] | 93 | write(*,*)trim(message)//" "//trim(name)//" temp(i,k)=",temp(i,k),& |
---|
| 94 | " for i=",i," k=",k," >",tmax |
---|
[2541] | 95 | endif |
---|
| 96 | enddo |
---|
| 97 | enddo |
---|
| 98 | |
---|
| 99 | end subroutine check_temperature |
---|
| 100 | |
---|
[2570] | 101 | subroutine check_winds(message,u,v,ok,wind_max) |
---|
[2541] | 102 | use dimphy, only: klon, klev |
---|
| 103 | implicit none |
---|
[2570] | 104 | character(len=*),intent(in):: message ! text message for outputs |
---|
[2541] | 105 | real,intent(in) :: u(klon,klev) ! zonal wind (m/s) |
---|
| 106 | real,intent(in) :: v(klon,klev) ! meridional wind (m/s) |
---|
| 107 | logical,intent(out) :: ok ! returns .true. if everything OK, .false. otherwise |
---|
| 108 | real,intent(in),optional :: wind_max ! user provided acceptable maximum magnitude |
---|
| 109 | |
---|
| 110 | character(len=50) :: name="check_winds" |
---|
| 111 | real :: wmax |
---|
| 112 | integer :: i,k |
---|
| 113 | |
---|
| 114 | ! 0. Check optional inputs |
---|
| 115 | |
---|
| 116 | if (present(wind_max)) then |
---|
| 117 | wmax=wind_max |
---|
| 118 | else |
---|
| 119 | wmax=default_wind_max |
---|
| 120 | endif |
---|
| 121 | |
---|
| 122 | ! 1. initializations |
---|
| 123 | ok=.true. |
---|
| 124 | |
---|
| 125 | ! 2. do the checking |
---|
| 126 | do i=1,klon |
---|
| 127 | do k=1,klev |
---|
| 128 | ! look for NaN |
---|
| 129 | if (u(i,k).ne.u(i,k)) then |
---|
| 130 | ok=.false. |
---|
[2570] | 131 | write(*,*)trim(message)//" "//trim(name)//" u(i,k)=",u(i,k),& |
---|
| 132 | " for i=",i," k=",k |
---|
[2541] | 133 | endif |
---|
| 134 | if (v(i,k).ne.v(i,k)) then |
---|
| 135 | ok=.false. |
---|
[2570] | 136 | write(*,*)trim(message)//" "//trim(name)//" v(i,k)=",v(i,k),& |
---|
| 137 | " for i=",i," k=",k |
---|
[2541] | 138 | endif |
---|
| 139 | ! check for magnitudes too high |
---|
| 140 | if (abs(u(i,k)).gt.wmax) then |
---|
| 141 | ok=.false. |
---|
[2570] | 142 | write(*,*)trim(message)//" "//trim(name)//" u(i,k)=",u(i,k),& |
---|
| 143 | " for i=",i," k=",k," >",wmax |
---|
[2541] | 144 | endif |
---|
| 145 | if (abs(v(i,k)).gt.wmax) then |
---|
| 146 | ok=.false. |
---|
[2570] | 147 | write(*,*)trim(message)//" "//trim(name)//" v(i,k)=",v(i,k),& |
---|
| 148 | " for i=",i," k=",k," >",wmax |
---|
[2541] | 149 | endif |
---|
| 150 | enddo |
---|
| 151 | enddo |
---|
| 152 | |
---|
| 153 | end subroutine check_winds |
---|
| 154 | |
---|
[2570] | 155 | subroutine check_ps(message,ps,ok,ps_min,ps_max) |
---|
[2541] | 156 | use dimphy, only: klon |
---|
| 157 | implicit none |
---|
[2570] | 158 | character(len=*),intent(in):: message ! text message for outputs |
---|
[2541] | 159 | real,intent(in) :: ps(klon) |
---|
| 160 | logical,intent(out) :: ok ! returns .true. if everything OK, .false. otherwise |
---|
| 161 | real,intent(in),optional :: ps_min ! user provided acceptable minimum |
---|
| 162 | real,intent(in),optional :: ps_max ! user provided acceptable maximum |
---|
| 163 | |
---|
| 164 | character(len=50) :: name="check_ps" |
---|
| 165 | real :: pmin,pmax |
---|
| 166 | integer :: i |
---|
| 167 | |
---|
| 168 | ! 0. Check optional inputs |
---|
| 169 | if (present(ps_min)) then |
---|
| 170 | pmin=ps_min |
---|
| 171 | else |
---|
| 172 | pmin=default_ps_min |
---|
| 173 | endif |
---|
| 174 | |
---|
| 175 | if (present(ps_max)) then |
---|
| 176 | pmax=ps_max |
---|
| 177 | else |
---|
| 178 | pmax=default_ps_max |
---|
| 179 | endif |
---|
| 180 | |
---|
| 181 | ! 1. initializations |
---|
| 182 | ok=.true. |
---|
| 183 | |
---|
| 184 | ! 2. do the checking |
---|
| 185 | do i=1,klon |
---|
| 186 | ! look for NaN |
---|
| 187 | if (ps(i).ne.ps(i)) then |
---|
| 188 | ok=.false. |
---|
[2570] | 189 | write(*,*)trim(message)//" "//trim(name)//" ps(i)=",ps(i)," for i=",i |
---|
[2541] | 190 | endif |
---|
| 191 | ! check for pressures too low |
---|
| 192 | if (ps(i).lt.pmin) then |
---|
| 193 | ok=.false. |
---|
[2570] | 194 | write(*,*)trim(message)//" "//trim(name)//" ps(i)=",ps(i)," for i=",i,& |
---|
| 195 | " <",pmin |
---|
[2541] | 196 | endif |
---|
| 197 | ! check for pressures too high |
---|
| 198 | if (ps(i).gt.pmax) then |
---|
| 199 | ok=.false. |
---|
[2570] | 200 | write(*,*)trim(message)//" "//trim(name)//" ps(i)=",ps(i)," for i=",i,& |
---|
| 201 | " >",pmax |
---|
[2541] | 202 | endif |
---|
| 203 | enddo |
---|
| 204 | |
---|
| 205 | end subroutine check_ps |
---|
| 206 | |
---|
[2570] | 207 | subroutine check_tracers(message,q,ok) |
---|
| 208 | use dimphy, only: klon, klev |
---|
| 209 | use tracer_mod, only: nqmx,noms |
---|
| 210 | implicit none |
---|
| 211 | character(len=*),intent(in):: message ! text message for outputs |
---|
| 212 | real,intent(in) :: q(klon,klev,nqmx) ! tracer mixing ratio |
---|
| 213 | logical,intent(inout) :: ok ! set to .false. if something is wrong |
---|
| 214 | |
---|
| 215 | character(len=50) :: name="check_tracers" |
---|
| 216 | integer :: i,k,iq |
---|
| 217 | integer :: nb_bad_neg ! number of problematic points (negative values) |
---|
| 218 | integer :: nb_bad_nan ! number of problematic points (NaNs) |
---|
| 219 | |
---|
| 220 | ! 1. initializations |
---|
| 221 | nb_bad_nan=0 |
---|
| 222 | |
---|
| 223 | ! 2. do the checking |
---|
| 224 | do iq=1,nqmx |
---|
| 225 | nb_bad_neg=0 ! initialize |
---|
| 226 | do i=1,klon |
---|
| 227 | do k=1,klev |
---|
| 228 | ! look for NaN |
---|
| 229 | if (q(i,k,iq).ne.q(i,k,iq)) then |
---|
| 230 | ok=.false. |
---|
| 231 | nb_bad_nan=nb_bad_nan+1 |
---|
| 232 | endif |
---|
| 233 | ! look for negative values |
---|
| 234 | if (q(i,k,iq).lt.0) then |
---|
| 235 | ! ok=.false. |
---|
| 236 | nb_bad_neg=nb_bad_neg+1 |
---|
| 237 | endif |
---|
| 238 | enddo |
---|
| 239 | enddo |
---|
| 240 | if (nb_bad_neg>0) then |
---|
| 241 | write(*,*)trim(message)//" "//trim(name)//" tracer "//trim(noms(iq))//& |
---|
| 242 | " contains ",nb_bad_neg," negative values!" |
---|
| 243 | endif |
---|
| 244 | enddo !of do iq=1,nqmx |
---|
| 245 | |
---|
| 246 | end subroutine check_tracers |
---|
| 247 | |
---|
[2541] | 248 | end module check_fields_mod |
---|