Changeset 2238 for trunk/LMDZ.MARS/util
- Timestamp:
- Feb 4, 2020, 6:46:34 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LMDZ.MARS/util/simu_MCS_temp.F90
r2202 r2238 8 8 !=================================================================================================== 9 9 ! 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 : 11 11 ! - a GCM simulation (diagfi.nc) that covers the observation period, 12 12 ! - a GCM stats file (stats.nc) after extending it to cover the observation period. … … 15 15 ! the Observer's spatial coordinates, at every GCM sol value in each 5°-interval of Ls, before 16 16 ! 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). 18 20 ! 19 ! Eventually, the program outputs a netcdf file, filled with the output bin'sdata and edited with21 ! Eventually, the program outputs a netcdf file, filled with the GCM binned data and edited with 20 22 ! the same format than the MCS file (and with the same dimensions' declaration order). 21 23 ! 22 24 ! 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 29 30 ! 30 31 ! See also NOTA BENE in section 1.3 31 32 ! More details can also be found in my internship report (in French) : 32 33 ! /planeto/abierjon/rapportstage2019/Rapport_de_PFE_Master_Bierjon_2019.pdf 33 ! or directly in my office !34 34 !=================================================================================================== 35 35 36 36 37 37 use netcdf 38 38 39 39 40 !=================================================================================================== … … 43 44 implicit none ! for no implicitly typed variables 44 45 46 !------------------------ 45 47 ! Files: 46 48 character(len=256) :: gcmfile ! GCM simulation file … … 49 51 character(len=256) :: outfile ! output file 50 52 53 !------------------------ 51 54 ! NetCDF stuff 52 55 integer :: status ! NetCDF routines return code … … 55 58 integer :: obsfid ! NetCDF observation file ID 56 59 integer :: outfid ! NetCDF output file ID 57 integer :: GCMvarid, OBSvarid, LT_id, outvarid ! to store the ID of a variable60 integer :: GCMvarid, OBSvarid, LT_id, numbin_id, outvarid ! to store the ID of a variable 58 61 integer :: lat_dimid_obs,lon_dimid_obs,alt_dimid_obs,time_dimid_obs ! dimensions' ID in OBS and output files 59 62 integer :: 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 63 integer :: GCMvarshape(4), OBSvarshape(4), LTshape(3),numbinshape(4) ! to store a variable's coordinates order 64 integer :: nb ! nb of dimensions of a variable 65 66 !------------------------ 67 ! Dimensions 63 68 real,dimension(:),allocatable :: GCMlon, OBSlon ! longitude in the GCM & the Observer files 64 69 integer GCMlonlen, OBSlonlen ! # of grid points along GCMlon & OBSlon 65 66 70 real,dimension(:),allocatable :: GCMlat, OBSlat ! latitude in the GCM & the Observer files 67 71 integer GCMlatlen, OBSlatlen ! # of grid points along GCMlat & OBSlat 68 69 72 real,dimension(:),allocatable :: GCMalt, OBSalt ! can be geometric heights or pressure 70 73 integer GCMaltlen, OBSaltlen ! # of grid point along GCMalt & OBSalt 71 74 character (len=256) :: units ! to store the units attribute of altitude 72 75 character(len=1) :: GCMalttype, OBSalttype ! altitude coord. type:'z' (altitude, m) 'p' (pressure, Pa) 73 74 76 real,dimension(:),allocatable :: GCMtime, OBSLs ! time in the GCM diagfi (sols) & the Observer files (Ls) 75 77 real,dimension(:),allocatable :: GCMstatstime ! time in the GCM stats file (LT at lon 0°) … … 77 79 real :: starttimeoffset=0 ! offset (in sols) wrt Ls=0 of sol 0 in GCM file 78 80 81 !------------------------ 82 ! Variables 79 83 character (len=64) :: GCMvarname, OBSvarname ! to store the name of the variable to retrieve 80 84 real,dimension(:,:,:,:),allocatable :: GCM_var,OBS_var ! the 4D variable extracted from GCM & OBS files 81 85 character (len=64) :: OBSLTave_name, OBSLTmax_name, OBSLTmin_name ! to store the name of the average, max and min of LT (ex : dtimeave, ntimemax...) 82 86 real,dimension(:,:,:),allocatable :: OBSLT, OBSLTmax, OBSLTmin ! 3D variables extracted from obsfile (average, max and min of LT in a bin) 87 character (len=64) :: numbin_name ! to store the name of the nb of values in an OBS temp bin (dnumbintemp/nnumbintemp) 88 real,dimension(:,:,:,:),allocatable :: numbintemp ! nb of values in an OBS temp bin 83 89 real :: GCMmiss_val, OBSmiss_val, LTmiss_val ! value to denote non-existant data 84 90 real :: extr_value ! to store the result of the extraction subroutine 85 91 real, dimension(:,:,:,:), allocatable :: outvar ! outvar(,,,): 4D array to store the output variable's data 92 93 !------------------------ 94 ! Time binning management 86 95 real :: OBSdeltaLs ! difference of Ls between each observation bin 87 96 real :: sol, maxsol, minsol ! sol date corresponding to Observed Ls and LT 88 97 integer :: m_maxsol, m_minsol ! indexes of the maximum and minimum GCM sol taken in a bin for interpolation 89 98 90 real,dimension(:,:,:),allocatable :: LTmod_arraymax, LTmod_arraymin ! declaration of the type of the function LTmod_array 99 external LTmod ! declaration of the function LTmod 91 100 real :: 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 101 integer :: LTcount ! nb of LT samples on which the interpolation is performed, for every LT interval = numbintemp[lon,lat,alt,Ls] 94 102 95 103 integer :: solcount ! number of GCM sol integer values in one Ls interval … … 99 107 integer :: errcount = 0 ! total number of GCM missing values 100 108 real :: 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 103 112 real :: lon_val, lat_val, alt_val, Ls_val, LT_val ! where and when the output file is written at 104 113 … … 106 115 integer :: m,m_int,n ! sol binning loops iteration index 107 116 108 real, dimension(:,:,:,:), allocatable :: outvar ! outvar(,,,): 4D array to store the output variable's data109 117 110 118 !=================================================================================================== … … 228 236 !=============================================================================== 229 237 230 ! Observer variables to extract :231 238 !******************** NOTA BENE (cf sections 1.3 and 4)************************* 232 239 ! We execute the program a first time with the daytime values, and then a second … … 234 241 ! independent of this distinction, hence we execute them only in the first loop, 235 242 ! 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 w ether243 ! the first loop) or CASE (when it's executed in both loops but depends on whether 237 244 ! it is daytime or nighttime). 238 ! This shouldbe changed one day with a cleaner version of the code...245 ! This may be changed one day with a cleaner version of the code... 239 246 !******************************************************************************* 247 248 ! Observer variables to extract : 240 249 OBSvarname="dtemp" ! we begin with daytime temperature 241 250 write(*,*)"" ; write(*,*) "Beginning the 1st loop, on daytime values"; write(*,*)"" … … 304 313 OBSLTmax_name = "dtimemax" 305 314 OBSLTmin_name = "dtimemin" 315 numbin_name = "dnumbintemp" 306 316 CASE ("ntemp") 307 317 OBSLTave_name = "ntimeave" 308 318 OBSLTmax_name = "ntimemax" 309 319 OBSLTmin_name = "ntimemin" 320 numbin_name = "nnumbintemp" 310 321 END SELECT 311 322 323 ! Get the average values of LT in the OBS bins 312 324 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) 314 326 call status_check(status,error_text) 315 327 ! Sanity checks on the variable … … 351 363 ! Get the maximum values of LT in the OBS bins 352 364 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) 354 366 call status_check(status,error_text) 355 367 ! Sanity checks on the variable … … 386 398 ! Get the minimum values of LT in the OBS bins 387 399 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) 389 401 call status_check(status,error_text) 390 402 ! Sanity checks on the variable … … 418 430 write(*,*) "Loaded ", trim(OBSLTmin_name), " from the obsfile" 419 431 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" 443 470 444 471 !=================================================================================================== … … 453 480 write(*,*)"";write(*,*) "-> Enter input file name (GCM simulation) :" 454 481 read(*,*) gcmfile 455 if (index(gcmfile,"stats").ne.0) then ! if the GCM file name contains "stats", we assume it is a stats file456 ! => A REMPLACER PAR UN TEST SUR LA DIMENSION TIME ? REGARDER DANS AUTRES UTILITAIRES457 is_stats = .true.458 write(*,*)"The GCM file is recognized as a stats file."459 else460 write(*,*)"The GCM file is recognized as a diagfi/concatnc file."461 endif462 482 463 483 ! Open GCM file … … 512 532 ! GCM Time 513 533 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 529 542 status=nf90_inq_varid(gcmfid,"Time",GCMvarid) 530 543 error_text="Failed to find GCM time ID" 531 544 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)) 539 558 status=nf90_get_var(gcmfid,GCMvarid,GCMstatstime) 540 559 error_text="Failed to load GCMstatstime (LT at lon 0)" 541 560 call status_check(status,error_text) 561 else 562 write(*,*)"The GCM file is recognized as a diagfi/concatnc file." 542 563 endif 543 564 … … 550 571 GCMtime(:)=GCMtime(:)+starttimeoffset 551 572 endif 552 553 ! Get the timestep of the simulation (in Martian hours)554 if (.not.is_stats) then555 GCMdeltat = (GCMtime(2)-GCMtime(1))*24.556 else557 GCMdeltat = (GCMstatstime(2)-GCMstatstime(1))558 endif559 write(*,*)"GCM simulation's timestep is ", GCMdeltat, " hours."560 573 561 574 ! Check of temporal coherence between gcmfile & obsfile … … 749 762 error_text="Error: could not define the variable "//trim(OBSLTave_name)//" in the outfile" 750 763 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) 751 768 752 769 ! Write the attributes … … 792 809 write(*,*)"Local Time (", trim(OBSLTave_name), ") has been created in the outfile" 793 810 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 794 824 795 825 ! End the netcdf define mode (and thus enter the "data writing" mode) … … 867 897 if (lon_val.gt.180.) lon_val=lon_val-360. 868 898 869 LT_val=OBSLT(i,j,l) ! find the Observer corresponding LT value at lon_val, lat_val, Ls_val870 899 LT_val=OBSLT(i,j,l) ! find the Observer average LT value at bin(lon_val, lat_val, Ls_val) 900 871 901 if ((LT_val.lt.0.).or.(LT_val.gt.24.)) then 872 902 if (LT_val.eq.LTmiss_val) then … … 880 910 endif 881 911 endif 882 ! Generate the sol list for the interpolation883 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)886 912 887 913 altitude: do k=1,OBSaltlen ! loop on all observed altitudes … … 897 923 !! 3.3.2 Compute GCM sol date corresponding to Observer Ls 898 924 !! (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 900 942 solerrcount=0 901 943 solbinned_value=0 … … 929 971 930 972 errcount=errcount+solerrcount 931 973 974 deallocate(sol_list) 975 932 976 enddo altitude ! end loop on observed altitudes 933 934 deallocate(sol_list)935 936 977 enddo longitude ! end loop on observed longitudes 937 978 enddo latitude ! end loop on observed latitudes … … 951 992 952 993 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 956 1001 !!============================================================================== 957 1002 !! 4. End of the Day/Night loop … … 965 1010 deallocate(OBSLTmax) 966 1011 deallocate(OBSLTmin) 1012 deallocate(numbintemp) 967 1013 deallocate(outvar) 968 1014 write(*,*)"";write(*,*)""; write(*,*) "Beginning the 2nd loop, on nighttime values" ; write(*,*)"" … … 1562 1608 real, intent(in) :: lon ! longitude value for the transformation into a sol value at lon=0° 1563 1609 external f_LT ! function that changes LT interval for night LT 1564 real ::f_LT1610 real f_LT 1565 1611 character (len=64), intent(in) :: LTname ! to know if we have day or night values 1566 1612 … … 1657 1703 ! night local times) 1658 1704 !================================================================ 1659 real :: LT 1705 implicit none 1706 real,intent(in) :: LT 1660 1707 1661 1708 LTmod = 2*mod(LT,12.)-LT
Note: See TracChangeset
for help on using the changeset viewer.