LCOV - code coverage report
Current view: top level - physics/carma/base - newstate_calc.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 78 95 82.1 %
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 manages the calculations that update state variables
       6             : !! of the model with new values at the current simulation time. It supports
       7             : !! a retry mechanism, so the the number of steps can be increased dynamically
       8             : !! if the fast microphysics was not able to generate a valid solution. The
       9             : !! validity of the solution is control by the convergence thresholds
      10             : !! (dgc_threshold, dt_threshold and ds_threshold)
      11             : !!
      12             : !! NOTE: For cloud models, this routine may get called multiple times, once for
      13             : !! in-cloud calculations and again for clear sky.
      14             : !!
      15             : !! @author Bardeen
      16             : !! @version Jan 2012
      17     1050624 : subroutine newstate_calc(carma, cstate, scale_threshold, rc)
      18             : 
      19             :   ! types
      20             :   use carma_precision_mod
      21             :   use carma_enums_mod
      22             :   use carma_constants_mod
      23             :   use carma_types_mod
      24             :   use carmastate_mod
      25             :   use carma_mod
      26             : 
      27             :   implicit none
      28             : 
      29             :   type(carma_type), intent(in)         :: carma   !! the carma object
      30             :   type(carmastate_type), intent(inout) :: cstate  !! the carma state object
      31             :   real(kind=f), intent(in)             :: scale_threshold(NZ)  !! Scaling factor for convergence thresholds
      32             :   integer, intent(inout)               :: rc      !! return code, negative indicates failure
      33             : 
      34     2101248 :   real(kind=f)                    :: sedlayer(NBIN,NELEM)
      35     2101248 :   real(kind=f)                    :: pcd_last(NBIN,NELEM)
      36             :   integer                         :: kb
      37             :   integer                         :: ke
      38             :   integer                         :: idk
      39             :   integer                         :: iz
      40             :   integer                         :: isubstep
      41             :   integer                         :: igroup
      42             :   integer                         :: igas
      43             :   integer                         :: ielem
      44             :   integer                         :: ibin
      45             :   integer                         :: ntsubsteps
      46             :   logical                         :: takeSteps
      47             :   real(kind=f)                    :: fraction            ! Fraction of dT, dgc and pdc to be added in a substep.
      48             : 
      49             :   1 format(/,'newstate::ERROR - Substep failed, maximum retries execeed. : iz=',i4,',isubstep=',i12, &
      50             :              ',ntsubsteps=',i12,',nretries=',F9.0)
      51             : 
      52             : 
      53             :   ! Redetermine the maximum particle values.
      54     1050624 :   if ((do_vtran) .or. do_incloud) then
      55    74594304 :     do iz = 1, NZ
      56    73543680 :       call maxconc(carma, cstate, iz, rc)
      57    74594304 :       if (rc < RC_OK) return
      58             :     end do
      59             :   end if
      60             : 
      61             :   ! Calculate changes in particle concentrations due to microphysical
      62             :   ! processes, part 1.  (potentially slower microphysical calcs)
      63             :   ! All spatial points are handled by one call to this routine.
      64     1050624 :   if (do_coag) then
      65     1050624 :     call microslow(carma, cstate, rc)
      66     1050624 :     if (rc < RC_OK) return
      67             :   endif
      68             : 
      69     1050624 :   call fixcorecol(carma, cstate, rc)
      70             : 
      71             :   ! If there is any microsphysics that happens on a faster time scale,
      72             :   ! then check to see if the time step needs to be subdivided and then
      73             :   ! perform the fast microphysical calculations.
      74     1050624 :   if (do_grow) then
      75             : 
      76             :     ! Set vertical loop index to increment downwards
      77             :     ! (for substepping of sedimentation)
      78     1050624 :     if (igridv .eq. I_CART) then
      79           0 :       kb  = NZ
      80           0 :       ke  = 1
      81           0 :       idk = -1
      82             :     else
      83     1050624 :       kb  = 1
      84     1050624 :       ke  = NZ
      85     1050624 :       idk = 1
      86             :     endif
      87             : 
      88             :     ! Initialize sedimentation source to zero at top of model
      89   155492352 :     dpc_sed(:,:) = 0._f
      90             : 
      91             :     ! Save the results from the slow operations, since we might need to retry the
      92             :     ! fast operations
      93 10451607552 :     pcl(:,:,:) = pc(:,:,:)
      94             : 
      95     1050624 :     if (do_substep) then
      96     3151872 :       do igas = 1,NGAS
      97   150239232 :         gcl(:,igas) = gc(:,igas)
      98             :       end do
      99    74594304 :       told(:) = t(:)
     100             :     endif
     101             : 
     102             : 
     103    74594304 :     do iz = kb,ke,idk
     104             : 
     105             :       ! Compute or specify number of sub-timestep intervals for current spatial point
     106             :       ! (Could be same for all spatial pts, or could vary as a function of location)
     107    73543680 :       ntsubsteps = minsubsteps
     108             : 
     109    73543680 :       call nsubsteps(carma, cstate, iz, dtime_orig, ntsubsteps, rc)
     110    73543680 :       if (rc <  RC_OK) return
     111             : 
     112             :       ! Grab sedimentation source for entire step for this layer
     113             :       ! and set accumlated source for underlying layer to zero
     114 10884464640 :       sedlayer(:,:) = dpc_sed(:,:)
     115             : 
     116             :       ! Do sub-timestepping for current spatial grid point, and allow for
     117             :       ! retrying should this level of substepping not be enough to keep the
     118             :       ! gas concentration from going negative.
     119    73543680 :       nretries = 0._f
     120    73543680 :       takeSteps = .true.
     121             : 
     122   233682277 :       do while (takeSteps)
     123             : 
     124             :         ! Compute sub-timestep time interval for current spatial grid point
     125   160138597 :         dtime = dtime_orig / ntsubsteps
     126             : 
     127             :         ! Don't retry unless requested.
     128   160138597 :         takeSteps = .false.
     129             : 
     130             :         ! Reset the amount that has been collected to sedimented down to the
     131             :         ! layer below.
     132 23700512356 :         dpc_sed(:,:) = 0._f
     133             : 
     134             :         ! Reset the total nucleation for the step.
     135 23700512356 :         pc_nucl(iz,:,:) = 0._f
     136             : 
     137             :         ! Remember the amount of detrained particles.
     138   160138597 :         if (do_detrain) then
     139           0 :           pcd_last(:,:) = pcd(iz,:,:)
     140             :         end if
     141             : 
     142             :         ! Reset average heating rates.
     143   160138597 :         rlheat(iz)     = 0._f
     144   160138597 :         partheat(iz)   = 0._f
     145             : 
     146  1565790798 :         do isubstep = 1,ntsubsteps
     147             : 
     148             :           ! If substepping, then increment the gas concentration and the temperature by
     149             :           ! an amount for one substep.
     150  1418703438 :           if (do_substep) then
     151             : 
     152             :             ! Since we don't really know how the gas and temperature changes arrived during the
     153             :             ! step, we can try different assumptions for how the gas and temperature are add to
     154             :             ! the values from the previous substep.
     155             : 
     156             :             ! Linear increment for substepping.
     157  1418703438 :             fraction     = 1._f / ntsubsteps
     158             : 
     159  4256110314 :             do igas = 1,NGAS
     160  4256110314 :               gc(iz,igas) = gc(iz,igas) + d_gc(iz,igas) * fraction
     161             :             enddo
     162             : 
     163  1418703438 :             t(iz) = t(iz) + d_t(iz) * fraction
     164             : 
     165             : 
     166             :             ! Detrainment puts the full gridbox amount into the incloud portion.
     167  1418703438 :             if (do_detrain) then
     168           0 :               pc(iz,:,:)  = pc(iz,:,:)  + pcd_last(:,:) * fraction
     169           0 :               pcd(iz,:,:) = pcd(iz,:,:) - pcd_last(:,:) * fraction
     170             :             end if
     171             :           endif
     172             : 
     173             : 
     174             :           ! Redetermine maximum particle concentrations.
     175  1418703438 :           call maxconc(carma, cstate, iz, rc)
     176  1418703438 :           if (rc < RC_OK) return
     177             : 
     178  1418703438 :           call coremasscheck( carma, cstate, iz, .true.,.false.,.false., "BeforeMicrofast", rc )
     179  1418703438 :           if (rc < RC_OK) return
     180             : 
     181             :           ! Calculate changes in particle concentrations for current spatial point
     182             :           ! due to microphysical processes, part 2.  (faster microphysical calcs)
     183  1418703438 :           call microfast(carma, cstate, iz, scale_threshold(iz), rc)
     184  1418703438 :           if (rc < RC_OK) return
     185             : 
     186  1418703438 :           call coremasscheck( carma, cstate, iz, .true.,.false.,.false., "AfterMicrofast", rc )
     187  1418703438 :           if (rc < RC_OK) return
     188             : 
     189             :           ! If there was a retry warning message and substepping is enabled, then retry
     190             :           ! the operation with more substepping.
     191  2910950556 :           if (rc == RC_WARNING_RETRY) then
     192    86594917 :             if (do_substep) then
     193             : 
     194             :               ! Only retry for so long ...
     195    86594917 :               nretries = nretries + 1
     196             : 
     197    86594917 :               if (nretries > maxretries) then
     198           0 :                 if (do_print) write(LUNOPRT,1) iz, isubstep, ntsubsteps, nretries - 1._f
     199           0 :                 rc = RC_ERROR
     200             :                 exit
     201             :               end if
     202             : 
     203             :               ! Try twice the substeps
     204             :               !
     205             :               ! NOTE: We are going to rely upon retries, so don't clutter the log
     206             :               ! with retry print statements. They slow down the run.
     207    86594917 :               ntsubsteps = ntsubsteps * 2
     208             : 
     209             : !              if (do_print) write(LUNOPRT,*) "newstate::WARNING - Substep failed, retrying with ", ntsubsteps, " substeps."
     210             : 
     211             :               ! Reset the state to the beginning of the step
     212 12816047716 :               pc(iz,:,:) = pcl(iz,:,:)
     213 12816047716 :               pcd(iz,:,:) = pcd_last(:,:)
     214    86594917 :               t(iz) = told(iz)
     215   259784751 :               do igas = 1,NGAS
     216   173189834 :                 gc(iz,igas) = gcl(iz,igas)
     217             : 
     218             :                 ! Now that we have reset the gas concentration, we need to recalculate the supersaturation.
     219   173189834 :                 call supersat(carma, cstate, iz, igas, rc)
     220   259784751 :                 if (rc < RC_OK) return
     221             :               end do
     222             : 
     223    86594917 :               rc = RC_OK
     224    86594917 :               takeSteps = .true.
     225    86594917 :               exit
     226             : 
     227             : 
     228             :             ! If substepping is not enabled, than the retry warning should be treated as an error.
     229             :             else
     230             : 
     231           0 :               if (do_print) write(LUNOPRT,*) "newstate::ERROR - Step failed, suggest enabling substepping."
     232           0 :               rc = RC_ERROR
     233             :               exit
     234             :             end if
     235             :           end if
     236             :         end do
     237             :       end do
     238             : 
     239             : 
     240             :       ! Keep track of substepping and retry statistics for performance tuning.
     241    73543680 :       max_nsubstep = max(max_nsubstep, ntsubsteps)
     242    73543680 :       max_nretry   = max(max_nretry, nretries)
     243             : 
     244    73543680 :       nstep    = nstep    + 1._f
     245    73543680 :       nsubstep = nsubstep + ntsubsteps
     246    73543680 :       nretry   = nretry   + nretries
     247             : 
     248    74594304 :       if (do_substep) zsubsteps(iz) = ntsubsteps
     249             :     end do
     250             : 
     251             :     ! Restore normal timestep
     252     1050624 :     dtime = dtime_orig
     253             : 
     254             :   else
     255             : 
     256             :     ! If there is no reason to substep, but substepping was enabled, get the gas and
     257             :     ! temperature back to their final states.
     258           0 :     if (do_substep) then
     259             : 
     260           0 :       do igas = 1,NGAS
     261           0 :         gc(:,igas) = gc(:,igas) + d_gc(:,igas)
     262             :       enddo
     263             : 
     264           0 :       t(:) = t(:) + d_t(:)
     265             :     end if
     266             : 
     267             :     ! Do the detrainment, if it was being done in the growth loop.
     268           0 :     if (do_detrain) then
     269           0 :       pc(:,:,:)    = pc(:,:,:) + pcd(:,:,:)
     270             : 
     271             :       ! Remove the ice from the detrained ice, so that total ice will be conserved.
     272           0 :       pcd(:,:,:)   = 0._f
     273             :     end if
     274             :   end if
     275             : 
     276             :   ! Calculate average heating rates.
     277     1050624 :   if (do_grow) then
     278    74594304 :     rlheat(:)    = rlheat(:)   / dtime
     279    74594304 :     partheat(:)  = partheat(:) / dtime
     280             :   end if
     281             : 
     282             :   ! Return to caller with new state computed
     283             :   return
     284     1050624 : end

Generated by: LCOV version 1.14