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