00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 module shr_tInterp_mod
00019
00020
00021
00022 use shr_sys_mod
00023 use shr_cal_mod
00024 use shr_kind_mod
00025 use shr_const_mod
00026 use shr_log_mod, only: s_loglev => shr_log_Level
00027 use shr_log_mod, only: s_logunit => shr_log_Unit
00028 use shr_orb_mod, only: shr_orb_cosz, shr_orb_decl
00029
00030 implicit none
00031
00032 private
00033
00034
00035
00036
00037
00038
00039
00040 public :: shr_tInterp_getFactors
00041 public :: shr_tInterp_getAvgCosz
00042 public :: shr_tInterp_getCosz
00043 public :: shr_tInterp_setAbort
00044 public :: shr_tInterp_setDebug
00045 public :: shr_tInterp_getDebug
00046
00047
00048
00049
00050
00051
00052
00053 real(SHR_KIND_R8),parameter :: c0 = 0.0_SHR_KIND_R8
00054 real(SHR_KIND_R8),parameter :: c1 = 1.0_SHR_KIND_R8
00055 real(SHR_KIND_R8),parameter :: eps = 1.0E-12_SHR_KIND_R8
00056
00057 logical ,save :: doabort = .true.
00058 integer ,save :: debug = 0
00059
00060
00061 contains
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 subroutine shr_tInterp_getFactors(D1,S1,D2,S2,Din,Sin,f1,f2,algo,rc)
00088
00089 implicit none
00090
00091
00092
00093
00094
00095 integer(SHR_KIND_IN),intent(in) :: D1,S1
00096 integer(SHR_KIND_IN),intent(in) :: D2,S2
00097 integer(SHR_KIND_IN),intent(in) :: Din,Sin
00098 real(SHR_KIND_R8) ,intent(out) :: f1
00099 real(SHR_KIND_R8) ,intent(out) :: f2
00100 character(*) ,intent(in) ,optional :: algo
00101 integer(SHR_KIND_IN),intent(out),optional :: rc
00102
00103
00104
00105
00106 real(SHR_KIND_R8) :: etime1
00107 real(SHR_KIND_R8) :: etime2
00108 real(SHR_KIND_R8) :: etimeIn
00109 integer(SHR_KIND_IN) :: eday
00110 character(SHR_KIND_CS) :: lalgo
00111 integer(SHR_KIND_IN) :: lrc
00112
00113
00114 character(*),parameter :: subName = "(shr_tInterp_getFactors) "
00115 character(*),parameter :: F00 = "('(shr_tInterp_getFactors) ',8a)"
00116 character(*),parameter :: F01 = "('(shr_tInterp_getFactors) ',a,2f17.8)"
00117 character(*),parameter :: F02 = "('(shr_tInterp_getFactors) ',a,3f17.8)"
00118 character(*),parameter :: F03 = "('(shr_tInterp_getFactors) ',2a,3(i9.8,i6))"
00119
00120
00121
00122
00123
00124 lrc = 0
00125
00126 if (present(algo)) then
00127 lalgo = algo
00128 else
00129 lalgo = 'linear'
00130 endif
00131
00132
00133 call shr_cal_date2eday(D1, eday)
00134 etime1 = real(eday,SHR_KIND_R8) + real(s1,SHR_KIND_R8)/shr_const_cDay
00135
00136 call shr_cal_date2eday(D2, eday)
00137 etime2 = real(eday,SHR_KIND_R8) + real(s2,SHR_KIND_R8)/shr_const_cDay
00138
00139 call shr_cal_date2eday(Din, eday)
00140 etimein = real(eday,SHR_KIND_R8) + real(sin,SHR_KIND_R8)/shr_const_cDay
00141
00142
00143
00144
00145
00146 if (etime2 < etime1) then
00147 if (s_loglev > 0) write(s_logunit,F01) ' ERROR: etime2 < etime1 ',etime2,etime1
00148 lrc = 1
00149 call shr_tInterp_abort(subName//' etime2 < etime1 ')
00150 endif
00151
00152 f1 = c0
00153 f2 = c0
00154
00155 if (trim(lalgo) == 'lower') then
00156 if (etime1 < etime2) then
00157 f1 = c1
00158 else
00159 f2 = c1
00160 endif
00161 elseif (trim(lalgo) == 'upper') then
00162 if (etime1 < etime2) then
00163 f2 = c1
00164 else
00165 f1 = c1
00166 endif
00167 elseif (trim(lalgo) == 'nearest') then
00168 if (abs(etimein-etime1) <= abs(etime2-etimein)) then
00169 f1 = c1
00170 f2 = c0
00171 else
00172 f1 = c0
00173 f2 = c1
00174 endif
00175 elseif (trim(lalgo) == 'linear') then
00176
00177 if (etime2 < etimein .or. etime1 > etimein) then
00178 write(s_logunit,F02) ' ERROR illegal linear times: ',etime1,etimein,etime2
00179 lrc = 1
00180 call shr_tInterp_abort(subName//' illegal etimes ')
00181 endif
00182 if (etime2 == etime1) then
00183 f1 = 0.5_SHR_KIND_R8
00184 f2 = 0.5_SHR_KIND_R8
00185 else
00186 f1 = (etime2-etimein)/(etime2-etime1)
00187 f2 = c1 - f1
00188 endif
00189 else
00190 if (s_loglev > 0) write(s_logunit,F00) 'ERROR: illegal lalgo option: ',trim(lalgo)
00191 lrc = 1
00192 call shr_tInterp_abort(subName//' illegal algo option '//trim(lalgo))
00193 endif
00194
00195
00196 if (f1 < c0-eps .or. f1 > c1+eps .or. &
00197 f2 < c0-eps .or. f2 > c1+eps .or. &
00198 abs(f1+f2-c1) > eps) then
00199 if (s_loglev > 0) write(s_logunit,F01) 'ERROR: illegal tInterp values ',f1,f2
00200 lrc = 1
00201 call shr_tInterp_abort(subName//' illegal tInterp values ')
00202 endif
00203
00204 if (debug > 0 .and. s_loglev > 0) then
00205 write(s_logunit,F03) 'DEBUG: algo,D1,S1,Din,Sin,D2,S2=',trim(lAlgo),D1,S1,Din,Sin,D2,S2
00206 write(s_logunit,F01) 'DEBUG: algo,f1,f2= '//trim(lAlgo),f1,f2
00207 endif
00208
00209 if (present(rc)) rc = lrc
00210
00211 end subroutine shr_tInterp_getFactors
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 subroutine shr_tInterp_getAvgCosz(tavCosz,lonr,latr,ymd1,tod1,ymd2,tod2,eccen,mvelpp,lambm0,obliqr,dt)
00232
00233 implicit none
00234
00235
00236
00237
00238
00239 real(SHR_KIND_R8) ,intent(out) :: tavCosz(:)
00240 real(SHR_KIND_R8) ,intent(in) :: latr(:)
00241 real(SHR_KIND_R8) ,intent(in) :: lonr(:)
00242 integer(SHR_KIND_IN),intent(in) :: ymd1,tod1
00243 integer(SHR_KIND_IN),intent(in) :: ymd2,tod2
00244 real(SHR_KIND_R8) ,intent(in) :: eccen
00245 real(SHR_KIND_R8) ,intent(in) :: mvelpp
00246 real(SHR_KIND_R8) ,intent(in) :: lambm0
00247 real(SHR_KIND_R8) ,intent(in) :: obliqr
00248 integer(SHR_KIND_IN),intent(in) :: dt
00249
00250
00251
00252
00253 integer(SHR_KIND_IN) :: lsize
00254 integer(SHR_KIND_IN) :: eday1, eday2
00255 real(SHR_KIND_R8) :: reday1,reday2
00256 integer(SHR_KIND_IN) :: n
00257 integer(SHR_KIND_IN) :: eday
00258 real(SHR_KIND_R8) :: reday
00259 integer(SHR_KIND_IN) :: ymd,tod,ymd0,tod0
00260 real(SHR_KIND_R8),pointer :: cosz(:)
00261
00262
00263 character(*),parameter :: subName = "(shr_tInterp_getAvgCosz) "
00264 character(*),parameter :: F00 = "('(shr_tInterp_getAvgCosz) ',8a)"
00265 character(*),parameter :: F01 = "('(shr_tInterp_getAvgCosz) ',a,2f17.8)"
00266 character(*),parameter :: F02 = "('(shr_tInterp_getAvgCosz) ',a,3f17.8)"
00267 character(*),parameter :: F03 = "('(shr_tInterp_getAvgCosz) ',2a,3(i9.8,i6))"
00268
00269
00270
00271
00272
00273 lsize = size(lonr)
00274 allocate(cosz(lsize))
00275 if (lsize < 1 .or. size(latr) /= lsize .or. size(tavCosz) /= lsize) then
00276 call shr_sys_abort(subname//' ERROR: lon lat tavCosz sizes disagree')
00277 endif
00278
00279
00280 call shr_cal_date2eday(ymd1,eday1)
00281 call shr_cal_date2eday(ymd2,eday2)
00282 reday1 = eday1 + tod1/SHR_CONST_CDAY
00283 reday2 = eday2 + tod2/SHR_CONST_CDAY
00284 if (reday1 > reday2) call shr_sys_abort(subname//'ERROR: lower-bound > upper-bound')
00285
00286
00287 tavCosz = 0.0_SHR_KIND_R8
00288 n = 0
00289 reday = reday1
00290 ymd = ymd1
00291 tod = tod1
00292 do while( reday < reday2)
00293
00294
00295 n = n + 1
00296 ymd0 = ymd
00297 tod0 = tod
00298 call shr_cal_advDateInt(dt,'seconds',ymd0,tod0,ymd,tod)
00299 call shr_cal_date2eday(ymd ,eday )
00300 reday = eday + tod/SHR_CONST_CDAY
00301
00302
00303 call shr_tInterp_getCosz(cosz,lonr,latr,ymd,tod,eccen,mvelpp,lambm0,obliqr)
00304 tavCosz = tavCosz + cosz
00305
00306 end do
00307 tavCosz = tavCosz/real(n,SHR_KIND_R8)
00308
00309 deallocate( cosz )
00310
00311 end subroutine shr_tInterp_getAvgCosz
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 subroutine shr_tInterp_getCosz(cosz,lonr,latr,ymd,tod,eccen,mvelpp,lambm0,obliqr)
00329
00330 implicit none
00331
00332
00333
00334
00335
00336 real(SHR_KIND_R8) ,intent(out) :: cosz(:)
00337 real(SHR_KIND_R8) ,intent(in) :: latr(:)
00338 real(SHR_KIND_R8) ,intent(in) :: lonr(:)
00339 integer(SHR_KIND_IN),intent(in) :: ymd,tod
00340 real(SHR_KIND_R8) ,intent(in) :: eccen
00341 real(SHR_KIND_R8) ,intent(in) :: mvelpp
00342 real(SHR_KIND_R8) ,intent(in) :: lambm0
00343 real(SHR_KIND_R8) ,intent(in) :: obliqr
00344
00345
00346
00347
00348 integer(SHR_KIND_IN) :: n
00349 integer(SHR_KIND_IN) :: lsize
00350 real(SHR_KIND_R8) :: calday
00351 real(SHR_KIND_R8) :: declin,eccf
00352
00353 real(SHR_KIND_R8),parameter :: solZenMin = 0.001_SHR_KIND_R8
00354
00355
00356 character(*),parameter :: subName = "(shr_tInterp_getCosz) "
00357 character(*),parameter :: F00 = "('(shr_tInterp_getCosz) ',8a)"
00358 character(*),parameter :: F01 = "('(shr_tInterp_getCosz) ',a,2f17.8)"
00359 character(*),parameter :: F02 = "('(shr_tInterp_getCosz) ',a,3f17.8)"
00360 character(*),parameter :: F03 = "('(shr_tInterp_getCosz) ',2a,3(i9.8,i6))"
00361
00362
00363
00364
00365
00366 lsize = size(lonr)
00367 if (lsize < 1 .or. size(latr) /= lsize .or. size(cosz) /= lsize) then
00368 call shr_sys_abort(subname//' ERROR: lon lat cosz sizes disagree')
00369 endif
00370
00371 call shr_cal_date2julian(ymd,tod,calday)
00372 call shr_orb_decl( calday, eccen, mvelpp, lambm0, obliqr, declin, eccf)
00373 do n = 1,lsize
00374 cosz(n) = max(solZenMin, shr_orb_cosz( calday, latr(n), lonr(n), declin ))
00375 end do
00376
00377 end subroutine shr_tInterp_getCosz
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 subroutine shr_tInterp_setAbort(flag)
00395
00396 implicit none
00397
00398
00399
00400 logical,intent(in) :: flag
00401
00402
00403
00404
00405 character(*),parameter :: subName = "(shr_tInterp_setAbort) "
00406 character(*),parameter :: F00 = "('(shr_tInterp_setAbort) ',a) "
00407
00408
00409
00410
00411
00412 doabort = flag
00413
00414 end subroutine shr_tInterp_setAbort
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 subroutine shr_tInterp_abort(string)
00432
00433 implicit none
00434
00435
00436
00437 character(*),optional,intent(in) :: string
00438
00439
00440
00441
00442 character(SHR_KIND_CL) :: lstring
00443 character(*),parameter :: subName = "(shr_tInterp_abort) "
00444 character(*),parameter :: F00 = "('(shr_tInterp_abort) ',a) "
00445
00446
00447
00448
00449
00450 lstring = ''
00451 if (present(string)) lstring = string
00452
00453 if (doabort) then
00454 call shr_sys_abort(lstring)
00455 else
00456 write(s_logunit,F00) trim(lstring)
00457 endif
00458
00459 end subroutine shr_tInterp_abort
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 subroutine shr_tInterp_getDebug(level)
00477
00478 implicit none
00479
00480
00481
00482 integer,intent(out) :: level
00483
00484
00485
00486
00487 character(*),parameter :: subName = "(shr_tInterp_getDebug) "
00488 character(*),parameter :: F00 = "('(shr_tInterp_getDebug) ',a) "
00489
00490
00491
00492
00493
00494 level = debug
00495
00496 end subroutine shr_tInterp_getDebug
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 subroutine shr_tInterp_setDebug(iflag)
00514
00515 implicit none
00516
00517
00518
00519 integer,intent(in) :: iflag
00520
00521
00522
00523
00524 character(*),parameter :: subName = "(shr_tInterp_setDebug) "
00525 character(*),parameter :: F01 = "('(shr_tInterp_setDebug) ',a,i3) "
00526
00527
00528
00529
00530
00531 debug = iflag
00532 if (debug>0 .and. s_loglev > 0) write(s_logunit,F01) "DEBUG: level changed to ",debug
00533
00534 end subroutine shr_tInterp_setDebug
00535
00536
00537
00538
00539 end module shr_tInterp_mod