- Timestamp:
- Jan 25, 2021, 8:03:25 PM (4 years ago)
- Location:
- trunk/LMDZ.MARS
- Files:
-
- 1 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LMDZ.MARS/README
r2449 r2450 3270 3270 - Minor cleanup and update in aeropacity_mod.F and read_dust_scenario.F90 to be 3271 3271 able to use MY35 dust scenario 3272 3273 == 25/01/2021 == AB 3274 Changes in lslin.F90 : 3275 - make sure the interpolation takes into account potential missing values in 3276 the input file fields, especially when the average/binning option is not used 3277 (ticket #68) 3278 - enable the averaging option even when the Ls timestep is set automatically 3279 /!\ previous lslin.def must be updated in consequence ! 3280 - code clean-up, especially remove duplicates on controle field and altitude units 3281 - replace all the tests "if (ndim.ge.3) then" by a unique test at the beginning 3282 of the var loop 3283 - change "title" attribute into "long_name" by default (ticket #48) 3284 3285 + add an indicative updated lslin.def 3286 + update util/README -
trunk/LMDZ.MARS/util/README
r2443 r2450 90 90 91 91 -------------------------------------------------------------------- 92 4) lslin.e : redistribute and AVERAGEgcm output in Ls coordinate.93 -------------------------------------------------------------------- 94 95 This program has been designed to interpol data in Solar Longitude (Ls)92 4) lslin.e : redistribute and average gcm output in Ls coordinate. 93 -------------------------------------------------------------------- 94 95 This program has been designed to interpolate data in Solar Longitude (Ls) 96 96 linear time coordinate (usable with grads) from Netcdf diagfi or concatnc 97 files and to AVERAGE the instantaneous data in Ls period (for comparison with98 binned dataset, for instance).97 files, and to average the instantaneous data in periodic Ls intervals 98 (for comparison with binned dataset, for instance). 99 99 100 100 lslin also creates a lslin.ctl file that can be read … … 103 103 is too small"... 104 104 105 Output file is : name_of_input_file_L S.nc105 Output file is : name_of_input_file_Ls.nc 106 106 107 107 -------------------------------------------------------------------- -
trunk/LMDZ.MARS/util/lslin.F90
r2432 r2450 23 23 character (len=50), dimension(:), allocatable :: var 24 24 ! var(): names of the variables 25 character (len=50) :: title,units 26 ! title(),units(): [netcdf] "title" and "units" attributes 27 character (len=50) :: units_alt 28 ! var(): units of altitude which can be 'km' or 'Pa' (after zrecast) 25 character (len=50) :: long_name,units 26 ! long_name(),units(): [netcdf] "long_name" and "units" attributes 29 27 character (len=50) :: altlong_name,altunits,altpositive 30 28 ! altlong_name(): [netcdf] altitude "long_name" attribute … … 37 35 ! vartmp(): used for temporary storage of various strings 38 36 character (len=1) :: answer 39 ! answer: the character 'y' (or 'Y'), if input file is of 'concatnc' type37 ! answer: user's answers at multiple questions (especially, answer='y'/'Y') 40 38 character (len=1) :: average 41 39 ! average: the character 'y' to average within the Ls timestep … … 55 53 integer :: day_ini ! Ehouarn: integer or real ? 56 54 ! day_ini: starting date/time of the run stored in input file 57 integer, parameter :: length=10058 ! length: (default) lenght of tab_cntrl()59 real, dimension(length) :: tab_cntrl60 ! tab_cntrl(length): array, stored in the input file,61 ! which contains various control parameters.62 55 real, dimension(:), allocatable:: lat,lon,alt,time,lsgcm,timels,ctl 63 56 ! lat(): latitude coordinates (read from input file) … … 129 122 read(*,'(a50)') infile 130 123 131 !write(*,*) "Is it a concatnc file? (y/n)?"132 write(*,*) "Do you want to specify the beginning day of the file"133 write(*,*) "in case the controle field is not present ? (y/n)?"134 read(*,*) answer135 if ((answer=="y").or.(answer=="Y")) then136 write(*,*) "Beginning day of the file?"137 read(*,*) reptime138 ! start_var=8 ! 'concatnc' type of file139 !else140 ! start_var=16 ! 'diagfi' type of file141 ! N.B.: start_var is now computed; see below142 endif143 144 145 124 !============================================================================== 146 125 ! 1.2. Open input file and read/list the variables it contains … … 178 157 ierr=NF_INQ_NVARS(nid,nbvarfile) 179 158 ! nbvarfile is now equal to the (total) number of variables in input file 180 181 allocate(var(nbvarfile-(start_var-1)))182 183 ! Yield the list of variables (to the screen)184 write(*,*)185 do i=start_var,nbvarfile186 ierr=NF_INQ_VARNAME(nid,i,vartmp)187 write(*,*) trim(vartmp)188 enddo189 !nbvar=0190 191 ! Ehouarn: Redundant (and obsolete) lines ?192 ! nbvar=nbvarfile-(start_var-1)193 ! do j=start_var,nbvarfile194 ! ierr=nf_inq_varname(nid,j,var(j-(start_var-1)))195 ! enddo196 159 197 160 ! Get the variables' names from the input file (and store them in var()) 161 write(*,*) "" 198 162 nbvar=nbvarfile-(start_var-1) 163 allocate(var(nbvar)) 199 164 do i=1,nbvar 200 165 ierr=NF_INQ_VARNAME(nid,i+(start_var-1),var(i)) … … 205 170 ! 1.3. Output file name 206 171 !============================================================================== 207 ! outfile="lslin.nc"208 172 outfile=infile(1:len_trim(infile)-3)//"_Ls.nc" 209 write(*,*) outfile 173 write(*,*) "" 174 write(*,*) "Output file : "//trim(outfile) 210 175 211 176 … … 247 212 else 248 213 ierr=NF_INQ_DIMLEN(nid,altdim,altlen) 249 units_alt="" 250 ierr=NF_GET_ATT_TEXT(nid,varid,"units",units_alt) 251 endif 252 write(*,*) "altlen: ",altlen 253 ! Get altitude attributes to handle files with any altitude type 254 ierr=nf_get_att_text(nid,altvar,'long_name',altlong_name) 255 ierr=nf_get_att_text(nid,altvar,'units',altunits) 256 ierr=nf_get_att_text(nid,altvar,'positive',altpositive) 214 215 ! Get altitude attributes to handle files with any altitude type 216 ierr=nf_get_att_text(nid,altvar,'long_name',altlong_name) 217 ierr=nf_get_att_text(nid,altvar,'units',altunits) 218 ierr=nf_get_att_text(nid,altvar,'positive',altpositive) 219 endif 220 ! write(*,*) "altlen: ",altlen 257 221 258 222 259 223 ! Allocate lat(), lon() and alt() 260 261 262 224 allocate(lat(latlen)) 225 allocate(lon(lonlen)) 226 allocate(alt(altlen)) 263 227 264 228 ! Read lat(),lon() and alt() from input file 265 266 267 268 269 270 229 ierr = NF_GET_VAR_REAL(nid,latvar,lat) 230 ierr = NF_GET_VAR_REAL(nid,lonvar,lon) 231 ierr = NF_GET_VAR_REAL(nid,altvar,alt) 232 if (ierr.NE.NF_NOERR) then 233 if (altlen.eq.1) alt(1)=0. 234 end if 271 235 272 236 … … 304 268 305 269 !============================================================================== 306 ! 2.2. Create (and initialize latitude, longitude and altitude in)output file270 ! 2.2. Create (and initialize) latitude, longitude and altitude in output file 307 271 !============================================================================== 308 272 … … 316 280 nout,londimout,latdimout,altdimout) 317 281 282 write(*,*)"" 318 283 !============================================================================== 319 284 ! 2.3. Read time from input file … … 339 304 allocate(lsgcm(timelen)) 340 305 341 342 343 344 306 ierr = NF_GET_VAR_REAL(nid,timevar,time) 345 307 346 347 308 !============================================================================== 348 309 ! 2.4. Initialize day_ini (starting day of the run) 349 310 !============================================================================== 350 311 351 352 write(*,*) 'answer',answer 312 if (ctllen .ne. 0) then ! controle is present in input file 313 write(*,*) "Do you want to specify the beginning day of the file (y/n) ?" 314 write(*,*) "If 'n', the value stored in the controle field will be used." 315 read(*,*) answer 316 else ! controle is not present in the input file 317 write(*,*) "There is no field controle in file "//trim(infile) 318 write(*,*) "You have to specify the beginning day of the file." 319 answer="y" 320 endif 321 322 if ((answer=="y").or.(answer=="Y")) then 323 write(*,*) "Beginning day of the file?" 324 read(*,*) reptime 325 endif 326 327 write(*,*) 'answer : ',answer 353 328 if ((answer/="y").and.(answer/="Y")) then 354 ! input file is of 'concatnc' type;the starting date of the run329 ! the starting date of the run 355 330 ! is stored in the "controle" array 356 ierr = NF_INQ_VARID (nid, "controle", varid) 357 if (ierr .NE. NF_NOERR) then 358 write(*,*) 'ERROR: <controle> variable is missing' 359 write(*,*) NF_STRERROR(ierr) 360 stop "" 361 endif 362 363 364 365 366 ierr = NF_GET_VAR_REAL(nid, varid, tab_cntrl) 367 368 369 if (ierr .NE. NF_NOERR) then 370 write(*,*) 'ERROR: Failed to read <controle>' 371 write(*,*) NF_STRERROR(ierr) 372 stop "" 373 endif 374 375 day_ini = nint(tab_cntrl(4)) 331 332 day_ini = nint(ctl(4)) 376 333 day_ini = modulo(day_ini,669) 377 334 write(*,*) 'day_ini', day_ini … … 397 354 write(*,*) 'Input data LS range :', lsgcm(1),lsgcm(timelen) 398 355 399 ! ******************************************400 write(*,*) "Automatic Ls time tsep (y/n)?"356 ! generate the time step of the new Ls axis for the output 357 write(*,*) "Automatic Ls timestep (y/n)?" 401 358 read(*,*) answer 402 359 if ((answer=="y").or.(answer=="Y")) then … … 417 374 ls0=lsgcm(1) ! First Ls date 418 375 else 419 write(*,*) "New timestep in Ls (deg) "376 write(*,*) "New timestep in Ls (deg) :" 420 377 read(*,*) deltals 421 write(*,*) "First Ls (deg) "378 write(*,*) "First Ls (deg) :" 422 379 read(*,*) ls0 423 380 if (ls0.lt.lsgcm(1)) then … … 426 383 end if 427 384 write(*,*) "First Ls date (deg) = ", ls0 ! FF2013 428 429 do while((average.ne.'y').and.(average.ne.'n')) 430 write(*,*) "Average data within the Ls timestep (y/n) or interpolate ? " 431 read(*,*) average 432 end do 433 endif 434 NLs=int(Int((lsgcm(timelen)-ls0)/deltals) +1) ! FF2013 435 !******************************************** 385 endif 386 387 NLs=int(int((lsgcm(timelen)-ls0)/deltals) +1) ! FF2013 436 388 allocate(timels(Nls)) 437 389 438 390 ! Build timels() 439 timels(1) = 0.01*nint(100.*ls0) 391 timels(1) = 0.01*nint(100.*ls0) ! 2 decimals 440 392 do k=2,Nls 441 393 timels(k) = timels(k-1) + deltals 442 394 end do 443 395 444 write(*,*) 'timestep in Ls (deg) ', deltals 445 write(*,*) 'output data LS range : ', timels(1),timels(Nls) 396 write(*,*) 'New timestep in Ls (deg) ', deltals 397 write(*,*) 'Output data LS range : ', timels(1),timels(Nls) 398 399 ! create averaged bins or interpolate at exact Ls ? 400 write(*,*) "Average data within the Ls timestep (y/n) or interpolate ? " 401 read(*,*) average 402 write(*,*)"" 446 403 447 404 !============================================================================== … … 450 407 451 408 do k=1,Nls 452 453 454 455 ierr= NF_PUT_VARA_REAL(nout,timevarout,k,1,timels(k)) 456 409 ierr= NF_PUT_VARA_REAL(nout,timevarout,k,1,timels(k)) 457 410 enddo 458 459 411 460 412 !============================================================================== … … 474 426 write(*,*) 'ERROR: Field <',var(j),'> not found' 475 427 write(*,*) NF_STRERROR(ierr) 476 stop "" 477 endif 428 stop "Better stop now..." 429 endif 430 478 431 ! Get the value of 'ndim' for this varriable 479 432 ierr=NF_INQ_VARNDIMS(nid,varid,ndim) 480 433 write(*,*) 'ndim', ndim 434 435 ! Check that it is a 3D or 4D variable 436 if (ndim.lt.3) then 437 write(*,*) "Error:",trim(var(j))," is neither a 3D nor a 4D variable" 438 write(*,*) "We'll skip that variable..." 439 CYCLE ! go directly to the next variable 440 endif 481 441 482 442 !============================================================================== … … 527 487 ! 3.3 Write this variable's definition and attributes to the output file 528 488 !============================================================================== 529 if (ndim.ge.3) then 530 units="" 531 title="" 532 ierr=NF_GET_ATT_TEXT(nid,varid,"title",title) 533 ierr=NF_GET_ATT_TEXT(nid,varid,"units",units) 534 535 call def_var(nout,var(j),title,units,ndim,dim,varidout,ierr) 536 end if 489 units=" " 490 long_name=" " 491 ierr=nf_get_att_text(nid,varid,"long_name",long_name) 492 if (ierr.ne.nf_noerr) then 493 ! if no attribute "long_name", try "title" 494 ierr=nf_get_att_text(nid,varid,"title",long_name) 495 endif 496 ierr=nf_get_att_text(nid,varid,"units",units) 497 498 call def_var(nout,var(j),long_name,units,ndim,dim,varidout,ierr) 537 499 538 500 !============================================================================== 539 501 ! 3.4 Read variable 540 !==== ========================================================================== 541 542 if (ndim.ge.3) then 543 ierr = NF_GET_VAR_REAL(nid,varid,var3d) 544 miss=NF_GET_ATT_REAL(nid,varid,"missing_value",missing) 545 validr=NF_GET_ATT_REAL(nid,varid,"valid_range",valid_range) 546 end if 547 502 !============================================================================== 503 504 ierr = NF_GET_VAR_REAL(nid,varid,var3d) 505 miss=NF_GET_ATT_REAL(nid,varid,"missing_value",missing) 506 validr=NF_GET_ATT_REAL(nid,varid,"valid_range",valid_range) 548 507 549 508 !============================================================================== … … 578 537 endif 579 538 enddo 580 else ! average = n581 call interpolf(timels(n),resultat, lsgcm,var3dxy,timelen)539 else ! average = 'n' 540 call interpolf(timels(n),resultat,missing,lsgcm,var3dxy,timelen) 582 541 var3dls(x,y,n,1)=resultat 583 542 endif … … 612 571 endif 613 572 enddo 614 else ! average = n615 call interpolf(timels(n),resultat, lsgcm,var3dxy,timelen)573 else ! average = 'n' 574 call interpolf(timels(n),resultat,missing,lsgcm,var3dxy,timelen) 616 575 var3dls(x,y,k,n)=resultat 617 end 576 endif 618 577 enddo 619 578 enddo … … 626 585 !============================================================================== 627 586 628 629 630 if (ndim.ge.3) then 631 632 ierr= NF_PUT_VARA_REAL(nout,varidout,corner,edges,var3dls) 633 634 635 if (ierr.ne.NF_NOERR) then 636 write(*,*) 'PUT_VAR ERROR: ',NF_STRERROR(ierr) 637 stop "" 638 endif 587 ierr= NF_PUT_VARA_REAL(nout,varidout,corner,edges,var3dls) 588 589 if (ierr.ne.NF_NOERR) then 590 write(*,*) 'PUT_VAR ERROR: ',NF_STRERROR(ierr) 591 stop "" 592 endif 639 593 640 594 ! In case there is a "missing value" attribute and "valid range" 641 if (miss.eq.NF_NOERR) then 642 call missing_value(nout,varidout,missing) 643 end if 644 645 deallocate(var3d) 646 deallocate(var3dls) 647 deallocate(var3dxy) 648 endif ! if (ndim.ge.3) 595 if (miss.eq.NF_NOERR) then 596 call missing_value(nout,varidout,missing) 597 endif 598 599 deallocate(var3d) 600 deallocate(var3dls) 601 deallocate(var3dxy) 649 602 650 603 enddo ! of do j=1,nbvar loop … … 666 619 ! Writing ctl file to directly read Ls coordinate in grads 667 620 ! (because of bug in grads that refuse to read date like 0089 in .nc files) 668 !open(33,file='lslin.ctl') 621 write(*,*)"" 622 write(*,*) "Writing a controle file to directly read Ls coordinate with Grads..." 623 669 624 open(33,file=infile(1:len_trim(infile)-3)//"_Ls.ctl") 670 625 date= (timels(1)-int(timels(1)))*365. … … 686 641 99 format("TDEF Time ",i5," LINEAR ", i2,a3,i4.4,1x,i2,a2) 687 642 688 deallocate(timels) 643 deallocate(timels) 644 645 write(*,*)"" 646 write(*,*) "Program completed !" 647 689 648 contains 690 649 … … 876 835 ierr = NF_DEF_VAR (nout,"controle",NF_FLOAT,1,ctldimout,nvarid) 877 836 878 ierr = NF_PUT_ATT_TEXT (nout,nvarid," title",18,"Control parameters")837 ierr = NF_PUT_ATT_TEXT (nout,nvarid,"long_name",18,"Control parameters") 879 838 880 839 ! End netcdf define mode … … 1081 1040 1082 1041 !****************************************************************************** 1083 subroutine def_var(nid,name, title,units,nbdim,dim,nvarid,ierr)1042 subroutine def_var(nid,name,long_name,units,nbdim,dim,nvarid,ierr) 1084 1043 !============================================================================== 1085 1044 ! Purpose: Write a variable (i.e: add a variable to a dataset) 1086 ! called "name"; along with its attributes " title", "units"...1045 ! called "name"; along with its attributes "long_name", "units"... 1087 1046 ! to a file (following the NetCDF format) 1088 1047 !============================================================================== … … 1102 1061 character (len=*), intent(in) :: name 1103 1062 ! name(): [netcdf] variable's name 1104 character (len=*), intent(in) :: title1105 ! title(): [netcdf] variable's "title" attribute1063 character (len=*), intent(in) :: long_name 1064 ! long_name(): [netcdf] variable's "long_name" attribute 1106 1065 character (len=*), intent(in) :: units 1107 1066 ! unit(): [netcdf] variable's "units" attribute … … 1122 1081 1123 1082 ! Write the attributes 1124 ierr=NF_PUT_ATT_TEXT(nid,nvarid," title",len_trim(adjustl(title)),adjustl(title))1083 ierr=NF_PUT_ATT_TEXT(nid,nvarid,"long_name",len_trim(adjustl(long_name)),adjustl(long_name)) 1125 1084 ierr=NF_PUT_ATT_TEXT(nid,nvarid,"units",len_trim(adjustl(units)),adjustl(units)) 1126 1085 … … 1182 1141 ! print*,'missing_value: valid_range attribution failed' 1183 1142 ! print*, NF_STRERROR(ierr) 1184 ! !write(*,*) 'NF_NOERR', NF_NOERR1185 ! !CALL abort1186 1143 ! stop "" 1187 1144 !endif … … 1193 1150 print*, 'missing_value: missing value attribution failed' 1194 1151 print*, NF_STRERROR(ierr) 1195 ! WRITE(*,*) 'NF_NOERR', NF_NOERR1196 ! CALL abort1197 1152 stop "" 1198 1153 endif … … 1296 1251 1297 1252 end subroutine sol2ls 1298 !************************************ 1299 1300 Subroutine interpolf(x,y,xd,yd,nd) 1301 !interpolation, give y = f(x) with array xd,yd known, size nd 1302 ! Version with CONSTANT values oustide limits 1303 ! Variable declaration 1304 ! -------------------- 1305 ! Arguments : 1306 real x,y 1307 real xd(*),yd(*) 1308 integer nd 1309 ! internal 1310 integer i 1311 real y_undefined 1312 1313 ! run 1314 ! --- 1315 y_undefined=1.e20 1316 1317 y=0. 1318 if ((x.le.xd(1)).and.(x.le.xd(nd))) then 1319 if (xd(1).lt.xd(nd)) y = yd(1) !y_undefined 1320 if (xd(1).ge.xd(nd)) y = y_undefined ! yd(nd) 1321 else if ((x.ge.xd(1)).and.(x.ge.xd(nd))) then 1322 if (xd(1).lt.xd(nd)) y = y_undefined ! yd(nd) 1323 if (xd(1).ge.xd(nd)) y = y_undefined ! yd(1) 1324 y = yd(nd) 1325 else 1326 do i=1,nd-1 1327 if ( ( (x.ge.xd(i)).and.(x.lt.xd(i+1)) ).or.((x.le.xd(i)).and.(x.gt.xd(i+1))) ) then 1328 y=yd(i)+(x-xd(i))*(yd(i+1)-yd(i))/(xd(i+1)-xd(i)) 1329 goto 99 1330 end if 1331 end do 1332 end if 1333 1334 ! write (*,*)' x , y' , x,y 1335 ! do i=1,nd 1336 ! write (*,*)' i, xd , yd' ,i, xd(i),yd(i) 1337 ! end do 1338 ! stop 1339 1340 99 continue 1341 1253 1254 !****************************************************************************** 1255 subroutine interpolf(x,y,missing,xd,yd,nd) 1256 !============================================================================== 1257 ! Purpose: 1258 ! Yield y=f(x), where xd() end yd() are arrays of known values, 1259 ! using linear interpolation 1260 ! If x is not included in the interval spaned by xd(), then y is set 1261 ! to a default value 'missing' 1262 ! Note: 1263 ! Array xd() should contain ordered (either increasing or decreasing) abscissas 1264 !============================================================================== 1265 implicit none 1266 !============================================================================== 1267 ! Arguments: 1268 !============================================================================== 1269 real,intent(in) :: x ! abscissa at which interpolation is to be done 1270 real,intent(in) :: missing ! missing value (if no interpolation is performed) 1271 integer :: nd ! size of arrays 1272 real,dimension(nd),intent(in) :: xd ! array of known absissas 1273 real,dimension(nd),intent(in) :: yd ! array of correponding values 1274 1275 real,intent(out) :: y ! interpolated value 1276 !============================================================================== 1277 ! Local variables: 1278 !============================================================================== 1279 integer :: i 1280 1281 ! default: set y to 'missing' 1282 y=missing 1283 1284 do i=1,nd-1 1285 if (((x.ge.xd(i)).and.(x.le.xd(i+1))).or.& 1286 ((x.le.xd(i)).and.(x.ge.xd(i+1)))) then 1287 if ((yd(i).eq.missing).or.(yd(i+1).eq.missing)) then 1288 ! cannot perform the interpolation if an encompasing value 1289 ! is already set to 'missing' 1290 else 1291 !linear interpolation based on encompassing values 1292 y=yd(i)+(x-xd(i))*(yd(i+1)-yd(i))/(xd(i+1)-xd(i)) 1293 endif 1294 exit 1295 endif 1296 enddo 1297 1298 1342 1299 end subroutine interpolf 1343 1300 1301 !****************************************************************************** 1302 1344 1303 end program lslin
Note: See TracChangeset
for help on using the changeset viewer.