LCOV - code coverage report
Current view: top level - physics/carma/base - microfast.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 82 114 71.9 %
Date: 2025-03-14 01:33:33 Functions: 1 1 100.0 %

          Line data    Source code
       1             : ! Include shortname defintions, so that the F77 code does not have to be modified to
       2             : ! reference the CARMA structure.
       3             : #include "carma_globaer.h"
       4             : 
       5             : !!  This routine drives the fast microphysics calculations.
       6             : !!
       7             : !! @author Eric Jensen, Bill McKie
       8             : !! @version Sep-1997
       9  1418703438 : subroutine microfast(carma, cstate, iz, scale_threshold, rc)
      10             : 
      11             :   ! types
      12             :   use carma_precision_mod
      13             :   use carma_enums_mod
      14             :   use carma_constants_mod
      15             :   use carma_types_mod
      16             :   use carmastate_mod
      17             :   use carma_mod
      18             : 
      19             :   implicit none
      20             : 
      21             :   type(carma_type), intent(in)         :: carma       !! the carma object
      22             :   type(carmastate_type), intent(inout) :: cstate      !! the carma state object
      23             :   integer, intent(in)                  :: iz          !! z index
      24             :   real(kind=f)                         :: scale_threshold !! Scaling factor for convergence thresholds
      25             :   integer, intent(inout)               :: rc          !! return code, negative indicates failure
      26             : 
      27             :   ! Local Variables
      28             :   integer                              :: ielem   ! element index
      29             :   integer                              :: ibin    ! bin index
      30             :   integer                              :: igas    ! gas index
      31  2837406876 :   real(kind=f)                         :: previous_ice(NGAS)      ! total ice at the start of substep
      32  2837406876 :   real(kind=f)                         :: previous_liquid(NGAS)   ! total liquid at the start of substep
      33  2837406876 :   real(kind=f)                         :: previous_supsatl(NGAS)  ! supersaturation wrt ice at the start of substep
      34  2837406876 :   real(kind=f)                         :: previous_supsati(NGAS)  ! supersaturation wrt liquid at the start of substep
      35             :   real(kind=f)                         :: supsatold
      36             :   real(kind=f)                         :: supsatnew
      37             :   real(kind=f)                         :: srat
      38             :   real(kind=f)                         :: srat1
      39             :   real(kind=f)                         :: srat2
      40             :   real(kind=f)                         :: s_threshold
      41             : 
      42             :   1 format(/,'microfast::ERROR - excessive change in supersaturation for ',a,' : iz=',i4,',xc=', &
      43             :               f7.2,',yc=',f7.2,',srat=',e10.3,',supsatiold=',e10.3,',supsatlold=',e10.3,',supsati=',e10.3, &
      44             :               ',supsatl=',e10.3,',t=',f6.2)
      45             :   2 format('microfast::ERROR - conditions at beginning of the step : gc=',e10.3,',supsati=',e17.10, &
      46             :               ',supsatl=',e17.10,',t=',f6.2,',d_gc=',e10.3,',d_t=',f6.2)
      47             :   3 format(/,'microfast::ERROR - excessive change in supersaturation for ',a,' : iz=',i4,',xc=', &
      48             :               f7.2,',yc=',f7.2,',supsatiold=',e10.3,',supsatlold=',e10.3,',supsati=',e10.3, &
      49             :               ',supsatl=',e10.3,',t=',f6.2)
      50             : 
      51             :    ! Set production and loss rates to zero.
      52  1418703438 :   call zeromicro(carma, cstate, iz, rc)
      53  1418703438 :   if (rc < RC_OK) return
      54             : 
      55             :   ! Calculate (implicit) particle loss rates for nucleation, growth,
      56             :   ! evaporation, melting, etc.
      57  1418703438 :   if (do_grow) then
      58             : 
      59             :     ! Save off the current condensate totals so the gas and latent heating can be
      60             :     ! figured out in a way that conserves mass and energy.
      61  1418703438 :     call totalcondensate(carma, cstate, iz, previous_ice, previous_liquid, rc)
      62  1418703438 :     if (rc < RC_OK) return
      63             : 
      64  4256110314 :     do igas = 1, NGAS
      65  2837406876 :       call supersat(carma, cstate, iz, igas, rc)
      66  2837406876 :       if (rc < RC_OK) return
      67             : 
      68  2837406876 :       previous_supsati(igas) = supsati(iz, igas)
      69  4256110314 :       previous_supsatl(igas) = supsatl(iz, igas)
      70             :     end do
      71             : 
      72             :     ! Have water vapor and sulfuric acid been defined?
      73  1418703438 :     if ((igash2o /= 0) .and. (igash2so4 /= 0)) then
      74             : 
      75             :       ! Are both gases avaialble?
      76  1418703438 :       if ((gc(iz, igash2o) > 0._f) .and. (gc(iz,igash2so4) > 0._f)) then
      77             : 
      78             :         ! See if any sulfates will form.
      79  1418703437 :         call sulfnuc(carma, cstate, iz, rc)
      80             :       endif
      81             :     end if
      82             : 
      83  1418703438 :     call growevapl(carma, cstate, iz, rc)
      84  1418703438 :     if (rc < RC_OK) return
      85             : 
      86  1418703438 :     call actdropl(carma, cstate, iz, rc)
      87  1418703438 :     if (rc < RC_OK) return
      88             : 
      89             :     ! The Koop, Tabazadeh and Mohler routines provide different schemes for aerosol freezing.
      90             :     ! Only one of these parameterizatons should be active at one time.  However, any
      91             :     ! of these routines can be used in conjunction with heterogenous nucleation of glassy
      92             :     ! aerosols.
      93  1418703438 :     call freezaerl_tabazadeh2000(carma, cstate, iz, rc)
      94  1418703438 :     if (rc < RC_OK) return
      95             : 
      96  1418703438 :     call freezaerl_koop2000(carma, cstate, iz, rc)
      97  1418703438 :     if (rc < RC_OK) return
      98             : 
      99  1418703438 :     call freezaerl_mohler2010(carma, cstate, iz, rc)
     100  1418703438 :     if (rc < RC_OK) return
     101             : 
     102  1418703438 :     call freezglaerl_murray2010(carma, cstate, iz, rc)
     103  1418703438 :     if (rc < RC_OK) return
     104             : 
     105  1418703438 :     call hetnucl(carma, cstate, iz, rc)
     106  1418703438 :     if (rc < RC_OK) return
     107             : 
     108  1418703438 :     call freezdropl(carma, cstate, iz, rc)
     109  1418703438 :     if (rc < RC_OK) return
     110             : 
     111  1418703438 :     call melticel(carma, cstate, iz, rc)
     112  1418703438 :     if (rc < RC_OK) return
     113             :   endif
     114             : 
     115  1418703438 :   if(do_coremasscheck)then
     116           0 :     call coremasscheck( carma, cstate, iz, .false.,.true.,.true., "Beforegrowth", rc )
     117           0 :     if (rc < RC_OK) return
     118             :   end if
     119             : 
     120             :   ! Calculate particle production terms and solve for particle
     121             :   ! concentrations at end of time step.
     122 11349627504 :   do ielem = 1,NELEM
     123 >20996*10^7 :     do ibin = 1,NBIN
     124             : 
     125 >19861*10^7 :       if( do_grow )then
     126 >19861*10^7 :         call growp(carma, cstate, iz, ibin, ielem, rc)
     127 >19861*10^7 :         if (rc < RC_OK) return
     128             : 
     129 >19861*10^7 :         call upgxfer(carma, cstate, iz, ibin, ielem, rc)
     130 >19861*10^7 :         if (rc < RC_OK) return
     131             :       endif
     132             : 
     133 >19861*10^7 :       call psolve(carma, cstate, iz, ibin, ielem, rc)
     134 >20854*10^7 :      if (rc < RC_OK) return
     135             :     enddo
     136             :   enddo
     137             : 
     138             :   ! Calculate particle production terms for evaporation;
     139             :   ! gas loss rates and production terms due to particle nucleation;
     140             :   ! growth, and evaporation;
     141             :   ! apply evaporation production terms to particle concentrations;
     142             :   ! and solve for gas concentrations at end of time step.
     143  1418703438 :   if (do_grow) then
     144  1418703438 :     call evapp(carma, cstate, iz, rc)
     145  1418703438 :     if (rc < RC_OK) return
     146             : 
     147  1418703438 :     call downgxfer(carma, cstate, iz, rc)
     148  1418703438 :     if (rc < RC_OK) return
     149             : 
     150             : ! NOTE: Not needed because changes in gas concentrations and latent
     151             : ! heats are now calculated later in gsolve using total condensate.
     152             : !    call gasexchange(carma, cstate, iz, rc)
     153             : !    if (rc < RC_OK) return
     154             : 
     155  1418703438 :     call downgevapply(carma, cstate, iz, rc)
     156  1418703438 :     if (rc < RC_OK) return
     157             : 
     158  1418703438 :     call gsolve(carma, cstate, iz, previous_ice, previous_liquid, scale_threshold, rc)
     159  1418703438 :     if (rc /=RC_OK) return
     160             :   endif
     161             : 
     162  1332108521 :   call coremasscheck( carma, cstate, iz, .true.,.false.,.false., "AfterGsolve", rc )
     163  1332108521 :   if (rc < RC_OK) return
     164             : 
     165             :   ! Update temperature if thermal processes requested
     166  1332108521 :   if (do_thermo) then
     167           0 :     call tsolve(carma, cstate, iz, scale_threshold, rc)
     168           0 :     if (rc /= RC_OK) return
     169             :   endif
     170             : 
     171             :   !  Update saturation ratios
     172  1332108521 :   if (do_grow .or. do_thermo) then
     173  3996325563 :     do igas = 1, NGAS
     174  2664217042 :       call supersat(carma, cstate, iz, igas, rc)
     175  2664217042 :       if (rc < RC_OK) return
     176             : 
     177             :       ! Check to see how much the supersaturation changed during this step. If it
     178             :       ! has changed to much, then cause a retry.
     179  2664217042 :       if (t(iz) >= T0) then
     180  1152128432 :         supsatold = previous_supsatl(igas)
     181  1152128432 :         supsatnew = supsatl(iz,igas)
     182             :       else
     183  1512088610 :         supsatold = previous_supsati(igas)
     184  1512088610 :         supsatnew = supsati(iz,igas)
     185             :       end if
     186             : 
     187             :       ! If ds_threshold is positive, then it indicates that the criteria should
     188             :       ! be based on the percentage change in saturation.
     189  3996325563 :       if (ds_threshold(igas) > 0._f) then
     190             : 
     191           0 :         if (supsatold >= 1.e-4_f) then
     192           0 :           srat1 = abs(supsatnew / supsatold - 1._f)
     193             :         else
     194             :           srat1 = 0._f
     195             :         end if
     196             : 
     197           0 :         if (supsatnew >= 1.e-4_f) then
     198           0 :           srat2 = abs(supsatold / supsatnew - 1._f)
     199             :         else
     200             :           srat2 = 0._f
     201             :         end if
     202             : 
     203           0 :         srat = max(srat1, srat2)
     204             : 
     205             :         ! Don't let one substep change the supersaturation by too much.
     206             :         if (ds_threshold(igas) > 0._f) then
     207             : !          if (srat >= ds_threshold(igas)) then
     208           0 :           if ((srat >= ds_threshold(igas)) .and. (abs(supsatold - supsatnew) > 0.1_f)) then
     209           0 :             if (do_substep) then
     210           0 :               if (nretries == maxretries) then
     211           0 :                 if (do_print) write(LUNOPRT,1) trim(gasname(igas)), iz, &
     212           0 :                      xc, yc, srat, previous_supsati(igas), previous_supsatl(igas), &
     213           0 :                      supsati(iz, igas), supsatl(iz,igas), t(iz)
     214           0 :                 if (do_print) write(LUNOPRT,2) gcl(iz,igas), supsatiold(iz, igas), &
     215           0 :                      supsatlold(iz,igas), told(iz), d_gc(iz, igas), d_t(iz)
     216             :               end if
     217             : 
     218           0 :               rc = RC_WARNING_RETRY
     219             :             else
     220           0 :               if (do_print) write(LUNOPRT,1) trim(gasname(igas)), iz, xc, yc, &
     221           0 :                    srat, previous_supsati(igas), previous_supsatl(igas), &
     222           0 :                    supsati(iz, igas), supsatl(iz,igas), t(iz)
     223             :             end if
     224             :           end if
     225             :         end if
     226             : 
     227             : 
     228             :       ! If ds_threshold is negative, then it indicates that the criteria is based
     229             :       ! upon the supersaturation crossing 0, Indicating a shift from growth to
     230             :       ! evaporation and a potential overshoot in the result.
     231  2664217042 :       else if (ds_threshold(igas) < 0._f) then
     232             : 
     233             :         ! Adjust the saturation threshold to allow a worse solution if getting a better
     234             :         ! solution is taking too much time. The particular solution at any individual
     235             :         ! point is probably not going to affect the overall result by too much.
     236  1332108521 :         s_threshold = abs(ds_threshold(igas))
     237             : 
     238  1332108521 :         if (nretries >= (0.8_f * maxretries)) then
     239     5636096 :           s_threshold = 4._f  * s_threshold
     240  1326472425 :         else if (nretries >= (0.7_f * maxretries)) then
     241    11681906 :           s_threshold = 3.5_f * s_threshold
     242  1314790519 :         else if (nretries >= (0.6_f * maxretries)) then
     243    42252495 :           s_threshold = 3._f  * s_threshold
     244  1272538024 :         else if (nretries >= (0.5_f * maxretries)) then
     245   184273692 :           s_threshold = 2.5_f * s_threshold
     246  1088264332 :         else if (nretries >= (0.4_f * maxretries)) then
     247   345062953 :           s_threshold = 2._f  * s_threshold
     248             :         end if
     249             : 
     250             :         ! If the supersaturation changed signs, then we went from growth to evaporation
     251             :         ! or vice versa. Don't let the new supersaturation go too far past 0 in one substep.
     252             :         ! This is to prevent overshooting as growth/evaporation should normally stop when
     253             :         ! the supersaturation is 0.
     254  1332108521 :         if (((supsatnew * supsatold) < 0._f) .and. (abs(supsatnew) > s_threshold)) then
     255             : 
     256           0 :           if (do_substep) then
     257           0 :             if (nretries == maxretries) then
     258           0 :               if (do_print) write(LUNOPRT,3) trim(gasname(igas)), iz, &
     259           0 :                    xc, yc, previous_supsati(igas), previous_supsatl(igas), &
     260           0 :                    supsati(iz, igas), supsatl(iz,igas), t(iz)
     261           0 :               if (do_print) write(LUNOPRT,2) gcl(iz,igas), supsatiold(iz, igas), &
     262           0 :                    supsatlold(iz,igas), told(iz), d_gc(iz, igas), d_t(iz)
     263             :             end if
     264             :           else
     265           0 :             if (do_print) write(LUNOPRT,3) trim(gasname(igas)), iz, &
     266           0 :                  xc, yc, previous_supsati(igas), previous_supsatl(igas), &
     267           0 :                  supsati(iz, igas), supsatl(iz,igas), t(iz)
     268             :           end if
     269             : 
     270           0 :           rc = RC_WARNING_RETRY
     271             :         end if
     272             :       end if
     273             :     end do
     274             :   endif
     275             : 
     276             :   ! Return to caller with new particle and gas concentrations.
     277             :   return
     278  1418703438 : end

Generated by: LCOV version 1.14