Ignore:
Timestamp:
Mar 24, 2026, 5:27:57 PM (3 weeks ago)
Author:
yluo
Message:

Mars PCM:
Refactored the tracer mass-conservation fixer for dynamics introduced in r4142:
Added a runtime flag to enable/disable the correction of tracer mass non-conservation in dynamics.
Reorganized the implementation into a modular structure.
Restricted the correction to a subset of tracers: CO, O2, H2, HO2, H2O2, N2, Ar, and He.
Enabled correction for dynamics timesteps preceding the first physics timestep of a simulation.
YCL

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/LMDZ.MARS/libf/phymars/physiq_mod.F

    r4143 r4150  
    275275      REAL,INTENT(in) :: pt(ngrid,nlayer) ! temperature (K)
    276276      REAL,INTENT(in) :: pq(ngrid,nlayer,nq) ! tracers (.../kg_of_air)
    277       REAL pq_corrdyn(ngrid,nlayer,nq) ! tracer mass mixing ratio after correcting
    278                                        ! mass non-conservations in dynamics
    279277      REAL,INTENT(in) :: flxw(ngrid,nlayer) ! vertical mass flux (ks/s) at lower boundary of layer
    280278
     
    286284      REAL,INTENT(out) :: pdt(ngrid,nlayer) ! temperature tendency (K/s)
    287285      REAL,INTENT(out) :: pdq(ngrid,nlayer,nq) ! tracer tendencies (../kg/s)
    288       REAL pdq_corrdyn(ngrid,nlayer,nq) ! tracer mass mixing ratio tendencies in order to correct
    289                                         ! mass non-conservations in dynamics
    290286      REAL,INTENT(out) :: pdpsrf(ngrid) ! surface pressure tendency (Pa/s)
    291287
     
    451447      real colden(ngrid,nq)     ! vertical column of tracers
    452448      real mass(nq)             ! global mass of tracers (g)
    453       real, allocatable, save :: mass_predyn(:) ! tracer mass in the whole atmosphere
    454                                                 ! before dynamics
    455       real mass_postdyn(nq) ! tracer mass in the whole atmosphere after dynamics
    456 
    457 !$OMP THREADPRIVATE(mass_predyn)
    458 
    459       real masscorrfac(nq) ! mass correction factor for non-conservations in dynamics
    460449      REAL mtot(ngrid)          ! Total mass of water vapor (kg/m2)
    461450      REAL mstormdtot(ngrid)    ! Total mass of stormdust tracer (kg/m2)
     
    826815     &                              presnivs,pseudoalt,mlayer)
    827816#endif
    828 
    829          allocate(mass_predyn(nq))
    830 
    831817      ENDIF        !  (end of "if firstcall")
    832818
     
    892878      zplay(:,:) = pplay(:,:)
    893879      ps(:) = pplev(:,1)
    894 
    895 c     Correct mass non-conservation in dynamics
    896 c     ~~~~~~~~~~~~~~~~~~
    897       call compute_global_mass(pq, ngrid, nlayer, nq, zplev,
    898      &                         mass_postdyn)
    899 
    900       if (.not.firstcall) then ! At first call, mass_predyn does not exist
    901          do iq = 1, nq
    902             if (noms(iq) .ne. "dust_mass" .and.
    903      &          noms(iq) .ne. "dust_number" .and.
    904      &          noms(iq) .ne. "ccn_mass" .and.
    905      &          noms(iq) .ne. "ccn_number" .and.
    906      &          noms(iq) .ne. "ccnco2_mass" .and.
    907      &          noms(iq) .ne. "ccnco2_number" .and.
    908      &          noms(iq) .ne. "stormdust_mass" .and.
    909      &          noms(iq) .ne. "stormdust_number" .and.
    910      &          noms(iq) .ne. "topdust_mass" .and.
    911      &          noms(iq) .ne. "topdust_number") then
    912                masscorrfac(iq) = mass_predyn(iq)/mass_postdyn(iq)
    913             endif
    914          enddo
    915 
    916          pq_corrdyn = pq
    917          do ig = 1, ngrid
    918             do l = 1, min(nlayer, 40) ! Correction only applied to the lowest 40 layers
    919                do iq = 1, nq
    920                   if (noms(iq) .ne. "dust_mass" .and.
    921      &                noms(iq) .ne. "dust_number" .and.
    922      &                noms(iq) .ne. "ccn_mass" .and.
    923      &                noms(iq) .ne. "ccn_number" .and.
    924      &                noms(iq) .ne. "ccnco2_mass" .and.
    925      &                noms(iq) .ne. "ccnco2_number" .and.
    926      &                noms(iq) .ne. "stormdust_mass" .and.
    927      &                noms(iq) .ne. "stormdust_number" .and.
    928      &                noms(iq) .ne. "topdust_mass" .and.
    929      &                noms(iq) .ne. "topdust_number" .and.
    930      &                iq .ne. igcm_co2) then
    931                      ! Correcting species other than CO2
    932                      pq_corrdyn(ig, l, iq) =
    933      &                    pq(ig, l, iq) * masscorrfac(iq)
    934                      ! Adjust CO2 to compensate for mass creation/loss
    935                      pq_corrdyn(ig, l, igcm_co2) =
    936      &                    pq_corrdyn(ig, l, igcm_co2) -
    937      &                    pq(ig, l, iq) * (masscorrfac(iq) - 1.)
    938                   endif
    939                enddo
    940             enddo
    941          enddo
    942 
    943          pdq_corrdyn = (pq_corrdyn - pq)/ptimestep ! Mass fixer pdq
    944          pdq = pdq + pdq_corrdyn
    945       endif
    946880
    947881!#ifndef MESOSCALE
     
    26342568        ENDDO
    26352569      ENDDO
    2636 
    2637       call compute_global_mass(zq, ngrid, nlayer, nq, zplev,
    2638      &                         mass_predyn)
    26392570
    26402571      ! Density
     
    41994130      END SUBROUTINE physiq
    42004131
    4201       subroutine compute_global_mass(zq, ngrid, nlayer, nq, zplev, mass)
    4202 
    4203          use tracer_mod, only: mmol
    4204          use comcstfi_h, only: g
    4205          use geometry_mod, only: cell_area
    4206          use tracer_mod, only: noms
    4207          use planetwide_mod, only: planetwide_sumval
    4208 
    4209          real, intent(in)    :: zq(ngrid, nlayer, nq)
    4210          integer, intent(in) :: ngrid
    4211          integer, intent(in) :: nlayer
    4212          integer, intent(in) :: nq
    4213          real, intent(in)    :: zplev(ngrid, nlayer + 1)
    4214          real, intent(out)   :: mass(nq)
    4215          real    colden(ngrid, nq)
    4216          integer iq, ig, l
    4217 
    4218          do iq = 1, nq
    4219             if (noms(iq) .ne. "dust_mass" .and.
    4220      &          noms(iq) .ne. "dust_number" .and.
    4221      &          noms(iq) .ne. "ccn_mass" .and.
    4222      &          noms(iq) .ne. "ccn_number" .and.
    4223      &          noms(iq) .ne. "ccnco2_mass" .and.
    4224      &          noms(iq) .ne. "ccnco2_number" .and.
    4225      &          noms(iq) .ne. "stormdust_mass" .and.
    4226      &          noms(iq) .ne. "stormdust_number" .and.
    4227      &          noms(iq) .ne. "topdust_mass" .and.
    4228      &          noms(iq) .ne. "topdust_number") then
    4229 
    4230                do ig = 1, ngrid
    4231                    colden(ig, iq) = 0.
    4232                end do
    4233                do l = 1, nlayer
    4234                   do ig = 1, ngrid
    4235                      colden(ig, iq) = colden(ig, iq) + zq(ig, l, iq)*
    4236      &                                (zplev(ig, l) - zplev(ig, l+1))*
    4237      &                                6.022e22/(mmol(iq)*g)
    4238                   end do
    4239                end do
    4240 
    4241                call planetwide_sumval(colden(:, iq)/6.022e23
    4242      &                    *mmol(iq)*1.e4*cell_area, mass(iq))
    4243 
    4244             end if
    4245          end do
    4246 
    4247       end subroutine
    4248 
    42494132      END MODULE physiq_mod
Note: See TracChangeset for help on using the changeset viewer.