Skip to content

TEMPO Microphysics for NCAR MPAS#1393

Open
AndersJensen-NOAA wants to merge 26 commits intoMPAS-Dev:developfrom
AndersJensen-NOAA:tempo_for_ncar_mpas
Open

TEMPO Microphysics for NCAR MPAS#1393
AndersJensen-NOAA wants to merge 26 commits intoMPAS-Dev:developfrom
AndersJensen-NOAA:tempo_for_ncar_mpas

Conversation

@AndersJensen-NOAA
Copy link
Copy Markdown
Collaborator

@AndersJensen-NOAA AndersJensen-NOAA commented Jan 9, 2026

This PR connects TEMPO microphysics to MPAS.

@AndersJensen-NOAA AndersJensen-NOAA marked this pull request as ready for review February 5, 2026 21:01
weiwangncar pushed a commit to wrf-model/WRF that referenced this pull request Feb 12, 2026
TYPE: new feature

KEYWORDS: Microphysics, Operational models

SOURCE: Anders Jensen NOAA/GSL

DESCRIPTION OF CHANGES:
Problem:
Microphysics development of a Thompson-Eidhammer based scheme for operational applications has advanced to a submodule, TEMPO. This new development should be made available to WRF users.

Solution:
Connect TEMPO to WRF. A cleaned and refactored version of TEMPO is being tested in the UFS community's MPAS. Additionally, a PR, MPAS-Dev/MPAS-Model#1393, to add TEMPO to NCAR's MPAS is in progress. This current PR will allow the community to use this same microphysics across the UFS, MPAS, and WRF.

LIST OF MODIFIED FILES: 
M   .gitmodules
M   main/depends.common
M   Makefile
M   clean
M   phys/Makefile
M   phys/module_physics_init.F
M   phys/module_microphysics_driver.F
M   Registry.EM_COMMON
M   dyn_em/module_initialize_real.F

TESTS CONDUCTED: 
1. compiled and ran em_quarter_ss
2. restart test with em_quarter_ss
3. bit-for-bit with different number of processes using em_quarter_ss.
4. Passed regression tests.

RELEASE NOTE:
TEMPO is the Thompson-Eidhammer Microphysics Parameterization for Operations. TEMPO lives here: https://github.com/NCAR/TEMPO and technical documentation lives here: https://ncar.github.io/TEMPO/.

TEMPO specific release notes are here:
https://github.com/NCAR/TEMPO/releases/tag/tempo_v3.0.0
TEMPO version 3.0.0 is the current release version. 

TEMPO is being tested in the ufs-community fork of MPAS for next-generation convection-allowing forecast systems (https://github.com/ufs-community/MPAS-Model). Thus, TEMPO is being
continually evaluated for improvement.

Additionally, there is a PR in progress to connect TEMPO (v3.0.0) to NCAR's MPAS (MPAS-Dev/MPAS-Model#1393). The version of TEMPO currently in the CCPP
(https://github.com/ufs-community/ccpp-physics) will be updated to
v3.0.0 soonish. TEMPO is connected to WRF, MPAS, and CCPP as a submodule, and the same v3.0.0 code will be connected to WRF (this PR), MPAS, and CCPP.

In WRF, supported namelist options include `tempo_aerosolaware==1` to use the aerosol-aware version, and `tempo_hailaware==1` to use the hail-aware version. Both options are on by default.

Key improvements include:
- TEMPO is in a submodule that allows for flexibility when connecting TEMPO to dynamical cores
- Code modularity was been improved and technical documentation has been added
- Bux fix for cloud droplet number concentration during evaporation
- Surface emissions of water-friendly aerosols have been reduced based on a sensitivity simulation that aimed to better constrain water-friendly aerosol concentrations over 24-36 hour forecast periods and reduce the accumulation of aerosols in the atmosphere
- A few modifications were made to graupel number concentration tendencies (when using the hail-aware option) for processes that cause rain to freeze to increase reflectivity in deep convective storms
- Added simple sedimentation tests
- Added unit tests
- Added a program to build lookup tables with MPI capability 
- Lookup tables have been unified
@mgduda mgduda requested review from jihyeonjang and mgduda April 23, 2026 19:17
@mgduda mgduda changed the base branch from master to develop April 23, 2026 19:19
Comment thread src/core_init_atmosphere/Registry.xml Outdated
@mgduda
Copy link
Copy Markdown
Contributor

mgduda commented Apr 23, 2026

When building with Make using the gnu build target, there are a couple of compilation errors (perhaps because we include the -std=f2008 flag):

src/module_mp_tempo_diags.F90:119:28:

  119 |       dbz(k) = max(-35._wp, 10._wp*log10((ze_rain(k)+ze_snow(k)+ze_graupel(k))*1.e18_dp))
      |                            1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_diags.F90:53:59:

   53 |         re_qs(k) = max(5.01e-6_wp, min(0.5_wp*(smoc/smob), 999.e-6_wp))
      |                                                           1
Error: GNU Extension: Different type kinds at (1)

@mgduda
Copy link
Copy Markdown
Contributor

mgduda commented Apr 23, 2026

When building with Make, after the physics have all been compiled, we symbolically link physics look-up tables into the top-level MPAS-Model directory (see https://github.com/MPAS-Dev/MPAS-Model/blob/v8.4.0/src/core_atmosphere/Makefile#L49-L54). Should we do this for the ccn_activate.bin file as well?

@mgduda
Copy link
Copy Markdown
Contributor

mgduda commented Apr 23, 2026

@AndersJensen-NOAA From where should users obtain the file freeze_water_data_tempo_v3? This doesn't seem to be present in the TEMPO/tables directory.

Here's the runtime error I'm seeing without this file in my run directory:

ERROR STOP --- file "freeze_water_data_tempo_v3" needed for TEMPO microphysics was not found.

Comment thread src/core_atmosphere/physics/mpas_atmphys_interface.F
@AndersJensen-NOAA
Copy link
Copy Markdown
Collaborator Author

@AndersJensen-NOAA From where should users obtain the file freeze_water_data_tempo_v3? This doesn't seem to be present in the TEMPO/tables directory.

Here's the runtime error I'm seeing without this file in my run directory:

ERROR STOP --- file "freeze_water_data_tempo_v3" needed for TEMPO microphysics was not found.

@mgduda you need three tables that are large-ish so they aren't stored on git at the moment.
I keep a copy of the table on noaa servers:
wget https://gsl.noaa.gov/thredds/fileServer/retro/jensen/qr_acr_qg_data_tempo_v3
wget https://gsl.noaa.gov/thredds/fileServer/retro/jensen/qr_acr_qs_data_tempo_v3
wget https://gsl.noaa.gov/thredds/fileServer/retro/jensen/freeze_water_data_tempo_v3

If you need to build the tables, you can compile/run the standalone build_tables program. If you are using gfortran to build the tables you will want to modify the default optimization or use MPI, otherwise the build will take a long time.
https://ncar.github.io/TEMPO/program/build_tables.html

I'm open to suggestions for better ways to deal the lookup tables. Maybe they can be automatically downoaded/linked?

@AndersJensen-NOAA
Copy link
Copy Markdown
Collaborator Author

When building with Make, after the physics have all been compiled, we symbolically link physics look-up tables into the top-level MPAS-Model directory (see https://github.com/MPAS-Dev/MPAS-Model/blob/v8.4.0/src/core_atmosphere/Makefile#L49-L54). Should we do this for the ccn_activate.bin file as well?

Yes.

@mgduda
Copy link
Copy Markdown
Contributor

mgduda commented Apr 23, 2026

I'm open to suggestions for better ways to deal the lookup tables. Maybe they can be automatically downoaded/linked?

Would it be feasible to incorporate your stand-alone program for computing these tables into MPAS-A's existing src/core_atmosphere/utils directory? If the code is more or less static, we could just place the source file directly in the MPAS-Model repository; otherwise, we could fetch the code from a repository with manage_externals.

@AndersJensen-NOAA
Copy link
Copy Markdown
Collaborator Author

I'm open to suggestions for better ways to deal the lookup tables. Maybe they can be automatically downoaded/linked?

Would it be feasible to incorporate your stand-alone program for computing these tables into MPAS-A's existing src/core_atmosphere/utils directory? If the code is more or less static, we could just place the source file directly in the MPAS-Model repository; otherwise, we could fetch the code from a repository with manage_externals.

The lookup tables are now the same for WRF/MPAS/CCPP, and I image that 99% of users won't want to change or rebuild the tables. Even though the build code is mostly static at this point, I'd like to keep the executable in the TEMPO repository so I don't have manage the program outside of TEMPO. I think the best path forward is to to either pull the lookup tables from NOAA servers or store them as git artifacts or in git LFS.

@AndersJensen-NOAA
Copy link
Copy Markdown
Collaborator Author

When building with Make using the gnu build target, there are a couple of compilation errors (perhaps because we include the -std=f2008 flag):

src/module_mp_tempo_diags.F90:119:28:

  119 |       dbz(k) = max(-35._wp, 10._wp*log10((ze_rain(k)+ze_snow(k)+ze_graupel(k))*1.e18_dp))
      |                            1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_diags.F90:53:59:

   53 |         re_qs(k) = max(5.01e-6_wp, min(0.5_wp*(smoc/smob), 999.e-6_wp))
      |                                                           1
Error: GNU Extension: Different type kinds at (1)

This commit should fix the issue:
NCAR/TEMPO@8e30fc0

@mgduda
Copy link
Copy Markdown
Contributor

mgduda commented May 4, 2026

The changes in NCAR/TEMPO@8e30fc0 seem to fix the original compilation issues I was seeing (with -std=f2008), though I'm now getting a different set of errors:

src/module_mp_tempo_main.F90:3085:63:

 3085 |             melt_f = max(0.05_wp, min(tend%prr_gml(k)*dt/rg(k),1._wp))
      |                                                               1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_main.F90:2418:53:

 2418 |               snow_dens_frac = min(1._wp, max(0._wp, rs(k)*odt / &
      |                                                     1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_main.F90:1092:10:

 1092 |           min(cig(1)*oig2*qi1d(k)/am_i*lami**bm_i, max_ni/rho(k)))
      |          1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_main.F90:945:64:

  945 |             min(ccg(1,nu_c)*ocg2(nu_c)*qc1d(k)/am_r*lamc**bm_r, nt_c_max/rho(k)))
      |                                                                1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_main.F90:956:66:

  956 |         mvd_c(k) = max(min((3.0_wp + nu_c + 0.672_wp) * ilamc(k), d0r), d0c)
      |                                                                  1
Error: GNU Extension: Different type kinds at (1)

@mgduda
Copy link
Copy Markdown
Contributor

mgduda commented May 4, 2026

I'm open to suggestions for better ways to deal the lookup tables. Maybe they can be automatically downoaded/linked?

Would it be feasible to incorporate your stand-alone program for computing these tables into MPAS-A's existing src/core_atmosphere/utils directory? If the code is more or less static, we could just place the source file directly in the MPAS-Model repository; otherwise, we could fetch the code from a repository with manage_externals.

The lookup tables are now the same for WRF/MPAS/CCPP, and I image that 99% of users won't want to change or rebuild the tables. Even though the build code is mostly static at this point, I'd like to keep the executable in the TEMPO repository so I don't have manage the program outside of TEMPO. I think the best path forward is to to either pull the lookup tables from NOAA servers or store them as git artifacts or in git LFS.

I can help with changes to download the tables. However, I think we might want to consider how to version these. What happens, for example, if the tables on the NOAA server are updated to support a newer version of TEMPO, but a user is still running an older release of MPAS-Atmosphere (with an older version of TEMPO)?

@AndersJensen-NOAA
Copy link
Copy Markdown
Collaborator Author

The changes in NCAR/TEMPO@8e30fc0 seem to fix the original compilation issues I was seeing (with -std=f2008), though I'm now getting a different set of errors:

src/module_mp_tempo_main.F90:3085:63:

 3085 |             melt_f = max(0.05_wp, min(tend%prr_gml(k)*dt/rg(k),1._wp))
      |                                                               1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_main.F90:2418:53:

 2418 |               snow_dens_frac = min(1._wp, max(0._wp, rs(k)*odt / &
      |                                                     1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_main.F90:1092:10:

 1092 |           min(cig(1)*oig2*qi1d(k)/am_i*lami**bm_i, max_ni/rho(k)))
      |          1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_main.F90:945:64:

  945 |             min(ccg(1,nu_c)*ocg2(nu_c)*qc1d(k)/am_r*lamc**bm_r, nt_c_max/rho(k)))
      |                                                                1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_main.F90:956:66:

  956 |         mvd_c(k) = max(min((3.0_wp + nu_c + 0.672_wp) * ilamc(k), d0r), d0c)
      |                                                                  1
Error: GNU Extension: Different type kinds at (1)

@mgduda I'm working out final issues with gnu debug, and came upon this issue when opening lookup tables to read:

src/module_mp_tempo_driver.F90:624:43:

624 | action='read', iostat=istat, convert='big_endian')
| 1
Error: GNU Extension: CONVERT tag at (1)

It seems like the convert option in the open statement is not supported by f2008 (but otherwise okay). Our computers are down today, but I'll confirm later this week that this is in fact the case. Do you have any thoughts on how to get around this? I think that convert is only needed for the ccpp since WRF and MPAS force big_endian at compile time.

@mgduda
Copy link
Copy Markdown
Contributor

mgduda commented May 5, 2026

@mgduda I'm working out final issues with gnu debug, and came upon this issue when opening lookup tables to read:

src/module_mp_tempo_driver.F90:624:43:

624 | action='read', iostat=istat, convert='big_endian') | 1 Error: GNU Extension: CONVERT tag at (1)

It seems like the convert option in the open statement is not supported by f2008 (but otherwise okay). Our computers are down today, but I'll confirm later this week that this is in fact the case. Do you have any thoughts on how to get around this? I think that convert is only needed for the ccpp since WRF and MPAS force big_endian at compile time.

I don't think the Fortran standard provides a way to force I/O to assume a particular byte order, and so this is something that must be handled in a compiler-specific way.

There are probably better ways of going about this, but one option might be to add the convert='big_endian' keyword argument conditionally through pre-processing, e.g.,

    open(unit=mp_unit, file=filename, form='unformatted', status='old', &
         action='read', iostat=istat &
#ifdef TEMPO_USE_CONVERT_ARGUMENT
         , convert='big_endian' &
#endif
         )

For host models whose build systems don't provide compiler-specific flags to assume big-endian I/O, you could define the TEMPO_USE_CONVERT_ARGUMENT macro during compilation (recognizing that this would be incompatible with strict standards compliance).

- adds TEMPO registry
- adds include flags and module use statements to connect tempo to
  microphysics driver
- adds substepping to tempo microphysics when dt > 90s
- adds tempo and aerosolaware options to interface
- adds initialization routines for tempo with aerosolaware option
@AndersJensen-NOAA
Copy link
Copy Markdown
Collaborator Author

@mgduda I'm working out final issues with gnu debug, and came upon this issue when opening lookup tables to read:
src/module_mp_tempo_driver.F90:624:43:
624 | action='read', iostat=istat, convert='big_endian') | 1 Error: GNU Extension: CONVERT tag at (1)
It seems like the convert option in the open statement is not supported by f2008 (but otherwise okay). Our computers are down today, but I'll confirm later this week that this is in fact the case. Do you have any thoughts on how to get around this? I think that convert is only needed for the ccpp since WRF and MPAS force big_endian at compile time.

I don't think the Fortran standard provides a way to force I/O to assume a particular byte order, and so this is something that must be handled in a compiler-specific way.

There are probably better ways of going about this, but one option might be to add the convert='big_endian' keyword argument conditionally through pre-processing, e.g.,

    open(unit=mp_unit, file=filename, form='unformatted', status='old', &
         action='read', iostat=istat &
#ifdef TEMPO_USE_CONVERT_ARGUMENT
         , convert='big_endian' &
#endif
         )

For host models whose build systems don't provide compiler-specific flags to assume big-endian I/O, you could define the TEMPO_USE_CONVERT_ARGUMENT macro during compilation (recognizing that this would be incompatible with strict standards compliance).

I let AI write a block of code for the MPAS TEMPO makefile, which will use the convert= argument unless gnu/f2008 is being use:

# Check if the compiler is GNU Fortran by querying its version string
IS_GNU := $(shell $(FC) --version 2>/dev/null | grep -i "GNU Fortran")

# Evaluate the logic and print statements
ifneq ($(IS_GNU),)
    # Check if -std=f2008 is present in FFLAGS
    ifneq (,$(findstring -std=f2008,$(FFLAGS)))
        TEMPO_FFLAGS += -DTEMPO_IGNORE_CONVERT_ARG
        # Prevent duplication: check if big-endian is ALREADY in FFLAGS
        ifeq (,$(findstring -fconvert=big-endian,$(FFLAGS)))
            TEMPO_FFLAGS += -fconvert=big-endian
        endif
    endif
endif

@AndersJensen-NOAA
Copy link
Copy Markdown
Collaborator Author

The changes in NCAR/TEMPO@8e30fc0 seem to fix the original compilation issues I was seeing (with -std=f2008), though I'm now getting a different set of errors:

src/module_mp_tempo_main.F90:3085:63:

 3085 |             melt_f = max(0.05_wp, min(tend%prr_gml(k)*dt/rg(k),1._wp))
      |                                                               1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_main.F90:2418:53:

 2418 |               snow_dens_frac = min(1._wp, max(0._wp, rs(k)*odt / &
      |                                                     1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_main.F90:1092:10:

 1092 |           min(cig(1)*oig2*qi1d(k)/am_i*lami**bm_i, max_ni/rho(k)))
      |          1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_main.F90:945:64:

  945 |             min(ccg(1,nu_c)*ocg2(nu_c)*qc1d(k)/am_r*lamc**bm_r, nt_c_max/rho(k)))
      |                                                                1
Error: GNU Extension: Different type kinds at (1)
src/module_mp_tempo_main.F90:956:66:

  956 |         mvd_c(k) = max(min((3.0_wp + nu_c + 0.672_wp) * ilamc(k), d0r), d0c)
      |                                                                  1
Error: GNU Extension: Different type kinds at (1)

I fixed these issues and a few more: I can now compile on our machines with gnu DEBUG=true

Comment thread src/core_init_atmosphere/mpas_init_atm_core_interface.F Outdated
@mgduda
Copy link
Copy Markdown
Contributor

mgduda commented May 8, 2026

@mgduda I'm working out final issues with gnu debug, and came upon this issue when opening lookup tables to read:
src/module_mp_tempo_driver.F90:624:43:
624 | action='read', iostat=istat, convert='big_endian') | 1 Error: GNU Extension: CONVERT tag at (1)
It seems like the convert option in the open statement is not supported by f2008 (but otherwise okay). Our computers are down today, but I'll confirm later this week that this is in fact the case. Do you have any thoughts on how to get around this? I think that convert is only needed for the ccpp since WRF and MPAS force big_endian at compile time.

I don't think the Fortran standard provides a way to force I/O to assume a particular byte order, and so this is something that must be handled in a compiler-specific way.
There are probably better ways of going about this, but one option might be to add the convert='big_endian' keyword argument conditionally through pre-processing, e.g.,

    open(unit=mp_unit, file=filename, form='unformatted', status='old', &
         action='read', iostat=istat &
#ifdef TEMPO_USE_CONVERT_ARGUMENT
         , convert='big_endian' &
#endif
         )

For host models whose build systems don't provide compiler-specific flags to assume big-endian I/O, you could define the TEMPO_USE_CONVERT_ARGUMENT macro during compilation (recognizing that this would be incompatible with strict standards compliance).

I let AI write a block of code for the MPAS TEMPO makefile, which will use the convert= argument unless gnu/f2008 is being use:

# Check if the compiler is GNU Fortran by querying its version string
IS_GNU := $(shell $(FC) --version 2>/dev/null | grep -i "GNU Fortran")

# Evaluate the logic and print statements
ifneq ($(IS_GNU),)
    # Check if -std=f2008 is present in FFLAGS
    ifneq (,$(findstring -std=f2008,$(FFLAGS)))
        TEMPO_FFLAGS += -DTEMPO_IGNORE_CONVERT_ARG
        # Prevent duplication: check if big-endian is ALREADY in FFLAGS
        ifeq (,$(findstring -fconvert=big-endian,$(FFLAGS)))
            TEMPO_FFLAGS += -fconvert=big-endian
        endif
    endif
endif

Since the MPAS build system ensures that big-endian / byteswap flags are used for all supported compilers, it seems like we could just always define TEMPO_IGNORE_CONVERT_ARG in the Makefile.mpas (assuming this file is only used by MPAS). The AI-generated logic could be replaced with something like

#
# The MPAS build system ensures that compiler-specific flags are used to
# set big-endian byte order for unformatted file I/O, so the non-standard
# convert='big_endian' argument to open(...) is not necessary
#
TEMPO_FFLAGS += -DTEMPO_IGNORE_CONVERT_ARG

@AndersJensen-NOAA
Copy link
Copy Markdown
Collaborator Author

I'm open to suggestions for better ways to deal the lookup tables. Maybe they can be automatically downoaded/linked?

Would it be feasible to incorporate your stand-alone program for computing these tables into MPAS-A's existing src/core_atmosphere/utils directory? If the code is more or less static, we could just place the source file directly in the MPAS-Model repository; otherwise, we could fetch the code from a repository with manage_externals.

The lookup tables are now the same for WRF/MPAS/CCPP, and I image that 99% of users won't want to change or rebuild the tables. Even though the build code is mostly static at this point, I'd like to keep the executable in the TEMPO repository so I don't have manage the program outside of TEMPO. I think the best path forward is to to either pull the lookup tables from NOAA servers or store them as git artifacts or in git LFS.

I can help with changes to download the tables. However, I think we might want to consider how to version these. What happens, for example, if the tables on the NOAA server are updated to support a newer version of TEMPO, but a user is still running an older release of MPAS-Atmosphere (with an older version of TEMPO)?

I'm open to suggestions for better ways to deal the lookup tables. Maybe they can be automatically downoaded/linked?

Would it be feasible to incorporate your stand-alone program for computing these tables into MPAS-A's existing src/core_atmosphere/utils directory? If the code is more or less static, we could just place the source file directly in the MPAS-Model repository; otherwise, we could fetch the code from a repository with manage_externals.

The lookup tables are now the same for WRF/MPAS/CCPP, and I image that 99% of users won't want to change or rebuild the tables. Even though the build code is mostly static at this point, I'd like to keep the executable in the TEMPO repository so I don't have manage the program outside of TEMPO. I think the best path forward is to to either pull the lookup tables from NOAA servers or store them as git artifacts or in git LFS.

I can help with changes to download the tables. However, I think we might want to consider how to version these. What happens, for example, if the tables on the NOAA server are updated to support a newer version of TEMPO, but a user is still running an older release of MPAS-Atmosphere (with an older version of TEMPO)?

I don't have a good way to version tables off the top of my head. Currently the tables all have "_v3" at the end of the filenames, and my plan is to ensure that these tables will always work with Tempo v3.x.x. If tables are updated but the user is still running an older release then either the code will crash if the table sizes are different from what the code expects or results will be answer changing. We can keep old tables on servers, but we'll still need a way to version/communicate changes to users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants