00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
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
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 module seq_frac_mct
00141
00142
00143
00144 use shr_kind_mod , only: R8 => SHR_KIND_R8
00145 use shr_sys_mod
00146 use shr_const_mod
00147
00148 use mct_mod
00149 use seq_cdata_mod
00150 use map_iceocn_mct
00151 use map_atmice_mct
00152 use map_atmocn_mct
00153 use map_atmlnd_mct
00154 use seq_comm_mct, only: logunit, loglevel
00155
00156 implicit none
00157 private
00158 save
00159
00160
00161
00162
00163
00164
00165
00166 public seq_frac_init
00167 public seq_frac_set
00168
00169
00170
00171
00172
00173
00174
00175 #ifdef CPP_VECTOR
00176 logical :: usevector = .true.
00177 #else
00178 logical :: usevector = .false.
00179 #endif
00180
00181 #ifdef SYSUNICOS
00182 logical :: usealltoall = .true.
00183 #else
00184 logical :: usealltoall = .false.
00185 #endif
00186
00187 integer, private :: seq_frac_debug = 1
00188 logical, private :: seq_frac_abort = .true.
00189 logical, private :: seq_frac_dead
00190
00191
00192 real(r8),parameter :: eps_fracsum = 1.0e-02
00193 real(r8),parameter :: eps_fracval = 1.0e-02
00194 real(r8),parameter :: eps_fraclim = 1.0e-03
00195 logical ,parameter :: atm_frac_correct = .false.
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 private seq_frac_check
00208
00209
00210 contains
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 subroutine seq_frac_init(cdata_a, cdata_i, cdata_l, cdata_o, cdata_g, &
00228 ice_present, ocn_present, lnd_present, glc_present, &
00229 dead_comps, &
00230 fractions_a, fractions_i, fractions_l, fractions_o, &
00231 fractions_g)
00232
00233
00234
00235 type(seq_cdata), intent(in) :: cdata_a
00236 type(seq_cdata), intent(in) :: cdata_i
00237 type(seq_cdata), intent(in) :: cdata_l
00238 type(seq_cdata), intent(in) :: cdata_o
00239 type(seq_cdata), intent(in) :: cdata_g
00240 logical , intent(in) :: ice_present
00241 logical , intent(in) :: ocn_present
00242 logical , intent(in) :: lnd_present
00243 logical , intent(in) :: glc_present
00244 logical , intent(in) :: dead_comps
00245 type(mct_aVect), intent(inout) :: fractions_a
00246 type(mct_aVect), intent(inout) :: fractions_i
00247 type(mct_aVect), intent(inout) :: fractions_l
00248 type(mct_aVect), intent(inout) :: fractions_o
00249 type(mct_aVect), intent(inout) :: fractions_g
00250
00251
00252
00253
00254 integer :: j,n
00255 integer :: ka, ki, kl, ko, kf, kk
00256 integer :: lsize
00257 integer :: debug_old
00258 type(mct_gGrid), pointer :: dom_a
00259 type(mct_gGrid), pointer :: dom_i
00260 type(mct_gGrid), pointer :: dom_l
00261 type(mct_gGrid), pointer :: dom_o
00262 type(mct_gGrid), pointer :: dom_g
00263
00264 character(*),parameter :: fraclist_a = 'afrac:ifrac:ofrac:lfrac:lfrin'
00265 character(*),parameter :: fraclist_o = 'afrac:ifrac:ofrac:ifrad:ofrad'
00266 character(*),parameter :: fraclist_i = 'afrac:ifrac:ofrac'
00267 character(*),parameter :: fraclist_l = 'afrac:lfrac:lfrin'
00268 character(*),parameter :: fraclist_g = 'gfrac'
00269
00270
00271 character(*),parameter :: subName = '(seq_frac_init) '
00272
00273
00274
00275
00276
00277 debug_old = seq_frac_debug
00278 seq_frac_debug = 2
00279
00280 seq_frac_dead = dead_comps
00281
00282
00283
00284
00285 call seq_cdata_setptrs(cdata_a, dom=dom_a)
00286
00287 lSize = mct_aVect_lSize(dom_a%data)
00288 call mct_aVect_init(fractions_a,rList=fraclist_a,lsize=lsize)
00289 call mct_aVect_zero(fractions_a)
00290
00291 ka = mct_aVect_indexRa(fractions_a,"afrac",perrWith=subName)
00292 fractions_a%rAttr(ka,:) = 1.0_r8
00293
00294
00295
00296
00297 if (glc_present) then
00298 call seq_cdata_setptrs(cdata_g, dom=dom_g)
00299
00300 lSize = mct_aVect_lSize(dom_g%data)
00301 call mct_aVect_init(fractions_g,rList=fraclist_g,lsize=lsize)
00302 call mct_aVect_zero(fractions_g)
00303 fractions_g%rAttr(:,:) = 1.0_r8
00304
00305 end if
00306
00307
00308
00309 if (lnd_present) then
00310 call seq_cdata_setptrs(cdata_l, dom=dom_l)
00311
00312 lSize = mct_aVect_lSize(dom_l%data)
00313 call mct_aVect_init(fractions_l,rList=fraclist_l,lsize=lsize)
00314 call mct_aVect_zero(fractions_l)
00315
00316 kk = mct_aVect_indexRA(fractions_l,"lfrin",perrWith=subName)
00317 kf = mct_aVect_indexRA(dom_l%data ,"frac" ,perrWith=subName)
00318 fractions_l%rAttr(kk,:) = dom_l%data%rAttr(kf,:)
00319
00320 call map_lnd2atm_mct(cdata_l, fractions_l, cdata_a, fractions_a, fluxlist='lfrin')
00321 call map_atm2lnd_mct(cdata_a, fractions_a, cdata_l, fractions_l, fluxlist='afrac')
00322
00323 end if
00324
00325
00326
00327 if (ice_present) then
00328 call seq_cdata_setptrs(cdata_i, dom=dom_i)
00329
00330 lSize = mct_aVect_lSize(dom_i%data)
00331 call mct_aVect_init(fractions_i,rList=fraclist_i,lsize=lsize)
00332 call mct_aVect_zero(fractions_i)
00333
00334 ko = mct_aVect_indexRa(fractions_i,"ofrac",perrWith=subName)
00335 kf = mct_aVect_indexRA(dom_i%data ,"frac" ,perrWith=subName)
00336 fractions_i%rAttr(ko,:) = dom_i%data%rAttr(kf,:)
00337
00338 call map_ice2atm_mct(cdata_i, fractions_i, cdata_a, fractions_a, fluxlist='ofrac')
00339
00340 end if
00341
00342
00343
00344
00345 if (ocn_present) then
00346 call seq_cdata_setptrs(cdata_o, dom=dom_o)
00347
00348 lSize = mct_aVect_lSize(dom_o%data)
00349 call mct_aVect_init(fractions_o,rList=fraclist_o,lsize=lsize)
00350 call mct_aVect_zero(fractions_o)
00351
00352 if (ice_present) then
00353 call map_ice2ocn_mct(cdata_i, fractions_i, cdata_o, fractions_o, fluxlist='ofrac')
00354 else
00355 ko = mct_aVect_indexRa(fractions_o,"ofrac",perrWith=subName)
00356 kf = mct_aVect_indexRA(dom_o%data ,"frac" ,perrWith=subName)
00357 fractions_o%rAttr(ko,:) = dom_o%data%rAttr(kf,:)
00358 call map_ocn2atm_mct(cdata_o, fractions_o, cdata_a, fractions_a, fluxlist='ofrac')
00359 endif
00360
00361 call map_atm2ocn_mct(cdata_a, fractions_a, cdata_o, fractions_o, fluxlist='afrac')
00362 if (ice_present) then
00363
00364 call map_ocn2ice_mct(cdata_o, fractions_o, cdata_i, fractions_i, fluxlist='afrac')
00365 endif
00366
00367 end if
00368
00369
00370
00371
00372
00373
00374 ka = mct_aVect_indexRa(fractions_a,"afrac",perrWith=subName)
00375 ki = mct_aVect_indexRa(fractions_a,"ifrac",perrWith=subName)
00376 kl = mct_aVect_indexRa(fractions_a,"lfrac",perrWith=subName)
00377 ko = mct_aVect_indexRa(fractions_a,"ofrac",perrWith=subName)
00378 kk = mct_aVect_indexRa(fractions_a,"lfrin",perrWith=subName)
00379 lSize = mct_aVect_lSize(fractions_a)
00380
00381 if (ice_present .or. ocn_present) then
00382 do n = 1,lsize
00383 fractions_a%rAttr(kl,n) = 1.0_r8 - fractions_a%rAttr(ko,n)
00384 if (abs(fractions_a%rAttr(kl,n)) < eps_fraclim) then
00385 fractions_a%rAttr(kl,n) = 0.0_r8
00386 if (atm_frac_correct) fractions_a%rAttr(ko,n) = 1.0_r8
00387 endif
00388 enddo
00389 else if (lnd_present) then
00390 do n = 1,lsize
00391 fractions_a%rAttr(kl,n) = fractions_a%rAttr(kk,n)
00392 fractions_a%rAttr(ko,n) = 1.0_r8 - fractions_a%rAttr(kl,n)
00393 if (abs(fractions_a%rAttr(ko,n)) < eps_fraclim) then
00394 fractions_a%rAttr(ko,n) = 0.0_r8
00395 if (atm_frac_correct) fractions_a%rAttr(kl,n) = 1.0_r8
00396 endif
00397 enddo
00398 endif
00399
00400
00401
00402 if (lnd_present) then
00403 call map_atm2lnd_mct(cdata_a, fractions_a, cdata_l, fractions_l, fluxlist='lfrac')
00404 end if
00405
00406 if (lnd_present) call seq_frac_check(fractions_l,'lnd init')
00407 if (glc_present) call seq_frac_check(fractions_g,'glc init')
00408 if (ice_present) call seq_frac_check(fractions_i,'ice init')
00409 if (ocn_present) call seq_frac_check(fractions_o,'ocn init')
00410 if (lnd_present.or.ice_present.or.ocn_present) &
00411 call seq_frac_check(fractions_a,'atm init')
00412 seq_frac_debug = debug_old
00413
00414 end subroutine seq_frac_init
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 subroutine seq_frac_set(i2x_i, cdata_a, cdata_i, cdata_l, cdata_o, cdata_g, &
00430 ice_present, ocn_present, lnd_present, glc_present, &
00431 fractions_a, fractions_i, fractions_l, fractions_o, &
00432 fractions_g)
00433
00434
00435
00436 type(mct_aVect), intent(in) :: i2x_i
00437 type(seq_cdata), intent(in) :: cdata_a
00438 type(seq_cdata), intent(in) :: cdata_i
00439 type(seq_cdata), intent(in) :: cdata_l
00440 type(seq_cdata), intent(in) :: cdata_o
00441 type(seq_cdata), intent(in) :: cdata_g
00442 logical , intent(in) :: ice_present
00443 logical , intent(in) :: ocn_present
00444 logical , intent(in) :: lnd_present
00445 logical , intent(in) :: glc_present
00446 type(mct_aVect), intent(inout) :: fractions_a
00447 type(mct_aVect), intent(inout) :: fractions_i
00448 type(mct_aVect), intent(inout) :: fractions_l
00449 type(mct_aVect), intent(inout) :: fractions_o
00450 type(mct_aVect), intent(inout) :: fractions_g
00451
00452
00453
00454
00455 integer :: j, n
00456 integer :: ki, kl, ka, ko, kf
00457 integer :: lsize
00458 real(r8),allocatable :: fcorr(:)
00459 type(mct_gGrid), pointer :: dom_i
00460
00461
00462 character(*),parameter :: subName = '(seq_frac_set) '
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 if (ice_present) then
00477 call mct_aVect_copy(i2x_i, fractions_i,"Si_ifrac","ifrac")
00478 call seq_cdata_setptrs(cdata_i, dom=dom_i)
00479 ki = mct_aVect_indexRA(fractions_i,"ifrac")
00480 ko = mct_aVect_indexRA(fractions_i,"ofrac")
00481 kf = mct_aVect_indexRA(dom_i%data ,"frac" ,perrWith=subName)
00482 fractions_i%rAttr(ki,:) = fractions_i%rAttr(ki,:) * dom_i%data%rAttr(kf,:)
00483 fractions_i%rAttr(ko,:) = dom_i%data%rAttr(kf,:) - fractions_i%rAttr(ki,:)
00484 call seq_frac_check(fractions_i,'ice set')
00485
00486 if (ocn_present) then
00487 call map_ice2ocn_mct(cdata_i, fractions_i, cdata_o, fractions_o, fluxlist='ofrac:ifrac')
00488 call seq_frac_check(fractions_o,'ocn set')
00489 endif
00490
00491
00492 call map_ice2atm_mct(cdata_i, fractions_i, cdata_a, fractions_a, fluxlist='ofrac:ifrac')
00493
00494
00495 if (atm_frac_correct) then
00496 ki = mct_aVect_indexRA(fractions_a,"ifrac")
00497 ko = mct_aVect_indexRA(fractions_a,"ofrac")
00498 kl = mct_aVect_indexRA(fractions_a,"lfrac")
00499 lSize = mct_aVect_lSize(fractions_a)
00500 allocate(fcorr(lsize))
00501 do n = 1,lsize
00502 if ((fractions_a%rAttr(ki,n)+fractions_a%rAttr(ko,n)) > 0.0_r8) then
00503 fcorr(n) = ((1.0_r8-fractions_a%rAttr(kl,n))/(fractions_a%rAttr(ki,n)+fractions_a%rAttr(ko,n)))
00504 else
00505 fcorr(n) = 0.0_r8
00506 endif
00507 enddo
00508 fractions_a%rAttr(ki,:) = fractions_a%rAttr(ki,:) * fcorr(:)
00509 fractions_a%rAttr(ko,:) = fractions_a%rAttr(ko,:) * fcorr(:)
00510 deallocate(fcorr)
00511 endif
00512
00513 call seq_frac_check(fractions_a,'atm set')
00514
00515 end if
00516
00517 end subroutine seq_frac_set
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532 subroutine seq_frac_check(fractions,string)
00533
00534
00535
00536 type(mct_aVect) , intent(in) :: fractions
00537 character(len=*), intent(in), optional :: string
00538
00539
00540
00541
00542 integer :: n, lsize
00543 integer :: ncnt
00544 real(r8) :: sum,diff,maxerr
00545 real(r8) :: aminval,amaxval
00546 real(r8) :: lminval,lmaxval
00547 real(r8) :: ominval,omaxval
00548 real(r8) :: iminval,imaxval
00549 real(r8) :: gminval,gmaxval
00550 real(r8) :: kminval,kmaxval
00551 real(r8) :: sminval,smaxval
00552 integer :: ka,kl,ki,ko,kg,kk
00553 character(len=128) :: lstring
00554 logical :: error
00555
00556
00557 character(*),parameter :: subName = '(seq_frac_check) '
00558 character(*),parameter :: F01 = "('(seq_frac_check) ',2a,i8,g26.18)"
00559 character(*),parameter :: F02 = "('(seq_frac_check) ',2a,2g26.18)"
00560
00561
00562
00563
00564
00565 if (present(string)) then
00566 lstring='['//trim(string)//']'
00567 else
00568 lstring=''
00569 endif
00570
00571 ka = -1
00572 kl = -1
00573 ki = -1
00574 ko = -1
00575 kk = -1
00576 kg = -1
00577 aminval = 0.0_r8
00578 amaxval = 0.0_r8
00579 lminval = 0.0_r8
00580 lmaxval = 0.0_r8
00581 iminval = 0.0_r8
00582 imaxval = 0.0_r8
00583 ominval = 0.0_r8
00584 omaxval = 0.0_r8
00585 gminval = 0.0_r8
00586 gmaxval = 0.0_r8
00587 kminval = 0.0_r8
00588 kmaxval = 0.0_r8
00589 sminval = 0.0_r8
00590 smaxval = 0.0_r8
00591
00592 lsize = mct_avect_lsize(fractions)
00593 ka = mct_aVect_indexRA(fractions,"afrac",perrWith='quiet')
00594 kl = mct_aVect_indexRA(fractions,"lfrac",perrWith='quiet')
00595 ki = mct_aVect_indexRA(fractions,"ifrac",perrWith='quiet')
00596 ko = mct_aVect_indexRA(fractions,"ofrac",perrWith='quiet')
00597 kg = mct_aVect_indexRA(fractions,"gfrac",perrWith='quiet')
00598 kk = mct_aVect_indexRA(fractions,"lfrin",perrWith='quiet')
00599
00600 if (ka > 0) then
00601 aminval = minval(fractions%rAttr(ka,:))
00602 amaxval = maxval(fractions%rAttr(ka,:))
00603 endif
00604 if (kl > 0) then
00605 lminval = minval(fractions%rAttr(kl,:))
00606 lmaxval = maxval(fractions%rAttr(kl,:))
00607 endif
00608 if (ko > 0) then
00609 ominval = minval(fractions%rAttr(ko,:))
00610 omaxval = maxval(fractions%rAttr(ko,:))
00611 endif
00612 if (ki > 0) then
00613 iminval = minval(fractions%rAttr(ki,:))
00614 imaxval = maxval(fractions%rAttr(ki,:))
00615 endif
00616 if (kg > 0) then
00617 gminval = minval(fractions%rAttr(kg,:))
00618 gmaxval = maxval(fractions%rAttr(kg,:))
00619 endif
00620 if (kk > 0) then
00621 kminval = minval(fractions%rAttr(kk,:))
00622 kmaxval = maxval(fractions%rAttr(kk,:))
00623 endif
00624
00625 ncnt = 0
00626 maxerr = 0.0_r8
00627 if (kl > 0 .and. ko > 0 .and. ki > 0) then
00628 sminval = 9999._r8
00629 smaxval = -9999._r8
00630 do n = 1,lsize
00631 sum = fractions%rAttr(ko,n) + fractions%rAttr(kl,n) + fractions%rAttr(ki,n)
00632 sminval = min(sum,sminval)
00633 smaxval = max(sum,smaxval)
00634 diff = abs(1.0_r8 - sum)
00635 if (diff > eps_fracsum) then
00636 ncnt = ncnt + 1
00637 maxerr = max(maxerr, diff)
00638
00639 endif
00640 enddo
00641 endif
00642
00643 error = .false.
00644 if (ncnt > 0) error = .true.
00645 if (aminval < 0.0_r8-eps_fracval .or. amaxval > 1.0_r8+eps_fracval) error = .true.
00646 if (lminval < 0.0_r8-eps_fracval .or. lmaxval > 1.0_r8+eps_fracval) error = .true.
00647 if (ominval < 0.0_r8-eps_fracval .or. omaxval > 1.0_r8+eps_fracval) error = .true.
00648 if (iminval < 0.0_r8-eps_fracval .or. imaxval > 1.0_r8+eps_fracval) error = .true.
00649 if (gminval < 0.0_r8-eps_fracval .or. gmaxval > 1.0_r8+eps_fracval) error = .true.
00650 if (kminval < 0.0_r8-eps_fracval .or. kmaxval > 1.0_r8+eps_fracval) error = .true.
00651
00652 if (error .or. seq_frac_debug > 1) then
00653 if (ka > 0) &
00654 write(logunit,F02) trim(lstring),' afrac min/max = ',aminval,amaxval
00655 if (kl > 0) &
00656 write(logunit,F02) trim(lstring),' lfrac min/max = ',lminval,lmaxval
00657 if (kg > 0) &
00658 write(logunit,F02) trim(lstring),' gfrac min/max = ',gminval,gmaxval
00659 if (ko > 0) &
00660 write(logunit,F02) trim(lstring),' ofrac min/max = ',ominval,omaxval
00661 if (ki > 0) &
00662 write(logunit,F02) trim(lstring),' ifrac min/max = ',iminval,imaxval
00663 if (kk > 0) &
00664 write(logunit,F02) trim(lstring),' lfrin min/max = ',kminval,kmaxval
00665 if (kl > 0 .and. ko > 0 .and. ki > 0) then
00666 write(logunit,F02) trim(lstring),' sum min/max = ',sminval,smaxval
00667 write(logunit,F01) trim(lstring),' sum ncnt/maxerr = ',ncnt,maxerr
00668 endif
00669 if (error .and. .not. seq_frac_dead .and. seq_frac_abort) then
00670 write(logunit,F02) trim(lstring),' ERROR aborting '
00671 call shr_sys_abort()
00672 elseif (error) then
00673 write(logunit,F02) trim(lstring),' ERROR but NOT aborting '
00674 endif
00675 endif
00676
00677 end subroutine seq_frac_check
00678
00679 end module seq_frac_mct