source: trunk/LMDZ.MARS/util/extract.F90 @ 282

Last change on this file since 282 was 282, checked in by emillour, 13 years ago

Ajout utilitaire "extract" pour sorties GCM Mars.
EM

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