1 | program extract |
---|
2 | |
---|
3 | ! program to extract (ie: interpolates) pointwise values of an atmospheric |
---|
4 | ! variable from a 'zrecast'ed diagfi file (works if altitude is geometrical |
---|
5 | ! height or a pressure vertical coordinates) |
---|
6 | ! user has to specify: |
---|
7 | ! - name of input file |
---|
8 | ! - date (in sols) offset wrt the input file (e.g. if the input file "begins" |
---|
9 | ! at Ls=0, then the offset is 0; if the input file begins at Ls=90, the |
---|
10 | ! offset date corresponding to the first 3 months is 61+66+66=193 sols, etc.) |
---|
11 | ! NB: that means the input file must have its "Time" coordinate in sols |
---|
12 | ! - the "extraction mode": |
---|
13 | ! 1: extract individual values; user will specify values of |
---|
14 | ! lon lat alt Ls LT (all on a same line) |
---|
15 | ! on as many lines as there are sought values |
---|
16 | ! 2: extract a profile: user will specify on a first line the values of |
---|
17 | ! lon lat Ls LT (all on a same line) |
---|
18 | ! and then only specify values of altitudes (m or Pa depending on the |
---|
19 | ! coordinate in the input file), one per line, at which values are |
---|
20 | ! sought |
---|
21 | ! - output values are sent to (ASCII) output file 'infile_var_.dat', where |
---|
22 | ! 'infile' is the input file name (without trailing '.nc') and |
---|
23 | ! 'var' is the sought variable, for extraction mode 1 as |
---|
24 | ! lines of "lon lat alt Ls LT value" and for a profile (extraction mode 2) |
---|
25 | ! as lines of "alt value" |
---|
26 | ! |
---|
27 | ! NB: If there is no data to do an appropriate interpolation to extract |
---|
28 | ! the sought value, then a "missing_value" (taken from the variable's |
---|
29 | ! attribute in the input file, most likely -9.99E33) is returned. |
---|
30 | ! |
---|
31 | ! EM. Sept. 2011 |
---|
32 | |
---|
33 | use netcdf |
---|
34 | implicit none |
---|
35 | |
---|
36 | ! Input file: |
---|
37 | character(len=256) :: infile |
---|
38 | character(len=256) :: outfile |
---|
39 | |
---|
40 | character (len=256) :: text ! to store some text |
---|
41 | character (len=64) :: varname ! to store the name of the variable to retreive |
---|
42 | |
---|
43 | ! NetCDF stuff |
---|
44 | integer :: status ! NetCDF return code |
---|
45 | integer :: inid ! NetCDF file IDs |
---|
46 | integer :: varid ! to store the ID of a variable |
---|
47 | integer :: lat_dimid,lon_dimid,alt_dimid,time_dimid |
---|
48 | integer :: datashape(4) |
---|
49 | |
---|
50 | real,dimension(:),allocatable :: longitude ! longitude |
---|
51 | integer lonlen ! # of grid points along longitude |
---|
52 | real,dimension(:),allocatable :: latitude ! latitude |
---|
53 | integer latlen ! # of grid points along latitude |
---|
54 | real,dimension(:),allocatable :: altitude ! can be geometric heights or pressure |
---|
55 | integer altlen ! # of grid point along altitude |
---|
56 | real,dimension(:),allocatable :: time ! time |
---|
57 | integer timelen ! # of points along time |
---|
58 | character :: alttype ! altitude coord. type:'z' (altitude, m) 'p' (pressure, Pa) |
---|
59 | real,dimension(:,:,:,:),allocatable :: field |
---|
60 | real :: missing_value ! value to denote non-existant data |
---|
61 | real :: starttimeoffset ! offset (in sols) wrt Ls=0 of sol 0 in file |
---|
62 | integer :: extract_mode ! 1: point-by-point extraction 2: extract a profile |
---|
63 | |
---|
64 | ! point at which data is sought: |
---|
65 | real :: lon,lat,alt,Ls,LT,value |
---|
66 | real :: sol ! sol GCM date corresponding to sought Ls and LT |
---|
67 | |
---|
68 | integer :: nb |
---|
69 | |
---|
70 | !=============================================================================== |
---|
71 | ! 1.1 Input file |
---|
72 | !=============================================================================== |
---|
73 | |
---|
74 | write(*,*) "" |
---|
75 | write(*,*) " Program valid for diagfi.nc or concatnc.nc files" |
---|
76 | write(*,*) " processed by zrecast " |
---|
77 | write(*,*) " Enter input file name:" |
---|
78 | |
---|
79 | read(*,'(a)') infile |
---|
80 | write(*,*) "" |
---|
81 | |
---|
82 | ! open input file |
---|
83 | status=nf90_open(infile,NF90_NOWRITE,inid) |
---|
84 | if (status.ne.nf90_noerr) then |
---|
85 | write(*,*)"Failed to open datafile ",trim(infile) |
---|
86 | write(*,*)trim(nf90_strerror(status)) |
---|
87 | stop |
---|
88 | endif |
---|
89 | |
---|
90 | write(*,*) " Beginning date of the file?" |
---|
91 | write(*,*) " (i.e. number of sols since Ls=0 that the Time=0.0 in the input" |
---|
92 | write(*,*) " file corresponds to)" |
---|
93 | read(*,*) starttimeoffset |
---|
94 | |
---|
95 | write(*,*) " Extraction mode?" |
---|
96 | write(*,*) " ( 1: pointwise extraction , 2: profile extraction)" |
---|
97 | read(*,*,iostat=status) extract_mode |
---|
98 | if ((status.ne.0).or.(extract_mode.lt.1) & |
---|
99 | .or.(extract_mode.gt.2)) then |
---|
100 | write(*,*) "Error: invalid extraction mode:",extract_mode |
---|
101 | stop |
---|
102 | endif |
---|
103 | |
---|
104 | !=============================================================================== |
---|
105 | ! 1.2 Input variable to extract |
---|
106 | !=============================================================================== |
---|
107 | |
---|
108 | write(*,*) "Enter variable to extract:" |
---|
109 | read(*,*) varname |
---|
110 | ! check that input file contains that variable |
---|
111 | status=nf90_inq_varid(inid,trim(varname),varid) |
---|
112 | if (status.ne.nf90_noerr) then |
---|
113 | write(*,*) "Failed to find variable ",trim(varname)," in ",trim(infile) |
---|
114 | write(*,*)trim(nf90_strerror(status)) |
---|
115 | write(*,*) " Might as well stop here." |
---|
116 | stop |
---|
117 | endif |
---|
118 | |
---|
119 | !=============================================================================== |
---|
120 | ! 1.3 Get grids for dimensions lon,lat,alt,time |
---|
121 | !=============================================================================== |
---|
122 | |
---|
123 | ! latitude |
---|
124 | status=nf90_inq_dimid(inid,"latitude",lat_dimid) |
---|
125 | if (status.ne.nf90_noerr) then |
---|
126 | write(*,*)"Failed to find latitude dimension" |
---|
127 | write(*,*)trim(nf90_strerror(status)) |
---|
128 | stop |
---|
129 | endif |
---|
130 | status=nf90_inquire_dimension(inid,lat_dimid,len=latlen) |
---|
131 | if (status.ne.nf90_noerr) then |
---|
132 | write(*,*)"Failed to find latitude length" |
---|
133 | write(*,*)trim(nf90_strerror(status)) |
---|
134 | endif |
---|
135 | allocate(latitude(latlen)) |
---|
136 | status=nf90_inq_varid(inid,"latitude",varid) |
---|
137 | if (status.ne.nf90_noerr) then |
---|
138 | write(*,*) "Failed to find latitude ID" |
---|
139 | write(*,*)trim(nf90_strerror(status)) |
---|
140 | stop |
---|
141 | endif |
---|
142 | ! read latitude |
---|
143 | status=nf90_get_var(inid,varid,latitude) |
---|
144 | if (status.ne.nf90_noerr) then |
---|
145 | write(*,*) "Failed to load latitude" |
---|
146 | write(*,*)trim(nf90_strerror(status)) |
---|
147 | stop |
---|
148 | endif |
---|
149 | |
---|
150 | !longitude |
---|
151 | status=nf90_inq_dimid(inid,"longitude",lon_dimid) |
---|
152 | if (status.ne.nf90_noerr) then |
---|
153 | write(*,*)"Failed to find longitude dimension" |
---|
154 | write(*,*)trim(nf90_strerror(status)) |
---|
155 | stop |
---|
156 | endif |
---|
157 | status=nf90_inquire_dimension(inid,lon_dimid,len=lonlen) |
---|
158 | if (status.ne.nf90_noerr) then |
---|
159 | write(*,*)"Failed to find longitude length" |
---|
160 | write(*,*)trim(nf90_strerror(status)) |
---|
161 | endif |
---|
162 | allocate(longitude(lonlen)) |
---|
163 | status=nf90_inq_varid(inid,"longitude",varid) |
---|
164 | if (status.ne.nf90_noerr) then |
---|
165 | write(*,*) "Failed to find longitude ID" |
---|
166 | write(*,*)trim(nf90_strerror(status)) |
---|
167 | stop |
---|
168 | endif |
---|
169 | ! read longitude |
---|
170 | status=nf90_get_var(inid,varid,longitude) |
---|
171 | if (status.ne.nf90_noerr) then |
---|
172 | write(*,*) "Failed to load longitude" |
---|
173 | write(*,*)trim(nf90_strerror(status)) |
---|
174 | stop |
---|
175 | endif |
---|
176 | |
---|
177 | !time |
---|
178 | status=nf90_inq_dimid(inid,"Time",time_dimid) |
---|
179 | if (status.ne.nf90_noerr) then |
---|
180 | write(*,*)"Failed to find Time dimension" |
---|
181 | write(*,*)trim(nf90_strerror(status)) |
---|
182 | stop |
---|
183 | endif |
---|
184 | status=nf90_inquire_dimension(inid,time_dimid,len=timelen) |
---|
185 | if (status.ne.nf90_noerr) then |
---|
186 | write(*,*)"Failed to find Time length" |
---|
187 | write(*,*)trim(nf90_strerror(status)) |
---|
188 | endif |
---|
189 | allocate(time(timelen)) |
---|
190 | status=nf90_inq_varid(inid,"Time",varid) |
---|
191 | if (status.ne.nf90_noerr) then |
---|
192 | write(*,*) "Failed to find Time ID" |
---|
193 | write(*,*)trim(nf90_strerror(status)) |
---|
194 | stop |
---|
195 | endif |
---|
196 | ! read Time |
---|
197 | status=nf90_get_var(inid,varid,time) |
---|
198 | if (status.ne.nf90_noerr) then |
---|
199 | write(*,*) "Failed to load Time" |
---|
200 | write(*,*)trim(nf90_strerror(status)) |
---|
201 | stop |
---|
202 | endif |
---|
203 | ! add the offset to time(:) |
---|
204 | time(:)=time(:)+starttimeoffset |
---|
205 | |
---|
206 | !altitude |
---|
207 | status=nf90_inq_dimid(inid,"altitude",alt_dimid) |
---|
208 | if (status.ne.nf90_noerr) then |
---|
209 | write(*,*)"Failed to find altitude dimension" |
---|
210 | write(*,*)trim(nf90_strerror(status)) |
---|
211 | stop |
---|
212 | endif |
---|
213 | status=nf90_inquire_dimension(inid,alt_dimid,len=altlen) |
---|
214 | if (status.ne.nf90_noerr) then |
---|
215 | write(*,*)"Failed to find altitude length" |
---|
216 | write(*,*)trim(nf90_strerror(status)) |
---|
217 | endif |
---|
218 | allocate(altitude(altlen)) |
---|
219 | status=nf90_inq_varid(inid,"altitude",varid) |
---|
220 | if (status.ne.nf90_noerr) then |
---|
221 | write(*,*) "Failed to find altitude ID" |
---|
222 | write(*,*)trim(nf90_strerror(status)) |
---|
223 | stop |
---|
224 | endif |
---|
225 | ! read altitude |
---|
226 | status=nf90_get_var(inid,varid,altitude) |
---|
227 | if (status.ne.nf90_noerr) then |
---|
228 | write(*,*) "Failed to load altitude" |
---|
229 | write(*,*)trim(nf90_strerror(status)) |
---|
230 | stop |
---|
231 | endif |
---|
232 | ! check altitude attribute "units" to find out altitude type |
---|
233 | status=nf90_get_att(inid,varid,"units",text) |
---|
234 | if (status.ne.nf90_noerr) then |
---|
235 | write(*,*) "Failed to load altitude units attribute" |
---|
236 | write(*,*)trim(nf90_strerror(status)) |
---|
237 | stop |
---|
238 | else |
---|
239 | if (trim(text).eq."Pa") then |
---|
240 | alttype="p" ! pressure coordinate |
---|
241 | else if (trim(text).eq."m") then |
---|
242 | alttype="z" ! altitude coordinate |
---|
243 | else |
---|
244 | write(*,*)" I do not understand this unit ",trim(text)," for altitude!" |
---|
245 | stop |
---|
246 | endif |
---|
247 | endif |
---|
248 | |
---|
249 | !=============================================================================== |
---|
250 | ! 1.3 Get input dataset |
---|
251 | !=============================================================================== |
---|
252 | status=nf90_inq_varid(inid,trim(varname),varid) |
---|
253 | if (status.ne.nf90_noerr) then |
---|
254 | write(*,*) "Failed to find variable ",trim(varname)," in ",trim(infile) |
---|
255 | write(*,*)trim(nf90_strerror(status)) |
---|
256 | write(*,*) " Might as well stop here." |
---|
257 | stop |
---|
258 | endif |
---|
259 | |
---|
260 | ! sanity checks on the variable |
---|
261 | status=nf90_inquire_variable(inid,varid,ndims=nb,dimids=datashape) |
---|
262 | if (status.ne.nf90_noerr) then |
---|
263 | write(*,*) "Failed to obtain information on variable ",trim(varname) |
---|
264 | write(*,*)trim(nf90_strerror(status)) |
---|
265 | write(*,*) " Might as well stop here." |
---|
266 | stop |
---|
267 | else |
---|
268 | ! check that it is a 4D variable |
---|
269 | if (nb.ne.4) then |
---|
270 | write(*,*) "Error, expected a 4D (lon-lat-alt-time) variable!" |
---|
271 | stop |
---|
272 | endif |
---|
273 | ! check that its dimensions are indeed lon,lat,alt,time |
---|
274 | if (datashape(1).ne.lon_dimid) then |
---|
275 | write(*,*) "Error, expected first dimension to be longitude!" |
---|
276 | stop |
---|
277 | endif |
---|
278 | if (datashape(2).ne.lat_dimid) then |
---|
279 | write(*,*) "Error, expected second dimension to be latitude!" |
---|
280 | stop |
---|
281 | endif |
---|
282 | if (datashape(3).ne.alt_dimid) then |
---|
283 | write(*,*) "Error, expected third dimension to be altitude!" |
---|
284 | stop |
---|
285 | endif |
---|
286 | if (datashape(4).ne.time_dimid) then |
---|
287 | write(*,*) "Error, expected fourth dimension to be time!" |
---|
288 | stop |
---|
289 | endif |
---|
290 | endif |
---|
291 | |
---|
292 | allocate(field(lonlen,latlen,altlen,timelen)) |
---|
293 | |
---|
294 | ! load dataset |
---|
295 | status=nf90_get_var(inid,varid,field) |
---|
296 | if (status.ne.nf90_noerr) then |
---|
297 | write(*,*) "Failed to load ",trim(varname) |
---|
298 | write(*,*)trim(nf90_strerror(status)) |
---|
299 | stop |
---|
300 | else |
---|
301 | write(*,*) "Loaded ",trim(varname) |
---|
302 | endif |
---|
303 | ! get dataset's missing_value attribute |
---|
304 | status=nf90_get_att(inid,varid,"missing_value",missing_value) |
---|
305 | if (status.ne.nf90_noerr) then |
---|
306 | write(*,*) "Failed to load missing_value attribute" |
---|
307 | write(*,*)trim(nf90_strerror(status)) |
---|
308 | stop |
---|
309 | else |
---|
310 | write(*,'(" with missing_value attribute : ",1pe12.5)') missing_value |
---|
311 | endif |
---|
312 | |
---|
313 | !=============================================================================== |
---|
314 | ! 2. Process and interpolate |
---|
315 | !=============================================================================== |
---|
316 | |
---|
317 | !=============================================================================== |
---|
318 | ! 2.1 Create output file |
---|
319 | !=============================================================================== |
---|
320 | |
---|
321 | outfile=trim(infile(1:index(infile,".nc",back=.true.)-1))//"_"//& |
---|
322 | trim(varname)//".dat" |
---|
323 | open(42,file=outfile,form="formatted") |
---|
324 | write(*,*) "Output file is: ",trim(outfile) |
---|
325 | |
---|
326 | !=============================================================================== |
---|
327 | ! 2.2 Extract values |
---|
328 | !=============================================================================== |
---|
329 | |
---|
330 | if (extract_mode==1) then ! pointwise extraction |
---|
331 | write(*,*) " Enter values of: lon lat alt Ls LT (all on the same line," |
---|
332 | write(*,*) " using as many lines as sought data values)" |
---|
333 | write(*,*) " (enter anything else, e.g. blank line, nonesense,... to quit)" |
---|
334 | else ! extract_mode==2 , profile extraction |
---|
335 | write(*,*) " Enter values of: lon lat Ls LT (all on the same line)" |
---|
336 | read(*,*) lon,lat,Ls,LT |
---|
337 | write(*,*) " Enter values of altitude (one per line)" |
---|
338 | write(*,*) " (enter anything else, e.g. blank line, nonesense,... to quit)" |
---|
339 | endif |
---|
340 | do |
---|
341 | ! 2.1 read coordinates and do some sanity checks |
---|
342 | text="" !initialize text to empty string |
---|
343 | read(*,'(a)') text ! store input as text (to spot empty input line) |
---|
344 | if (len_trim(adjustl(text)).eq.0) exit |
---|
345 | |
---|
346 | if (extract_mode==1) then |
---|
347 | read(text,*,iostat=status) lon,lat,alt,Ls,LT |
---|
348 | ! Ls in degrees, LT (local true solar time) in hours, i.e. in [0:24] |
---|
349 | else ! extract_mode==2 , read alt only |
---|
350 | read(text,*,iostat=status) alt |
---|
351 | endif |
---|
352 | if (status.ne.0) exit |
---|
353 | |
---|
354 | if ((lon.lt.-360.).or.(lon.gt.360.)) then |
---|
355 | write(*,*) "Unexpected value for lon: ",lon |
---|
356 | stop |
---|
357 | endif |
---|
358 | ! we want lon in [-180:180] |
---|
359 | if (lon.lt.-180.) lon=lon+360. |
---|
360 | if (lon.gt.180.) lon=lon-360. |
---|
361 | |
---|
362 | if ((lat.lt.-90.).or.(lat.gt.90.)) then |
---|
363 | write(*,*) "Unexpected value for lat: ",lat |
---|
364 | stop |
---|
365 | endif |
---|
366 | |
---|
367 | if ((Ls.lt.0.).or.(Ls.gt.360.)) then |
---|
368 | write(*,*) "Unexpected value for Ls: ",Ls |
---|
369 | stop |
---|
370 | endif |
---|
371 | |
---|
372 | if ((LT.lt.0.).or.(LT.gt.24.)) then |
---|
373 | write(*,*) "Unexpected value for LT: ",LT |
---|
374 | stop |
---|
375 | endif |
---|
376 | |
---|
377 | ! 2.2 compute GCM sol date corresponding to sought Ls and LT |
---|
378 | call ls2sol(Ls,sol) |
---|
379 | !shift 'sol' decimal part to ensure a compatible LT with the desired one |
---|
380 | sol=floor(sol)+(LT-lon/15.)/24. |
---|
381 | ! handle bordeline cases: |
---|
382 | if (sol.gt.669) sol=sol-669 |
---|
383 | if (sol.lt.0) sol=sol+669 |
---|
384 | |
---|
385 | ! write(*,*) " Ls=",Ls," LT=",LT," => sol=",sol |
---|
386 | |
---|
387 | ! 2.3 do the interpolation |
---|
388 | call extraction(lon,lat,alt,sol,& |
---|
389 | lonlen,latlen,altlen,timelen,& |
---|
390 | longitude,latitude,altitude,time,& |
---|
391 | field,missing_value,alttype,varname,value) |
---|
392 | ! 2.4 Write value to output |
---|
393 | if (extract_mode==1) then ! pointwise extraction |
---|
394 | write(42,'(6(1x,1pe12.5))')lon,lat,alt,Ls,LT,value |
---|
395 | else ! profile |
---|
396 | write(42,'(6(1x,1pe12.5))')alt,value |
---|
397 | endif |
---|
398 | enddo ! of do while |
---|
399 | |
---|
400 | ! close output file |
---|
401 | close(42) |
---|
402 | |
---|
403 | end program extract |
---|
404 | |
---|
405 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
---|
406 | subroutine extraction(lon,lat,alt,sol,& |
---|
407 | lonlen,latlen,altlen,timelen,& |
---|
408 | longitude,latitude,altitude,time,& |
---|
409 | field,missing_value,alttype,varname,value) |
---|
410 | |
---|
411 | implicit none |
---|
412 | ! Arguments: |
---|
413 | real,intent(in) :: lon ! sought longitude (deg, in [-180:180]) |
---|
414 | real,intent(in) :: lat ! sought latitude (deg, in [-90:90]) |
---|
415 | real,intent(in) :: alt ! sought altitude (m or Pa) |
---|
416 | real,intent(in) :: sol ! sought date (sols) |
---|
417 | integer,intent(in) :: lonlen |
---|
418 | integer,intent(in) :: latlen |
---|
419 | integer,intent(in) :: altlen |
---|
420 | integer,intent(in) :: timelen |
---|
421 | real,intent(in) :: longitude(lonlen) |
---|
422 | real,intent(in) :: latitude(latlen) |
---|
423 | real,intent(in) :: altitude(altlen) |
---|
424 | real,intent(in) :: time(timelen) |
---|
425 | real,intent(in) :: field(lonlen,latlen,altlen,timelen) |
---|
426 | real,intent(in) :: missing_value ! default value in GCM file for "no data" |
---|
427 | character,intent(in) :: alttype ! altitude coord. type:'z' (altitude, m) |
---|
428 | ! 'p' (pressure, Pa) |
---|
429 | character(len=*),intent(in) :: varname ! variable name (in GCM file) |
---|
430 | real,intent(out) :: value |
---|
431 | |
---|
432 | ! Local variables: |
---|
433 | real,save :: prev_lon=-99 ! previous value of 'lon' routine was called with |
---|
434 | real,save :: prev_lat=-99 ! previous value of 'lat' routine was called with |
---|
435 | real,save :: prev_alt=-9.e20 ! ! previous value of 'alt' |
---|
436 | real,save :: prev_sol=-99 ! previous value of 'sol' routine was called with |
---|
437 | |
---|
438 | ! encompasing indexes: |
---|
439 | integer,save :: ilon_inf=-1,ilon_sup=-1 ! along longitude |
---|
440 | integer,save :: ilat_inf=-1,ilat_sup=-1 ! along latitude |
---|
441 | integer,save :: ialt_inf=-1,ialt_sup=-1 ! along altitude |
---|
442 | integer,save :: itim_inf=-1,itim_sup=-1 ! along time |
---|
443 | |
---|
444 | ! intermediate interpolated values |
---|
445 | real :: t_interp(2,2,2) ! after time interpolation |
---|
446 | real :: zt_interp(2,2) ! after altitude interpolation |
---|
447 | real :: yzt_interp(2) ! after latitude interpolation |
---|
448 | real :: coeff ! interpolation coefficient |
---|
449 | |
---|
450 | integer :: i |
---|
451 | |
---|
452 | ! By default, set value to missing_value |
---|
453 | value=missing_value |
---|
454 | |
---|
455 | ! 1. Find encompassing indexes |
---|
456 | if (lon.ne.prev_lon) then |
---|
457 | do i=1,lonlen-1 |
---|
458 | if (longitude(i).le.lon) then |
---|
459 | ilon_inf=i |
---|
460 | else |
---|
461 | exit |
---|
462 | endif |
---|
463 | enddo |
---|
464 | ilon_sup=ilon_inf+1 |
---|
465 | endif ! of if (lon.ne.prev_lon) |
---|
466 | !write(*,*) 'ilon_inf=',ilon_inf," longitude(ilon_inf)=",longitude(ilon_inf) |
---|
467 | |
---|
468 | if (lat.ne.prev_lat) then |
---|
469 | ! recall that latitudes start from north pole |
---|
470 | do i=1,latlen-1 |
---|
471 | if (latitude(i).ge.lat) then |
---|
472 | ilat_inf=i |
---|
473 | else |
---|
474 | exit |
---|
475 | endif |
---|
476 | enddo |
---|
477 | ilat_sup=ilat_inf+1 |
---|
478 | endif ! of if (lat.ne.prev_lat) |
---|
479 | !write(*,*) 'ilat_inf=',ilat_inf," latitude(ilat_inf)=",latitude(ilat_inf) |
---|
480 | |
---|
481 | if (alt.ne.prev_alt) then |
---|
482 | if (alttype.eq.'p') then ! pressures are ordered from max to min |
---|
483 | !handle special case for alt not in the altitude(1:altlen) interval |
---|
484 | if ((alt.gt.altitude(1)).or.(alt.lt.altitude(altlen))) then |
---|
485 | ialt_inf=-1 |
---|
486 | ialt_sup=-1 |
---|
487 | ! return to main program (with value=missing_value) |
---|
488 | return |
---|
489 | else ! general case |
---|
490 | do i=1,altlen-1 |
---|
491 | if (altitude(i).ge.alt) then |
---|
492 | ialt_inf=i |
---|
493 | else |
---|
494 | exit |
---|
495 | endif |
---|
496 | enddo |
---|
497 | ialt_sup=ialt_inf+1 |
---|
498 | endif ! of if ((alt.gt.altitude(1)).or.(alt.lt.altitude(altlen))) |
---|
499 | else ! altitudes (m) are ordered from min to max |
---|
500 | !handle special case for alt not in the altitude(1:altlen) interval |
---|
501 | if ((alt.lt.altitude(1)).or.(alt.gt.altitude(altlen))) then |
---|
502 | ialt_inf=-1 |
---|
503 | ialt_sup=-1 |
---|
504 | ! return to main program (with value=missing_value) |
---|
505 | return |
---|
506 | else ! general case |
---|
507 | do i=1,altlen-1 |
---|
508 | if (altitude(i).le.alt) then |
---|
509 | ialt_inf=i |
---|
510 | else |
---|
511 | exit |
---|
512 | endif |
---|
513 | enddo |
---|
514 | ialt_sup=ialt_inf+1 |
---|
515 | endif ! of if ((alt.lt.altitude(1)).or.(alt.gt.altitude(altlen))) |
---|
516 | endif ! of if (alttype.eq.'p') |
---|
517 | endif ! of if (alt.ne.prev_alt) |
---|
518 | !write(*,*) 'ialt_inf=',ialt_inf," altitude(ialt_inf)=",altitude(ialt_inf) |
---|
519 | |
---|
520 | if (sol.ne.prev_sol) then |
---|
521 | !handle special case for sol not in the time(1):time(timenlen) interval |
---|
522 | if ((sol.lt.time(1)).or.(sol.gt.time(timelen))) then |
---|
523 | itim_inf=-1 |
---|
524 | itim_sup=-1 |
---|
525 | ! return to main program (with value=missing_value) |
---|
526 | return |
---|
527 | else ! general case |
---|
528 | do i=1,timelen-1 |
---|
529 | if (time(i).le.sol) then |
---|
530 | itim_inf=i |
---|
531 | else |
---|
532 | exit |
---|
533 | endif |
---|
534 | enddo |
---|
535 | itim_sup=itim_inf+1 |
---|
536 | endif ! of if ((sol.lt.time(1)).or.(sol.gt.time(timenlen))) |
---|
537 | endif ! of if (sol.ne.prev_sol) |
---|
538 | !write(*,*) 'itim_inf=',itim_inf," time(itim_inf)=",time(itim_inf) |
---|
539 | !write(*,*) 'itim_sup=',itim_sup," time(itim_sup)=",time(itim_sup) |
---|
540 | |
---|
541 | ! 2. Interpolate |
---|
542 | ! check that there are no "missing_value" in the field() elements we need |
---|
543 | ! otherwise return to main program (with value=missing_value) |
---|
544 | if (field(ilon_inf,ilat_inf,ialt_inf,itim_inf).eq.missing_value) return |
---|
545 | if (field(ilon_inf,ilat_inf,ialt_inf,itim_sup).eq.missing_value) return |
---|
546 | if (field(ilon_inf,ilat_inf,ialt_sup,itim_inf).eq.missing_value) return |
---|
547 | if (field(ilon_inf,ilat_inf,ialt_sup,itim_sup).eq.missing_value) return |
---|
548 | if (field(ilon_inf,ilat_sup,ialt_inf,itim_inf).eq.missing_value) return |
---|
549 | if (field(ilon_inf,ilat_sup,ialt_inf,itim_sup).eq.missing_value) return |
---|
550 | if (field(ilon_inf,ilat_sup,ialt_sup,itim_inf).eq.missing_value) return |
---|
551 | if (field(ilon_inf,ilat_sup,ialt_sup,itim_sup).eq.missing_value) return |
---|
552 | if (field(ilon_sup,ilat_inf,ialt_inf,itim_inf).eq.missing_value) return |
---|
553 | if (field(ilon_sup,ilat_inf,ialt_inf,itim_sup).eq.missing_value) return |
---|
554 | if (field(ilon_sup,ilat_inf,ialt_sup,itim_inf).eq.missing_value) return |
---|
555 | if (field(ilon_sup,ilat_inf,ialt_sup,itim_sup).eq.missing_value) return |
---|
556 | if (field(ilon_sup,ilat_sup,ialt_inf,itim_inf).eq.missing_value) return |
---|
557 | if (field(ilon_sup,ilat_sup,ialt_inf,itim_sup).eq.missing_value) return |
---|
558 | if (field(ilon_sup,ilat_sup,ialt_sup,itim_inf).eq.missing_value) return |
---|
559 | if (field(ilon_sup,ilat_sup,ialt_sup,itim_sup).eq.missing_value) return |
---|
560 | |
---|
561 | ! 2.1 Linear interpolation in time |
---|
562 | coeff=(sol-time(itim_inf))/(time(itim_sup)-time(itim_inf)) |
---|
563 | t_interp(1,1,1)=field(ilon_inf,ilat_inf,ialt_inf,itim_inf)+ & |
---|
564 | coeff*(field(ilon_inf,ilat_inf,ialt_inf,itim_sup)- & |
---|
565 | field(ilon_inf,ilat_inf,ialt_inf,itim_inf)) |
---|
566 | t_interp(1,1,2)=field(ilon_inf,ilat_inf,ialt_sup,itim_inf)+ & |
---|
567 | coeff*(field(ilon_inf,ilat_inf,ialt_sup,itim_sup)- & |
---|
568 | field(ilon_inf,ilat_inf,ialt_sup,itim_inf)) |
---|
569 | t_interp(1,2,1)=field(ilon_inf,ilat_sup,ialt_inf,itim_inf)+ & |
---|
570 | coeff*(field(ilon_inf,ilat_sup,ialt_inf,itim_sup)- & |
---|
571 | field(ilon_inf,ilat_sup,ialt_inf,itim_inf)) |
---|
572 | t_interp(1,2,2)=field(ilon_inf,ilat_sup,ialt_sup,itim_inf)+ & |
---|
573 | coeff*(field(ilon_inf,ilat_sup,ialt_sup,itim_sup)- & |
---|
574 | field(ilon_inf,ilat_sup,ialt_sup,itim_inf)) |
---|
575 | t_interp(2,1,1)=field(ilon_sup,ilat_inf,ialt_inf,itim_inf)+ & |
---|
576 | coeff*(field(ilon_sup,ilat_inf,ialt_inf,itim_sup)- & |
---|
577 | field(ilon_sup,ilat_inf,ialt_inf,itim_inf)) |
---|
578 | t_interp(2,1,2)=field(ilon_sup,ilat_inf,ialt_sup,itim_inf)+ & |
---|
579 | coeff*(field(ilon_sup,ilat_inf,ialt_sup,itim_sup)- & |
---|
580 | field(ilon_sup,ilat_inf,ialt_sup,itim_inf)) |
---|
581 | t_interp(2,2,1)=field(ilon_sup,ilat_sup,ialt_inf,itim_inf)+ & |
---|
582 | coeff*(field(ilon_sup,ilat_sup,ialt_inf,itim_sup)- & |
---|
583 | field(ilon_sup,ilat_sup,ialt_inf,itim_inf)) |
---|
584 | t_interp(2,2,2)=field(ilon_sup,ilat_sup,ialt_sup,itim_inf)+ & |
---|
585 | coeff*(field(ilon_sup,ilat_sup,ialt_sup,itim_sup)- & |
---|
586 | field(ilon_sup,ilat_sup,ialt_sup,itim_inf)) |
---|
587 | |
---|
588 | ! 2.2 Vertical interpolation |
---|
589 | if (((varname=='rho').or.(varname=='pressure')).and.(alttype=='z')) then |
---|
590 | ! do the interpolation on the log of the quantity |
---|
591 | coeff=(alt-altitude(ialt_inf))/(altitude(ialt_sup)-altitude(ialt_inf)) |
---|
592 | zt_interp(1,1)=log(t_interp(1,1,1))+coeff* & |
---|
593 | (log(t_interp(1,1,2))-log(t_interp(1,1,1))) |
---|
594 | zt_interp(1,2)=log(t_interp(1,2,1))+coeff* & |
---|
595 | (log(t_interp(1,2,2))-log(t_interp(1,2,1))) |
---|
596 | zt_interp(2,1)=log(t_interp(2,1,1))+coeff* & |
---|
597 | (log(t_interp(2,1,2))-log(t_interp(2,1,1))) |
---|
598 | zt_interp(2,2)=log(t_interp(2,2,1))+coeff* & |
---|
599 | (log(t_interp(2,2,2))-log(t_interp(2,2,1))) |
---|
600 | zt_interp(1:2,1:2)=exp(zt_interp(1:2,1:2)) |
---|
601 | else ! general case |
---|
602 | coeff=(alt-altitude(ialt_inf))/(altitude(ialt_sup)-altitude(ialt_inf)) |
---|
603 | zt_interp(1,1)=t_interp(1,1,1)+coeff*(t_interp(1,1,2)-t_interp(1,1,1)) |
---|
604 | zt_interp(1,2)=t_interp(1,2,1)+coeff*(t_interp(1,2,2)-t_interp(1,2,1)) |
---|
605 | zt_interp(2,1)=t_interp(2,1,1)+coeff*(t_interp(2,1,2)-t_interp(2,1,1)) |
---|
606 | zt_interp(2,2)=t_interp(2,2,1)+coeff*(t_interp(2,2,2)-t_interp(2,2,1)) |
---|
607 | endif |
---|
608 | |
---|
609 | ! 2.3 Latitudinal interpolation |
---|
610 | coeff=(lat-latitude(ilat_inf))/(latitude(ilat_sup)-latitude(ilat_inf)) |
---|
611 | yzt_interp(1)=zt_interp(1,1)+coeff*(zt_interp(1,2)-zt_interp(1,1)) |
---|
612 | yzt_interp(2)=zt_interp(2,1)+coeff*(zt_interp(2,2)-zt_interp(2,1)) |
---|
613 | |
---|
614 | ! 2.4 longitudinal interpolation |
---|
615 | coeff=(lon-longitude(ilon_inf))/(longitude(ilon_sup)-longitude(ilon_inf)) |
---|
616 | value=yzt_interp(1)+coeff*(yzt_interp(2)-yzt_interp(1)) |
---|
617 | |
---|
618 | end subroutine extraction |
---|
619 | |
---|
620 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
---|
621 | subroutine ls2sol(ls,sol) |
---|
622 | |
---|
623 | implicit none |
---|
624 | ! Arguments: |
---|
625 | real,intent(in) :: ls |
---|
626 | real,intent(out) :: sol |
---|
627 | |
---|
628 | ! Local: |
---|
629 | double precision xref,zx0,zteta,zz |
---|
630 | !xref: mean anomaly, zteta: true anomaly, zx0: eccentric anomaly |
---|
631 | double precision year_day |
---|
632 | double precision peri_day,timeperi,e_elips |
---|
633 | double precision pi,degrad |
---|
634 | parameter (year_day=668.6d0) ! number of sols in a martian year |
---|
635 | parameter (peri_day=485.35d0) ! date (in sols) of perihelion |
---|
636 | ! timeperi: 2*pi*( 1 - Ls(perihelion)/ 360 ); Ls(perihelion)=250.99 |
---|
637 | parameter (timeperi=1.90258341759902d0) |
---|
638 | parameter (e_elips=0.0934d0) ! eccentricity of orbit |
---|
639 | parameter (pi=3.14159265358979d0) |
---|
640 | parameter (degrad=57.2957795130823d0) |
---|
641 | |
---|
642 | if (abs(ls).lt.1.0e-5) then |
---|
643 | if (ls.ge.0.0) then |
---|
644 | sol = 0.0 |
---|
645 | else |
---|
646 | sol = real(year_day) |
---|
647 | end if |
---|
648 | return |
---|
649 | end if |
---|
650 | |
---|
651 | zteta = ls/degrad + timeperi |
---|
652 | zx0 = 2.0*datan(dtan(0.5*zteta)/dsqrt((1.+e_elips)/(1.-e_elips))) |
---|
653 | xref = zx0-e_elips*dsin(zx0) |
---|
654 | zz = xref/(2.*pi) |
---|
655 | sol = real(zz*year_day + peri_day) |
---|
656 | if (sol.lt.0.0) sol = sol + real(year_day) |
---|
657 | if (sol.ge.year_day) sol = sol - real(year_day) |
---|
658 | |
---|
659 | |
---|
660 | end subroutine ls2sol |
---|
661 | |
---|