Changeset 2238 for trunk/LMDZ.MARS/util


Ignore:
Timestamp:
Feb 4, 2020, 6:46:34 PM (5 years ago)
Author:
abierjon
Message:

Mars GCM:
Small improvements in simu_MCS_temp.F90 : 1) The binning method is now more consistent with the MCS file ; 2) stats files are more rigorously recognized.
AB

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/LMDZ.MARS/util/simu_MCS_temp.F90

    r2202 r2238  
    88!===================================================================================================
    99! This program loads Observer's data file (MCS-type, binned by Luca Montabone), serving as a
    10 ! reference, then extract the dayside and nightside temperature data from either :
     10! reference, then extracts the dayside and nightside temperature data from either :
    1111!       - a GCM simulation (diagfi.nc) that covers the observation period,
    1212!       - a GCM stats file (stats.nc) after extending it to cover the observation period.
     
    1515! the Observer's spatial coordinates, at every GCM sol value in each 5°-interval of Ls, before
    1616! being averaged to create output bins for each interval. The binning in sols also takes into
    17 ! account the variability of Local Time in the bin and try to represent it too.
     17! account the variability of Local Time in the bin and tries to represent it (with a number of
     18! LT values in each sol bin equal to the number of values in each MCS bin, and centered
     19! around the corresponding MCS bin LT average).
    1820!
    19 ! Eventually, the program outputs a netcdf file, filled with the output bin's data and edited with
     21! Eventually, the program outputs a netcdf file, filled with the GCM binned data and edited with
    2022! the same format than the MCS file (and with the same dimensions' declaration order).
    2123!
    2224! Minimal requirements :
    23 !     - the MCS file must contain the variables dtemp,dtimeave,dtimemax,dtimemin,
    24 !                                               ntemp,ntimeave,ntimemax,ntimemin
    25 !     - the GCM file must : contain the variable temp (atmospheric temperature) ;
    26 !                           have the same altitude type as the MCS file ;
    27 !                           cover completely the NON-BINNED observation period
    28 !     - if the GCM file is a stats file, please name it with "stats" in it (to be changed in the future)
     25!     - the MCS file must contain the variables dtemp,dtimeave,dtimemax,dtimemin,dnumbintemp,
     26!                                               ntemp,ntimeave,ntimemax,ntimemin,nnumbintemp
     27!     - the GCM file must : # contain the variable temp (atmospheric temperature) ;
     28!                           # have the same altitude type as the MCS file ;
     29!                           # cover completely the observation period
    2930!
    3031! See also NOTA BENE in section 1.3
    3132! More details can also be found in my internship report (in French) :
    3233!           /planeto/abierjon/rapportstage2019/Rapport_de_PFE_Master_Bierjon_2019.pdf
    33 ! or directly in my office !
    3434!===================================================================================================
    3535
    3636
    3737use netcdf
     38
    3839
    3940!===================================================================================================
     
    4344implicit none ! for no implicitly typed variables
    4445
     46!------------------------
    4547! Files:
    4648character(len=256) :: gcmfile ! GCM simulation file
     
    4951character(len=256) :: outfile ! output file
    5052
     53!------------------------
    5154! NetCDF stuff
    5255integer :: status ! NetCDF routines return code
     
    5558integer :: obsfid ! NetCDF observation file ID
    5659integer :: outfid ! NetCDF output file ID
    57 integer :: GCMvarid, OBSvarid, LT_id, outvarid ! to store the ID of a variable
     60integer :: GCMvarid, OBSvarid, LT_id, numbin_id, outvarid ! to store the ID of a variable
    5861integer :: lat_dimid_obs,lon_dimid_obs,alt_dimid_obs,time_dimid_obs ! dimensions' ID in OBS and output files
    5962integer :: lat_dimid_gcm,lon_dimid_gcm,alt_dimid_gcm,time_dimid_gcm ! dimensions' ID in GCM file
    60 integer :: GCMvarshape(4), OBSvarshape(4), LTshape(3) ! to store a variable's coordinates order
    61 integer :: nb
    62 
     63integer :: GCMvarshape(4), OBSvarshape(4), LTshape(3),numbinshape(4) ! to store a variable's coordinates order
     64integer :: nb ! nb of dimensions of a variable
     65
     66!------------------------
     67! Dimensions
    6368real,dimension(:),allocatable :: GCMlon, OBSlon ! longitude in the GCM & the Observer files
    6469integer GCMlonlen, OBSlonlen ! # of grid points along GCMlon & OBSlon
    65 
    6670real,dimension(:),allocatable :: GCMlat, OBSlat ! latitude in the GCM & the Observer files
    6771integer GCMlatlen, OBSlatlen ! # of grid points along GCMlat & OBSlat
    68 
    6972real,dimension(:),allocatable :: GCMalt, OBSalt ! can be geometric heights or pressure
    7073integer GCMaltlen, OBSaltlen ! # of grid point along GCMalt & OBSalt
    7174character (len=256) :: units ! to store the units attribute of altitude
    7275character(len=1) :: GCMalttype, OBSalttype ! altitude coord. type:'z' (altitude, m) 'p' (pressure, Pa)
    73 
    7476real,dimension(:),allocatable :: GCMtime, OBSLs ! time in the GCM diagfi (sols) & the Observer files (Ls)
    7577real,dimension(:),allocatable :: GCMstatstime ! time in the GCM stats file (LT at lon 0°)
     
    7779real :: starttimeoffset=0 ! offset (in sols) wrt Ls=0 of sol 0 in GCM file
    7880
     81!------------------------
     82! Variables
    7983character (len=64) :: GCMvarname, OBSvarname ! to store the name of the variable to retrieve
    8084real,dimension(:,:,:,:),allocatable :: GCM_var,OBS_var ! the 4D variable extracted from GCM & OBS files
    8185character (len=64) :: OBSLTave_name, OBSLTmax_name, OBSLTmin_name ! to store the name of the average, max and min of LT (ex : dtimeave, ntimemax...)
    8286real,dimension(:,:,:),allocatable :: OBSLT, OBSLTmax, OBSLTmin ! 3D variables extracted from obsfile (average, max and min of LT in a bin)
     87character (len=64) :: numbin_name ! to store the name of the nb of values in an OBS temp bin (dnumbintemp/nnumbintemp)
     88real,dimension(:,:,:,:),allocatable :: numbintemp ! nb of values in an OBS temp bin
    8389real :: GCMmiss_val, OBSmiss_val, LTmiss_val ! value to denote non-existant data
    8490real :: extr_value ! to store the result of the extraction subroutine
    85 
     91real, dimension(:,:,:,:), allocatable :: outvar ! outvar(,,,): 4D array to store the output variable's data
     92
     93!------------------------
     94! Time binning management
    8695real :: OBSdeltaLs ! difference of Ls between each observation bin
    8796real :: sol, maxsol, minsol ! sol date corresponding to Observed Ls and LT
    8897integer :: m_maxsol, m_minsol ! indexes of the maximum and minimum GCM sol taken in a bin for interpolation
    8998
    90 real,dimension(:,:,:),allocatable :: LTmod_arraymax, LTmod_arraymin ! declaration of the type of the function LTmod_array
     99external LTmod ! declaration of the function LTmod
    91100real :: LTmod ! declaration of the type of the function LTmod
    92 real :: maxLTvar ! maximum variability of LT within one MCS bin
    93 integer :: LTcount ! nb of LT samples on which the interpolation is performed, for every LT interval
     101integer :: LTcount ! nb of LT samples on which the interpolation is performed, for every LT interval = numbintemp[lon,lat,alt,Ls]
    94102
    95103integer :: solcount ! number of GCM sol integer values in one Ls interval
     
    99107integer :: errcount = 0 ! total number of GCM missing values
    100108real :: solbinned_value ! to store the extracted value averaged on sol samples, which is finally put in the output bin
    101 real :: GCMdeltat ! timestep of the GCM simulation (in Martian hours)
    102 
     109
     110!------------------------
     111! Extraction & loop indexes
    103112real :: lon_val, lat_val, alt_val, Ls_val, LT_val ! where and when the output file is written at
    104113
     
    106115integer :: m,m_int,n ! sol binning loops iteration index
    107116
    108 real, dimension(:,:,:,:), allocatable :: outvar ! outvar(,,,): 4D array to store the output variable's data
    109117
    110118!===================================================================================================
     
    228236!===============================================================================
    229237
    230 ! Observer variables to extract :
    231238!******************** NOTA BENE (cf sections 1.3 and 4)*************************
    232239! We execute the program a first time with the daytime values, and then a second
     
    234241! independent of this distinction, hence we execute them only in the first loop,
    235242! when OBSvarname="dtemp". It also implies a lot of IF (when it's only executed in
    236 ! the first loop) or CASE (when it's executed in both loops but depends on wether
     243! the first loop) or CASE (when it's executed in both loops but depends on whether
    237244! it is daytime or nighttime).
    238 ! This should be changed one day with a cleaner version of the code...
     245! This may be changed one day with a cleaner version of the code...
    239246!*******************************************************************************
     247
     248! Observer variables to extract :
    240249OBSvarname="dtemp" ! we begin with daytime temperature
    241250write(*,*)"" ; write(*,*) "Beginning the 1st loop, on daytime values"; write(*,*)""
     
    304313    OBSLTmax_name = "dtimemax"
    305314    OBSLTmin_name = "dtimemin"
     315    numbin_name   = "dnumbintemp"
    306316  CASE ("ntemp")
    307317    OBSLTave_name = "ntimeave"
    308318    OBSLTmax_name = "ntimemax"
    309319    OBSLTmin_name = "ntimemin"
     320    numbin_name   = "nnumbintemp"
    310321  END SELECT
    311322 
     323  ! Get the average values of LT in the OBS bins
    312324  status=nf90_inq_varid(obsfid,trim(OBSLTave_name),LT_id)
    313   error_text="Failed to find Observer local time ("//trim(OBSLTave_name)//") dimension"
     325  error_text="Failed to find Observer local time ("//trim(OBSLTave_name)//") ID in "//trim(obsfile)
    314326  call status_check(status,error_text)
    315327  ! Sanity checks on the variable
     
    351363  ! Get the maximum values of LT in the OBS bins
    352364  status=nf90_inq_varid(obsfid,trim(OBSLTmax_name),LT_id)
    353   error_text="Failed to find Observer max local time ("//trim(OBSLTmax_name)//") dimension"
     365  error_text="Failed to find Observer max local time ("//trim(OBSLTmax_name)//") ID in "//trim(obsfile)
    354366  call status_check(status,error_text)
    355367  ! Sanity checks on the variable
     
    386398  ! Get the minimum values of LT in the OBS bins
    387399  status=nf90_inq_varid(obsfid,trim(OBSLTmin_name),LT_id)
    388   error_text="Failed to find Observer min local time ("//trim(OBSLTmin_name)//") dimension"
     400  error_text="Failed to find Observer min local time ("//trim(OBSLTmin_name)//") ID in "//trim(obsfile)
    389401  call status_check(status,error_text)
    390402  ! Sanity checks on the variable
     
    418430  write(*,*) "Loaded ", trim(OBSLTmin_name), " from the obsfile"
    419431
    420  
    421   SELECT CASE (OBSvarname)
    422   CASE ("dtemp")
    423     maxLTvar=maxval((OBSLTmax(:,:,:)-OBSLTmin(:,:,:)))
    424     write(*,*)"The max daytime LT variability is ",maxLTvar,"hours (within a same bin)"
    425   CASE ("ntemp")
    426     ! in case of night local times, we replace hours from a [0;24[ interval to a
    427     ! [-12;12[ interval in which midnight = 0, with the subroutine LTmod
    428     allocate(LTmod_arraymax(OBSlonlen,OBSlatlen,OBSLslen))
    429     allocate(LTmod_arraymin(OBSlonlen,OBSlatlen,OBSLslen))
    430     do i=1,OBSlonlen
    431       do j=1,OBSlatlen
    432         do l=1,OBSLslen
    433           LTmod_arraymax(i,j,l) = LTmod(OBSLTmax(i,j,l))
    434           LTmod_arraymin(i,j,l) = LTmod(OBSLTmin(i,j,l))
    435         enddo
    436       enddo
    437     enddo
    438     maxLTvar=maxval(LTmod_arraymax(:,:,:) - LTmod_arraymin(:,:,:))
    439     write(*,*)"The max nighttime LT variability is ",maxLTvar,"hours (within a same bin)"
    440   END SELECT
    441  
    442   LTcount=floor(maxLTvar) ! integer nb of hours fitting in the broadest interval of LT
     432
     433  ! Get the number of values of temp in the OBS bins
     434  status=nf90_inq_varid(obsfid,trim(numbin_name),numbin_id)
     435  error_text="Failed to find Observer nb of temp values in bin ("//trim(numbin_name)//")'s ID in "//trim(obsfile)
     436  call status_check(status,error_text)
     437  ! Sanity checks on the variable
     438  status=nf90_inquire_variable(obsfid,numbin_id,ndims=nb,dimids=numbinshape)
     439  error_text="Failed to obtain information on variable "//trim(numbin_name)
     440  call status_check(status,error_text)
     441  ! Check that it is a 4D variable
     442  if (nb.ne.4) then
     443    write(*,*) "Error, expected a 4D (lon-lat-alt-time) variable for of ", trim(numbin_name), "!"
     444    stop
     445  endif
     446  ! Check that its dimensions are indeed lon,lat,alt,time (in the right order)
     447  if (numbinshape(1).ne.lon_dimid_obs) then
     448    write(*,*) "Error, expected first dimension of ", trim(numbin_name), " to be longitude!"
     449    stop
     450  endif
     451  if (numbinshape(2).ne.lat_dimid_obs) then
     452    write(*,*) "Error, expected second dimension of ", trim(numbin_name), " to be latitude!"
     453    stop
     454  endif
     455  if (numbinshape(3).ne.alt_dimid_obs) then
     456    write(*,*) "Error, expected third dimension of ", trim(numbin_name), " to be altitude!"
     457    stop
     458  endif
     459  if (numbinshape(4).ne.time_dimid_obs) then
     460    write(*,*) "Error, expected fourth dimension of ", trim(numbin_name), " to be time!"
     461    stop
     462  endif
     463  ! Length allocation for each dimension of the 4D variable
     464  allocate(numbintemp(OBSlonlen,OBSlatlen,OBSaltlen,OBSLslen))
     465  ! Load datasets
     466  status=nf90_get_var(obsfid,numbin_id,numbintemp)
     467  error_text="Failed to load "//trim(numbin_name)//" from the obsfile"
     468  call status_check(status,error_text)
     469  write(*,*) "Loaded ", trim(numbin_name), " from the obsfile"
    443470
    444471!===================================================================================================
     
    453480    write(*,*)"";write(*,*) "-> Enter input file name (GCM simulation) :"
    454481    read(*,*) gcmfile
    455     if (index(gcmfile,"stats").ne.0) then ! if the GCM file name contains "stats", we assume it is a stats file
    456     ! => A REMPLACER PAR UN TEST SUR LA DIMENSION TIME ? REGARDER DANS AUTRES UTILITAIRES
    457       is_stats = .true.
    458       write(*,*)"The GCM file is recognized as a stats file."
    459     else
    460       write(*,*)"The GCM file is recognized as a diagfi/concatnc file."
    461     endif
    462482
    463483    ! Open GCM file
     
    512532    ! GCM Time
    513533    status=nf90_inq_dimid(gcmfid,"Time",time_dimid_gcm)
    514     error_text="Failed to find GCM time (sols) dimension"
    515     call status_check(status,error_text)
    516 
    517     if (.not.is_stats) then
    518       status=nf90_inquire_dimension(gcmfid,time_dimid_gcm,len=GCMtimelen)
    519       error_text="Failed to find GCM time length"
    520       call status_check(status,error_text)
    521       allocate(GCMtime(GCMtimelen))
    522     else
    523       status=nf90_inquire_dimension(gcmfid,time_dimid_gcm,len=GCMstatstimelen)
    524       error_text="Failed to find GCM stats time length"
    525       call status_check(status,error_text)
    526       allocate(GCMstatstime(GCMstatstimelen))
    527     endif
    528 
     534    error_text="Failed to find GCM time dimension"
     535    call status_check(status,error_text)
     536
     537    status=nf90_inquire_dimension(gcmfid,time_dimid_gcm,len=GCMtimelen)
     538    error_text="Failed to find GCM time length"
     539    call status_check(status,error_text)
     540    allocate(GCMtime(GCMtimelen))
     541   
    529542    status=nf90_inq_varid(gcmfid,"Time",GCMvarid)
    530543    error_text="Failed to find GCM time ID"
    531544    call status_check(status,error_text)
    532 
    533     ! Read GCMtime
    534     if (.not.is_stats) then ! if GCM file is a diagfi, time is in sols at longitude 0°
    535       status=nf90_get_var(gcmfid,GCMvarid,GCMtime)
    536       error_text="Failed to load GCMtime (sols)"
    537       call status_check(status,error_text)
    538     else ! if GCM file is a stats, time is in LT at longitude 0°
     545   
     546    status=nf90_get_var(gcmfid,GCMvarid,GCMtime)
     547    error_text="Failed to load GCMtime"
     548    call status_check(status,error_text)
     549
     550    ! is_stats ?
     551    if ((GCMtimelen.eq.12).and.(GCMtime(1).eq.2.).and.(GCMtime(GCMtimelen).eq.24.)) then
     552      ! if GCM file is a stats, time is in LT at longitude 0° and not in sols at longitude 0°
     553      write(*,*)"The GCM file is recognized as a stats file."
     554      is_stats = .true.
     555      deallocate(GCMtime)
     556      GCMstatstimelen = GCMtimelen
     557      allocate(GCMstatstime(GCMstatstimelen))
    539558      status=nf90_get_var(gcmfid,GCMvarid,GCMstatstime)
    540559      error_text="Failed to load GCMstatstime (LT at lon 0)"
    541560      call status_check(status,error_text)
     561    else
     562      write(*,*)"The GCM file is recognized as a diagfi/concatnc file."
    542563    endif
    543564
     
    550571      GCMtime(:)=GCMtime(:)+starttimeoffset
    551572    endif
    552 
    553     ! Get the timestep of the simulation (in Martian hours)
    554     if (.not.is_stats) then
    555       GCMdeltat = (GCMtime(2)-GCMtime(1))*24.
    556     else
    557       GCMdeltat = (GCMstatstime(2)-GCMstatstime(1))
    558     endif
    559     write(*,*)"GCM simulation's timestep is ", GCMdeltat, " hours."
    560573
    561574    ! Check of temporal coherence between gcmfile & obsfile
     
    749762  error_text="Error: could not define the variable "//trim(OBSLTave_name)//" in the outfile"
    750763  call status_check(status,error_text)
     764 
     765  status=nf90_def_var(outfid,trim(numbin_name),nf90_float,numbinshape,numbin_id)
     766  error_text="Error: could not define the variable "//trim(numbin_name)//" in the outfile"
     767  call status_check(status,error_text)
    751768
    752769  ! Write the attributes
     
    792809  write(*,*)"Local Time (", trim(OBSLTave_name), ") has been created in the outfile"
    793810  write(*,'("  with missing_value attribute : ",1pe12.5)')OBSmiss_val
     811 
     812  !! Number of temp values in bin
     813  SELECT CASE (OBSvarname)
     814  CASE ("dtemp")
     815    status=nf90_put_att(outfid,numbin_id,"long_name","Number of temp values in bin - day side")
     816  CASE ("ntemp")
     817    status=nf90_put_att(outfid,numbin_id,"long_name","Number of temp values in bin - night side")
     818  END SELECT
     819  error_text="Error: could not put the long_name attribute for the variable "//trim(numbin_name)//" in the outfile"
     820  call status_check(status,error_text)
     821
     822  write(*,*)"Number of temp values in bin (", trim(numbin_name), ") has been created in the outfile"
     823 
    794824
    795825  ! End the netcdf define mode (and thus enter the "data writing" mode)
     
    867897        if (lon_val.gt.180.) lon_val=lon_val-360.
    868898
    869         LT_val=OBSLT(i,j,l) ! find the Observer corresponding LT value at lon_val, lat_val, Ls_val
    870        
     899        LT_val=OBSLT(i,j,l) ! find the Observer average LT value at bin(lon_val, lat_val, Ls_val)
     900       
    871901        if ((LT_val.lt.0.).or.(LT_val.gt.24.)) then
    872902          if (LT_val.eq.LTmiss_val) then
     
    880910          endif
    881911        endif
    882         ! Generate the sol list for the interpolation
    883         allocate(sol_list(solcount*LTcount))
    884         call gen_sol_list(solcount,int_sol_list,LTcount,LT_val,OBSLTmax(i,j,l),OBSLTmin(i,j,l),lon_val,LTmod,OBSvarname,&
    885                           sol_list)
    886912
    887913        altitude: do k=1,OBSaltlen ! loop on all observed altitudes
     
    897923!! 3.3.2 Compute GCM sol date corresponding to Observer Ls
    898924!!       (via m_(min/max)sol) and LT (via OBSLT(min/max))
    899 !!===============================================================       
     925!!===============================================================
     926          LTcount=floor(numbintemp(i,j,k,l)) ! find the Observer number of temp values at bin(lon_val, lat_val, alt_val, Ls_val)
     927          if (LTcount.eq.0.) then
     928            ! Write a missing_value to output
     929            outvar(i,j,k,l)=OBSmiss_val
     930            CYCLE altitude ! go directly to the next altitude
     931          endif
     932          if (LTcount.lt.0.) then
     933            write(*,*) "Unexpected value for LTcount: ",LTcount
     934            stop
     935          endif
     936
     937          ! Generate the sol list for the interpolation
     938          allocate(sol_list(solcount*LTcount))
     939          call gen_sol_list(solcount,int_sol_list,LTcount,LT_val,OBSLTmax(i,j,l),OBSLTmin(i,j,l),lon_val,LTmod,OBSvarname,&
     940                            sol_list)
     941               
    900942          solerrcount=0
    901943          solbinned_value=0
     
    929971
    930972          errcount=errcount+solerrcount
    931 
     973         
     974          deallocate(sol_list)
     975         
    932976        enddo altitude ! end loop on observed altitudes
    933 
    934         deallocate(sol_list)
    935 
    936977      enddo longitude ! end loop on observed longitudes
    937978    enddo latitude ! end loop on observed latitudes
     
    951992
    952993  status = nf90_put_var(outfid, LT_id, OBSLT) ! write the MCS d/ntimeave as the output Local Time
    953   error_text="Error: could not write Local Time data in the outfile"
    954   call status_check(status,error_text)
    955 
     994  error_text="Error: could not write "//trim(OBSLTave_name)//" data in the outfile"
     995  call status_check(status,error_text)
     996 
     997  status = nf90_put_var(outfid, numbin_id, numbintemp)
     998  error_text="Error: could not write "//trim(numbin_name)//" data in the outfile"
     999  call status_check(status,error_text)
     1000 
    9561001!!============================================================================== 
    9571002!! 4. End of the Day/Night loop
     
    9651010    deallocate(OBSLTmax)
    9661011    deallocate(OBSLTmin)
     1012    deallocate(numbintemp)
    9671013    deallocate(outvar)
    9681014    write(*,*)"";write(*,*)""; write(*,*) "Beginning the 2nd loop, on nighttime values" ; write(*,*)""
     
    15621608real, intent(in) :: lon ! longitude value for the transformation into a sol value at lon=0°
    15631609external f_LT ! function that changes LT interval for night LT
    1564 real :: f_LT
     1610real f_LT
    15651611character (len=64), intent(in) :: LTname ! to know if we have day or night values
    15661612
     
    16571703! night local times)
    16581704!================================================================
    1659 real :: LT
     1705implicit none
     1706real,intent(in) :: LT
    16601707
    16611708LTmod = 2*mod(LT,12.)-LT
Note: See TracChangeset for help on using the changeset viewer.