├── .gitignore
├── test
├── unit-test
│ ├── tests
│ │ ├── CMakeLists.txt
│ │ ├── utilities
│ │ │ ├── CMakeLists.txt
│ │ │ └── test_state_converters.pf
│ │ ├── phys_utils
│ │ │ ├── CMakeLists.txt
│ │ │ ├── test_atmos_pbl_utils.pf
│ │ │ └── test_atmos_rad_utils.pf
│ │ └── mmm
│ │ │ └── CMakeLists.txt
│ ├── include
│ │ └── ccpp_kinds.F90
│ ├── README.md
│ └── CMakeLists.txt
├── musica
│ ├── configuration
│ │ ├── micm_util
│ │ │ ├── config.json
│ │ │ ├── species.json
│ │ │ └── reactions.json
│ │ └── analytical
│ │ │ ├── config.json
│ │ │ ├── species.json
│ │ │ └── reactions.json
│ ├── README.md
│ ├── micm
│ │ ├── test_micm_mock_mods.F90
│ │ └── CMakeLists.txt
│ ├── musica_ccpp_namelist.F90
│ ├── util
│ │ └── CMakeLists.txt
│ ├── aerosol_stub
│ │ └── CMakeLists.txt
│ ├── aerosol
│ │ └── CMakeLists.txt
│ └── tuvx
│ │ ├── test_tuvx_wavelength_grid.F90
│ │ ├── test_tuvx_surface_albedo.F90
│ │ └── test_tuvx_temperature.F90
├── cmake
│ ├── SetDefaults.cmake
│ └── TestUtils.cmake
├── .dockerignore
├── include
│ └── ccpp_kinds.F90
├── test_suites
│ ├── suite_file_io_test.xml
│ ├── suite_dme_adjust.xml
│ ├── suite_tj2016_precip.xml
│ ├── suite_dry_adiabatic_adjust.xml
│ ├── suite_tropopause_find.xml
│ ├── suite_tj2016_sfc_pbl_hs.xml
│ ├── suite_rayleigh_friction.xml
│ ├── suite_kessler_test.xml
│ ├── suite_convection_permitting.xml
│ ├── suite_zhang_mcfarlane.xml
│ ├── suite_gw_cam4.xml
│ ├── suite_convect_shallow_hack.xml
│ └── suite_gw_cam7_se.xml
├── test_schemes
│ ├── initialize_constituents.meta
│ └── file_io_test.meta
├── CMakeLists.txt
├── valgrind.supp
└── docker
│ └── Dockerfile.musica.no_install
├── to_be_ccppized
├── coords_1d.meta
├── namelist_utils.F90
├── ccpp_const_utils.F90
└── ccpp_tuvx_utils.F90
├── .github
├── pull_request_template.md
├── PULL_REQUEST_TEMPLATE
│ ├── main-template.md
│ └── develop-template.md
└── workflows
│ ├── no-direct-pr-to-main.yaml
│ ├── test.yaml
│ └── unit-tests.yaml
├── schemes
├── rrtmgp
│ ├── objects
│ │ ├── ccpp_fluxes.meta
│ │ ├── ccpp_fluxes_byband.meta
│ │ ├── ccpp_gas_concentrations.meta
│ │ ├── ccpp_source_functions.meta
│ │ ├── ccpp_gas_optics_rrtmgp.meta
│ │ ├── ccpp_fluxes.F90
│ │ ├── ccpp_fluxes_byband.F90
│ │ ├── ccpp_gas_concentrations.F90
│ │ ├── ccpp_optical_props.meta
│ │ ├── ccpp_source_functions.F90
│ │ ├── ccpp_gas_optics_rrtmgp.F90
│ │ └── ccpp_optical_props.F90
│ └── utils
│ │ └── rrtmgp_dry_static_energy_tendency.F90
├── musica
│ ├── aerosol_stub
│ │ └── README.md
│ ├── aerosol
│ │ └── musica_ccpp_aerosol_state.F90
│ ├── util
│ │ └── musica_ccpp_util.F90
│ └── tuvx
│ │ ├── musica_ccpp_tuvx_wavelength_grid.F90
│ │ └── musica_ccpp_tuvx_temperature.F90
├── mmm
│ ├── ccpp_kind_types.F90
│ └── CMakeLists.txt
├── conservation_adjust
│ └── check_energy
│ │ ├── check_energy_chng_namelist.xml
│ │ ├── check_energy_save_teout.meta
│ │ ├── check_energy_scaling.meta
│ │ ├── check_energy_save_teout.F90
│ │ ├── check_energy_zero_fluxes.F90
│ │ ├── check_energy_zero_fluxes.meta
│ │ ├── dycore_energy_consistency_adjust.meta
│ │ ├── check_energy_scaling.F90
│ │ ├── check_energy_fix.meta
│ │ ├── check_energy_fix.F90
│ │ └── dycore_energy_consistency_adjust.F90
├── sima_diagnostics
│ ├── check_energy_gmean_diagnostics_namelist.xml
│ ├── kessler_diagnostics.meta
│ ├── compute_cloud_fraction_diagnostics.meta
│ ├── gravity_wave_drag_common_diagnostics.meta
│ ├── rayleigh_friction_diagnostics.meta
│ ├── sima_tend_diagnostics.meta
│ ├── convective_cloud_cover_diagnostics.meta
│ ├── check_energy_gmean_diagnostics.meta
│ ├── check_energy_fix_diagnostics.meta
│ ├── compute_cloud_fraction_diagnostics.F90
│ ├── kessler_diagnostics.F90
│ ├── zm_tendency_diagnostics.meta
│ ├── gravity_wave_drag_common_diagnostics.F90
│ ├── zm_convr_tendency_diagnostics.meta
│ ├── sima_tend_diagnostics.F90
│ ├── check_energy_diagnostics.meta
│ ├── zm_momtran_tendency_diagnostics.meta
│ ├── zm_convr_tendency_diagnostics.F90
│ ├── cloud_particle_sedimentation_diagnostics.meta
│ ├── convective_cloud_cover_diagnostics.F90
│ ├── check_energy_gmean_diagnostics.F90
│ ├── rayleigh_friction_diagnostics.F90
│ ├── zm_momtran_tendency_diagnostics.F90
│ └── zm_evap_tendency_diagnostics.meta
├── utilities
│ ├── to_be_ccppized_temporary.meta
│ ├── to_be_ccppized_temporary.F90
│ ├── static_energy.F90
│ ├── convert_dry_constituent_tendencies_to_dry_air_basis.meta
│ ├── static_energy.meta
│ └── convert_dry_constituent_tendencies_to_dry_air_basis.F90
├── hack_shallow
│ ├── set_shallow_conv_fluxes_to_general.F90
│ ├── hack_convect_shallow_namelist.xml
│ ├── set_shallow_conv_fluxes_to_general.meta
│ └── set_general_conv_fluxes_to_shallow.F90
├── cloud_fraction
│ ├── set_cloud_fraction_top.meta
│ ├── set_cloud_fraction_top.F90
│ └── cloud_fraction_fice.meta
├── zhang_mcfarlane
│ ├── set_deep_conv_fluxes_to_general.F90
│ ├── set_deep_conv_fluxes_to_general.meta
│ ├── set_general_conv_fluxes_to_deep.F90
│ ├── save_ttend_from_convect_deep.meta
│ └── save_ttend_from_convect_deep.F90
├── holtslag_boville
│ ├── holtslag_boville_diff_options.meta
│ └── holtslag_boville_diff_options.F90
├── vertical_diffusion
│ ├── vertical_diffusion_options.meta
│ ├── vertical_diffusion_options.F90
│ └── vertical_diffusion_sponge_layer.meta
├── thermo_water_update
│ ├── thermo_water_update.meta
│ └── thermo_water_update.F90
├── rayleigh_friction
│ └── rayleigh_friction_namelist.xml
└── gravity_wave_drag
│ ├── gravity_wave_drag_top_taper.meta
│ ├── gw_common.meta
│ ├── gravity_wave_drag_top_taper.F90
│ └── gw_utils.F90
├── suites
├── suite_musica.xml
├── suite_held_suarez_1994.xml
├── suite_adiabatic.xml
├── suite_tj2016.xml
└── suite_kessler.xml
├── doc
└── ChangeLog_template
├── .gitmodules
├── phys_utils
├── atmos_phys_rad_utils.F90
└── atmos_phys_string_utils.F90
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | **/*.DS_Store
2 | **/*.pyc
3 | **/build/
4 | **/CMakeCache.txt
5 | **/CMakeFiles/
6 | .vscode
7 | xcode/
--------------------------------------------------------------------------------
/test/unit-test/tests/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_subdirectory(utilities)
2 | add_subdirectory(phys_utils)
3 | add_subdirectory(mmm)
4 |
--------------------------------------------------------------------------------
/test/musica/configuration/micm_util/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "camp-files": [
3 | "species.json",
4 | "reactions.json"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/test/musica/configuration/analytical/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "camp-files": [
3 | "species.json",
4 | "reactions.json"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/to_be_ccppized/coords_1d.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = coords1d
3 | type = ddt
4 |
5 | [ccpp-arg-table]
6 | name = coords1d
7 | type = ddt
8 |
--------------------------------------------------------------------------------
/test/unit-test/tests/utilities/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_pfunit_ctest(utilities_tests
2 | TEST_SOURCES test_state_converters.pf
3 | LINK_LIBRARIES utilities
4 | )
5 |
6 |
--------------------------------------------------------------------------------
/to_be_ccppized/namelist_utils.F90:
--------------------------------------------------------------------------------
1 | module namelist_utils
2 |
3 | use shr_nl_mod, only: &
4 | find_group_name => shr_nl_find_group_name
5 |
6 | end module namelist_utils
7 |
--------------------------------------------------------------------------------
/test/cmake/SetDefaults.cmake:
--------------------------------------------------------------------------------
1 | # Overwrite the init values choosen by CMake
2 | if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
3 | set(CMAKE_Fortran_FLAGS_DEBUG_INIT "-g")
4 | endif()
5 |
--------------------------------------------------------------------------------
/test/.dockerignore:
--------------------------------------------------------------------------------
1 | # ignore all
2 | *
3 |
4 | # add things to copy
5 | !cmake/
6 | !docker/
7 | !held_suarez
8 | !kessler
9 | !musica/
10 | !test/
11 | !utilities
12 | !zm
13 | !CMakeLists.txt
--------------------------------------------------------------------------------
/test/include/ccpp_kinds.F90:
--------------------------------------------------------------------------------
1 | module ccpp_kinds
2 |
3 | use ISO_FORTRAN_ENV, only: kind_phys => REAL64
4 |
5 | implicit none
6 | private
7 |
8 | public kind_phys
9 |
10 | end module ccpp_kinds
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | Please go the the `Preview` tab and select the appropriate PR template:
2 |
3 | * [development branch](?expand=1&template=develop-template.md)
4 | * [main branch](?expand=1&template=main-template.md)
5 |
--------------------------------------------------------------------------------
/test/unit-test/include/ccpp_kinds.F90:
--------------------------------------------------------------------------------
1 | module ccpp_kinds
2 |
3 | use ISO_FORTRAN_ENV, only: kind_phys => REAL64
4 |
5 | implicit none
6 | private
7 |
8 | public :: kind_phys
9 |
10 | end module ccpp_kinds
11 |
12 |
--------------------------------------------------------------------------------
/test/unit-test/tests/phys_utils/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_pfunit_ctest(phys_utils_tests
2 | TEST_SOURCES test_atmos_pbl_utils.pf
3 | TEST_SOURCES test_atmos_string_utils.pf
4 | TEST_SOURCES test_atmos_rad_utils.pf
5 | LINK_LIBRARIES phys_utils
6 | )
7 |
--------------------------------------------------------------------------------
/schemes/rrtmgp/objects/ccpp_fluxes.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = ty_fluxes_broadband_ccpp
3 | type = ddt
4 | # dependencies = /path/to/ext/rte-frontend/mo_fluxes.F90
5 |
6 | [ccpp-arg-table]
7 | name = ty_fluxes_broadband_ccpp
8 | type = ddt
9 |
--------------------------------------------------------------------------------
/schemes/rrtmgp/objects/ccpp_fluxes_byband.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = ty_fluxes_byband_ccpp
3 | type = ddt
4 | # dependencies = /path/to/ext/extensions/mo_fluxes_byband.F90
5 |
6 | [ccpp-arg-table]
7 | name = ty_fluxes_byband_ccpp
8 | type = ddt
9 |
--------------------------------------------------------------------------------
/schemes/rrtmgp/objects/ccpp_gas_concentrations.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = ty_gas_concs_ccpp
3 | type = ddt
4 | # dependencies = /path/to/ext/gas-optics/mo_gas_concentrations.F90
5 |
6 | [ccpp-arg-table]
7 | name = ty_gas_concs_ccpp
8 | type = ddt
9 |
--------------------------------------------------------------------------------
/test/unit-test/tests/mmm/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_pfunit_ctest(mmm_physics_compat_tests
2 | TEST_SOURCES
3 | mmm_physics_compat_tests.pf
4 | OTHER_SOURCES
5 | ../../include/ccpp_kinds.F90
6 | LINK_LIBRARIES
7 | mmm_physics_compat
8 | )
9 |
--------------------------------------------------------------------------------
/schemes/rrtmgp/objects/ccpp_source_functions.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = ty_source_func_lw_ccpp
3 | type = ddt
4 | # dependencies = /path/to/ext/rte-frontend/mo_source_functions.F90
5 |
6 | [ccpp-arg-table]
7 | name = ty_source_func_lw_ccpp
8 | type = ddt
9 |
--------------------------------------------------------------------------------
/schemes/musica/aerosol_stub/README.md:
--------------------------------------------------------------------------------
1 | The stub aerosol model
2 | ======================
3 |
4 | The files in this folder define a stub aerosol model, primarily for use during
5 | development. Functions of the stub aerosol classes return values corresponding
6 | to the absence of aerosols.
--------------------------------------------------------------------------------
/schemes/rrtmgp/objects/ccpp_gas_optics_rrtmgp.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = ty_gas_optics_rrtmgp_ccpp
3 | type = ddt
4 | # dependencies = /path/to/ext/rrtmgp-frontend/mo_gas_optics_rrtmgp.F90
5 |
6 | [ccpp-arg-table]
7 | name = ty_gas_optics_rrtmgp_ccpp
8 | type = ddt
9 |
--------------------------------------------------------------------------------
/test/test_suites/suite_file_io_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | file_io_test
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE/main-template.md:
--------------------------------------------------------------------------------
1 | Tag name (The PR title should also include the tag name):
2 | Originator(s):
3 |
4 | List all `development` PR numbers included in this PR and the title of each:
5 |
6 | List all automated tests that failed, as well as an explanation for why they weren't fixed:
7 |
--------------------------------------------------------------------------------
/test/musica/README.md:
--------------------------------------------------------------------------------
1 | MUSICA tests for CAM-SIMA Physics
2 | =================================
3 |
4 | To build and run the MUSICA tests for CAM-SIMA in a Docker container, from the
5 | top-level folder run:
6 |
7 | ```
8 | docker build -t atmos-phys . -f test/docker/Docker.musica
9 | docker run -it atmos-phys bash
10 | make test
11 | ```
--------------------------------------------------------------------------------
/test/test_suites/suite_dme_adjust.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | initialize_constituents
6 | dme_adjust
7 | sima_state_diagnostics
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/suites/suite_musica.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | calc_dry_air_ideal_gas_density
6 | musica_ccpp
7 |
8 |
9 | sima_state_diagnostics
10 |
11 |
12 |
--------------------------------------------------------------------------------
/schemes/mmm/ccpp_kind_types.F90:
--------------------------------------------------------------------------------
1 | !> The mere existence of this module is to satisfy the misdirected dependency of MMM physics,
2 | !> which inexplicably depends on `ccpp_kind_types` instead of `ccpp_kinds`.
3 | module ccpp_kind_types
4 | use ccpp_kinds, only: kind_phys
5 |
6 | implicit none
7 |
8 | private
9 | public :: kind_phys
10 | contains
11 | end module ccpp_kind_types
12 |
--------------------------------------------------------------------------------
/test/test_suites/suite_tj2016_precip.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | tj2016_precip
6 | apply_heating_rate
7 | qneg
8 | sima_state_diagnostics
9 | sima_tend_diagnostics
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/schemes/rrtmgp/objects/ccpp_fluxes.F90:
--------------------------------------------------------------------------------
1 | module ccpp_fluxes
2 | ! CCPP wrapper for ty_fluxes_broadband DDT from RRTMGP
3 | use mo_fluxes, only: ty_fluxes_broadband
4 |
5 | !> \section arg_table_ty_fluxes_broadband_ccpp Argument Table
6 | !! \htmlinclude ty_fluxes_broadband_ccpp.html
7 | type, public :: ty_fluxes_broadband_ccpp
8 | type(ty_fluxes_broadband) :: fluxes
9 | end type
10 |
11 | end module ccpp_fluxes
12 |
--------------------------------------------------------------------------------
/schemes/rrtmgp/objects/ccpp_fluxes_byband.F90:
--------------------------------------------------------------------------------
1 | module ccpp_fluxes_byband
2 | ! CCPP wrapper for ty_fluxes_byband DDT from RRTMGP
3 | use mo_fluxes_byband, only: ty_fluxes_byband
4 |
5 | !> \section arg_table_ty_fluxes_byband_ccpp Argument Table
6 | !! \htmlinclude ty_fluxes_byband_ccpp.html
7 | type, public :: ty_fluxes_byband_ccpp
8 | type(ty_fluxes_byband) :: fluxes
9 | end type
10 |
11 | end module ccpp_fluxes_byband
12 |
--------------------------------------------------------------------------------
/schemes/rrtmgp/objects/ccpp_gas_concentrations.F90:
--------------------------------------------------------------------------------
1 | module ccpp_gas_concentrations
2 | ! CCPP wrapper for ty_gas_concs DDT from RRTMGP
3 | use mo_gas_concentrations, only: ty_gas_concs
4 |
5 | !> \section arg_table_ty_gas_concs_ccpp Argument Table
6 | !! \htmlinclude ty_gas_concs_ccpp.html
7 | type, public :: ty_gas_concs_ccpp
8 | type(ty_gas_concs) :: gas_concs
9 | end type
10 |
11 | end module ccpp_gas_concentrations
12 |
--------------------------------------------------------------------------------
/schemes/rrtmgp/objects/ccpp_optical_props.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = ty_optical_props_1scl_ccpp
3 | type = ddt
4 | # dependencies = /path/to/ext/rte-frontend/mo_optical_props.F90
5 |
6 | [ccpp-arg-table]
7 | name = ty_optical_props_1scl_ccpp
8 | type = ddt
9 |
10 | [ccpp-table-properties]
11 | name = ty_optical_props_2str_ccpp
12 | type = ddt
13 |
14 | [ccpp-arg-table]
15 | name = ty_optical_props_2str_ccpp
16 | type = ddt
17 |
--------------------------------------------------------------------------------
/schemes/rrtmgp/objects/ccpp_source_functions.F90:
--------------------------------------------------------------------------------
1 | module ccpp_source_functions
2 | ! CCPP wrapper for ty_source_func_lw DDT from RRTMGP
3 | use mo_source_functions, only: ty_source_func_lw
4 |
5 | !> \section arg_table_ty_source_func_lw_ccpp Argument Table
6 | !! \htmlinclude ty_source_func_lw_ccpp.html
7 | type, public :: ty_source_func_lw_ccpp
8 | type(ty_source_func_lw) :: sources
9 | end type
10 |
11 | end module ccpp_source_functions
12 |
--------------------------------------------------------------------------------
/test/test_suites/suite_dry_adiabatic_adjust.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | dadadj
7 | apply_constituent_tendencies
8 | apply_heating_rate
9 | qneg
10 | geopotential_temp
11 |
12 |
13 |
--------------------------------------------------------------------------------
/schemes/rrtmgp/objects/ccpp_gas_optics_rrtmgp.F90:
--------------------------------------------------------------------------------
1 | module ccpp_gas_optics_rrtmgp
2 | ! CCPP wrapper for ty_gas_optics_rrtmgp DDT from RRTMGP
3 | use mo_gas_optics_rrtmgp, only: ty_gas_optics_rrtmgp
4 |
5 | !> \section arg_table_ty_gas_optics_rrtmgp_ccpp Argument Table
6 | !! \htmlinclude ty_gas_optics_rrtmgp_ccpp.html
7 | type, public :: ty_gas_optics_rrtmgp_ccpp
8 | type(ty_gas_optics_rrtmgp) :: gas_props
9 | end type
10 |
11 | end module ccpp_gas_optics_rrtmgp
12 |
--------------------------------------------------------------------------------
/schemes/musica/aerosol/musica_ccpp_aerosol_state.F90:
--------------------------------------------------------------------------------
1 | ! Copyright (C) 2025 University Corporation for Atmospheric Research
2 | ! SPDX-License-Identifier: Apache-2.0
3 | module musica_ccpp_aerosol_state
4 |
5 | implicit none
6 | private
7 |
8 | public :: aerosol_state_t
9 |
10 | !> Defines the state of an aerosol system according to
11 | !! the aerosol representation of a specific aerosol package.
12 | type, abstract :: aerosol_state_t
13 | end type aerosol_state_t
14 |
15 | end module musica_ccpp_aerosol_state
--------------------------------------------------------------------------------
/test/musica/configuration/micm_util/species.json:
--------------------------------------------------------------------------------
1 | {
2 | "camp-data": [
3 | {
4 | "name": "A",
5 | "type": "CHEM_SPEC",
6 | "__is advected": true
7 | },
8 | {
9 | "name": "B",
10 | "type": "CHEM_SPEC",
11 | "__is advected": true
12 | },
13 | {
14 | "name": "C",
15 | "type": "CHEM_SPEC",
16 | "__is advected": true
17 | },
18 | {
19 | "name": "D",
20 | "type": "CHEM_SPEC",
21 | "__is advected": true
22 | }
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/test/test_suites/suite_tropopause_find.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | tropopause_find
9 | tropopause_diagnostics
10 | qneg
11 |
12 |
13 |
--------------------------------------------------------------------------------
/test/test_suites/suite_tj2016_sfc_pbl_hs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | tj2016_sfc_pbl_hs
6 | apply_heating_rate
7 | apply_tendency_of_eastward_wind
8 | apply_tendency_of_northward_wind
9 | qneg
10 | sima_state_diagnostics
11 | sima_tend_diagnostics
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/test/test_suites/suite_rayleigh_friction.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | rayleigh_friction
7 | rayleigh_friction_diagnostics
8 | apply_heating_rate
9 | apply_tendency_of_eastward_wind
10 | apply_tendency_of_northward_wind
11 | geopotential_temp
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/doc/ChangeLog_template:
--------------------------------------------------------------------------------
1 | ===============================================================
2 |
3 | Tag name:
4 | Originator(s):
5 | Date:
6 | One-line Summary:
7 | Github PR URL:
8 |
9 | This PR fixes the following NCAR/atmospheric_physics Github issues:
10 |
11 | Code reviewed by:
12 |
13 | List all existing files that have been added (A), modified (M), or deleted (D),
14 | and describe the changes:
15 |
16 | List and Describe any test failures:
17 |
18 | Summarize any changes to answers:
19 |
20 | ===============================================================
21 |
--------------------------------------------------------------------------------
/suites/suite_held_suarez_1994.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | held_suarez_1994
6 | apply_tendency_of_eastward_wind
7 | apply_tendency_of_northward_wind
8 | apply_heating_rate
9 | geopotential_temp
10 | sima_state_diagnostics
11 |
12 |
13 | sima_tend_diagnostics
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.github/workflows/no-direct-pr-to-main.yaml:
--------------------------------------------------------------------------------
1 | name: PRs to main must be from development branch
2 | on:
3 | pull_request_target:
4 | types:
5 | - opened
6 | - reopened
7 | - synchronize
8 | - edited
9 | branches:
10 | - main
11 | jobs:
12 | check-branches:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Check branches
16 | run: |
17 | if [ ${{ github.head_ref }} != "development" ]; then
18 | echo "Merge requests to main branch are only allowed from the development branch."
19 | exit 1
20 | fi
21 |
--------------------------------------------------------------------------------
/test/musica/micm/test_micm_mock_mods.F90:
--------------------------------------------------------------------------------
1 | ! Copyright (C) 2024-2025 University Corporation for Atmospheric Research
2 | ! SPDX-License-Identifier: Apache-2.0
3 | module musica_ccpp_species
4 | ! Mock module for testing
5 | use ccpp_kinds, only: kind_phys
6 |
7 | implicit none
8 | private
9 | public :: micm_indices_constituent_props, micm_molar_mass_array
10 |
11 | integer, parameter :: micm_indices_constituent_props(4) = (/ 1, 2, 3, 4 /)
12 | real(kind_phys), parameter :: micm_molar_mass_array(4) = &
13 | (/ 200._kind_phys, 100._kind_phys, 150._kind_phys, 250._kind_phys /)
14 | end module musica_ccpp_species
15 |
--------------------------------------------------------------------------------
/schemes/conservation_adjust/check_energy/check_energy_chng_namelist.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | logical
8 | diagnostics
9 | check_energy_nl
10 | flag_for_energy_conservation_warning
11 | flag
12 |
13 | Turn on verbose output identifying columns that fail energy/water conservation checks. Default: FALSE
14 |
15 |
16 | false
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/check_energy_gmean_diagnostics_namelist.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | logical
8 | diagnostics
9 | check_energy_gmean_nl
10 | flag_for_energy_global_means_output
11 | flag
12 |
13 | Turn on output of global means of total energy and heating rate for energy conservation. Default: TRUE
14 |
15 |
16 | true
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/schemes/utilities/to_be_ccppized_temporary.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = to_be_ccppized_temporary
3 | type = scheme
4 | dependencies = ../../to_be_ccppized/wv_saturation.F90
5 | [ccpp-arg-table]
6 | name = to_be_ccppized_temporary_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | long_name = Error message for error handling in CCPP
11 | units = none
12 | type = character | kind = len=512
13 | dimensions = ()
14 | intent = out
15 | [ errflg ]
16 | standard_name = ccpp_error_code
17 | long_name = Error flag for error handling in CCPP
18 | units = 1
19 | type = integer
20 | dimensions = ()
21 | intent = out
22 |
23 |
--------------------------------------------------------------------------------
/test/musica/micm/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_executable(test_micm_util test_micm_util.F90 test_micm_mock_mods.F90)
2 |
3 | target_sources(test_micm_util
4 | PUBLIC
5 | ${MUSICA_SRC_PATH}/micm/musica_ccpp_micm_util.F90
6 | ${MUSICA_SRC_PATH}/util/musica_ccpp_util.F90
7 | ${CCPP_TEST_SRC_PATH}/ccpp_kinds.F90
8 | )
9 |
10 | target_link_libraries(test_micm_util
11 | PRIVATE
12 | musica-fortran musica mechanism_configuration yaml-cpp stdc++ netcdff
13 | )
14 |
15 | add_test(
16 | NAME test_micm_util
17 | COMMAND $
18 | WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
19 | )
20 |
21 | add_memory_check_test(test_micm_util $ "" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "mmm-physics"]
2 | path = schemes/mmm/mmm_physics
3 | url = https://github.com/NCAR/MMM-physics.git
4 | fxtag = 20250616-MPASv8.3
5 | fxrequired = AlwaysRequired
6 | fxDONOTUSEurl = https://github.com/NCAR/MMM-physics.git
7 | [submodule "pumas"]
8 | path = schemes/pumas/pumas
9 | url = https://github.com/ESCOMP/PUMAS
10 | fxrequired = AlwaysRequired
11 | fxtag = pumas_cam-release_v1.39
12 | fxDONOTUSEurl = https://github.com/ESCOMP/PUMAS
13 | [submodule "rte-rrtmgp"]
14 | path = schemes/rrtmgp/ext
15 | url = https://github.com/earth-system-radiation/rte-rrtmgp.git
16 | fxrequired = AlwaysRequired
17 | fxtag = v1.9.2
18 | fxDONOTUSEurl = https://github.com/earth-system-radiation/rte-rrtmgp.git
19 |
--------------------------------------------------------------------------------
/test/musica/musica_ccpp_namelist.F90:
--------------------------------------------------------------------------------
1 | ! Copyright (C) 2024-2025 University Corporation for Atmospheric Research
2 | ! SPDX-License-Identifier: Apache-2.0
3 |
4 | ! Stub for auto-generated MUSICA namelist module
5 | module musica_ccpp_namelist
6 |
7 | implicit none
8 |
9 | private
10 |
11 | character(len=250), public :: micm_solver_type = 'Rosenbrock'
12 | character(len=250), public :: filename_of_micm_configuration = 'musica_configurations/chapman/micm/config.json'
13 | character(len=250), public :: filename_of_tuvx_configuration = 'musica_configurations/chapman/tuvx/config.json'
14 | character(len=250), public :: filename_of_tuvx_micm_mapping_configuration = 'musica_configurations/chapman/tuvx_micm_mapping.json'
15 |
16 | end module musica_ccpp_namelist
17 |
--------------------------------------------------------------------------------
/schemes/rrtmgp/objects/ccpp_optical_props.F90:
--------------------------------------------------------------------------------
1 | module ccpp_optical_props
2 | ! CCPP wrapper for ty_optical_props_* DDTs from RRTMGP
3 | use mo_optical_props, only: ty_optical_props_1scl
4 | use mo_optical_props, only: ty_optical_props_2str
5 |
6 | !> \section arg_table_ty_optical_props_1scl_ccpp Argument Table
7 | !! \htmlinclude ty_optical_props_1scl_ccpp.html
8 | type, public :: ty_optical_props_1scl_ccpp
9 | type(ty_optical_props_1scl) :: optical_props
10 | end type
11 |
12 | !> \section arg_table_ty_optical_props_2str_ccpp Argument Table
13 | !! \htmlinclude ty_optical_props_2str_ccpp.html
14 | type, public :: ty_optical_props_2str_ccpp
15 | type(ty_optical_props_2str) :: optical_props
16 | end type
17 |
18 | end module ccpp_optical_props
19 |
--------------------------------------------------------------------------------
/test/unit-test/tests/utilities/test_state_converters.pf:
--------------------------------------------------------------------------------
1 | @test
2 | subroutine test_temp_to_potential_temp()
3 | use funit
4 | use state_converters, only : temp_to_potential_temp_run
5 | use ccpp_kinds, only: kind_phys
6 |
7 | integer, parameter :: ncol = 5
8 | integer, parameter :: nz = 5
9 |
10 | real(kind_phys) :: temp(ncol, nz)
11 | real(kind_phys) :: exner(ncol, nz)
12 | real(kind_phys) :: theta(ncol, nz)
13 | character(len=512) :: errmsg
14 | integer :: errflg
15 |
16 | temp = 1
17 | exner = 1
18 | theta = 1
19 |
20 | errmsg = ""
21 | errflg = 0
22 |
23 | call temp_to_potential_temp_run(ncol, nz, temp, exner, theta, errmsg, errflg)
24 |
25 | @assertEqual(0, errflg)
26 |
27 | end subroutine test_temp_to_potential_temp
28 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE/develop-template.md:
--------------------------------------------------------------------------------
1 | Originator(s):
2 |
3 | Description (include issue title and the keyword ['closes', 'fixes', 'resolves'] and issue number):
4 |
5 | List all namelist files that were added or changed:
6 |
7 | List all files eliminated and why:
8 |
9 | List all files added and what they do:
10 |
11 | List all existing files that have been modified, and describe the changes:
12 | (Helpful git command: `git diff --name-status development...`)
13 |
14 | List all automated tests that failed, as well as an explanation for why they weren't fixed:
15 |
16 | Is this an answer-changing PR? If so, is it a new physics package, algorithm change, tuning change, etc?
17 |
18 | If yes to the above question, describe how this code was validated with the new/modified features:
19 |
--------------------------------------------------------------------------------
/schemes/hack_shallow/set_shallow_conv_fluxes_to_general.F90:
--------------------------------------------------------------------------------
1 | module set_shallow_conv_fluxes_to_general
2 |
3 | use ccpp_kinds, only: kind_phys
4 |
5 | implicit none
6 |
7 | contains
8 |
9 | !> \section arg_table_set_shallow_conv_fluxes_to_general_run Argument Table
10 | !! \htmlinclude set_shallow_conv_fluxes_to_general_run.html
11 | subroutine set_shallow_conv_fluxes_to_general_run(prec_gen, prec_sh, prdprec_gen, prdprec_sh)
12 |
13 | real(kind_phys), intent(out) :: prec_gen(:)
14 | real(kind_phys), intent(in) :: prec_sh(:)
15 | real(kind_phys), intent(out) :: prdprec_gen(:,:)
16 | real(kind_phys), intent(in) :: prdprec_sh(:,:)
17 |
18 | prec_gen = prec_sh
19 | prdprec_gen = prdprec_sh
20 |
21 | end subroutine set_shallow_conv_fluxes_to_general_run
22 |
23 | end module set_shallow_conv_fluxes_to_general
24 |
--------------------------------------------------------------------------------
/schemes/cloud_fraction/set_cloud_fraction_top.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = set_cloud_fraction_top
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = set_cloud_fraction_top_init
7 | type = scheme
8 | [ trop_cloud_top_lev ]
9 | standard_name = vertical_layer_index_of_troposphere_cloud_physics_top
10 | units = index
11 | type = integer
12 | dimensions = ()
13 | intent = in
14 | [ top_lev ]
15 | standard_name = vertical_layer_index_of_cloud_fraction_top
16 | units = index
17 | type = integer
18 | dimensions = ()
19 | intent = out
20 | [ errmsg ]
21 | standard_name = ccpp_error_message
22 | units = none
23 | type = character | kind = len=512
24 | dimensions = ()
25 | intent = out
26 | [ errflg ]
27 | standard_name = ccpp_error_code
28 | units = 1
29 | type = integer
30 | dimensions = ()
31 | intent = out
32 |
--------------------------------------------------------------------------------
/schemes/zhang_mcfarlane/set_deep_conv_fluxes_to_general.F90:
--------------------------------------------------------------------------------
1 | module set_deep_conv_fluxes_to_general
2 |
3 | use ccpp_kinds, only: kind_phys
4 |
5 | implicit none
6 |
7 | contains
8 |
9 | !===============================================================================
10 | !> \section arg_table_set_deep_conv_fluxes_to_general_run Argument Table
11 | !! \htmlinclude set_deep_conv_fluxes_to_general_run.html
12 | !!
13 |
14 | subroutine set_deep_conv_fluxes_to_general_run(prec_gen, prec_dp, prdprec_gen, prdprec_dp)
15 |
16 | real(kind_phys), intent(out) :: prec_gen(:)
17 | real(kind_phys), intent(in) :: prec_dp(:)
18 | real(kind_phys), intent(out) :: prdprec_gen(:,:)
19 | real(kind_phys), intent(in) :: prdprec_dp(:,:)
20 |
21 | prec_gen = prec_dp
22 | prdprec_gen = prdprec_dp
23 |
24 | end subroutine set_deep_conv_fluxes_to_general_run
25 |
26 | end module set_deep_conv_fluxes_to_general
27 |
--------------------------------------------------------------------------------
/schemes/utilities/to_be_ccppized_temporary.F90:
--------------------------------------------------------------------------------
1 | module to_be_ccppized_temporary
2 | ! This module is a TEMPORARY place to put calls to initialization routines which have not yet
3 | ! been CCPP'ized, and the run methods are being called directly in CCPP'ized routines.
4 |
5 | ! Once a module has been CCPP'ized, then the call in this routine needs to be removed
6 |
7 | implicit none
8 |
9 | contains
10 |
11 | !> \section arg_table_to_be_ccppized_temporary_init Argument Table
12 | !! \htmlinclude to_be_ccppized_temporary_init.html
13 | !!
14 | subroutine to_be_ccppized_temporary_init(errmsg, errflg)
15 |
16 | use wv_saturation, only: wv_sat_init
17 |
18 | character(len=512), intent(out) :: errmsg
19 | integer, intent(out) :: errflg
20 |
21 | errmsg = ' '
22 | errflg = 0
23 |
24 | call wv_sat_init()
25 |
26 | end subroutine to_be_ccppized_temporary_init
27 |
28 | end module to_be_ccppized_temporary
29 |
30 |
--------------------------------------------------------------------------------
/test/test_suites/suite_kessler_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | calc_exner
6 | temp_to_potential_temp
7 | calc_dry_air_ideal_gas_density
8 | wet_to_dry_water_vapor
9 | wet_to_dry_cloud_liquid_water
10 | wet_to_dry_rain
11 | kessler
12 | potential_temp_to_temp
13 | dry_to_wet_water_vapor
14 | dry_to_wet_cloud_liquid_water
15 | dry_to_wet_rain
16 | kessler_update
17 | qneg
18 | geopotential_temp
19 |
20 |
21 | sima_state_diagnostics
22 | kessler_diagnostics
23 |
24 |
25 |
--------------------------------------------------------------------------------
/schemes/holtslag_boville/holtslag_boville_diff_options.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = holtslag_boville_diff_options
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = holtslag_boville_diff_options_init
7 | type = scheme
8 | [ amIRoot ]
9 | standard_name = flag_for_mpi_root
10 | units = flag
11 | type = logical
12 | dimensions = ()
13 | intent = in
14 | [ iulog ]
15 | standard_name = log_output_unit
16 | units = 1
17 | type = integer
18 | dimensions = ()
19 | intent = in
20 | [ is_hbr_pbl_scheme ]
21 | standard_name = flag_for_hbr_configuration_of_holtslag_boville_mixing_scheme
22 | units = flag
23 | type = logical
24 | dimensions = ()
25 | intent = in
26 | [ errmsg ]
27 | standard_name = ccpp_error_message
28 | units = none
29 | type = character | kind = len=512
30 | dimensions = ()
31 | intent = out
32 | [ errflg ]
33 | standard_name = ccpp_error_code
34 | units = 1
35 | type = integer
36 | dimensions = ()
37 | intent = out
38 |
--------------------------------------------------------------------------------
/test/unit-test/tests/phys_utils/test_atmos_pbl_utils.pf:
--------------------------------------------------------------------------------
1 | @test
2 | subroutine test_free_eddy_coef_is_zero_when_ri_equals_zero()
3 | use funit
4 | use atmos_phys_pbl_utils, only : calc_free_atm_eddy_flux_coefficient
5 | use ccpp_kinds, only: kind_phys
6 |
7 | real(kind_phys) :: kvf
8 |
9 | kvf = calc_free_atm_eddy_flux_coefficient(30.0_kind_phys, 0.0_kind_phys, 0.01_kind_phys)
10 |
11 | @assertEqual(0.0_kind_phys, kvf)
12 | end subroutine test_free_eddy_coef_is_zero_when_ri_equals_zero
13 |
14 | @test
15 | subroutine test_free_eddy_atm_coef_is_zero_when_ri_stable_near_zero()
16 | use funit
17 | use atmos_phys_pbl_utils, only : calc_free_atm_eddy_flux_coefficient
18 | use ccpp_kinds, only: kind_phys
19 |
20 | real(kind_phys) :: kvf
21 |
22 | kvf = calc_free_atm_eddy_flux_coefficient(30.0_kind_phys, nearest(0.0_kind_phys, 1.0_kind_phys), 0.01_kind_phys)
23 |
24 | @assertEqual(0.0_kind_phys, kvf)
25 | end subroutine test_free_eddy_atm_coef_is_zero_when_ri_stable_near_zero
26 |
--------------------------------------------------------------------------------
/test/musica/configuration/analytical/species.json:
--------------------------------------------------------------------------------
1 | {
2 | "camp-data": [
3 | {
4 | "name": "A",
5 | "type": "CHEM_SPEC",
6 | "molecular weight [kg mol-1]": 0.01802,
7 | "__is advected": true
8 | },
9 | {
10 | "name": "B",
11 | "type": "CHEM_SPEC",
12 | "molecular weight [kg mol-1]": 0.02897,
13 | "__is advected": true
14 | },
15 | {
16 | "name": "C",
17 | "type": "CHEM_SPEC",
18 | "molecular weight [kg mol-1]": 0.0319988,
19 | "__is advected": true
20 | },
21 | {
22 | "name": "D",
23 | "type": "CHEM_SPEC",
24 | "molecular weight [kg mol-1]": 0.0479982,
25 | "__is advected": true
26 | },
27 | {
28 | "name": "E",
29 | "type": "CHEM_SPEC",
30 | "molecular weight [kg mol-1]": 0.07254,
31 | "__is advected": true
32 | },
33 | {
34 | "name": "F",
35 | "type": "CHEM_SPEC",
36 | "molecular weight [kg mol-1]": 0.082356,
37 | "__is advected": true
38 | }
39 | ]
40 | }
41 |
--------------------------------------------------------------------------------
/test/cmake/TestUtils.cmake:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Utility functions for creating tests
3 |
4 | if(CCPP_ENABLE_MEMCHECK)
5 | find_program(MEMORYCHECK_COMMAND "valgrind")
6 |
7 | # Set the Valgrind suppressions file for tests
8 | set(MEMCHECK_SUPPRESS "--suppressions=${CMAKE_SOURCE_DIR}/valgrind.supp")
9 | endif()
10 |
11 | ################################################################################
12 | # Runs a test with memory checking if enabled
13 |
14 | function(add_memory_check_test test_name test_binary test_args working_dir)
15 | if(CCPP_ENABLE_MEMCHECK)
16 | add_test(NAME memcheck_${test_name}
17 | COMMAND mpirun -v -np 1 ${MEMORYCHECK_COMMAND} --leak-check=full --error-exitcode=1 --trace-children=yes --gen-suppressions=all ${MEMCHECK_SUPPRESS}
18 | ${test_binary} ${test_args}
19 | WORKING_DIRECTORY ${working_dir})
20 | endif()
21 | endfunction(add_memory_check_test)
22 |
23 | ################################################################################
--------------------------------------------------------------------------------
/test/musica/util/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # MUSICA grid test
2 | add_executable(test_musica_grid test_musica_grid.F90)
3 |
4 | target_sources(test_musica_grid
5 | PUBLIC
6 | ${MUSICA_CCPP_SOURCES}
7 | ${TO_BE_CCPPIZED_SRC_PATH}/ccpp_const_utils.F90
8 | ${TO_BE_CCPPIZED_SRC_PATH}/ccpp_tuvx_utils.F90
9 | ${CCPP_SRC_PATH}/ccpp_constituent_prop_mod.F90
10 | ${CCPP_SRC_PATH}/ccpp_hash_table.F90
11 | ${CCPP_SRC_PATH}/ccpp_hashable.F90
12 | ${CCPP_TEST_SRC_PATH}/ccpp_kinds.F90
13 | ../musica_ccpp_namelist.F90
14 | )
15 |
16 | target_link_libraries(test_musica_grid
17 | PRIVATE
18 | musica-fortran musica mechanism_configuration yaml-cpp stdc++ netcdff
19 | )
20 |
21 | set_target_properties(test_musica_grid
22 | PROPERTIES
23 | LINKER_LANGUAGE Fortran
24 | )
25 |
26 | add_test(
27 | NAME test_musica_grid
28 | COMMAND $
29 | WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
30 | )
31 |
32 | add_memory_check_test(test_musica_grid $ "" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
33 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/kessler_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = kessler_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = kessler_diagnostics_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | units = none
11 | type = character | kind = len=512
12 | dimensions = ()
13 | intent = out
14 | [ errflg ]
15 | standard_name = ccpp_error_code
16 | units = 1
17 | type = integer
18 | dimensions = ()
19 | intent = out
20 |
21 | [ccpp-arg-table]
22 | name = kessler_diagnostics_run
23 | type = scheme
24 | [ precl ]
25 | standard_name = total_precipitation_rate_at_surface
26 | units = m s-1
27 | type = real | kind = kind_phys
28 | dimensions = (horizontal_loop_extent)
29 | intent = in
30 | [ errmsg ]
31 | standard_name = ccpp_error_message
32 | units = none
33 | type = character | kind = len=512
34 | dimensions = ()
35 | intent = out
36 | [ errflg ]
37 | standard_name = ccpp_error_code
38 | units = 1
39 | type = integer
40 | dimensions = ()
41 | intent = out
42 |
--------------------------------------------------------------------------------
/schemes/mmm/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.20)
2 |
3 | # `mmm_physics_compat` has not been integrated into the CMake build of any top level projects yet,
4 | # and this CMakeLists.txt file is currently for unit testing purposes only.
5 | # Making a change to this CMakeLists.txt file will not impact the build of a parent project at this time.
6 | project(mmm_physics_compat
7 | VERSION
8 | 0.1.0
9 | DESCRIPTION
10 | "MMM physics compatibility layer for CCPP"
11 | LANGUAGES
12 | Fortran
13 | )
14 |
15 | add_library(mmm_physics_compat)
16 | target_sources(mmm_physics_compat
17 | PRIVATE
18 | ../../test/unit-test/include/ccpp_kinds.F90
19 | ccpp_kind_types.F90
20 | mmm_physics_compat.F90
21 | )
22 | target_compile_options(mmm_physics_compat
23 | PRIVATE
24 | $<$,$>:-fbacktrace -fcheck=all -std=f2018 -Wall -Wextra -Wpedantic>
25 | )
26 | target_include_directories(mmm_physics_compat
27 | INTERFACE
28 | ${CMAKE_CURRENT_BINARY_DIR}
29 | )
30 |
--------------------------------------------------------------------------------
/.github/workflows/test.yaml:
--------------------------------------------------------------------------------
1 | name: build
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | - development
8 | workflow_dispatch:
9 | pull_request:
10 |
11 | jobs:
12 | test_musica_api:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: actions/checkout@v4
16 | with:
17 | submodules: recursive
18 | - name: build Docker image
19 | run: docker build -t musica -f test/docker/Dockerfile.musica .
20 | - name: run tests in container
21 | run: docker run --name test-container -t musica bash -c 'make test ARGS="--rerun-failed --output-on-failure -j8"'
22 | test_musica_api_no_install:
23 | runs-on: ubuntu-latest
24 | steps:
25 | - uses: actions/checkout@v4
26 | with:
27 | submodules: recursive
28 | - name: build Docker image
29 | run: docker build -t musica-no-install -f test/docker/Dockerfile.musica.no_install .
30 | - name: run tests in container
31 | run: docker run --name test-container -t musica-no-install bash -c 'make test ARGS="--rerun-failed --output-on-failure -j8"'
32 |
--------------------------------------------------------------------------------
/schemes/hack_shallow/hack_convect_shallow_namelist.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | real
8 | conv
9 | hkconv_nl
10 | characteristic_adjustment_time_for_shallow_convection
11 | s
12 |
13 | Characteristic adjustment time scale for Hack shallow scheme. Default: 1800.0
14 |
15 |
16 | 1800.0
17 |
18 |
19 |
20 | real
21 | conv
22 | hkconv_nl
23 | rain_water_autoconversion_coefficient_for_shallow_convection
24 | m-1
25 |
26 | Rain water autoconversion coefficient for Hack shallow scheme. Resolution dependent.
27 |
28 |
29 | 2.0e-4
30 | 1.0e-4
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/phys_utils/atmos_phys_rad_utils.F90:
--------------------------------------------------------------------------------
1 | module atmos_phys_rad_utils
2 | ! Radiation utility functions
3 |
4 | implicit none
5 | private
6 |
7 | public :: is_visible
8 |
9 | contains
10 |
11 | pure logical function is_visible(wavenumber)
12 | ! Returns true if the provided wavenumber is above the visible threshold
13 | use ccpp_kinds, only: kind_phys
14 |
15 | ! Wavenumber is in the visible if it is above the visible threshold
16 | ! wavenumber, and in the infrared if it is below the threshold
17 | ! This function doesn't distinquish between visible and UV.
18 |
19 | ! wavenumber in inverse cm (cm^-1)
20 | real(kind_phys), intent(in) :: wavenumber
21 |
22 | ! Set threshold between visible and infrared to 0.7 micron, or 14286 cm^-1
23 | real(kind_phys), parameter :: visible_wavenumber_threshold = 14286._kind_phys ! cm^-1
24 |
25 | if (wavenumber > visible_wavenumber_threshold) then
26 | is_visible = .true.
27 | else
28 | is_visible = .false.
29 | end if
30 |
31 | end function is_visible
32 |
33 | end module atmos_phys_rad_utils
34 |
--------------------------------------------------------------------------------
/test/musica/aerosol_stub/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # MUSICA stub aerosol model tests
2 | add_executable(test_stub_aerosol_model test_stub_aerosol_model.F90)
3 |
4 | target_sources(test_stub_aerosol_model
5 | PUBLIC
6 | ${MUSICA_CCPP_SOURCES}
7 | ${TO_BE_CCPPIZED_SRC_PATH}/ccpp_const_utils.F90
8 | ${TO_BE_CCPPIZED_SRC_PATH}/ccpp_tuvx_utils.F90
9 | ${CCPP_SRC_PATH}/ccpp_constituent_prop_mod.F90
10 | ${CCPP_SRC_PATH}/ccpp_hash_table.F90
11 | ${CCPP_SRC_PATH}/ccpp_hashable.F90
12 | ${CCPP_TEST_SRC_PATH}/ccpp_kinds.F90
13 | ../musica_ccpp_namelist.F90
14 | )
15 |
16 | target_link_libraries(test_stub_aerosol_model
17 | PRIVATE
18 | musica-fortran musica mechanism_configuration yaml-cpp stdc++ netcdff
19 | )
20 |
21 | set_target_properties(test_stub_aerosol_model
22 | PROPERTIES
23 | LINKER_LANGUAGE Fortran
24 | )
25 |
26 | add_test(
27 | NAME test_stub_aerosol_model
28 | COMMAND $
29 | WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
30 | )
31 |
32 | add_memory_check_test(test_stub_aerosol_model $ "" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
--------------------------------------------------------------------------------
/schemes/conservation_adjust/check_energy/check_energy_save_teout.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = check_energy_save_teout
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = check_energy_save_teout_run
7 | type = scheme
8 | [ ncol ]
9 | standard_name = horizontal_loop_extent
10 | units = count
11 | type = integer
12 | dimensions = ()
13 | intent = in
14 | [ te_cur_dyn ]
15 | standard_name = vertically_integrated_total_energy_using_dycore_energy_formula
16 | units = J m-2
17 | type = real | kind = kind_phys
18 | dimensions = (horizontal_loop_extent)
19 | intent = in
20 | [ teout ]
21 | standard_name = vertically_integrated_total_energy_using_dycore_energy_formula_at_end_of_physics_timestep
22 | units = J m-2
23 | type = real | kind = kind_phys
24 | dimensions = (horizontal_loop_extent)
25 | intent = out
26 | [ errmsg ]
27 | standard_name = ccpp_error_message
28 | units = none
29 | type = character | kind = len=512
30 | dimensions = ()
31 | intent = out
32 | [ errflg ]
33 | standard_name = ccpp_error_code
34 | units = 1
35 | type = integer
36 | dimensions = ()
37 | intent = out
38 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/compute_cloud_fraction_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = compute_cloud_fraction_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = compute_cloud_fraction_diagnostics_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | units = none
11 | type = character | kind = len=512
12 | dimensions = ()
13 | intent = out
14 | [ errflg ]
15 | standard_name = ccpp_error_code
16 | units = 1
17 | type = integer
18 | dimensions = ()
19 | intent = out
20 |
21 | [ccpp-arg-table]
22 | name = compute_cloud_fraction_diagnostics_run
23 | type = scheme
24 | [ cldst ]
25 | standard_name = stratiform_cloud_area_fraction
26 | units = fraction
27 | type = real | kind = kind_phys
28 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
29 | intent = in
30 | [ errmsg ]
31 | standard_name = ccpp_error_message
32 | units = none
33 | type = character | kind = len=512
34 | dimensions = ()
35 | intent = out
36 | [ errflg ]
37 | standard_name = ccpp_error_code
38 | units = 1
39 | type = integer
40 | dimensions = ()
41 | intent = out
42 |
--------------------------------------------------------------------------------
/schemes/vertical_diffusion/vertical_diffusion_options.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = vertical_diffusion_options
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = vertical_diffusion_options_init
7 | type = scheme
8 | [ amIRoot ]
9 | standard_name = flag_for_mpi_root
10 | units = flag
11 | type = logical
12 | dimensions = ()
13 | intent = in
14 | [ iulog ]
15 | standard_name = log_output_unit
16 | units = 1
17 | type = integer
18 | dimensions = ()
19 | intent = in
20 | [ do_iss_in ]
21 | standard_name = do_implicit_total_surface_stress_in_vertical_diffusion
22 | units = flag
23 | type = logical
24 | dimensions = ()
25 | intent = in
26 | [ am_correction_in ]
27 | standard_name = do_angular_momentum_correction_in_vertical_diffusion
28 | units = flag
29 | type = logical
30 | dimensions = ()
31 | intent = in
32 | [ errmsg ]
33 | standard_name = ccpp_error_message
34 | units = none
35 | type = character | kind = len=512
36 | dimensions = ()
37 | intent = out
38 | [ errflg ]
39 | standard_name = ccpp_error_code
40 | units = 1
41 | type = integer
42 | dimensions = ()
43 | intent = out
44 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/gravity_wave_drag_common_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = gravity_wave_drag_common_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = gravity_wave_drag_common_diagnostics_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | units = none
11 | type = character | kind = len=512
12 | dimensions = ()
13 | intent = out
14 | [ errflg ]
15 | standard_name = ccpp_error_code
16 | units = 1
17 | type = integer
18 | dimensions = ()
19 | intent = out
20 |
21 | [ccpp-arg-table]
22 | name = gravity_wave_drag_common_diagnostics_run
23 | type = scheme
24 | [ egwdffi_tot ]
25 | standard_name = effective_diffusivity_coefficient_at_interfaces_due_to_gravity_wave_drag
26 | units = m2 s-1
27 | type = real | kind = kind_phys
28 | dimensions = (horizontal_loop_extent, vertical_interface_dimension)
29 | intent = in
30 | [ errmsg ]
31 | standard_name = ccpp_error_message
32 | units = none
33 | type = character | kind = len=512
34 | dimensions = ()
35 | intent = out
36 | [ errflg ]
37 | standard_name = ccpp_error_code
38 | units = 1
39 | type = integer
40 | dimensions = ()
41 | intent = out
42 |
--------------------------------------------------------------------------------
/test/musica/aerosol/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # MUSICA integration test for the abstract aerosol model
2 | add_executable(test_musica_aerosol_model_mock_host mock_host.F90)
3 |
4 | target_sources(test_musica_aerosol_model_mock_host
5 | PUBLIC
6 | ${MUSICA_CCPP_SOURCES}
7 | ${TO_BE_CCPPIZED_SRC_PATH}/ccpp_const_utils.F90
8 | ${TO_BE_CCPPIZED_SRC_PATH}/ccpp_tuvx_utils.F90
9 | ${CCPP_SRC_PATH}/ccpp_constituent_prop_mod.F90
10 | ${CCPP_SRC_PATH}/ccpp_hash_table.F90
11 | ${CCPP_SRC_PATH}/ccpp_hashable.F90
12 | ${CCPP_TEST_SRC_PATH}/ccpp_kinds.F90
13 | ../musica_ccpp_namelist.F90
14 | )
15 |
16 | target_link_libraries(test_musica_aerosol_model_mock_host
17 | PRIVATE
18 | musica-fortran musica mechanism_configuration yaml-cpp stdc++ netcdff
19 | )
20 |
21 | set_target_properties(test_musica_aerosol_model_mock_host
22 | PROPERTIES
23 | LINKER_LANGUAGE Fortran
24 | )
25 |
26 | add_test(
27 | NAME test_musica_aerosol_model_mock_host
28 | COMMAND $
29 | WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
30 | )
31 |
32 | add_memory_check_test(test_musica_aerosol_model_mock_host $ "" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
--------------------------------------------------------------------------------
/schemes/cloud_fraction/set_cloud_fraction_top.F90:
--------------------------------------------------------------------------------
1 | ! Copyright (C) 2024-2025 University Corporation for Atmospheric Research
2 | ! SPDX-License-Identifier: Apache-2.0
3 | !
4 | ! Stub scheme to set top of cloud physics to below top cloud level.
5 | ! Used for all macrophysical schemes except RK.
6 | module set_cloud_fraction_top
7 | implicit none
8 | private
9 |
10 | public :: set_cloud_fraction_top_init
11 |
12 | contains
13 |
14 | !> \section arg_table_set_cloud_fraction_top_init Argument Table
15 | !! \htmlinclude set_cloud_fraction_top_init.html
16 | subroutine set_cloud_fraction_top_init(trop_cloud_top_lev, top_lev, errmsg, errflg)
17 | integer, intent(in) :: trop_cloud_top_lev ! Troposphere cloud physics top level [index]
18 | integer, intent(out) :: top_lev ! Cloud fraction top level [index]
19 | character(len=512), intent(out) :: errmsg ! Error message
20 | integer, intent(out) :: errflg ! Error flag
21 |
22 | ! Initialize error handling
23 | errmsg = ''
24 | errflg = 0
25 |
26 | ! Limit CAM5+ cloud physics to below top cloud level.
27 | top_lev = trop_cloud_top_lev
28 |
29 | end subroutine set_cloud_fraction_top_init
30 |
31 | end module set_cloud_fraction_top
32 |
--------------------------------------------------------------------------------
/schemes/zhang_mcfarlane/set_deep_conv_fluxes_to_general.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = set_deep_conv_fluxes_to_general
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = set_deep_conv_fluxes_to_general_run
7 | type = scheme
8 | [ prec_gen ]
9 | standard_name = lwe_precipitation_rate_at_surface_due_to_convection
10 | units = m s-1
11 | type = real | kind = kind_phys
12 | dimensions = (horizontal_loop_extent)
13 | intent = out
14 | [ prec_dp ]
15 | standard_name = lwe_precipitation_rate_at_surface_due_to_deep_convection
16 | units = m s-1
17 | type = real | kind = kind_phys
18 | dimensions = (horizontal_loop_extent)
19 | intent = in
20 | [ prdprec_gen ]
21 | standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_convection_excluding_subcloud_evaporation
22 | units = kg kg-1 s-1
23 | type = real | kind = kind_phys
24 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
25 | intent = out
26 | [ prdprec_dp ]
27 | standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection_excluding_subcloud_evaporation
28 | units = kg kg-1 s-1
29 | type = real | kind = kind_phys
30 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
31 | intent = in
32 |
--------------------------------------------------------------------------------
/schemes/hack_shallow/set_shallow_conv_fluxes_to_general.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = set_shallow_conv_fluxes_to_general
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = set_shallow_conv_fluxes_to_general_run
7 | type = scheme
8 | [ prec_gen ]
9 | standard_name = lwe_precipitation_rate_at_surface_due_to_convection
10 | units = m s-1
11 | type = real | kind = kind_phys
12 | dimensions = (horizontal_loop_extent)
13 | intent = out
14 | [ prec_sh ]
15 | standard_name = lwe_precipitation_rate_at_surface_due_to_shallow_convection
16 | units = m s-1
17 | type = real | kind = kind_phys
18 | dimensions = (horizontal_loop_extent)
19 | intent = in
20 | [ prdprec_gen ]
21 | standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_convection_excluding_subcloud_evaporation
22 | units = kg kg-1 s-1
23 | type = real | kind = kind_phys
24 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
25 | intent = out
26 | [ prdprec_sh ]
27 | standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_shallow_convection_excluding_subcloud_evaporation
28 | units = kg kg-1 s-1
29 | type = real | kind = kind_phys
30 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
31 | intent = in
32 |
--------------------------------------------------------------------------------
/test/test_schemes/initialize_constituents.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = initialize_constituents
3 | type = scheme
4 | [ccpp-arg-table]
5 | name = initialize_constituents_register
6 | type = scheme
7 | [ constituents ]
8 | standard_name = dynamic_constituents_for_initialize_constituents
9 | units = none
10 | dimensions = (:)
11 | allocatable = True
12 | type = ccpp_constituent_properties_t
13 | intent = out
14 | [ errmsg ]
15 | standard_name = ccpp_error_message
16 | long_name = Error message for error handling in CCPP
17 | units = none
18 | type = character | kind = len=512
19 | dimensions = ()
20 | intent = out
21 | [ errcode ]
22 | standard_name = ccpp_error_code
23 | long_name = Error flag for error handling in CCPP
24 | units = 1
25 | type = integer
26 | dimensions = ()
27 | intent = out
28 | [ccpp-arg-table]
29 | name = initialize_constituents_run
30 | type = scheme
31 | [ errmsg ]
32 | standard_name = ccpp_error_message
33 | long_name = Error message for error handling in CCPP
34 | units = none
35 | type = character | kind = len=512
36 | dimensions = ()
37 | intent = out
38 | [ errcode ]
39 | standard_name = ccpp_error_code
40 | long_name = Error flag for error handling in CCPP
41 | units = 1
42 | type = integer
43 | dimensions = ()
44 | intent = out
45 |
--------------------------------------------------------------------------------
/test/test_schemes/file_io_test.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = file_io_test
3 | type = scheme
4 | dependencies=../../phys_utils/ccpp_io_reader.F90
5 | [ccpp-arg-table]
6 | name = file_io_test_init
7 | type = scheme
8 | [ file_path ]
9 | standard_name = filename_of_rrtmgp_shortwave_coefficients
10 | long_name = file name and path to RRTMGP shortwave coefficients file
11 | units = none
12 | type = character | kind = len=*
13 | dimensions = ()
14 | intent = in
15 | [ errmsg ]
16 | standard_name = ccpp_error_message
17 | long_name = Error message for error handling in CCPP
18 | units = none
19 | type = character | kind = len=512
20 | dimensions = ()
21 | intent = out
22 | [ errcode ]
23 | standard_name = ccpp_error_code
24 | long_name = Error flag for error handling in CCPP
25 | units = 1
26 | type = integer
27 | dimensions = ()
28 | intent = out
29 | [ccpp-arg-table]
30 | name = file_io_test_run
31 | type = scheme
32 | [ errmsg ]
33 | standard_name = ccpp_error_message
34 | long_name = Error message for error handling in CCPP
35 | units = none
36 | type = character | kind = len=512
37 | dimensions = ()
38 | intent = out
39 | [ errcode ]
40 | standard_name = ccpp_error_code
41 | long_name = Error flag for error handling in CCPP
42 | units = 1
43 | type = integer
44 | dimensions = ()
45 | intent = out
46 |
--------------------------------------------------------------------------------
/test/unit-test/README.md:
--------------------------------------------------------------------------------
1 | # Unit Tests
2 |
3 | To add or update unit tests, follow the instructions from the [development guide](https://escomp.github.io/CAM-SIMA-docs/atmospheric_physics/development_workflow/#5-unit-testing). Also, make sure [pFUnit](https://github.com/Goddard-Fortran-Ecosystem/pFUnit) is built and installed following the [build directions](https://github.com/Goddard-Fortran-Ecosystem/pFUnit?tab=readme-ov-file#building-and-installing-pfunit) (see the atmospheric_physics [github workflow file](../../.github/workflows/unit-tests.yaml) for a more detailed example of how to build pFUnit):
4 |
5 | ```bash
6 | $ git clone --depth 1 --branch v4.10.0 https://github.com/Goddard-Fortran-Ecosystem/pFUnit.git
7 | $ cd pFUnit
8 | $ cmake -B./build -S.
9 | $ cd build
10 | $ make install
11 | ```
12 |
13 | To run the tests, from the root directory of your clone, run:
14 |
15 | ```bash
16 | $ cmake \
17 | -DCMAKE_PREFIX_PATH=/build/installed \
18 | -DATMOSPHERIC_PHYSICS_ENABLE_CODE_COVERAGE=ON \
19 | -B./build \
20 | -S./test/unit-test
21 | $ cd build
22 | $ make
23 | $ ctest -V --output-on-failure
24 | ```
25 |
26 | Where `` is the path to your pfunit repository. The install path of pFUnit may be different depending on how you've built your local verison (see the example in the [workflow file](../../.github/workflows/unit-tests.yaml)).
27 |
--------------------------------------------------------------------------------
/test/unit-test/tests/phys_utils/test_atmos_rad_utils.pf:
--------------------------------------------------------------------------------
1 | @test
2 | subroutine wavenumber_is_visible()
3 | use funit
4 | use atmos_phys_rad_utils, only : is_visible
5 | use ccpp_kinds, only : kind_phys
6 |
7 | real(kind_phys), parameter :: test_wavenumber = 15555._kind_phys
8 | logical :: output_logical
9 |
10 | output_logical = is_visible(test_wavenumber)
11 |
12 | @assertEqual(.true., output_logical)
13 | end subroutine wavenumber_is_visible
14 |
15 | @test
16 | subroutine wavenumber_is_not_visible()
17 | use funit
18 | use atmos_phys_rad_utils, only : is_visible
19 | use ccpp_kinds, only : kind_phys
20 |
21 | real(kind_phys), parameter :: test_wavenumber = 823._kind_phys
22 | logical :: output_logical
23 |
24 | output_logical = is_visible(test_wavenumber)
25 |
26 | @assertEqual(.false., output_logical)
27 | end subroutine wavenumber_is_not_visible
28 |
29 | @test
30 | subroutine wavenumber_is_on_the_cusp()
31 | use funit
32 | use atmos_phys_rad_utils, only : is_visible
33 | use ccpp_kinds, only : kind_phys
34 |
35 | real(kind_phys), parameter :: test_wavenumber = 14286._kind_phys
36 | logical :: output_logical
37 |
38 | output_logical = is_visible(test_wavenumber)
39 |
40 | @assertEqual(.false., output_logical)
41 | end subroutine wavenumber_is_on_the_cusp
42 |
--------------------------------------------------------------------------------
/schemes/conservation_adjust/check_energy/check_energy_scaling.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = check_energy_scaling
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = check_energy_scaling_run
7 | type = scheme
8 | [ ncol ]
9 | standard_name = horizontal_loop_extent
10 | units = count
11 | type = integer
12 | dimensions = ()
13 | intent = in
14 | [ cp_or_cv_dycore ]
15 | standard_name = specific_heat_of_air_used_in_dycore
16 | units = J kg-1 K-1
17 | type = real | kind = kind_phys
18 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
19 | intent = in
20 | [ cpairv ]
21 | standard_name = composition_dependent_specific_heat_of_dry_air_at_constant_pressure
22 | units = J kg-1 K-1
23 | type = real | kind = kind_phys
24 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
25 | intent = in
26 | [ scaling_dycore ]
27 | standard_name = ratio_of_specific_heat_of_air_used_in_physics_energy_formula_to_specific_heat_of_air_used_in_dycore_energy_formula
28 | units = 1
29 | type = real | kind = kind_phys
30 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
31 | intent = out
32 | [ errmsg ]
33 | standard_name = ccpp_error_message
34 | units = none
35 | type = character | kind = len=512
36 | dimensions = ()
37 | intent = out
38 | [ errflg ]
39 | standard_name = ccpp_error_code
40 | units = 1
41 | type = integer
42 | dimensions = ()
43 | intent = out
44 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/rayleigh_friction_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = rayleigh_friction_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = rayleigh_friction_diagnostics_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | units = none
11 | type = character | kind = len=512
12 | dimensions = ()
13 | intent = out
14 | [ errflg ]
15 | standard_name = ccpp_error_code
16 | units = 1
17 | type = integer
18 | dimensions = ()
19 | intent = out
20 |
21 | [ccpp-arg-table]
22 | name = rayleigh_friction_diagnostics_run
23 | type = scheme
24 | [ dudt ]
25 | standard_name = tendency_of_eastward_wind
26 | units = m s-2
27 | type = real | kind = kind_phys
28 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
29 | intent = in
30 | [ dvdt ]
31 | standard_name = tendency_of_northward_wind
32 | units = m s-2
33 | type = real | kind = kind_phys
34 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
35 | intent = in
36 | [ dsdt ]
37 | standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure
38 | units = J kg-1 s-1
39 | type = real | kind = kind_phys
40 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
41 | intent = in
42 | [ errmsg ]
43 | standard_name = ccpp_error_message
44 | units = none
45 | type = character | kind = len=512
46 | dimensions = ()
47 | intent = out
48 | [ errflg ]
49 | standard_name = ccpp_error_code
50 | units = 1
51 | type = integer
52 | dimensions = ()
53 | intent = out
54 |
--------------------------------------------------------------------------------
/schemes/thermo_water_update/thermo_water_update.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = thermo_water_update
3 | type = scheme
4 | dependencies = ../../../../data/cam_thermo.F90
5 |
6 | [ccpp-arg-table]
7 | name = thermo_water_update_run
8 | type = scheme
9 | [ mmr ]
10 | standard_name = ccpp_constituents
11 | units = none
12 | type = real | kind = kind_phys
13 | dimensions = (horizontal_loop_extent, vertical_layer_dimension, number_of_ccpp_constituents)
14 | intent = in
15 | [ ncol ]
16 | standard_name = horizontal_loop_extent
17 | units = count
18 | type = integer
19 | dimensions = ()
20 | intent = in
21 | [ pver ]
22 | standard_name = vertical_layer_dimension
23 | units = count
24 | type = integer
25 | dimensions = ()
26 | intent = in
27 | [ energy_formula_dycore ]
28 | standard_name = total_energy_formula_for_dycore
29 | units = 1
30 | type = integer
31 | dimensions = ()
32 | intent = in
33 | [ pdel ]
34 | standard_name = air_pressure_thickness
35 | units = Pa
36 | type = real | kind = kind_phys
37 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
38 | intent = in
39 | [ pdeldry ]
40 | standard_name = air_pressure_thickness_of_dry_air
41 | units = Pa
42 | type = real | kind = kind_phys
43 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
44 | intent = in
45 | [ cp_or_cv_dycore ]
46 | standard_name = specific_heat_of_air_used_in_dycore
47 | units = J kg-1 K-1
48 | type = real | kind = kind_phys
49 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
50 | intent = out
51 |
--------------------------------------------------------------------------------
/schemes/vertical_diffusion/vertical_diffusion_options.F90:
--------------------------------------------------------------------------------
1 | ! Module to load namelist options for vertical diffusion solver scheme.
2 | module vertical_diffusion_options
3 |
4 | use ccpp_kinds, only: kind_phys
5 |
6 | implicit none
7 | private
8 | save
9 |
10 | ! CCPP-compliant public interfaces
11 | public :: vertical_diffusion_options_init
12 |
13 | contains
14 |
15 | !> \section arg_table_vertical_diffusion_options_init Argument Table
16 | !! \htmlinclude arg_table_vertical_diffusion_options_init.html
17 | subroutine vertical_diffusion_options_init( &
18 | amIRoot, iulog, &
19 | do_iss_in, &
20 | am_correction_in, &
21 | errmsg, errflg)
22 |
23 | ! Input arguments
24 | logical, intent(in) :: amIRoot ! are we on the MPI root task?
25 | integer, intent(in) :: iulog ! log output unit
26 | logical, intent(in) :: do_iss_in ! Use implicit turbulent surface stress computation
27 | logical, intent(in) :: am_correction_in ! Do angular momentum conservation correction
28 |
29 | character(len=512), intent(out) :: errmsg ! error message
30 | integer, intent(out) :: errflg ! error flag
31 |
32 | errmsg = ''
33 | errflg = 0
34 |
35 | if(amIRoot) then
36 | write(iulog,*) "vertical diffusion solver: do_iss ", do_iss_in
37 | write(iulog,*) "vertical diffusion solver: am_correction ", am_correction_in
38 | endif
39 |
40 | end subroutine vertical_diffusion_options_init
41 |
42 | end module vertical_diffusion_options
43 |
--------------------------------------------------------------------------------
/schemes/holtslag_boville/holtslag_boville_diff_options.F90:
--------------------------------------------------------------------------------
1 | ! Module to load namelist options for the Holstlag-Boville boundary layer scheme
2 | module holtslag_boville_diff_options
3 | use ccpp_kinds, only: kind_phys
4 |
5 | implicit none
6 | private
7 | save
8 |
9 | ! public CCPP-compliant subroutines
10 | public :: holtslag_boville_diff_options_init
11 |
12 | contains
13 |
14 | !> \section arg_table_holtslag_boville_diff_options_init Argument Table
15 | !! \htmlinclude arg_table_holtslag_boville_diff_options_init.html
16 | subroutine holtslag_boville_diff_options_init( &
17 | amIRoot, iulog, &
18 | is_hbr_pbl_scheme, &
19 | errmsg, errflg)
20 |
21 | ! Input arguments
22 | logical, intent(in) :: amIRoot ! are we on the MPI root task?
23 | integer, intent(in) :: iulog ! log output unit
24 | logical, intent(in) :: is_hbr_pbl_scheme ! is HBR = true; is HB = false [flag]
25 |
26 | ! Output arguments
27 | character(len=512), intent(out) :: errmsg ! error message
28 | integer, intent(out) :: errflg ! error flag
29 |
30 | errmsg = ''
31 | errflg = 0
32 |
33 | if(amIRoot) then
34 | if(is_hbr_pbl_scheme) then
35 | write(iulog,*) 'Holtslag-Boville PBL: initializing as HBR PBL scheme.'
36 | else
37 | write(iulog,*) 'Holtslag-Boville PBL: initializing as HB PBL scheme.'
38 | endif
39 | endif
40 |
41 | end subroutine holtslag_boville_diff_options_init
42 |
43 | end module holtslag_boville_diff_options
44 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/sima_tend_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = sima_tend_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = sima_tend_diagnostics_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | units = none
11 | type = character | kind = len=512
12 | dimensions = ()
13 | intent = out
14 | [ errflg ]
15 | standard_name = ccpp_error_code
16 | units = 1
17 | type = integer
18 | dimensions = ()
19 | intent = out
20 |
21 | [ccpp-arg-table]
22 | name = sima_tend_diagnostics_run
23 | type = scheme
24 | [ dTdt_total ]
25 | standard_name = tendency_of_air_temperature_due_to_model_physics
26 | units = K s-1
27 | type = real | kind = kind_phys
28 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
29 | intent = in
30 | [ dudt_total ]
31 | standard_name = tendency_of_eastward_wind_due_to_model_physics
32 | units = m s-2
33 | type = real | kind = kind_phys
34 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
35 | intent = in
36 | [ dvdt_total ]
37 | standard_name = tendency_of_northward_wind_due_to_model_physics
38 | units = m s-2
39 | type = real | kind = kind_phys
40 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
41 | intent = in
42 | [ errmsg ]
43 | standard_name = ccpp_error_message
44 | units = none
45 | type = character | kind = len=512
46 | dimensions = ()
47 | intent = out
48 | [ errflg ]
49 | standard_name = ccpp_error_code
50 | units = 1
51 | type = integer
52 | dimensions = ()
53 | intent = out
54 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/convective_cloud_cover_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = convective_cloud_cover_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = convective_cloud_cover_diagnostics_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | units = none
11 | type = character | kind = len=512
12 | dimensions = ()
13 | intent = out
14 | [ errflg ]
15 | standard_name = ccpp_error_code
16 | units = 1
17 | type = integer
18 | dimensions = ()
19 | intent = out
20 |
21 | [ccpp-arg-table]
22 | name = convective_cloud_cover_diagnostics_run
23 | type = scheme
24 | [ shallowcu ]
25 | standard_name = shallow_convective_cloud_area_fraction
26 | units = fraction
27 | type = real | kind = kind_phys
28 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
29 | intent = in
30 | [ deepcu ]
31 | standard_name = deep_convective_cloud_area_fraction
32 | units = fraction
33 | type = real | kind = kind_phys
34 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
35 | intent = in
36 | [ concld ]
37 | standard_name = convective_cloud_area_fraction
38 | units = fraction
39 | type = real | kind = kind_phys
40 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
41 | intent = in
42 | [ errmsg ]
43 | standard_name = ccpp_error_message
44 | units = none
45 | type = character | kind = len=512
46 | dimensions = ()
47 | intent = out
48 | [ errflg ]
49 | standard_name = ccpp_error_code
50 | units = 1
51 | type = integer
52 | dimensions = ()
53 | intent = out
54 |
--------------------------------------------------------------------------------
/schemes/conservation_adjust/check_energy/check_energy_save_teout.F90:
--------------------------------------------------------------------------------
1 | ! save total energy for global fixer in next timestep
2 | ! this must be called after the last parameterization and physics_update,
3 | ! and after a final check_energy_chng to compute te_cur.
4 | module check_energy_save_teout
5 | use ccpp_kinds, only: kind_phys
6 |
7 | implicit none
8 | private
9 |
10 | public :: check_energy_save_teout_run
11 |
12 | contains
13 |
14 | !> \section arg_table_check_energy_save_teout_run Argument Table
15 | !! \htmlinclude arg_table_check_energy_save_teout_run.html
16 | subroutine check_energy_save_teout_run(ncol, te_cur_dyn, teout, errmsg, errflg)
17 |
18 | ! Input arguments
19 | integer, intent(in) :: ncol ! number of atmospheric columns
20 | real(kind_phys), intent(in) :: te_cur_dyn (:) ! dycore formula: current total energy [J m-2]
21 |
22 | ! Output arguments
23 | real(kind_phys), intent(out) :: teout(:) ! total energy for global fixer in next timestep [J m-2]
24 | character(len=512), intent(out) :: errmsg ! error message
25 | integer, intent(out) :: errflg ! error flag
26 |
27 | errmsg = ''
28 | errflg = 0
29 |
30 | ! nb hplin: note that in physpkg.F90, the pbuf is updated to the previous dyn timestep
31 | ! through itim_old. Need to check if we need to replicate such pbuf functionality
32 | ! in the CAM-SIMA/CCPP infrastructure.
33 | teout(:ncol) = te_cur_dyn(:ncol)
34 |
35 | end subroutine check_energy_save_teout_run
36 |
37 | end module check_energy_save_teout
38 |
--------------------------------------------------------------------------------
/test/musica/configuration/analytical/reactions.json:
--------------------------------------------------------------------------------
1 | {
2 | "camp-data": [
3 | {
4 | "type": "MECHANISM",
5 | "name": "analytical test",
6 | "reactions": [
7 | {
8 | "type": "ARRHENIUS",
9 | "A": 0.004,
10 | "C": 50,
11 | "reactants": {
12 | "A": {
13 | "qty": 1
14 | }
15 | },
16 | "products": {
17 | "B": {
18 | "yield": 1
19 | }
20 | }
21 | },
22 | {
23 | "type": "ARRHENIUS",
24 | "A": 0.012,
25 | "B": -2,
26 | "C": 75,
27 | "D": 50,
28 | "E": 1.0e-6,
29 | "reactants": {
30 | "B": {
31 | "qty": 1
32 | }
33 | },
34 | "products": {
35 | "C": {
36 | "yield": 1
37 | }
38 | }
39 | },
40 | {
41 | "type": "ARRHENIUS",
42 | "A": 0.001,
43 | "reactants": {
44 | "D": {
45 | "qty": 1
46 | }
47 | },
48 | "products": {
49 | "E": {
50 | "yield": 1
51 | }
52 | }
53 | },
54 | {
55 | "type": "ARRHENIUS",
56 | "A": 0.002,
57 | "reactants": {
58 | "E": {
59 | "qty": 1
60 | }
61 | },
62 | "products": {
63 | "F": {
64 | "yield": 1
65 | }
66 | }
67 | }
68 | ]
69 | }
70 | ]
71 | }
72 |
--------------------------------------------------------------------------------
/suites/suite_adiabatic.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | check_energy_gmean
7 |
8 | check_energy_gmean_diagnostics
9 |
10 |
14 | check_energy_zero_fluxes
15 | check_energy_fix
16 | apply_heating_rate
17 | geopotential_temp
18 |
19 | check_energy_scaling
20 | check_energy_chng
21 |
22 | check_energy_fix_diagnostics
23 |
24 |
25 | check_energy_save_teout
26 |
27 |
28 | sima_state_diagnostics
29 |
30 |
31 |
32 | sima_tend_diagnostics
33 |
34 |
35 |
--------------------------------------------------------------------------------
/test/musica/configuration/micm_util/reactions.json:
--------------------------------------------------------------------------------
1 | {
2 | "camp-data": [
3 | {
4 | "type": "MECHANISM",
5 | "name": "analytical test",
6 | "reactions": [
7 | {
8 | "type": "ARRHENIUS",
9 | "A": 0.001,
10 | "reactants": {
11 | "A": {
12 | "qty": 1
13 | },
14 | "B": {
15 | "qty": 1
16 | }
17 | },
18 | "products": {
19 | "C": {
20 | "yield": 1
21 | },
22 | "D": {
23 | "yield": 1
24 | }
25 | }
26 | },
27 | {
28 | "type": "USER_DEFINED",
29 | "MUSICA name": "user1",
30 | "reactants": {
31 | "A": {
32 | "qty": 1
33 | },
34 | "B": {
35 | "qty": 1
36 | }
37 | },
38 | "products": {
39 | "C": {
40 | "yield": 1
41 | },
42 | "D": {
43 | "yield": 1
44 | }
45 | }
46 | },
47 | {
48 | "type": "USER_DEFINED",
49 | "MUSICA name": "user2",
50 | "reactants": {
51 | "A": {
52 | "qty": 1
53 | },
54 | "B": {
55 | "qty": 1
56 | }
57 | },
58 | "products": {
59 | "C": {
60 | "yield": 1
61 | },
62 | "D": {
63 | "yield": 1
64 | }
65 | }
66 | }
67 | ]
68 | }
69 | ]
70 | }
71 |
--------------------------------------------------------------------------------
/test/test_suites/suite_convection_permitting.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | calc_exner
6 | compute_characteristic_grid_length_scale
7 | geopotential_height_wrt_sfc_at_if_to_msl
8 | geopotential_height_wrt_sfc_to_msl
9 | temp_to_potential_temp
10 | wet_to_dry_water_vapor
11 | wet_to_dry_cloud_liquid_water
12 | wet_to_dry_cloud_ice
13 |
14 | mmm_physics_compat
15 |
16 | bl_gwdo_compat_pre
17 | bl_gwdo_compat
18 | bl_gwdo_diagnostics
19 |
20 | cu_ntiedtke_compat_pre
21 | cu_ntiedtke_compat
22 | cu_ntiedtke_diagnostics
23 |
24 | mmm_physics_accumulate_tendencies
25 | apply_tendency_of_eastward_wind
26 | apply_tendency_of_northward_wind
27 | apply_tendency_of_air_temperature
28 | dry_to_wet_water_vapor
29 | dry_to_wet_cloud_liquid_water
30 | dry_to_wet_cloud_ice
31 | qneg
32 | geopotential_temp
33 |
34 | mmm_physics_persist_states
35 |
36 | sima_state_diagnostics
37 |
38 |
39 | sima_tend_diagnostics
40 |
41 |
42 |
--------------------------------------------------------------------------------
/schemes/conservation_adjust/check_energy/check_energy_zero_fluxes.F90:
--------------------------------------------------------------------------------
1 | ! zeros input fluxes to check_energy
2 | ! before running other schemes
3 | module check_energy_zero_fluxes
4 | use ccpp_kinds, only: kind_phys
5 |
6 | implicit none
7 | private
8 |
9 | public :: check_energy_zero_fluxes_run
10 |
11 | contains
12 |
13 | !> \section arg_table_check_energy_zero_fluxes_run Argument Table
14 | !! \htmlinclude arg_table_check_energy_zero_fluxes_run.html
15 | subroutine check_energy_zero_fluxes_run(ncol, name, flx_vap, flx_cnd, flx_ice, flx_sen, errmsg, errflg)
16 | ! Input arguments
17 | integer, intent(in) :: ncol ! number of atmospheric columns
18 |
19 | ! Output arguments
20 | character(len=64), intent(out) :: name ! parameterization name for fluxes
21 | real(kind_phys), intent(out) :: flx_vap(:) ! boundary flux of vapor [kg m-2 s-1]
22 | real(kind_phys), intent(out) :: flx_cnd(:) ! boundary flux of liquid+ice (precip?) [m s-1]
23 | real(kind_phys), intent(out) :: flx_ice(:) ! boundary flux of ice (snow?) [m s-1]
24 | real(kind_phys), intent(out) :: flx_sen(:) ! boundary flux of sensible heat [W m-2]
25 | character(len=512), intent(out) :: errmsg ! error message
26 | integer, intent(out) :: errflg ! error flag
27 |
28 | errmsg = ''
29 | errflg = 0
30 |
31 | ! reset values to zero
32 | name = ''
33 | flx_vap(:) = 0._kind_phys
34 | flx_cnd(:) = 0._kind_phys
35 | flx_ice(:) = 0._kind_phys
36 | flx_sen(:) = 0._kind_phys
37 | end subroutine check_energy_zero_fluxes_run
38 |
39 | end module check_energy_zero_fluxes
40 |
--------------------------------------------------------------------------------
/schemes/utilities/static_energy.F90:
--------------------------------------------------------------------------------
1 | ! Updates dry static energy from updated temperature and geopotential height.
2 | ! If ran, must be after geopotential_temp scheme.
3 | module static_energy
4 |
5 | use ccpp_kinds, only: kind_phys
6 |
7 | implicit none
8 | private
9 |
10 | public :: update_dry_static_energy_run
11 |
12 | CONTAINS
13 |
14 | !> \section arg_table_update_dry_static_energy_run Argument Table
15 | !! \htmlinclude update_dry_static_energy_run.html
16 | subroutine update_dry_static_energy_run(nz, gravit, temp, zm, phis, &
17 | st_energy, cpair, errcode, errmsg)
18 |
19 | ! Dummy arguments
20 | integer, intent(in) :: nz ! Num vertical layers
21 | real(kind_phys), intent(in) :: gravit ! gravitational acceleration
22 | real(kind_phys), intent(in) :: temp(:,:) ! air temperature
23 | real(kind_phys), intent(in) :: zm(:,:) ! geopotential height
24 | real(kind_phys), intent(in) :: phis(:) ! surface geopotential
25 | real(kind_phys), intent(out) :: st_energy(:,:) ! dry static energy
26 | real(kind_phys), intent(in) :: cpair(:,:) ! specific heat, dry air
27 | integer, intent(out) :: errcode
28 | character(len=512), intent(out) :: errmsg
29 |
30 | ! Local variable
31 | integer :: klev
32 |
33 | errcode = 0
34 | errmsg = ''
35 |
36 | do klev = 1, nz
37 | st_energy(:, klev) = (temp(:, klev) * cpair(:,klev)) + &
38 | (gravit * zm(:, klev)) + phis(:)
39 | end do
40 |
41 | end subroutine update_dry_static_energy_run
42 |
43 | end module static_energy
44 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # IMPORTANT NOTE - This repository is currently under development and items contained within it should be used with caution.
2 |
3 | # NCAR CCPP-enabled Atmospheric Physics
4 |
5 | Physics packages which are CCPP_enabled (along with supporting routines) are stored in this repository.
6 |
7 | # Requirements for ccpp physics schemes
8 |
9 | * Physics schemes contain two files, a .F90 file which contains the routines and a .meta file which contains the CCPP metadata.
10 |
11 | * Standard names for metadata can be found [here](https://github.com/gold2718/ccpp-framework/wiki/Metadata-standard-names)
12 |
13 | * Physics modules may contain one or more of the following routines (where XXX is the name of the module containing the physics)
14 | * XXX_init - contains the startup/restart initialization required for the package. This is unthreaded and may contain I/O of undistibuted data (e.g. parameter tables)
15 | * XXX_timestep_init - contains the initialization required for each timestep. This is unthreaded and may contain I/O of undistibuted data (e.g. parameter tables)
16 | * XXX_run - the code which is run every timestep. Threading is controlled via the host model and the number of available threads will be passed into the routine. No I/O is permitted in this routine
17 | * XXX_timestep_final - contains any post timestep handling. This is unthreaded
18 | * XXX_final - contains any code logic which needs to be performed at the end of the run prior to the program exiting. This is unthreaded.
19 |
20 | # Steps to adding a physics package to the repository
21 | * Currently under discussion
22 |
23 | # CCPP resources
24 |
25 | * [ccpp framework repository](https://github.com/NCAR/ccpp-framework)
26 |
27 |
--------------------------------------------------------------------------------
/schemes/conservation_adjust/check_energy/check_energy_zero_fluxes.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = check_energy_zero_fluxes
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = check_energy_zero_fluxes_run
7 | type = scheme
8 | [ ncol ]
9 | standard_name = horizontal_loop_extent
10 | units = count
11 | type = integer
12 | dimensions = ()
13 | intent = in
14 | [ name ]
15 | standard_name = scheme_name
16 | units = none
17 | type = character | kind = len=64
18 | dimensions = ()
19 | intent = out
20 | [ flx_vap ]
21 | standard_name = net_water_vapor_fluxes_through_top_and_bottom_of_atmosphere_column
22 | units = kg m-2 s-1
23 | type = real | kind = kind_phys
24 | dimensions = (horizontal_loop_extent)
25 | intent = out
26 | [ flx_cnd ]
27 | standard_name = net_liquid_and_lwe_ice_fluxes_through_top_and_bottom_of_atmosphere_column
28 | units = m s-1
29 | type = real | kind = kind_phys
30 | dimensions = (horizontal_loop_extent)
31 | intent = out
32 | [ flx_ice ]
33 | standard_name = net_lwe_ice_fluxes_through_top_and_bottom_of_atmosphere_column
34 | units = m s-1
35 | type = real | kind = kind_phys
36 | dimensions = (horizontal_loop_extent)
37 | intent = out
38 | [ flx_sen ]
39 | standard_name = net_sensible_heat_flux_through_top_and_bottom_of_atmosphere_column
40 | units = W m-2
41 | type = real | kind = kind_phys
42 | dimensions = (horizontal_loop_extent)
43 | intent = out
44 | [ errmsg ]
45 | standard_name = ccpp_error_message
46 | units = none
47 | type = character | kind = len=512
48 | dimensions = ()
49 | intent = out
50 | [ errflg ]
51 | standard_name = ccpp_error_code
52 | units = 1
53 | type = integer
54 | dimensions = ()
55 | intent = out
56 |
--------------------------------------------------------------------------------
/schemes/rayleigh_friction/rayleigh_friction_namelist.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | integer
12 | rayleigh_friction
13 | rayleigh_friction_nl
14 | center_vertical_layer_for_rayleigh_friction
15 | index
16 |
17 | Variable to specify the vertical index at which the
18 | Rayleigh friction term is centered (the peak value).
19 |
20 |
21 | 2
22 |
23 |
24 |
25 |
26 | real
27 | kind_phys
28 | rayleigh_friction
29 | rayleigh_friction_nl
30 | number_of_vertical_layers_for_rayleigh_friction
31 | count
32 |
33 | Range (number of layers) of the Rayleigh Friction profile. If 0, range is set to satisfy center=2.
34 |
35 |
36 | 0
37 |
38 |
39 |
40 |
41 | real
42 | kind_phys
43 | rayleigh_friction
44 | rayleigh_friction_nl
45 | model_top_decay_time_for_rayleigh_friction
46 | days
47 |
48 | Approximate value of max decay time (in units of days) at model top. If 0, no Rayleigh Friction is computed or applied.
49 |
50 |
51 | 0
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/check_energy_gmean_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = check_energy_gmean_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = check_energy_gmean_diagnostics_init
7 | type = scheme
8 | [ print_global_means_in ]
9 | standard_name = flag_for_energy_global_means_output
10 | units = flag
11 | type = logical
12 | dimensions = ()
13 | intent = in
14 |
15 | [ccpp-arg-table]
16 | name = check_energy_gmean_diagnostics_run
17 | type = scheme
18 | [ amIRoot ]
19 | standard_name = flag_for_mpi_root
20 | units = flag
21 | type = logical
22 | dimensions = ()
23 | intent = in
24 | [ iulog ]
25 | standard_name = log_output_unit
26 | units = 1
27 | type = integer
28 | dimensions = ()
29 | intent = in
30 | [ teinp_glob ]
31 | standard_name = global_mean_vertically_integrated_total_energy_using_dycore_energy_formula_at_start_of_physics_timestep
32 | units = J m-2
33 | type = real | kind = kind_phys
34 | dimensions = ()
35 | intent = in
36 | [ teout_glob ]
37 | standard_name = global_mean_vertically_integrated_total_energy_using_dycore_energy_formula_at_end_of_physics_timestep
38 | units = J m-2
39 | type = real | kind = kind_phys
40 | dimensions = ()
41 | intent = in
42 | [ heat_glob ]
43 | standard_name = global_mean_heating_rate_correction_for_energy_conservation
44 | units = J kg-1 s-1
45 | type = real | kind = kind_phys
46 | dimensions = ()
47 | intent = in
48 | [ errmsg ]
49 | standard_name = ccpp_error_message
50 | units = none
51 | type = character | kind = len=512
52 | dimensions = ()
53 | intent = out
54 | [ errflg ]
55 | standard_name = ccpp_error_code
56 | units = 1
57 | type = integer
58 | dimensions = ()
59 | intent = out
60 |
--------------------------------------------------------------------------------
/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.21)
2 |
3 | project(
4 | atmosphericphysics
5 | VERSION 0.1.0
6 | LANGUAGES Fortran C CXX
7 | )
8 |
9 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH};${CMAKE_CURRENT_LIST_DIR}/cmake)
10 | set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_MODULE_PATH}/SetDefaults.cmake)
11 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
12 |
13 | set(CMAKE_CXX_STANDARD 20)
14 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
15 |
16 | # ---------------------------------------------------------------------------------------------
17 | # NOTE: If 'CCPP_ENABLE_MUSICA_TESTS' is enabled, this is no longer a stand-alone CMake project.
18 | # The MUSICA CCPP wrapper requires both the MUSICA library and ccpp-framework/src.
19 | # To enable 'CCPP_ENABLE_MUSICA_TESTS', you can either build a CMake project using
20 | # 'docker/Dockerfile.musica' or follow the build instructions outlined in that file.
21 | # The following '$ENV' variables are configured by the Dockerfile.
22 | # ---------------------------------------------------------------------------------------------
23 | option(CCPP_ENABLE_MUSICA_TESTS "Build the MUSICA tests" OFF)
24 | option(CCPP_ENABLE_MEMCHECK "Enable memory checks in tests" OFF)
25 |
26 | set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
27 | set(BUILD_GMOCK OFF CACHE BOOL "" FORCE)
28 |
29 | if (CCPP_ENABLE_MUSICA_TESTS)
30 | set(MUSICA_SRC_PATH ${CMAKE_SOURCE_DIR}/../schemes/musica)
31 | set(TO_BE_CCPPIZED_SRC_PATH ${CMAKE_SOURCE_DIR}/../to_be_ccppized)
32 | set(CCPP_SRC_PATH ${CMAKE_SOURCE_DIR}/$ENV{CCPP_SRC_PATH})
33 | set(CCPP_TEST_SRC_PATH ${CMAKE_SOURCE_DIR}/include)
34 |
35 | include(TestUtils)
36 | include(CTest)
37 | enable_testing()
38 |
39 | add_subdirectory(musica)
40 | endif()
41 |
--------------------------------------------------------------------------------
/schemes/cloud_fraction/cloud_fraction_fice.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = cloud_fraction_fice
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = cloud_fraction_fice_run
7 | type = scheme
8 | [ ncol ]
9 | standard_name = horizontal_loop_extent
10 | units = count
11 | type = integer
12 | dimensions = ()
13 | intent = in
14 | [ t ]
15 | standard_name = air_temperature
16 | units = K
17 | type = real | kind = kind_phys
18 | dimensions = (horizontal_loop_extent,vertical_layer_dimension)
19 | intent = in
20 | [ tmelt ]
21 | standard_name = freezing_point_of_water
22 | units = K
23 | type = real | kind = kind_phys
24 | dimensions = ()
25 | intent = in
26 | [ top_lev ]
27 | standard_name = vertical_layer_index_of_cloud_fraction_top
28 | units = index
29 | type = integer
30 | dimensions = ()
31 | intent = in
32 | [ pver ]
33 | standard_name = vertical_layer_dimension
34 | units = count
35 | type = integer
36 | dimensions = ()
37 | intent = in
38 | [ fice ]
39 | standard_name = mass_fraction_of_ice_content_within_stratiform_cloud
40 | units = fraction
41 | type = real | kind = kind_phys
42 | dimensions = (horizontal_loop_extent,vertical_layer_dimension)
43 | intent = out
44 | [ fsnow ]
45 | standard_name = mass_fraction_of_snow_content_within_stratiform_cloud
46 | units = fraction
47 | type = real | kind = kind_phys
48 | dimensions = (horizontal_loop_extent,vertical_layer_dimension)
49 | intent = out
50 | [ errmsg ]
51 | standard_name = ccpp_error_message
52 | units = none
53 | type = character | kind = len=512
54 | dimensions = ()
55 | intent = out
56 | [ errflg ]
57 | standard_name = ccpp_error_code
58 | units = 1
59 | type = integer
60 | dimensions = ()
61 | intent = out
62 |
--------------------------------------------------------------------------------
/schemes/conservation_adjust/check_energy/dycore_energy_consistency_adjust.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = dycore_energy_consistency_adjust
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = dycore_energy_consistency_adjust_run
7 | type = scheme
8 | [ ncol ]
9 | standard_name = horizontal_loop_extent
10 | units = count
11 | type = integer
12 | dimensions = ()
13 | intent = in
14 | [ pver ]
15 | standard_name = vertical_layer_dimension
16 | units = count
17 | type = integer
18 | dimensions = ()
19 | intent = in
20 | [ do_consistency_adjust ]
21 | standard_name = flag_for_dycore_energy_consistency_adjustment
22 | units = flag
23 | type = logical
24 | dimensions = ()
25 | intent = in
26 | [ scaling_dycore ]
27 | standard_name = ratio_of_specific_heat_of_air_used_in_physics_energy_formula_to_specific_heat_of_air_used_in_dycore_energy_formula
28 | units = 1
29 | type = real | kind = kind_phys
30 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
31 | intent = in
32 | [ tend_dTdt ]
33 | standard_name = tendency_of_air_temperature_due_to_model_physics
34 | units = K s-1
35 | type = real | kind = kind_phys
36 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
37 | intent = in
38 | [ tend_dTdt_local ]
39 | standard_name = tendency_of_air_temperature
40 | units = K s-1
41 | type = real | kind = kind_phys
42 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
43 | intent = out
44 | [ errmsg ]
45 | standard_name = ccpp_error_message
46 | units = none
47 | type = character | kind = len=512
48 | dimensions = ()
49 | intent = out
50 | [ errflg ]
51 | standard_name = ccpp_error_code
52 | units = 1
53 | type = integer
54 | dimensions = ()
55 | intent = out
56 |
--------------------------------------------------------------------------------
/test/test_suites/suite_zhang_mcfarlane.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | initialize_constituents
6 | to_be_ccppized_temporary
7 | set_cloud_fraction_top
8 | zm_conv_options
9 | zm_convr
10 | zm_convr_tendency_diagnostics
11 | apply_heating_rate
12 | apply_constituent_tendencies
13 | qneg
14 | geopotential_temp
15 | cloud_fraction_fice
16 | set_deep_conv_fluxes_to_general
17 | zm_conv_evap
18 | set_general_conv_fluxes_to_deep
19 | zm_evap_tendency_diagnostics
20 | apply_heating_rate
21 | apply_constituent_tendencies
22 | qneg
23 | geopotential_temp
24 | cloud_fraction_fice
25 | zm_conv_momtran
26 | zm_momtran_tendency_diagnostics
27 | apply_heating_rate
28 | apply_tendency_of_eastward_wind
29 | apply_tendency_of_northward_wind
30 | geopotential_temp
31 | zm_conv_convtran
32 | zm_tendency_diagnostics
33 | apply_constituent_tendencies
34 | qneg
35 | geopotential_temp
36 | zm_diagnostics
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/schemes/conservation_adjust/check_energy/check_energy_scaling.F90:
--------------------------------------------------------------------------------
1 | module check_energy_scaling
2 | use ccpp_kinds, only: kind_phys
3 |
4 | implicit none
5 | private
6 |
7 | public :: check_energy_scaling_run
8 |
9 | contains
10 |
11 | ! CCPP routine to get scaling factor for conversion of temperature increment.
12 | ! This is extracted to a separate subroutine so that scaling_dycore can be passed
13 | ! directly to the CCPP-ized check_energy_chng_run subroutine from CAM with subcolumns.
14 | !
15 | ! When subcolumns are removed from CAM, this dummy scheme can be removed, and
16 | ! scaling_dycore can just be calculated in check_energy_chng. (hplin, 9/5/24)
17 | !> \section arg_table_check_energy_scaling_run Argument Table
18 | !! \htmlinclude arg_table_check_energy_scaling_run.html
19 | subroutine check_energy_scaling_run( &
20 | ncol, &
21 | cp_or_cv_dycore, cpairv, &
22 | scaling_dycore, &
23 | errmsg, errflg)
24 |
25 | ! Input arguments
26 | integer, intent(in) :: ncol ! number of atmospheric columns
27 | real(kind_phys), intent(in) :: cp_or_cv_dycore(:,:) ! cp or cv from dycore [J kg-1 K-1]
28 | real(kind_phys), intent(in) :: cpairv(:,:) ! specific heat of dry air at constant pressure [J kg-1 K-1]
29 |
30 | ! Output arguments
31 | real(kind_phys), intent(out) :: scaling_dycore(:,:) ! scaling for conversion of temperature increment [1]
32 | character(len=512), intent(out) :: errmsg
33 | integer, intent(out) :: errflg
34 |
35 | errmsg = ''
36 | errflg = 0
37 |
38 | scaling_dycore(:ncol,:) = cpairv(:ncol,:) / cp_or_cv_dycore(:ncol,:)
39 |
40 | end subroutine check_energy_scaling_run
41 |
42 | end module check_energy_scaling
43 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/check_energy_fix_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = check_energy_fix_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = check_energy_fix_diagnostics_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | units = none
11 | type = character | kind = len=512
12 | dimensions = ()
13 | intent = out
14 | [ errflg ]
15 | standard_name = ccpp_error_code
16 | units = 1
17 | type = integer
18 | dimensions = ()
19 | intent = out
20 |
21 | [ccpp-arg-table]
22 | name = check_energy_fix_diagnostics_run
23 | type = scheme
24 | [ te_ini_dyn ]
25 | standard_name = vertically_integrated_total_energy_using_dycore_energy_formula_at_start_of_physics_timestep
26 | units = J m-2
27 | type = real | kind = kind_phys
28 | dimensions = (horizontal_loop_extent)
29 | intent = in
30 | [ te_cur_dyn ]
31 | standard_name = vertically_integrated_total_energy_using_dycore_energy_formula
32 | units = J m-2
33 | type = real | kind = kind_phys
34 | dimensions = (horizontal_loop_extent)
35 | intent = in
36 | [ teout ]
37 | standard_name = vertically_integrated_total_energy_using_dycore_energy_formula_at_end_of_physics_timestep
38 | units = J m-2
39 | type = real | kind = kind_phys
40 | dimensions = (horizontal_loop_extent)
41 | intent = in
42 | [ eshflx ]
43 | standard_name = net_sensible_heat_flux_through_top_and_bottom_of_atmosphere_column
44 | units = W m-2
45 | type = real | kind = kind_phys
46 | dimensions = (horizontal_loop_extent)
47 | intent = in
48 | [ errmsg ]
49 | standard_name = ccpp_error_message
50 | units = none
51 | type = character | kind = len=512
52 | dimensions = ()
53 | intent = out
54 | [ errflg ]
55 | standard_name = ccpp_error_code
56 | units = 1
57 | type = integer
58 | dimensions = ()
59 | intent = out
60 |
--------------------------------------------------------------------------------
/to_be_ccppized/ccpp_const_utils.F90:
--------------------------------------------------------------------------------
1 | ! ccpp_const_utils contains utility functions that use
2 | ! the ccpp constituent properties pointer.
3 | ! this code was separated out to remove circular dependencies.
4 | module ccpp_const_utils
5 | implicit none
6 | private
7 |
8 | public :: ccpp_const_get_idx
9 |
10 | contains
11 |
12 | subroutine ccpp_const_get_idx(constituent_props, name, cindex, errmsg, errflg)
13 | use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t
14 |
15 | ! Input arguments
16 | type(ccpp_constituent_prop_ptr_t), intent(in) :: constituent_props(:)
17 | character(len=*), intent(in) :: name ! constituent name
18 |
19 | ! Output arguments
20 | integer, intent(out) :: cindex ! global constituent index
21 | character(len=512), intent(out) :: errmsg ! error message
22 | integer, intent(out) :: errflg ! error flag
23 |
24 | ! Local variables
25 | integer :: t_cindex
26 | character(len=256) :: t_const_name
27 |
28 | errmsg = ''
29 | errflg = 0
30 |
31 | cindex = -1
32 |
33 | ! This convoluted loop is brought to you in exchange for avoiding a
34 | ! circular dependency on cam_ccpp_cap::cam_const_get_index.
35 | const_props_loop: do t_cindex = lbound(constituent_props, 1), ubound(constituent_props, 1)
36 | call constituent_props(t_cindex)%standard_name(t_const_name, errflg, errmsg)
37 | if (errflg /= 0) then
38 | ! Abort subroutine and return with error.
39 | return
40 | end if
41 |
42 | if (trim(t_const_name) == trim(name)) then
43 | cindex = t_cindex
44 | exit const_props_loop
45 | end if
46 | enddo const_props_loop
47 |
48 | end subroutine ccpp_const_get_idx
49 |
50 | end module ccpp_const_utils
51 |
--------------------------------------------------------------------------------
/schemes/utilities/convert_dry_constituent_tendencies_to_dry_air_basis.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = convert_dry_constituent_tendencies_to_dry_air_basis
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = convert_dry_constituent_tendencies_to_dry_air_basis_run
7 | type = scheme
8 | [ ncol ]
9 | standard_name = horizontal_loop_extent
10 | units = count
11 | type = integer
12 | dimensions = ()
13 | intent = in
14 | [ pver ]
15 | standard_name = vertical_layer_dimension
16 | units = count
17 | type = integer
18 | dimensions = ()
19 | intent = in
20 | [ pcnst ]
21 | standard_name = number_of_ccpp_constituents
22 | units = count
23 | type = integer
24 | dimensions = ()
25 | intent = in
26 | [ pdel ]
27 | standard_name = air_pressure_thickness
28 | units = Pa
29 | type = real | kind = kind_phys
30 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
31 | intent = in
32 | [ pdeldry ]
33 | standard_name = air_pressure_thickness_of_dry_air
34 | units = Pa
35 | type = real | kind = kind_phys
36 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
37 | intent = in
38 | [ const_props ]
39 | standard_name = ccpp_constituent_properties
40 | units = none
41 | type = ccpp_constituent_prop_ptr_t
42 | dimensions = (number_of_ccpp_constituents)
43 | intent = in
44 | [ tend_q ]
45 | standard_name = ccpp_constituent_tendencies
46 | units = none
47 | type = real | kind = kind_phys
48 | dimensions = (horizontal_loop_extent, vertical_layer_dimension, number_of_ccpp_constituents)
49 | intent = inout
50 | [ errmsg ]
51 | standard_name = ccpp_error_message
52 | units = none
53 | type = character | kind = len=512
54 | dimensions = ()
55 | intent = out
56 | [ errflg ]
57 | standard_name = ccpp_error_code
58 | units = 1
59 | type = integer
60 | dimensions = ()
61 | intent = out
62 |
--------------------------------------------------------------------------------
/schemes/gravity_wave_drag/gravity_wave_drag_top_taper.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = gravity_wave_drag_top_taper
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = gravity_wave_drag_top_taper_init
7 | type = scheme
8 | [ pver ]
9 | standard_name = vertical_layer_dimension
10 | units = count
11 | type = integer
12 | dimensions = ()
13 | intent = in
14 | [ amIRoot ]
15 | standard_name = flag_for_mpi_root
16 | units = flag
17 | type = logical
18 | dimensions = ()
19 | intent = in
20 | [ iulog ]
21 | standard_name = log_output_unit
22 | units = 1
23 | type = integer
24 | dimensions = ()
25 | intent = in
26 | [ gw_top_taper ]
27 | standard_name = taper_gravity_wave_drag_at_model_top
28 | units = flag
29 | type = logical
30 | dimensions = ()
31 | intent = in
32 | [ nbot_gravity_wave_top_taper ]
33 | standard_name = vertical_index_of_bottom_limit_for_tapering_gravity_wave_drag_at_model_top
34 | units = index
35 | type = integer
36 | dimensions = ()
37 | intent = in
38 | [ pref_edge ]
39 | standard_name = reference_pressure_at_interface
40 | units = Pa
41 | type = real | kind = kind_phys
42 | dimensions = (vertical_interface_dimension)
43 | intent = in
44 | [ pref_mid ]
45 | standard_name = reference_pressure_in_atmosphere_layer
46 | units = Pa
47 | type = real | kind = kind_phys
48 | dimensions = (vertical_layer_dimension)
49 | intent = in
50 | [ vramp ]
51 | standard_name = gravity_wave_drag_tapering_coefficients
52 | units = 1
53 | type = real | kind = kind_phys
54 | dimensions = (vertical_layer_dimension)
55 | intent = out
56 | [ errmsg ]
57 | standard_name = ccpp_error_message
58 | units = none
59 | type = character | kind = len=512
60 | dimensions = ()
61 | intent = out
62 | [ errflg ]
63 | standard_name = ccpp_error_code
64 | units = 1
65 | type = integer
66 | dimensions = ()
67 | intent = out
68 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/compute_cloud_fraction_diagnostics.F90:
--------------------------------------------------------------------------------
1 | ! Diagnostics for cloud fraction
2 | module compute_cloud_fraction_diagnostics
3 | use ccpp_kinds, only: kind_phys
4 |
5 | implicit none
6 | private
7 | save
8 |
9 | public :: compute_cloud_fraction_diagnostics_init
10 | public :: compute_cloud_fraction_diagnostics_run
11 |
12 | contains
13 |
14 | !> \section arg_table_compute_cloud_fraction_diagnostics_init Argument Table
15 | !! \htmlinclude compute_cloud_fraction_diagnostics_init.html
16 | subroutine compute_cloud_fraction_diagnostics_init(errmsg, errflg)
17 | use cam_history, only: history_add_field
18 | use cam_history_support, only: horiz_only
19 |
20 | character(len=512), intent(out) :: errmsg
21 | integer, intent(out) :: errflg
22 |
23 | ! Local variables:
24 |
25 | errmsg = ''
26 | errflg = 0
27 |
28 | ! History add field calls
29 | call history_add_field('CLDST', 'stratiform_cloud_area_fraction', 'lev', 'avg', 'fraction')
30 |
31 | end subroutine compute_cloud_fraction_diagnostics_init
32 |
33 | !> \section arg_table_compute_cloud_fraction_diagnostics_run Argument Table
34 | !! \htmlinclude compute_cloud_fraction_diagnostics_run.html
35 | subroutine compute_cloud_fraction_diagnostics_run( &
36 | cldst, &
37 | errmsg, errflg)
38 |
39 | use cam_history, only: history_out_field
40 |
41 | ! Input parameters
42 | real(kind_phys), intent(in) :: cldst(:,:)
43 |
44 |
45 | ! CCPP error handling variables
46 | character(len=512), intent(out) :: errmsg
47 | integer, intent(out) :: errflg
48 |
49 | errmsg = ''
50 | errflg = 0
51 |
52 | ! History out field calls
53 | call history_out_field('CLDST', cldst)
54 |
55 | end subroutine compute_cloud_fraction_diagnostics_run
56 |
57 | end module compute_cloud_fraction_diagnostics
58 |
--------------------------------------------------------------------------------
/test/unit-test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.17)
2 |
3 | project(atmospheric_physics VERSION 0.0.1 LANGUAGES Fortran)
4 |
5 | find_package(PFUNIT REQUIRED)
6 |
7 | if(NOT ATMOSPHERIC_PHYSICS_IS_TOP_LEVEL)
8 | message(WARNING "atmospheric-physics is not integrated into the CMake build of any top level "
9 | "project yet and this CMake is for testing purposes only. "
10 | "Making a change to this project's CMake will not impact the build of "
11 | "a parent project at this time.")
12 | endif()
13 |
14 | option(ATMOSPHERIC_PHYSICS_ENABLE_TESTS "Run pFUnit unit tests" OFF)
15 | option(ATMOSPHERIC_PHYSICS_ENABLE_CODE_COVERAGE "Run code coverage tool" OFF)
16 |
17 | if(ATMOSPHERIC_PHYSICS_ENABLE_CODE_COVERAGE)
18 | add_compile_options(-O0 --coverage)
19 | add_link_options(--coverage)
20 | endif()
21 |
22 | set(CMAKE_BUILD_TYPE Debug)
23 |
24 | set(UTILITIES_SRC
25 | ../../schemes/utilities/state_converters.F90
26 | ../../schemes/utilities/static_energy.F90
27 | ../../schemes/utilities/physics_tendency_updaters.F90
28 | include/ccpp_kinds.F90
29 | )
30 |
31 | add_library(utilities ${UTILITIES_SRC})
32 | target_compile_options(utilities PRIVATE -ffree-line-length-none)
33 | target_include_directories(utilities PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
34 |
35 | set(PHYS_UTILS_SRC
36 | ../../phys_utils/atmos_phys_pbl_utils.F90
37 | ../../phys_utils/atmos_phys_string_utils.F90
38 | ../../phys_utils/atmos_phys_rad_utils.F90
39 | include/ccpp_kinds.F90
40 | )
41 |
42 | add_library(phys_utils ${PHYS_UTILS_SRC})
43 | target_compile_options(phys_utils PRIVATE -ffree-line-length-none)
44 | target_include_directories(phys_utils PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
45 |
46 | add_subdirectory(../../schemes/mmm mmm)
47 |
48 | if(ATMOSPHERIC_PHYSICS_ENABLE_TESTS OR ATMOSPHERIC_PHYSICS_ENABLE_CODE_COVERAGE)
49 | enable_testing()
50 | add_subdirectory(tests)
51 | endif()
52 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/kessler_diagnostics.F90:
--------------------------------------------------------------------------------
1 | module kessler_diagnostics
2 | !
3 | ! Diagnostics for use by the Kessler physics suite only
4 | !
5 |
6 | use ccpp_kinds, only: kind_phys
7 |
8 | implicit none
9 | private
10 | save
11 |
12 | public :: kessler_diagnostics_init ! init routine
13 | public :: kessler_diagnostics_run ! main routine
14 |
15 | CONTAINS
16 |
17 | !> \section arg_table_kessler_diagnostics_init Argument Table
18 | !! \htmlinclude kessler_diagnostics_init.html
19 | subroutine kessler_diagnostics_init(errmsg, errflg)
20 | use cam_history, only: history_add_field
21 | use cam_history_support, only: horiz_only
22 |
23 | character(len=512), intent(out) :: errmsg
24 | integer, intent(out) :: errflg
25 |
26 | ! Local variables:
27 |
28 | errmsg = ''
29 | errflg = 0
30 |
31 | call history_add_field('PRECT', 'total_precipitation_rate_at_surface', horiz_only, 'avg', 'm s-1')
32 |
33 | end subroutine kessler_diagnostics_init
34 |
35 | !> \section arg_table_kessler_diagnostics_run Argument Table
36 | !! \htmlinclude kessler_diagnostics_run.html
37 | subroutine kessler_diagnostics_run(precl, errmsg, errflg)
38 |
39 | use cam_history, only: history_out_field
40 | !------------------------------------------------
41 | ! Input / output parameters
42 | !------------------------------------------------
43 | ! State variables
44 | real(kind_phys), intent(in) :: precl(:) ! Total precipitation
45 | ! CCPP error handling variables
46 | character(len=512), intent(out) :: errmsg
47 | integer, intent(out) :: errflg
48 |
49 | errmsg = ''
50 | errflg = 0
51 |
52 | call history_out_field('PRECT', precl)
53 |
54 | end subroutine kessler_diagnostics_run
55 |
56 | !=======================================================================
57 |
58 | end module kessler_diagnostics
59 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/zm_tendency_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = zm_tendency_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = zm_tendency_diagnostics_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | long_name = Error message for error handling in CCPP
11 | units = none
12 | type = character | kind = len=512
13 | dimensions = ()
14 | intent = out
15 | [ errflg ]
16 | standard_name = ccpp_error_code
17 | long_name = Error flag for error handling in CCPP
18 | units = 1
19 | type = integer
20 | dimensions = ()
21 | intent = out
22 |
23 | [ccpp-arg-table]
24 | name = zm_tendency_diagnostics_run
25 | type = scheme
26 | [ ncol ]
27 | standard_name = horizontal_loop_extent
28 | units = count
29 | type = integer
30 | dimensions = ()
31 | intent = in
32 | [ pver ]
33 | standard_name = vertical_layer_dimension
34 | units = count
35 | type = integer
36 | dimensions = ()
37 | intent = in
38 | [ pverp ]
39 | standard_name = vertical_interface_dimension
40 | units = count
41 | type = integer
42 | dimensions = ()
43 | intent = in
44 | [ const_props ]
45 | standard_name = ccpp_constituent_properties
46 | units = none
47 | type = ccpp_constituent_prop_ptr_t
48 | dimensions = (number_of_ccpp_constituents)
49 | intent = in
50 | [ dqdt ]
51 | standard_name = ccpp_constituent_tendencies
52 | units = none
53 | type = real | kind = kind_phys
54 | dimensions = (horizontal_loop_extent,vertical_layer_dimension,number_of_ccpp_constituents)
55 | intent = in
56 | [ errmsg ]
57 | standard_name = ccpp_error_message
58 | long_name = Error message for error handling in CCPP
59 | units = none
60 | type = character | kind = len=512
61 | dimensions = ()
62 | intent = out
63 | [ errflg ]
64 | standard_name = ccpp_error_code
65 | long_name = Error flag for error handling in CCPP
66 | units = 1
67 | type = integer
68 | dimensions = ()
69 | intent = out
70 |
--------------------------------------------------------------------------------
/schemes/conservation_adjust/check_energy/check_energy_fix.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = check_energy_fix
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = check_energy_fix_run
7 | type = scheme
8 | [ ncol ]
9 | standard_name = horizontal_loop_extent
10 | units = count
11 | type = integer
12 | dimensions = ()
13 | intent = in
14 | [ pver ]
15 | standard_name = vertical_layer_dimension
16 | units = count
17 | type = integer
18 | dimensions = ()
19 | intent = in
20 | [ pint ]
21 | standard_name = air_pressure_at_interface
22 | units = Pa
23 | type = real | kind = kind_phys
24 | dimensions = (horizontal_loop_extent, vertical_interface_dimension)
25 | intent = in
26 | [ gravit ]
27 | standard_name = standard_gravitational_acceleration
28 | units = m s-2
29 | type = real | kind = kind_phys
30 | dimensions = ()
31 | intent = in
32 | [ heat_glob ]
33 | standard_name = global_mean_heating_rate_correction_for_energy_conservation
34 | units = J kg-1 s-1
35 | type = real | kind = kind_phys
36 | dimensions = ()
37 | intent = in
38 | [ ptend_s ]
39 | standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure
40 | units = J kg-1 s-1
41 | type = real | kind = kind_phys
42 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
43 | intent = out
44 | [ eshflx ]
45 | standard_name = net_sensible_heat_flux_through_top_and_bottom_of_atmosphere_column
46 | units = W m-2
47 | type = real | kind = kind_phys
48 | dimensions = (horizontal_loop_extent)
49 | intent = out
50 | [ scheme_name ]
51 | standard_name = scheme_name
52 | units = none
53 | type = character | kind = len=64
54 | dimensions = ()
55 | intent = out
56 | [ errmsg ]
57 | standard_name = ccpp_error_message
58 | units = none
59 | type = character | kind = len=512
60 | dimensions = ()
61 | intent = out
62 | [ errflg ]
63 | standard_name = ccpp_error_code
64 | units = 1
65 | type = integer
66 | dimensions = ()
67 | intent = out
68 |
--------------------------------------------------------------------------------
/schemes/zhang_mcfarlane/set_general_conv_fluxes_to_deep.F90:
--------------------------------------------------------------------------------
1 | module set_general_conv_fluxes_to_deep
2 |
3 | use ccpp_kinds, only: kind_phys
4 |
5 | implicit none
6 |
7 | contains
8 |
9 | !===============================================================================
10 | !> \section arg_table_set_general_conv_fluxes_to_deep_run Argument Table
11 | !! \htmlinclude set_general_conv_fluxes_to_deep_run.html
12 | !!
13 |
14 | subroutine set_general_conv_fluxes_to_deep_run(tend_s_snwprd_gen, tend_s_snwprd_dp, tend_s_snwevmlt_gen, tend_s_snwevmlt_dp, &
15 | prec_gen, prec_dp, snow_gen, snow_dp, ntprprd_gen, ntprprd_dp, ntsnprd_gen, ntsnprd_dp, &
16 | flxprec_gen, flxprec_dp, flxsnow_gen, flxsnow_dp)
17 |
18 | real(kind_phys), intent(in) :: tend_s_snwprd_gen(:,:)
19 | real(kind_phys), intent(out) :: tend_s_snwprd_dp(:,:)
20 | real(kind_phys), intent(in) :: tend_s_snwevmlt_gen(:,:)
21 | real(kind_phys), intent(out) :: tend_s_snwevmlt_dp(:,:)
22 | real(kind_phys), intent(in) :: prec_gen(:)
23 | real(kind_phys), intent(out) :: prec_dp(:)
24 | real(kind_phys), intent(in) :: snow_gen(:)
25 | real(kind_phys), intent(out) :: snow_dp(:)
26 | real(kind_phys), intent(in) :: ntprprd_gen(:,:)
27 | real(kind_phys), intent(out) :: ntprprd_dp(:,:)
28 | real(kind_phys), intent(in) :: ntsnprd_gen(:,:)
29 | real(kind_phys), intent(out) :: ntsnprd_dp(:,:)
30 | real(kind_phys), intent(in) :: flxprec_gen(:,:)
31 | real(kind_phys), intent(out) :: flxprec_dp(:,:)
32 | real(kind_phys), intent(in) :: flxsnow_gen(:,:)
33 | real(kind_phys), intent(out) :: flxsnow_dp(:,:)
34 |
35 | tend_s_snwprd_dp = tend_s_snwprd_gen
36 | tend_s_snwevmlt_dp = tend_s_snwevmlt_gen
37 | prec_dp = prec_gen
38 | snow_dp = snow_gen
39 | ntprprd_dp = ntprprd_gen
40 | ntsnprd_dp = ntsnprd_gen
41 | flxprec_dp = flxprec_gen
42 | flxsnow_dp = flxsnow_gen
43 |
44 | end subroutine set_general_conv_fluxes_to_deep_run
45 |
46 | end module set_general_conv_fluxes_to_deep
47 |
--------------------------------------------------------------------------------
/suites/suite_tj2016.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | tj2016_precip
6 | apply_heating_rate
7 | qneg
8 |
9 |
13 | check_energy_zero_fluxes
14 | check_energy_scaling
15 | check_energy_chng
16 |
17 |
18 | sima_state_diagnostics
19 |
20 |
21 | tj2016_sfc_pbl_hs
22 | apply_heating_rate
23 | apply_tendency_of_eastward_wind
24 | apply_tendency_of_northward_wind
25 | qneg
26 |
27 |
28 | thermo_water_update
29 |
30 |
31 |
32 |
33 |
34 |
38 | check_energy_scaling
39 | dycore_energy_consistency_adjust
40 | apply_tendency_of_air_temperature
41 |
42 |
43 | sima_tend_diagnostics
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/schemes/utilities/static_energy.meta:
--------------------------------------------------------------------------------
1 | #########################################################
2 | [ccpp-table-properties]
3 | name = update_dry_static_energy
4 | type = scheme
5 | [ccpp-arg-table]
6 | name = update_dry_static_energy_run
7 | type = scheme
8 | [ nz ]
9 | standard_name = vertical_layer_dimension
10 | long_name = number of vertical layers
11 | units = count
12 | dimensions = ()
13 | type = integer
14 | intent = in
15 | [ gravit ]
16 | standard_name = standard_gravitational_acceleration
17 | units = m s-2
18 | dimensions = ()
19 | type = real | kind = kind_phys
20 | intent = in
21 | [ temp ]
22 | standard_name = air_temperature
23 | type = real | kind = kind_phys
24 | units = K
25 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
26 | intent = in
27 | [ zm ]
28 | standard_name = geopotential_height_wrt_surface
29 | type = real | kind = kind_phys
30 | units = m
31 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
32 | intent = in
33 | [ phis ]
34 | standard_name = surface_geopotential
35 | type = real | kind = kind_phys
36 | units = m2 s-2
37 | dimensions = (horizontal_loop_extent)
38 | intent = in
39 | [ st_energy ]
40 | standard_name = dry_static_energy
41 | long_name = Dry static energy
42 | type = real | kind = kind_phys
43 | units = J kg-1
44 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
45 | intent = out
46 | [ cpair ]
47 | standard_name = composition_dependent_specific_heat_of_dry_air_at_constant_pressure
48 | units = J kg-1 K-1
49 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
50 | type = real | kind = kind_phys
51 | intent = in
52 | [ errcode ]
53 | standard_name = ccpp_error_code
54 | long_name = Error flag for error handling in CCPP
55 | units = 1
56 | type = integer
57 | dimensions = ()
58 | intent = out
59 | [ errmsg ]
60 | standard_name = ccpp_error_message
61 | long_name = Error message for error handling in CCPP
62 | units = none
63 | type = character | kind = len=512
64 | dimensions = ()
65 | intent = out
66 |
--------------------------------------------------------------------------------
/schemes/conservation_adjust/check_energy/check_energy_fix.F90:
--------------------------------------------------------------------------------
1 | module check_energy_fix
2 | use ccpp_kinds, only: kind_phys
3 |
4 | implicit none
5 | private
6 |
7 | public :: check_energy_fix_run
8 |
9 | contains
10 |
11 | ! Add heating rate required for global mean total energy conservation
12 | !> \section arg_table_check_energy_fix_run Argument Table
13 | !! \htmlinclude arg_table_check_energy_fix_run.html
14 | subroutine check_energy_fix_run(ncol, pver, pint, gravit, heat_glob, ptend_s, eshflx, scheme_name, errmsg, errflg)
15 | ! Input arguments
16 | integer, intent(in) :: ncol ! number of atmospheric columns
17 | integer, intent(in) :: pver ! number of vertical layers
18 | real(kind_phys), intent(in) :: pint(:,:) ! interface pressure [Pa]
19 | real(kind_phys), intent(in) :: gravit ! gravitational acceleration [m s-2]
20 | real(kind_phys), intent(in) :: heat_glob ! global mean heating rate [J kg-1 s-1]
21 | real(kind_phys), intent(out) :: ptend_s(:,:) ! physics tendency heating rate [J kg-1 s-1]
22 | real(kind_phys), intent(out) :: eshflx(:) ! effective sensible heat flux [W m-2]
23 | ! for check_energy_chng
24 |
25 | ! Output arguments
26 | character(len=64), intent(out) :: scheme_name ! scheme name
27 | character(len=512), intent(out) :: errmsg ! error message
28 | integer, intent(out) :: errflg ! error flag
29 |
30 | ! Local variables
31 | integer :: i
32 |
33 | errmsg = ''
34 | errflg = 0
35 |
36 | ! Set scheme name for check_energy_chng
37 | scheme_name = "check_energy_fix"
38 |
39 | ! add (-) global mean total energy difference as heating
40 | ptend_s(:ncol, :pver) = heat_glob
41 |
42 | ! compute effective sensible heat flux
43 | do i = 1, ncol
44 | eshflx(i) = heat_glob * (pint(i,pver+1) - pint(i,1)) / gravit
45 | end do
46 | end subroutine check_energy_fix_run
47 |
48 | end module check_energy_fix
49 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/gravity_wave_drag_common_diagnostics.F90:
--------------------------------------------------------------------------------
1 | ! Diagnostics for all gravity wave drag parameterizations
2 | ! (used to output total diagnostics in the end of all gravity wave drag schemes)
3 | module gravity_wave_drag_common_diagnostics
4 | use ccpp_kinds, only: kind_phys
5 |
6 | implicit none
7 | private
8 |
9 | public :: gravity_wave_drag_common_diagnostics_init
10 | public :: gravity_wave_drag_common_diagnostics_run
11 |
12 | contains
13 |
14 | !> \section arg_table_gravity_wave_drag_common_diagnostics_init Argument Table
15 | !! \htmlinclude gravity_wave_drag_common_diagnostics_init.html
16 | subroutine gravity_wave_drag_common_diagnostics_init(errmsg, errflg)
17 | use cam_history, only: history_add_field
18 | use cam_history_support, only: horiz_only
19 |
20 | character(len=512), intent(out) :: errmsg
21 | integer, intent(out) :: errflg
22 |
23 | ! Local variables:
24 |
25 | errmsg = ''
26 | errflg = 0
27 |
28 | ! History add field calls
29 | call history_add_field('EKGW', 'effective_diffusivity_coefficient_at_interfaces_due_to_gravity_wave_drag', 'ilev', 'avg', 'm2 s-1')
30 |
31 | end subroutine gravity_wave_drag_common_diagnostics_init
32 |
33 | !> \section arg_table_gravity_wave_drag_common_diagnostics_run Argument Table
34 | !! \htmlinclude gravity_wave_drag_common_diagnostics_run.html
35 | subroutine gravity_wave_drag_common_diagnostics_run( &
36 | egwdffi_tot, &
37 | errmsg, errflg)
38 |
39 | use cam_history, only: history_out_field
40 |
41 | ! Input parameters
42 | real(kind_phys), intent(in) :: egwdffi_tot(:,:)
43 |
44 | ! CCPP error handling variables
45 | character(len=512), intent(out) :: errmsg
46 | integer, intent(out) :: errflg
47 |
48 | errmsg = ''
49 | errflg = 0
50 |
51 | ! History out field calls
52 | call history_out_field('EKGW', egwdffi_tot)
53 |
54 | end subroutine gravity_wave_drag_common_diagnostics_run
55 |
56 | end module gravity_wave_drag_common_diagnostics
57 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/zm_convr_tendency_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = zm_convr_tendency_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = zm_convr_tendency_diagnostics_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | long_name = Error message for error handling in CCPP
11 | units = none
12 | type = character | kind = len=512
13 | dimensions = ()
14 | intent = out
15 | [ errflg ]
16 | standard_name = ccpp_error_code
17 | long_name = Error flag for error handling in CCPP
18 | units = 1
19 | type = integer
20 | dimensions = ()
21 | intent = out
22 |
23 | [ccpp-arg-table]
24 | name = zm_convr_tendency_diagnostics_run
25 | type = scheme
26 | [ ncol ]
27 | standard_name = horizontal_loop_extent
28 | units = count
29 | type = integer
30 | dimensions = ()
31 | intent = in
32 | [ pver ]
33 | standard_name = vertical_layer_dimension
34 | units = count
35 | type = integer
36 | dimensions = ()
37 | intent = in
38 | [ cpair ]
39 | standard_name = specific_heat_of_dry_air_at_constant_pressure
40 | units = J kg-1 K-1
41 | type = real | kind = kind_phys
42 | dimensions = ()
43 | intent = in
44 | [ heat ]
45 | standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure
46 | units = J kg-1 s-1
47 | type = real | kind = kind_phys
48 | dimensions = (horizontal_loop_extent,vertical_layer_dimension)
49 | intent = in
50 | [ qtnd ]
51 | standard_name = tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water
52 | units = kg kg-1 s-1
53 | type = real | kind = kind_phys
54 | dimensions = (horizontal_loop_extent,vertical_layer_dimension)
55 | intent = in
56 | [ errmsg ]
57 | standard_name = ccpp_error_message
58 | long_name = Error message for error handling in CCPP
59 | units = none
60 | type = character | kind = len=512
61 | dimensions = ()
62 | intent = out
63 | [ errflg ]
64 | standard_name = ccpp_error_code
65 | long_name = Error flag for error handling in CCPP
66 | units = 1
67 | type = integer
68 | dimensions = ()
69 | intent = out
70 |
71 |
--------------------------------------------------------------------------------
/.github/workflows/unit-tests.yaml:
--------------------------------------------------------------------------------
1 | name: unit-test-code-coverage
2 |
3 | on:
4 | push:
5 | branches:
6 | - development
7 | - main
8 | workflow_dispatch:
9 | pull_request:
10 |
11 | concurrency:
12 | group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
13 | cancel-in-progress: true
14 |
15 | jobs:
16 | gcc-toolchain:
17 | runs-on: ubuntu-latest
18 | steps:
19 | - name: Checkout atmospheric_physics
20 | uses: actions/checkout@v4
21 |
22 | - name: Install dependencies
23 | run: |
24 | sudo apt update && sudo apt -y install libopenmpi-dev openmpi-bin
25 |
26 | - name: Build pFUnit
27 | run: |
28 | git clone --depth 1 --branch v4.10.0 https://github.com/Goddard-Fortran-Ecosystem/pFUnit.git
29 | cd pFUnit
30 | pwd
31 | cmake -B./build -S.
32 | cd build
33 | make install
34 |
35 | - name: Build atmospheric_physics
36 | run: |
37 | cmake \
38 | -DCMAKE_PREFIX_PATH=/home/runner/work/atmospheric_physics/atmospheric_physics/pFUnit/build/installed \
39 | -DATMOSPHERIC_PHYSICS_ENABLE_CODE_COVERAGE=ON \
40 | -B./build \
41 | -S./test/unit-test
42 | cd build
43 | make
44 |
45 | - name: Run tests
46 | run: |
47 | cd build && ctest -V --output-on-failure --output-junit test_results.xml
48 |
49 | - name: Upload unit test results
50 | uses: actions/upload-artifact@v4
51 | with:
52 | name: unit-test-results
53 | path: build/test_results.xml
54 |
55 | - name: Setup GCov
56 | run: |
57 | python3 -m venv venv
58 | source venv/bin/activate
59 | pip3 install gcovr
60 |
61 | - name: Run Gcov
62 | run: |
63 | source venv/bin/activate
64 | cd build
65 | gcovr -r .. --filter '\.\./schemes' --filter '\.\./phys_utils' --html atmospheric_physics_code_coverage.html --txt
66 |
67 | - name: Upload code coverage results
68 | uses: actions/upload-artifact@v4
69 | with:
70 | name: code-coverage-results
71 | path: build/atmospheric_physics_code_coverage.html
72 |
73 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/sima_tend_diagnostics.F90:
--------------------------------------------------------------------------------
1 | module sima_tend_diagnostics
2 |
3 | use ccpp_kinds, only: kind_phys
4 | use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t
5 |
6 | implicit none
7 | private
8 | save
9 |
10 | public :: sima_tend_diagnostics_init ! init routine
11 | public :: sima_tend_diagnostics_run ! main routine
12 |
13 |
14 | CONTAINS
15 |
16 | !> \section arg_table_sima_tend_diagnostics_init Argument Table
17 | !! \htmlinclude sima_tend_diagnostics_init.html
18 | subroutine sima_tend_diagnostics_init(errmsg, errflg)
19 | use cam_history, only: history_add_field
20 | character(len=512), intent(out) :: errmsg
21 | integer, intent(out) :: errflg
22 |
23 | ! Add tendency fields
24 | call history_add_field('TTEND', 'tendency_of_air_temperature_due_to_model_physics', 'lev', 'avg', 'K s-1')
25 | call history_add_field('UTEND', 'tendency_of_eastward_wind_due_to_model_physics', 'lev', 'avg', 'm s-2')
26 | call history_add_field('VTEND', 'tendency_of_northward_wind_due_to_model_physics', 'lev', 'avg', 'm s-2')
27 |
28 | end subroutine sima_tend_diagnostics_init
29 |
30 | !> \section arg_table_sima_tend_diagnostics_run Argument Table
31 | !! \htmlinclude sima_tend_diagnostics_run.html
32 | subroutine sima_tend_diagnostics_run(dTdt_total, dudt_total, dvdt_total, errmsg, errflg)
33 | use cam_history, only: history_out_field
34 | ! Tendency variables
35 | real(kind_phys), intent(in) :: dTdt_total(:,:) ! tendency of air temperature due to model physics
36 | real(kind_phys), intent(in) :: dudt_total(:,:) ! tendency of eastward wind due to model physics
37 | real(kind_phys), intent(in) :: dvdt_total(:,:) ! tendency of northward wind due to model physics
38 | character(len=512), intent(out) :: errmsg
39 | integer, intent(out) :: errflg
40 |
41 | ! Capture tendency fields
42 | call history_out_field('TTEND', dTdt_total)
43 | call history_out_field('UTEND', dudt_total)
44 | call history_out_field('VTEND', dvdt_total)
45 |
46 | end subroutine sima_tend_diagnostics_run
47 | !=======================================================================
48 | end module sima_tend_diagnostics
49 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/check_energy_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = check_energy_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = check_energy_diagnostics_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | units = none
11 | type = character | kind = len=512
12 | dimensions = ()
13 | intent = out
14 | [ errflg ]
15 | standard_name = ccpp_error_code
16 | units = 1
17 | type = integer
18 | dimensions = ()
19 | intent = out
20 |
21 | [ccpp-arg-table]
22 | name = check_energy_diagnostics_run
23 | type = scheme
24 | [ cp_or_cv_dycore ]
25 | standard_name = specific_heat_of_air_used_in_dycore
26 | units = J kg-1 K-1
27 | type = real | kind = kind_phys
28 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
29 | intent = in
30 | [ scaling_dycore ]
31 | standard_name = ratio_of_specific_heat_of_air_used_in_physics_energy_formula_to_specific_heat_of_air_used_in_dycore_energy_formula
32 | units = 1
33 | type = real | kind = kind_phys
34 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
35 | intent = in
36 | [ te_cur_phys ]
37 | standard_name = vertically_integrated_total_energy_using_physics_energy_formula
38 | units = J m-2
39 | type = real | kind = kind_phys
40 | dimensions = (horizontal_loop_extent)
41 | intent = in
42 | [ tw_cur ]
43 | standard_name = vertically_integrated_total_water
44 | units = kg m-2
45 | type = real | kind = kind_phys
46 | dimensions = (horizontal_loop_extent)
47 | intent = in
48 | [ tend_te_tnd ]
49 | standard_name = cumulative_total_energy_boundary_flux_using_physics_energy_formula
50 | units = J m-2 s-1
51 | type = real | kind = kind_phys
52 | dimensions = (horizontal_loop_extent)
53 | intent = in
54 | [ tend_tw_tnd ]
55 | standard_name = cumulative_total_water_boundary_flux
56 | units = kg m-2 s-1
57 | type = real | kind = kind_phys
58 | dimensions = (horizontal_loop_extent)
59 | intent = in
60 | [ errmsg ]
61 | standard_name = ccpp_error_message
62 | units = none
63 | type = character | kind = len=512
64 | dimensions = ()
65 | intent = out
66 | [ errflg ]
67 | standard_name = ccpp_error_code
68 | units = 1
69 | type = integer
70 | dimensions = ()
71 | intent = out
72 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/zm_momtran_tendency_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = zm_momtran_tendency_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = zm_momtran_tendency_diagnostics_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | long_name = Error message for error handling in CCPP
11 | units = none
12 | type = character | kind = len=512
13 | dimensions = ()
14 | intent = out
15 | [ errflg ]
16 | standard_name = ccpp_error_code
17 | long_name = Error flag for error handling in CCPP
18 | units = 1
19 | type = integer
20 | dimensions = ()
21 | intent = out
22 |
23 | [ccpp-arg-table]
24 | name = zm_momtran_tendency_diagnostics_run
25 | type = scheme
26 | [ ncol ]
27 | standard_name = horizontal_loop_extent
28 | units = count
29 | type = integer
30 | dimensions = ()
31 | intent = in
32 | [ pver ]
33 | standard_name = vertical_layer_dimension
34 | units = count
35 | type = integer
36 | dimensions = ()
37 | intent = in
38 | [ cpair ]
39 | standard_name = specific_heat_of_dry_air_at_constant_pressure
40 | units = J kg-1 K-1
41 | type = real | kind = kind_phys
42 | dimensions = ()
43 | intent = in
44 | [ windu_tend ]
45 | standard_name = tendency_of_eastward_wind
46 | units = m s-2
47 | type = real | kind = kind_phys
48 | dimensions = (horizontal_loop_extent,vertical_layer_dimension)
49 | intent = in
50 | [ windv_tend ]
51 | standard_name = tendency_of_northward_wind
52 | units = m s-2
53 | type = real | kind = kind_phys
54 | dimensions = (horizontal_loop_extent,vertical_layer_dimension)
55 | intent = in
56 | [ seten ]
57 | standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure
58 | units = J kg-1 s-1
59 | type = real | kind = kind_phys
60 | dimensions = (horizontal_loop_extent,vertical_layer_dimension)
61 | intent = in
62 | [ errmsg ]
63 | standard_name = ccpp_error_message
64 | long_name = Error message for error handling in CCPP
65 | units = none
66 | type = character | kind = len=512
67 | dimensions = ()
68 | intent = out
69 | [ errflg ]
70 | standard_name = ccpp_error_code
71 | long_name = Error flag for error handling in CCPP
72 | units = 1
73 | type = integer
74 | dimensions = ()
75 | intent = out
76 |
--------------------------------------------------------------------------------
/schemes/vertical_diffusion/vertical_diffusion_sponge_layer.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = vertical_diffusion_sponge_layer
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = vertical_diffusion_sponge_layer_init
7 | type = scheme
8 | [ amIRoot ]
9 | standard_name = flag_for_mpi_root
10 | units = flag
11 | dimensions = ()
12 | type = logical
13 | intent = in
14 | [ iulog ]
15 | standard_name = log_output_unit
16 | units = 1
17 | dimensions = ()
18 | type = integer
19 | intent = in
20 | [ ptop_ref ]
21 | standard_name = air_pressure_at_top_of_atmosphere_model
22 | units = Pa
23 | dimensions = ()
24 | type = real | kind = kind_phys
25 | intent = in
26 | [ errmsg ]
27 | standard_name = ccpp_error_message
28 | units = none
29 | dimensions = ()
30 | type = character | kind = len=512
31 | intent = out
32 | [ errflg ]
33 | standard_name = ccpp_error_code
34 | units = 1
35 | dimensions = ()
36 | type = integer
37 | intent = out
38 |
39 | [ccpp-arg-table]
40 | name = vertical_diffusion_sponge_layer_run
41 | type = scheme
42 | [ ncol ]
43 | standard_name = horizontal_loop_extent
44 | units = count
45 | dimensions = ()
46 | type = integer
47 | intent = in
48 | [ pverp ]
49 | standard_name = vertical_interface_dimension
50 | units = count
51 | dimensions = ()
52 | type = integer
53 | intent = in
54 | [ kvm ]
55 | standard_name = eddy_momentum_diffusivity_at_interfaces
56 | units = m2 s-1
57 | dimensions = (horizontal_loop_extent, vertical_interface_dimension)
58 | type = real | kind = kind_phys
59 | intent = inout
60 | [ errmsg ]
61 | standard_name = ccpp_error_message
62 | units = none
63 | dimensions = ()
64 | type = character | kind = len=512
65 | intent = out
66 | [ errflg ]
67 | standard_name = ccpp_error_code
68 | units = 1
69 | dimensions = ()
70 | type = integer
71 | intent = out
72 |
73 | [ccpp-arg-table]
74 | name = vertical_diffusion_sponge_layer_final
75 | type = scheme
76 | [ errmsg ]
77 | standard_name = ccpp_error_message
78 | units = none
79 | dimensions = ()
80 | type = character | kind = len=512
81 | intent = out
82 | [ errflg ]
83 | standard_name = ccpp_error_code
84 | units = 1
85 | dimensions = ()
86 | type = integer
87 | intent = out
88 |
--------------------------------------------------------------------------------
/schemes/hack_shallow/set_general_conv_fluxes_to_shallow.F90:
--------------------------------------------------------------------------------
1 | module set_general_conv_fluxes_to_shallow
2 |
3 | use ccpp_kinds, only: kind_phys
4 |
5 | implicit none
6 |
7 | contains
8 | !> \section arg_table_set_general_conv_fluxes_to_shallow_run Argument Table
9 | !! \htmlinclude set_general_conv_fluxes_to_shallow_run.html
10 | subroutine set_general_conv_fluxes_to_shallow_run(tend_s_snwprd_gen, tend_s_snwprd_sh, tend_s_snwevmlt_gen, tend_s_snwevmlt_sh, &
11 | prec_gen, prec_sh, snow_gen, snow_sh, ntprprd_gen, ntprprd_sh, ntsnprd_gen, ntsnprd_sh, &
12 | flxprec_gen, flxprec_sh, flxsnow_gen, flxsnow_sh, &
13 | flx_ice)
14 |
15 | real(kind_phys), intent(in) :: tend_s_snwprd_gen(:,:)
16 | real(kind_phys), intent(out) :: tend_s_snwprd_sh(:,:)
17 | real(kind_phys), intent(in) :: tend_s_snwevmlt_gen(:,:)
18 | real(kind_phys), intent(out) :: tend_s_snwevmlt_sh(:,:)
19 | real(kind_phys), intent(in) :: prec_gen(:) ! precipitation rate is modified by zm_conv_evap based on computed flux
20 | real(kind_phys), intent(out) :: prec_sh(:) ! and thus needs to be renamed from generic to shallow.
21 | real(kind_phys), intent(in) :: snow_gen(:)
22 | real(kind_phys), intent(out) :: snow_sh(:)
23 | real(kind_phys), intent(in) :: ntprprd_gen(:,:)
24 | real(kind_phys), intent(out) :: ntprprd_sh(:,:)
25 | real(kind_phys), intent(in) :: ntsnprd_gen(:,:)
26 | real(kind_phys), intent(out) :: ntsnprd_sh(:,:)
27 | real(kind_phys), intent(in) :: flxprec_gen(:,:)
28 | real(kind_phys), intent(out) :: flxprec_sh(:,:)
29 | real(kind_phys), intent(in) :: flxsnow_gen(:,:)
30 | real(kind_phys), intent(out) :: flxsnow_sh(:,:)
31 |
32 | real(kind_phys), intent(out) :: flx_ice(:) ! net_lwe_ice_fluxes_through_top_and_bottom_of_atmosphere_column [m s-1] for check_energy_chng
33 |
34 | tend_s_snwprd_sh = tend_s_snwprd_gen
35 | tend_s_snwevmlt_sh = tend_s_snwevmlt_gen
36 | prec_sh = prec_gen
37 | snow_sh = snow_gen
38 | ntprprd_sh = ntprprd_gen
39 | ntsnprd_sh = ntsnprd_gen
40 | flxprec_sh = flxprec_gen
41 | flxsnow_sh = flxsnow_gen
42 |
43 | ! boundary flux for check energy
44 | flx_ice = snow_sh
45 |
46 | end subroutine set_general_conv_fluxes_to_shallow_run
47 |
48 | end module set_general_conv_fluxes_to_shallow
49 |
--------------------------------------------------------------------------------
/schemes/thermo_water_update/thermo_water_update.F90:
--------------------------------------------------------------------------------
1 | ! This is a non-portable wrapper subroutine for cam_thermo_water_update
2 | ! in the cam_thermo module.
3 | module thermo_water_update
4 | use ccpp_kinds, only: kind_phys
5 |
6 | implicit none
7 | private
8 |
9 | public :: thermo_water_update_run
10 |
11 | contains
12 |
13 | ! Update water dependent properties
14 | !> \section arg_table_thermo_water_update_run Argument Table
15 | !! \htmlinclude arg_table_thermo_water_update_run.html
16 | subroutine thermo_water_update_run( &
17 | mmr, &
18 | ncol, pver, &
19 | energy_formula_dycore, &
20 | pdel, pdeldry, &
21 | cp_or_cv_dycore)
22 |
23 | ! This scheme is non-portable due to dependencies on cam_thermo
24 | ! for the actual logic of cam_thermo_water_update, which depends on air_composition
25 | ! and a series of other subroutines/module properties
26 | use cam_thermo, only: cam_thermo_water_update
27 |
28 | ! Input arguments
29 | real(kind_phys), intent(in) :: mmr(:,:,:) ! constituent mass mixing ratios [kg kg-1]
30 | integer, intent(in) :: ncol ! number of atmospheric columns
31 | integer, intent(in) :: pver ! number of vertical layers
32 | integer, intent(in) :: energy_formula_dycore ! total energy formulation used by dycore
33 | real(kind_phys), intent(in) :: pdel(:,:) ! layer thickness [Pa]
34 | real(kind_phys), intent(in) :: pdeldry(:,:) ! dry layer thickness [Pa]
35 |
36 | ! Output arguments
37 | real(kind_phys), intent(out) :: cp_or_cv_dycore(:,:) ! enthalpy or heat capacity, dycore dependent [J K-1 kg-1]
38 |
39 | call cam_thermo_water_update( &
40 | mmr = mmr, & ! mmr*factor is a dry mixing ratio
41 | ncol = ncol, &
42 | pver = pver, &
43 | energy_formula = energy_formula_dycore, &
44 | cp_or_cv_dycore = cp_or_cv_dycore(:ncol,:), &
45 | to_dry_factor = pdel(:ncol,:)/pdeldry(:ncol,:) & ! factor to convert to dry
46 | )
47 |
48 | end subroutine thermo_water_update_run
49 |
50 | end module thermo_water_update
51 |
--------------------------------------------------------------------------------
/schemes/musica/util/musica_ccpp_util.F90:
--------------------------------------------------------------------------------
1 | ! Copyright (C) 2024-2025 University Corporation for Atmospheric Research
2 | ! SPDX-License-Identifier: Apache-2.0
3 | module musica_ccpp_util
4 |
5 | use ccpp_kinds, only: kind_phys
6 |
7 | implicit none
8 |
9 | private
10 | public :: has_error_occurred, set_constants
11 |
12 | real(kind_phys), parameter, public :: PI = 3.14159265358979323846_kind_phys
13 | real(kind_phys), parameter, public :: DEGREE_TO_RADIAN = PI / 180.0_kind_phys
14 | real(kind_phys), public, protected :: MOLAR_MASS_DRY_AIR = -HUGE(1.0_kind_phys) ! kg mol-1
15 |
16 | !> Conversion factor for wavelength interfaces from meters (CAM-SIMA) to nanometers (TUV-x)
17 | real(kind_phys), parameter, public :: m_to_nm = 1.0e9_kind_phys
18 |
19 | contains
20 |
21 | !> @brief Set constants used for MUSICA components
22 | !> @param[in] molar_mass_dry_air_in The molar mass of dry air (kg mol-1).
23 | subroutine set_constants(molar_mass_dry_air_in)
24 |
25 | real(kind_phys), intent(in) :: molar_mass_dry_air_in
26 |
27 | MOLAR_MASS_DRY_AIR = molar_mass_dry_air_in
28 | end subroutine set_constants
29 |
30 | !> @brief Evaluate a MUSICA error for failure and convert to CCPP error data
31 | !> @param[in] error The error code to evaluate and convert.
32 | !> @param[out] error_message The CCPP error message.
33 | !> @param[out] error_code The CCPP error code.
34 | !> @return True for an error, false for success.
35 | logical function has_error_occurred(error, error_message, error_code)
36 | use musica_util, only: error_t
37 |
38 | type(error_t), intent(in) :: error
39 | character(len=512), intent(out) :: error_message
40 | integer, intent(out) :: error_code
41 |
42 | character(len=30) :: error_code_str
43 |
44 | if ( error%is_success( ) ) then
45 | error_code = 0
46 | error_message = ''
47 | has_error_occurred = .false.
48 | return
49 | end if
50 | error_code = error%code( )
51 | write(error_code_str, '(I30)') error%code( )
52 | error_message = '[MUSICA Error]: ' // error%category( ) // '[' // &
53 | trim( adjustl( error_code_str ) ) // ']: ' // error%message( )
54 | has_error_occurred = .true.
55 |
56 | end function has_error_occurred
57 |
58 | end module musica_ccpp_util
59 |
--------------------------------------------------------------------------------
/test/test_suites/suite_gw_cam4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
22 |
23 | initialize_constituents
24 |
25 |
26 | gravity_wave_drag_common
27 |
28 |
29 | check_energy_zero_fluxes
30 | gravity_wave_drag_prepare_profiles
31 |
32 |
33 | gravity_wave_drag_top_taper
34 |
35 |
36 | gravity_wave_drag_orographic
37 |
38 |
39 | convert_dry_constituent_tendencies_to_dry_air_basis
40 |
41 |
42 | gravity_wave_drag_common_diagnostics
43 |
44 |
45 | apply_tendency_of_eastward_wind
46 | apply_tendency_of_northward_wind
47 | apply_constituent_tendencies
48 | apply_heating_rate
49 | qneg
50 | geopotential_temp
51 | update_dry_static_energy
52 |
53 |
54 | check_energy_scaling
55 | check_energy_chng
56 |
57 |
58 |
--------------------------------------------------------------------------------
/phys_utils/atmos_phys_string_utils.F90:
--------------------------------------------------------------------------------
1 | module atmos_phys_string_utils
2 | ! String utils
3 |
4 | implicit none
5 | private
6 |
7 | public :: to_lower
8 | public :: to_upper
9 |
10 | contains
11 |
12 | pure function to_lower(input_string) result(lowercase_string)
13 | ! Return 'input_string' in all lower case
14 | character(len=*), intent(in) :: input_string
15 | character(len=len(input_string)) :: lowercase_string
16 | ! Local variables
17 |
18 | integer :: i ! Index
19 | integer :: aseq ! ascii collating sequence
20 | integer :: upper_to_lower ! integer to convert case
21 | character(len=1) :: ctmp ! Character temporary
22 | !-----------------------------------------------------------------------
23 | upper_to_lower = iachar("a") - iachar("A")
24 |
25 | do i = 1, len(input_string)
26 | ctmp = input_string(i:i)
27 | aseq = iachar(ctmp)
28 | if ( aseq >= iachar("A") .and. aseq <= iachar("Z") ) &
29 | ctmp = achar(aseq + upper_to_lower)
30 | lowercase_string(i:i) = ctmp
31 | end do
32 |
33 | end function to_lower
34 |
35 | !---------------------------------------------------------------------------
36 | !---------------------------------------------------------------------------
37 |
38 | pure function to_upper(input_string) result(uppercase_string)
39 | ! Return 'input_string' in all upper case
40 | character(len=*), intent(in) :: input_string
41 | character(len=len(input_string)) :: uppercase_string
42 |
43 | integer :: i ! Index
44 | integer :: aseq ! ascii collating sequence
45 | integer :: lower_to_upper ! integer to convert case
46 | character(len=1) :: ctmp ! Character temporary
47 | !-----------------------------------------------------------------------
48 | lower_to_upper = iachar("A") - iachar("a")
49 |
50 | do i = 1, len(input_string)
51 | ctmp = input_string(i:i)
52 | aseq = iachar(ctmp)
53 | if ( aseq >= iachar("a") .and. aseq <= iachar("z") ) &
54 | ctmp = achar(aseq + lower_to_upper)
55 | uppercase_string(i:i) = ctmp
56 | end do
57 |
58 | end function to_upper
59 |
60 | end module atmos_phys_string_utils
61 |
--------------------------------------------------------------------------------
/suites/suite_kessler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | calc_exner
6 | temp_to_potential_temp
7 | calc_dry_air_ideal_gas_density
8 | wet_to_dry_water_vapor
9 | wet_to_dry_cloud_liquid_water
10 | wet_to_dry_rain
11 | kessler
12 | potential_temp_to_temp
13 | dry_to_wet_water_vapor
14 | dry_to_wet_cloud_liquid_water
15 | dry_to_wet_rain
16 | kessler_update
17 | qneg
18 | geopotential_temp
19 |
20 |
24 | check_energy_zero_fluxes
25 | check_energy_scaling
26 | check_energy_chng
27 |
28 |
29 | sima_state_diagnostics
30 | kessler_diagnostics
31 |
32 |
33 |
34 |
35 | thermo_water_update
36 |
37 |
38 |
39 |
40 |
41 |
45 | check_energy_scaling
46 | dycore_energy_consistency_adjust
47 | apply_tendency_of_air_temperature
48 |
49 |
50 | sima_tend_diagnostics
51 |
52 |
53 |
--------------------------------------------------------------------------------
/schemes/zhang_mcfarlane/save_ttend_from_convect_deep.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = save_ttend_from_convect_deep
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = save_ttend_from_convect_deep_timestep_init
7 | type = scheme
8 | [ ncol ]
9 | standard_name = horizontal_dimension
10 | units = count
11 | type = integer
12 | dimensions = ()
13 | intent = in
14 | [ pver ]
15 | standard_name = vertical_layer_dimension
16 | units = count
17 | type = integer
18 | dimensions = ()
19 | intent = in
20 | [ ttend_dp ]
21 | standard_name = tendency_of_air_temperature_due_to_deep_convection
22 | units = K s-1
23 | type = real | kind = kind_phys
24 | dimensions = (horizontal_dimension, vertical_layer_dimension)
25 | intent = out
26 | [ errmsg ]
27 | standard_name = ccpp_error_message
28 | units = none
29 | type = character | kind = len=512
30 | dimensions = ()
31 | intent = out
32 | [ errflg ]
33 | standard_name = ccpp_error_code
34 | units = 1
35 | type = integer
36 | dimensions = ()
37 | intent = out
38 |
39 | [ccpp-arg-table]
40 | name = save_ttend_from_convect_deep_run
41 | type = scheme
42 | [ ncol ]
43 | standard_name = horizontal_loop_extent
44 | units = count
45 | type = integer
46 | dimensions = ()
47 | intent = in
48 | [ pver ]
49 | standard_name = vertical_layer_dimension
50 | units = count
51 | type = integer
52 | dimensions = ()
53 | intent = in
54 | [ tend_s ]
55 | standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure
56 | units = J kg-1 s-1
57 | type = real | kind = kind_phys
58 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
59 | intent = in
60 | [ cpair ]
61 | standard_name = specific_heat_of_dry_air_at_constant_pressure
62 | units = J kg-1 K-1
63 | type = real | kind = kind_phys
64 | dimensions = ()
65 | intent = in
66 | [ ttend_dp ]
67 | standard_name = tendency_of_air_temperature_due_to_deep_convection
68 | units = K s-1
69 | type = real | kind = kind_phys
70 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
71 | intent = inout
72 | [ errmsg ]
73 | standard_name = ccpp_error_message
74 | units = none
75 | type = character | kind = len=512
76 | dimensions = ()
77 | intent = out
78 | [ errflg ]
79 | standard_name = ccpp_error_code
80 | units = 1
81 | type = integer
82 | dimensions = ()
83 | intent = out
84 |
--------------------------------------------------------------------------------
/test/musica/tuvx/test_tuvx_wavelength_grid.F90:
--------------------------------------------------------------------------------
1 | ! Copyright (C) 2024-2025 University Corporation for Atmospheric Research
2 | ! SPDX-License-Identifier: Apache-2.0
3 | program test_tuvx_wavelength_grid
4 |
5 | use musica_ccpp_tuvx_wavelength_grid
6 |
7 | implicit none
8 |
9 | #define ASSERT(x) if (.not.(x)) then; write(*,*) "Assertion failed[", __FILE__, ":", __LINE__, "]: x"; stop 1; endif
10 | #define ASSERT_NEAR( a, b, abs_error ) if( (abs(a - b) >= abs_error) .and. (abs(a - b) /= 0.0) ) then; write(*,*) "Assertion failed[", __FILE__, ":", __LINE__, "]: a, b"; stop 1; endif
11 |
12 | call test_create_wavelength_grid()
13 |
14 | contains
15 |
16 | subroutine test_create_wavelength_grid()
17 | use musica_util, only: error_t
18 | use musica_tuvx_grid, only: grid_t
19 | use ccpp_kinds, only: kind_phys
20 |
21 | integer, parameter :: NUM_WAVELENGTH_GRID_MIDPOINTS = 2
22 | integer, parameter :: NUM_WAVELENGTH_GRID_INTERFACES = 3
23 | real, parameter :: ABS_ERROR = 1e-5
24 | real(kind_phys) :: host_interfaces(NUM_WAVELENGTH_GRID_INTERFACES) = [180.0_kind_phys, 200.0_kind_phys, 240.0_kind_phys] ! nm
25 | real(kind_phys) :: expected_midpoints(NUM_WAVELENGTH_GRID_MIDPOINTS) = [190.0_kind_phys, 220.0_kind_phys]
26 | real(kind_phys) :: interfaces(NUM_WAVELENGTH_GRID_INTERFACES)
27 | real(kind_phys) :: midpoints(NUM_WAVELENGTH_GRID_MIDPOINTS)
28 | type(grid_t), pointer :: wavelength_grid => null()
29 | character(len=512) :: errmsg
30 | integer :: errcode
31 | type(error_t) :: error
32 | integer :: i
33 |
34 | wavelength_grid => create_wavelength_grid(host_interfaces, errmsg, errcode)
35 | ASSERT(errcode == 0)
36 | ASSERT(associated(wavelength_grid))
37 |
38 | call wavelength_grid%get_edges(interfaces, error)
39 | ASSERT(error%is_success())
40 | do i = 1, NUM_WAVELENGTH_GRID_INTERFACES
41 | ASSERT_NEAR(interfaces(i), host_interfaces(i), ABS_ERROR)
42 | end do
43 |
44 | call wavelength_grid%get_midpoints(midpoints, error)
45 | ASSERT(error%is_success())
46 | do i = 1, NUM_WAVELENGTH_GRID_MIDPOINTS
47 | ASSERT_NEAR(midpoints(i), expected_midpoints(i), ABS_ERROR)
48 | end do
49 |
50 | deallocate(wavelength_grid)
51 |
52 | end subroutine test_create_wavelength_grid
53 |
54 | end program test_tuvx_wavelength_grid
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/zm_convr_tendency_diagnostics.F90:
--------------------------------------------------------------------------------
1 | module zm_convr_tendency_diagnostics
2 | use ccpp_kinds, only: kind_phys
3 |
4 | implicit none
5 | private
6 | save
7 |
8 | public :: zm_convr_tendency_diagnostics_init ! init routine
9 | public :: zm_convr_tendency_diagnostics_run ! main routine
10 |
11 | CONTAINS
12 |
13 | !> \section arg_table_zm_convr_tendency_diagnostics_init Argument Table
14 | !! \htmlinclude zm_convr_tendency_diagnostics_init.html
15 | subroutine zm_convr_tendency_diagnostics_init(errmsg, errflg)
16 | use cam_history, only: history_add_field
17 | use cam_history_support, only: horiz_only
18 |
19 | character(len=512), intent(out) :: errmsg
20 | integer, intent(out) :: errflg
21 |
22 | ! Local variables:
23 |
24 | errmsg = ''
25 | errflg = 0
26 |
27 | call history_add_field ('ZMDT', 'T tendency - Zhang-McFarlane moist convection', 'lev', 'avg', 'K s-1')
28 | call history_add_field ('ZMDQ', 'Q tendency - Zhang-McFarlane moist convection', 'lev', 'avg', 'kg kg-1 s-1')
29 |
30 | end subroutine zm_convr_tendency_diagnostics_init
31 |
32 | !> \section arg_table_zm_convr_tendency_diagnostics_run Argument Table
33 | !! \htmlinclude zm_convr_tendency_diagnostics_run.html
34 | subroutine zm_convr_tendency_diagnostics_run(ncol, pver, cpair, heat, qtnd, errmsg, errflg)
35 |
36 | use cam_history, only: history_out_field
37 |
38 | !------------------------------------------------
39 | ! Input / output parameters
40 | !------------------------------------------------
41 | integer, intent(in) :: ncol
42 | integer, intent(in) :: pver
43 |
44 | real(kind_phys), intent(in) :: cpair
45 | real(kind_phys), intent(in) :: heat(:,:)
46 | real(kind_phys), intent(in) :: qtnd(:,:)
47 |
48 | ! CCPP error handling variables
49 | character(len=512), intent(out) :: errmsg
50 | integer, intent(out) :: errflg
51 |
52 |
53 | real(kind_phys) :: ftem(ncol,pver)
54 |
55 | errmsg = ''
56 | errflg = 0
57 |
58 | ftem(:,:) = 0._kind_phys
59 |
60 | ftem(:ncol,:pver) = heat(:ncol,:pver)/cpair
61 | call history_out_field('ZMDT ', ftem)
62 | call history_out_field('ZMDQ ', qtnd)
63 |
64 | end subroutine zm_convr_tendency_diagnostics_run
65 |
66 | !=======================================================================
67 |
68 | end module zm_convr_tendency_diagnostics
69 |
--------------------------------------------------------------------------------
/schemes/gravity_wave_drag/gw_common.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = gravity_wave_drag_common
3 | type = scheme
4 | dependencies = ../../to_be_ccppized/linear_1d_operators.F90,../../to_be_ccppized/coords_1d.F90,../../to_be_ccppized/vdiff_lu_solver.F90,gw_diffusion.F90
5 |
6 | [ccpp-arg-table]
7 | name = gravity_wave_drag_common_init
8 | type = scheme
9 | [ pver_in ]
10 | standard_name = vertical_layer_dimension
11 | units = count
12 | type = integer
13 | dimensions = ()
14 | intent = in
15 | [ pverp_in ]
16 | standard_name = vertical_interface_dimension
17 | units = count
18 | type = integer
19 | dimensions = ()
20 | intent = in
21 | [ amIRoot ]
22 | standard_name = flag_for_mpi_root
23 | units = flag
24 | type = logical
25 | dimensions = ()
26 | intent = in
27 | [ iulog ]
28 | standard_name = log_output_unit
29 | units = 1
30 | type = integer
31 | dimensions = ()
32 | intent = in
33 | [ pref_edge ]
34 | standard_name = reference_pressure_at_interface
35 | units = Pa
36 | type = real | kind = kind_phys
37 | dimensions = (vertical_interface_dimension)
38 | intent = in
39 | [ tau_0_ubc_in ]
40 | standard_name = force_zero_stress_at_top_of_atmosphere_due_to_gravity_wave_drag
41 | units = flag
42 | type = logical
43 | dimensions = ()
44 | intent = in
45 | [ pi_in ]
46 | standard_name = pi_constant
47 | units = 1
48 | type = real | kind = kind_phys
49 | dimensions = ()
50 | intent = in
51 | [ gravit_in ]
52 | standard_name = standard_gravitational_acceleration
53 | units = m s-2
54 | type = real | kind = kind_phys
55 | dimensions = ()
56 | intent = in
57 | [ rair_in ]
58 | standard_name = gas_constant_of_dry_air
59 | units = J kg-1 K-1
60 | type = real | kind = kind_phys
61 | dimensions = ()
62 | intent = in
63 | [ prndl_in ]
64 | standard_name = inverse_prandtl_number_for_diffusion_in_gravity_wave_drag
65 | units = 1
66 | type = real | kind = kind_phys
67 | dimensions = ()
68 | intent = in
69 | [ qbo_hdepth_scaling_in ]
70 | standard_name = scaling_factor_for_heating_depth_in_gravity_waves_from_convection
71 | units = 1
72 | type = real | kind = kind_phys
73 | dimensions = ()
74 | intent = in
75 | [ errmsg ]
76 | standard_name = ccpp_error_message
77 | units = none
78 | type = character | kind = len=512
79 | dimensions = ()
80 | intent = out
81 | [ errflg ]
82 | standard_name = ccpp_error_code
83 | units = 1
84 | type = integer
85 | dimensions = ()
86 | intent = out
87 |
--------------------------------------------------------------------------------
/schemes/utilities/convert_dry_constituent_tendencies_to_dry_air_basis.F90:
--------------------------------------------------------------------------------
1 | ! Convert dry constituent tendencies from moist to dry air basis
2 | module convert_dry_constituent_tendencies_to_dry_air_basis
3 | use ccpp_kinds, only: kind_phys
4 |
5 | implicit none
6 | private
7 | save
8 |
9 | ! public CCPP-compliant subroutines
10 | public :: convert_dry_constituent_tendencies_to_dry_air_basis_run
11 |
12 | contains
13 |
14 | !> \section arg_table_convert_dry_constituent_tendencies_to_dry_air_basis_run Argument Table
15 | !! \htmlinclude convert_dry_constituent_tendencies_to_dry_air_basis_run.html
16 | subroutine convert_dry_constituent_tendencies_to_dry_air_basis_run( &
17 | ncol, pver, pcnst, &
18 | pdel, pdeldry, &
19 | const_props, &
20 | tend_q, &
21 | errmsg, errflg)
22 |
23 | use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t
24 |
25 | ! Input arguments
26 | integer, intent(in) :: ncol
27 | integer, intent(in) :: pver
28 | integer, intent(in) :: pcnst
29 | real(kind_phys), intent(in) :: pdel(:, :) ! Layer thickness (moist air) [Pa]
30 | real(kind_phys), intent(in) :: pdeldry(:, :) ! Layer thickness (dry air) [Pa]
31 |
32 | ! Framework dependency for constituent properties
33 | type(ccpp_constituent_prop_ptr_t), &
34 | intent(in) :: const_props(:) ! CCPP constituent properties pointer
35 |
36 | ! Input/Output arguments
37 | real(kind_phys), intent(inout) :: tend_q(:, :, :) ! Constituent tendencies [kg kg-1 s-1]
38 |
39 | ! Output arguments
40 | character(len=512), intent(out) :: errmsg
41 | integer, intent(out) :: errflg
42 |
43 | ! Local variables
44 | integer :: i, k, m
45 | logical :: const_is_dry
46 |
47 | errmsg = ''
48 | errflg = 0
49 |
50 | ! Convert the tendencies for the dry constituents to dry air basis
51 | do m = 1, pcnst
52 | ! Check if this constituent is dry type
53 | call const_props(m)%is_dry(const_is_dry, errflg, errmsg)
54 | if (errflg /= 0) return
55 |
56 | if (const_is_dry) then
57 | do k = 1, pver
58 | do i = 1, ncol
59 | tend_q(i, k, m) = tend_q(i, k, m) * pdel(i, k) / pdeldry(i, k)
60 | end do
61 | end do
62 | end if
63 | end do
64 |
65 | end subroutine convert_dry_constituent_tendencies_to_dry_air_basis_run
66 |
67 | end module convert_dry_constituent_tendencies_to_dry_air_basis
68 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/cloud_particle_sedimentation_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = cloud_particle_sedimentation_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = cloud_particle_sedimentation_diagnostics_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | units = none
11 | type = character | kind = len=512
12 | dimensions = ()
13 | intent = out
14 | [ errflg ]
15 | standard_name = ccpp_error_code
16 | units = 1
17 | type = integer
18 | dimensions = ()
19 | intent = out
20 |
21 | [ccpp-arg-table]
22 | name = cloud_particle_sedimentation_diagnostics_run
23 | type = scheme
24 | [ ncol ]
25 | standard_name = horizontal_loop_extent
26 | units = count
27 | type = integer
28 | dimensions = ()
29 | intent = in
30 | [ wvtend ]
31 | standard_name = tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water
32 | units = kg kg-1 s-1
33 | type = real | kind = kind_phys
34 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
35 | intent = in
36 | [ icetend ]
37 | standard_name = tendency_of_cloud_ice_mixing_ratio_wrt_moist_air_and_condensed_water
38 | units = kg kg-1 s-1
39 | type = real | kind = kind_phys
40 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
41 | intent = in
42 | [ liqtend ]
43 | standard_name = tendency_of_cloud_liquid_water_mixing_ratio_wrt_moist_air_and_condensed_water
44 | units = kg kg-1 s-1
45 | type = real | kind = kind_phys
46 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
47 | intent = in
48 | [ htend ]
49 | standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure
50 | units = J kg-1 s-1
51 | type = real | kind = kind_phys
52 | dimensions = (horizontal_loop_extent, vertical_layer_dimension)
53 | intent = in
54 | [ snow_sed ]
55 | standard_name = stratiform_lwe_cloud_ice_surface_flux_due_to_sedimentation
56 | units = m s-1
57 | type = real | kind = kind_phys
58 | dimensions = (horizontal_loop_extent)
59 | intent = in
60 | [ sfliq ]
61 | standard_name = stratiform_rain_flux_at_surface_due_to_sedimentation
62 | units = kg m-2 s-1
63 | type = real | kind = kind_phys
64 | dimensions = (horizontal_loop_extent)
65 | intent = in
66 | [ errmsg ]
67 | standard_name = ccpp_error_message
68 | units = none
69 | type = character | kind = len=512
70 | dimensions = ()
71 | intent = out
72 | [ errflg ]
73 | standard_name = ccpp_error_code
74 | units = 1
75 | type = integer
76 | dimensions = ()
77 | intent = out
78 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/convective_cloud_cover_diagnostics.F90:
--------------------------------------------------------------------------------
1 | ! Diagnostics for cloud fraction - convective cloud cover
2 | module convective_cloud_cover_diagnostics
3 | use ccpp_kinds, only: kind_phys
4 |
5 | implicit none
6 | private
7 | save
8 |
9 | public :: convective_cloud_cover_diagnostics_init
10 | public :: convective_cloud_cover_diagnostics_run
11 |
12 | contains
13 |
14 | !> \section arg_table_convective_cloud_cover_diagnostics_init Argument Table
15 | !! \htmlinclude convective_cloud_cover_diagnostics_init.html
16 | subroutine convective_cloud_cover_diagnostics_init(errmsg, errflg)
17 | use cam_history, only: history_add_field
18 | use cam_history_support, only: horiz_only
19 |
20 | character(len=512), intent(out) :: errmsg
21 | integer, intent(out) :: errflg
22 |
23 | ! Local variables:
24 |
25 | errmsg = ''
26 | errflg = 0
27 |
28 | ! History add field calls
29 | call history_add_field('SH_CLD', 'shallow_convective_cloud_area_fraction', 'lev', 'avg', 'fraction')
30 | call history_add_field('DP_CLD', 'deep_convective_cloud_area_fraction', 'lev', 'avg', 'fraction')
31 | call history_add_field('CONCLD', 'convective_cloud_area_fraction', 'lev', 'avg', 'fraction')
32 |
33 | end subroutine convective_cloud_cover_diagnostics_init
34 |
35 | !> \section arg_table_convective_cloud_cover_diagnostics_run Argument Table
36 | !! \htmlinclude convective_cloud_cover_diagnostics_run.html
37 | subroutine convective_cloud_cover_diagnostics_run( &
38 | shallowcu, deepcu, concld, &
39 | errmsg, errflg)
40 |
41 | use cam_history, only: history_out_field
42 |
43 | ! Input parameters
44 | real(kind_phys), intent(in) :: shallowcu(:, :) ! Shallow convective cloud fraction [fraction]
45 | real(kind_phys), intent(in) :: deepcu(:, :) ! Deep convective cloud fraction [fraction]
46 | real(kind_phys), intent(in) :: concld(:, :) ! Convective cloud cover [fraction]
47 |
48 |
49 | ! CCPP error handling variables
50 | character(len=512), intent(out) :: errmsg
51 | integer, intent(out) :: errflg
52 |
53 | errmsg = ''
54 | errflg = 0
55 |
56 | ! History out field calls
57 | call history_out_field('SH_CLD', shallowcu)
58 | call history_out_field('DP_CLD', deepcu)
59 | call history_out_field('CONCLD', concld)
60 |
61 | end subroutine convective_cloud_cover_diagnostics_run
62 |
63 | end module convective_cloud_cover_diagnostics
64 |
--------------------------------------------------------------------------------
/schemes/conservation_adjust/check_energy/dycore_energy_consistency_adjust.F90:
--------------------------------------------------------------------------------
1 | ! MPAS and SE dynamical core specific
2 | ! 1) scaling of temperature for enforcing energy consistency
3 | ! 2) and to ensure correct computation of temperature dependent diagnostic tendencies, e.g., dtcore
4 | module dycore_energy_consistency_adjust
5 | use ccpp_kinds, only: kind_phys
6 | implicit none
7 | private
8 |
9 | public :: dycore_energy_consistency_adjust_run
10 |
11 | contains
12 | !> \section arg_table_dycore_energy_consistency_adjust_run Argument Table
13 | !! \htmlinclude arg_table_dycore_energy_consistency_adjust_run.html
14 | subroutine dycore_energy_consistency_adjust_run( &
15 | ncol, pver, &
16 | do_consistency_adjust, &
17 | scaling_dycore, &
18 | tend_dTdt, &
19 | tend_dTdt_local, &
20 | errmsg, errflg)
21 |
22 | ! Input arguments
23 | integer, intent(in) :: ncol ! number of atmospheric columns
24 | integer, intent(in) :: pver ! number of vertical layers
25 | logical, intent(in) :: do_consistency_adjust ! do energy consistency adjustment?
26 | real(kind_phys), intent(in) :: scaling_dycore(:,:) ! scaling for conversion of temperature increment [1]
27 | real(kind_phys), intent(in) :: tend_dTdt(:,:) ! model physics temperature tendency [K s-1]
28 |
29 | ! Output arguments
30 | real(kind_phys), intent(out) :: tend_dTdt_local(:,:) ! (scheme) temperature tendency [K s-1]
31 | character(len=512), intent(out) :: errmsg ! error message
32 | integer, intent(out) :: errflg ! error flag
33 |
34 | errmsg = ''
35 | errflg = 0
36 |
37 | if (do_consistency_adjust) then
38 | ! original formula for scaling of temperature:
39 | ! T(:ncol,:) = temp_ini(:ncol,:) + &
40 | ! scaling_dycore(:ncol,:) * (T(:ncol,:) - temp_ini(:ncol,:))
41 | ! and temperature tendency due to model physics:
42 | ! tend_dTdt(:ncol,:) = scaling_dycore(:ncol,:) * tend_dTdt(:ncol,:)
43 | !
44 | ! the terms can be arranged for this scaling to be applied through scheme tendencies
45 | ! at the cost of a round-off level difference
46 | tend_dTdt_local(:ncol,:) = (scaling_dycore(:ncol,:) - 1._kind_phys) * tend_dTdt(:ncol,:)
47 | endif
48 | ! do nothing for dynamical cores with energy consistent with CAM physics
49 |
50 | end subroutine dycore_energy_consistency_adjust_run
51 |
52 | end module dycore_energy_consistency_adjust
53 |
--------------------------------------------------------------------------------
/schemes/musica/tuvx/musica_ccpp_tuvx_wavelength_grid.F90:
--------------------------------------------------------------------------------
1 | ! Copyright (C) 2024-2025 University Corporation for Atmospheric Research
2 | ! SPDX-License-Identifier: Apache-2.0
3 | module musica_ccpp_tuvx_wavelength_grid
4 |
5 | implicit none
6 |
7 | private
8 | public :: create_wavelength_grid
9 |
10 | ! TUV-x Wavelegnth grid notes
11 | !
12 | !-----------------------------------------------------------------------
13 | ! The wavelength grid used with TUV-x is based on the grid used in the
14 | ! CAM-Chem photolysis rate constant lookup tables. Slight modifications
15 | ! were made to the grid in the Shumann-Runge and Lyman-alpha regions to
16 | ! work with the expectations of the TUV-x code.
17 | !
18 | ! The wavelength grid is defined by the host model. Any wavelength-
19 | ! resolved quantities passed to TUV-x must be on this grid.
20 |
21 | !> Label for wavelength grid in TUV-x
22 | character(len=*), parameter, public :: wavelength_grid_label = "wavelength"
23 | !> Unit for wavelength grid in TUV-x
24 | character(len=*), parameter, public :: wavelength_grid_unit = "nm"
25 |
26 | contains
27 |
28 | !> Creates a TUV-x wavelength grid
29 | function create_wavelength_grid( wavelength_grid_interfaces, &
30 | errmsg, errcode ) result( wavelength_grid )
31 |
32 | use ccpp_kinds, only: kind_phys
33 | use musica_ccpp_util, only: has_error_occurred
34 | use musica_tuvx_grid, only: grid_t
35 | use musica_util, only: error_t
36 |
37 | real(kind_phys), intent(in) :: wavelength_grid_interfaces(:) ! nm
38 | character(len=*), intent(out) :: errmsg
39 | integer, intent(out) :: errcode
40 | type(grid_t), pointer :: wavelength_grid
41 |
42 | ! local variables
43 | reaL(kind_phys) :: midpoints( size( wavelength_grid_interfaces ) - 1 ) ! nm
44 | type(error_t) :: error
45 |
46 | midpoints(:) = &
47 | 0.5 * ( wavelength_grid_interfaces( 1: size( wavelength_grid_interfaces ) - 1 ) &
48 | + wavelength_grid_interfaces( 2: size( wavelength_grid_interfaces ) ) )
49 | wavelength_grid => grid_t( wavelength_grid_label, wavelength_grid_unit, &
50 | size( midpoints ), error )
51 | if ( has_error_occurred( error, errmsg, errcode ) ) return
52 | call wavelength_grid%set_edges( wavelength_grid_interfaces, error )
53 | if ( has_error_occurred( error, errmsg, errcode ) ) return
54 | call wavelength_grid%set_midpoints( midpoints, error )
55 | if ( has_error_occurred( error, errmsg, errcode ) ) return
56 |
57 | end function create_wavelength_grid
58 |
59 | end module musica_ccpp_tuvx_wavelength_grid
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/check_energy_gmean_diagnostics.F90:
--------------------------------------------------------------------------------
1 | ! Diagnostic scheme for check_energy_gmean
2 | ! This creates a debug printout with:
3 | ! - global mean input energy using dycore energy formula
4 | ! - global mean output energy at end of physics timestep using dycore energy formula
5 | ! - global mean heating rate for energy conservation
6 | ! These numbers are very useful for matching models bit-for-bit because they include "everything" in the model.
7 | module check_energy_gmean_diagnostics
8 | use ccpp_kinds, only: kind_phys
9 |
10 | implicit none
11 | private
12 | save
13 |
14 | public :: check_energy_gmean_diagnostics_init
15 | public :: check_energy_gmean_diagnostics_run ! main routine
16 |
17 | ! Private module options.
18 | logical :: print_global_means = .false.
19 |
20 | contains
21 |
22 | !> \section arg_table_check_energy_gmean_diagnostics_init Argument Table
23 | !! \htmlinclude arg_table_check_energy_gmean_diagnostics_init.html
24 | subroutine check_energy_gmean_diagnostics_init(print_global_means_in)
25 | ! Input arguments
26 | logical, intent(in) :: print_global_means_in
27 |
28 | print_global_means = print_global_means_in
29 | end subroutine check_energy_gmean_diagnostics_init
30 |
31 | !> \section arg_table_check_energy_gmean_diagnostics_run Argument Table
32 | !! \htmlinclude check_energy_gmean_diagnostics_run.html
33 | subroutine check_energy_gmean_diagnostics_run( &
34 | amIRoot, &
35 | iulog, &
36 | teinp_glob, &
37 | teout_glob, &
38 | heat_glob, &
39 | errmsg, errflg)
40 |
41 | logical, intent(in) :: amIRoot ! are we on the MPI root task?
42 | integer, intent(in) :: iulog ! log output unit
43 |
44 | real(kind_phys), intent(in) :: teinp_glob ! global mean energy of input state [J m-2]
45 | real(kind_phys), intent(in) :: teout_glob ! global mean energy of output state [J m-2]
46 | real(kind_phys), intent(in) :: heat_glob ! global mean heating rate [J kg-1 s-1]
47 |
48 | character(len=512), intent(out) :: errmsg
49 | integer, intent(out) :: errflg
50 |
51 | errmsg = ''
52 | errflg = 0
53 |
54 | if (print_global_means .and. amIRoot) then
55 | write(iulog,'(1x,a26,1x,e25.17,1x,a15,1x,e25.17)') 'global mean input energy =', teinp_glob, 'output energy =', teout_glob
56 | write(iulog,'(1x,a38,1x,e25.17)') 'heating rate for energy conservation =', heat_glob
57 | endif
58 |
59 | end subroutine check_energy_gmean_diagnostics_run
60 |
61 | end module check_energy_gmean_diagnostics
62 |
--------------------------------------------------------------------------------
/test/test_suites/suite_convect_shallow_hack.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | initialize_constituents
7 | to_be_ccppized_temporary
8 |
9 |
10 | zm_conv_options
11 |
12 |
27 |
28 |
29 | convect_shallow_diagnostics
30 |
31 |
32 | check_energy_zero_fluxes
33 | hack_convect_shallow
34 | convect_shallow_diagnostics_after_shallow_scheme
35 | apply_heating_rate
36 | apply_constituent_tendencies
37 | qneg
38 | geopotential_temp
39 |
40 |
41 | cloud_fraction_fice
42 |
43 |
44 | set_shallow_conv_fluxes_to_general
45 | zm_conv_evap
46 | set_general_conv_fluxes_to_shallow
47 | convect_shallow_diagnostics_after_convective_evaporation
48 | apply_heating_rate
49 | apply_constituent_tendencies
50 | qneg
51 | geopotential_temp
52 |
53 |
54 | check_energy_scaling
55 | check_energy_chng
56 |
57 |
58 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/rayleigh_friction_diagnostics.F90:
--------------------------------------------------------------------------------
1 | module rayleigh_friction_diagnostics
2 |
3 | use ccpp_kinds, only: kind_phys
4 |
5 | implicit none
6 | private
7 | save
8 |
9 | public :: rayleigh_friction_diagnostics_init ! init routine
10 | public :: rayleigh_friction_diagnostics_run ! main routine
11 |
12 | CONTAINS
13 |
14 | !> \section arg_table_rayleigh_friction_diagnostics_init Argument Table
15 | !! \htmlinclude rayleigh_friction_diagnostics_init.html
16 | subroutine rayleigh_friction_diagnostics_init(errmsg, errflg)
17 | use cam_history, only: history_add_field
18 | use cam_history_support, only: horiz_only
19 |
20 | character(len=512), intent(out) :: errmsg
21 | integer, intent(out) :: errflg
22 |
23 | ! Local variables:
24 |
25 | errmsg = ''
26 | errflg = 0
27 |
28 | ! History add field calls
29 | call history_add_field('UTEND_RAYLEIGH', 'Zonal wind tendency due to Rayleigh Friction', 'lev', 'avg', 'm s-2')
30 | call history_add_field('VTEND_RAYLEIGH', 'Meridional wind tendency due to Rayleigh Friction', 'lev', 'avg', 'm s-2')
31 | call history_add_field('STEND_RAYLEIGH', 'Dry air enthalpy tendency due to Rayleigh Friction', 'lev', 'avg', 'J kg-1')
32 |
33 | end subroutine rayleigh_friction_diagnostics_init
34 |
35 | !> \section arg_table_rayleigh_friction_diagnostics_run Argument Table
36 | !! \htmlinclude rayleigh_friction_diagnostics_run.html
37 | subroutine rayleigh_friction_diagnostics_run(dudt, dvdt, dsdt, errmsg, errflg)
38 |
39 | use cam_history, only: history_out_field
40 | !------------------------------------------------
41 | ! Input / output parameters
42 | !------------------------------------------------
43 | ! State variables
44 | real(kind_phys), intent(in) :: dudt(:,:) !tendency_of_eastward_wind due to RF
45 | real(kind_phys), intent(in) :: dvdt(:,:) !tendency_of_northward_wind due to RF
46 | real(kind_phys), intent(in) :: dsdt(:,:) !tendency_of_dry_air_enthalpy_at_constant_pressure due to RF
47 |
48 | ! CCPP error handling variables
49 | character(len=512), intent(out) :: errmsg
50 | integer, intent(out) :: errflg
51 |
52 | errmsg = ''
53 | errflg = 0
54 |
55 | ! History out field calls
56 | call history_out_field('UTEND_RAYLEIGH', dudt)
57 | call history_out_field('VTEND_RAYLEIGH', dvdt)
58 | call history_out_field('STEND_RAYLEIGH', dsdt)
59 |
60 | end subroutine rayleigh_friction_diagnostics_run
61 |
62 | !=======================================================================
63 |
64 | end module rayleigh_friction_diagnostics
65 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/zm_momtran_tendency_diagnostics.F90:
--------------------------------------------------------------------------------
1 | module zm_momtran_tendency_diagnostics
2 | use ccpp_kinds, only: kind_phys
3 |
4 | implicit none
5 | private
6 | save
7 |
8 | public :: zm_momtran_tendency_diagnostics_init ! init routine
9 | public :: zm_momtran_tendency_diagnostics_run ! main routine
10 |
11 | CONTAINS
12 |
13 | !> \section arg_table_zm_momtran_tendency_diagnostics_init Argument Table
14 | !! \htmlinclude zm_momtran_tendency_diagnostics_init.html
15 | subroutine zm_momtran_tendency_diagnostics_init(errmsg, errflg)
16 | use cam_history, only: history_add_field
17 | use cam_history_support, only: horiz_only
18 |
19 | character(len=512), intent(out) :: errmsg
20 | integer, intent(out) :: errflg
21 |
22 | ! Local variables:
23 |
24 | errmsg = ''
25 | errflg = 0
26 |
27 | call history_add_field ('ZMMTT', 'T tendency - ZM convective momentum transport', 'lev', 'avg', 'K s-1')
28 | call history_add_field ('ZMMTU', 'U tendency - ZM convective momentum transport', 'lev', 'avg', 'm s-2')
29 | call history_add_field ('ZMMTV', 'V tendency - ZM convective momentum transport', 'lev', 'avg', 'm s-2')
30 |
31 | end subroutine zm_momtran_tendency_diagnostics_init
32 |
33 | !> \section arg_table_zm_momtran_tendency_diagnostics_run Argument Table
34 | !! \htmlinclude zm_momtran_tendency_diagnostics_run.html
35 | subroutine zm_momtran_tendency_diagnostics_run(ncol, pver, cpair, windu_tend, windv_tend, seten, errmsg, errflg)
36 |
37 | use cam_history, only: history_out_field
38 | !------------------------------------------------
39 | ! Input / output parameters
40 | !------------------------------------------------
41 | integer, intent(in) :: ncol
42 | integer, intent(in) :: pver
43 | real(kind_phys), intent(in) :: cpair
44 | real(kind_phys), intent(in) :: windu_tend(:,:)
45 | real(kind_phys), intent(in) :: windv_tend(:,:)
46 | real(kind_phys), intent(in) :: seten(:,:)
47 |
48 | ! CCPP error handling variables
49 | character(len=512), intent(out) :: errmsg
50 | integer, intent(out) :: errflg
51 |
52 | real(kind_phys) :: ftem(ncol,pver)
53 |
54 | errmsg = ''
55 | errflg = 0
56 |
57 | call history_out_field('ZMMTU', windu_tend)
58 | call history_out_field('ZMMTV', windv_tend)
59 |
60 | ftem(:ncol,:pver) = seten(:ncol,:pver)/cpair
61 | call history_out_field('ZMMTT', ftem)
62 |
63 | end subroutine zm_momtran_tendency_diagnostics_run
64 |
65 | !=======================================================================
66 |
67 | end module zm_momtran_tendency_diagnostics
68 |
--------------------------------------------------------------------------------
/schemes/sima_diagnostics/zm_evap_tendency_diagnostics.meta:
--------------------------------------------------------------------------------
1 | [ccpp-table-properties]
2 | name = zm_evap_tendency_diagnostics
3 | type = scheme
4 |
5 | [ccpp-arg-table]
6 | name = zm_evap_tendency_diagnostics_init
7 | type = scheme
8 | [ errmsg ]
9 | standard_name = ccpp_error_message
10 | long_name = Error message for error handling in CCPP
11 | units = none
12 | type = character | kind = len=512
13 | dimensions = ()
14 | intent = out
15 | [ errflg ]
16 | standard_name = ccpp_error_code
17 | long_name = Error flag for error handling in CCPP
18 | units = 1
19 | type = integer
20 | dimensions = ()
21 | intent = out
22 |
23 | [ccpp-arg-table]
24 | name = zm_evap_tendency_diagnostics_run
25 | type = scheme
26 | [ ncol ]
27 | standard_name = horizontal_loop_extent
28 | units = count
29 | type = integer
30 | dimensions = ()
31 | intent = in
32 | [ pver ]
33 | standard_name = vertical_layer_dimension
34 | units = count
35 | type = integer
36 | dimensions = ()
37 | intent = in
38 | [ cpair ]
39 | standard_name = specific_heat_of_dry_air_at_constant_pressure
40 | units = J kg-1 K-1
41 | type = real | kind = kind_phys
42 | dimensions = ()
43 | intent = in
44 | [ tend_s_snwprd ]
45 | standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_frozen_precipitation_production_due_to_deep_convection
46 | units = J kg-1 s-1
47 | type = real | kind = kind_phys
48 | dimensions = (horizontal_loop_extent,vertical_layer_dimension)
49 | intent = in
50 | [ tend_s_snwevmlt ]
51 | standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_evaporation_and_melting_of_frozen_precipitation_due_to_deep_convection
52 | units = J kg-1 s-1
53 | type = real | kind = kind_phys
54 | dimensions = (horizontal_loop_extent,vertical_layer_dimension)
55 | intent = in
56 | [ qtnd ]
57 | standard_name = tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water
58 | units = kg kg-1 s-1
59 | type = real | kind = kind_phys
60 | dimensions = (horizontal_loop_extent,vertical_layer_dimension)
61 | intent = in
62 | [ heat ]
63 | standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure
64 | units = J kg-1 s-1
65 | type = real | kind = kind_phys
66 | dimensions = (horizontal_loop_extent,vertical_layer_dimension)
67 | intent = in
68 | [ errmsg ]
69 | standard_name = ccpp_error_message
70 | long_name = Error message for error handling in CCPP
71 | units = none
72 | type = character | kind = len=512
73 | dimensions = ()
74 | intent = out
75 | [ errflg ]
76 | standard_name = ccpp_error_code
77 | long_name = Error flag for error handling in CCPP
78 | units = 1
79 | type = integer
80 | dimensions = ()
81 | intent = out
82 |
--------------------------------------------------------------------------------
/schemes/zhang_mcfarlane/save_ttend_from_convect_deep.F90:
--------------------------------------------------------------------------------
1 | ! Save temperature tendency from deep convection
2 | ! for use by gravity wave parameterization
3 | !
4 | ! This scheme has to be run after all deep convective schemes,
5 | ! before the final tendencies are applied.
6 | ! Since ZM applies tendencies in each sub-scheme, this scheme has
7 | ! to run repeatedly to archive all tendencies from ZM.
8 | module save_ttend_from_convect_deep
9 | use ccpp_kinds, only: kind_phys
10 |
11 | implicit none
12 | private
13 |
14 | public :: save_ttend_from_convect_deep_timestep_init
15 | public :: save_ttend_from_convect_deep_run
16 |
17 | contains
18 |
19 | !> \section arg_table_save_ttend_from_convect_deep_timestep_init Argument Table
20 | !! \htmlinclude save_ttend_from_convect_deep_timestep_init.html
21 | subroutine save_ttend_from_convect_deep_timestep_init(ncol, pver, ttend_dp, errmsg, errflg)
22 | integer, intent(in) :: ncol
23 | integer, intent(in) :: pver
24 |
25 | real(kind_phys), intent(out) :: ttend_dp(:, :) ! Temperature tendency from deep convection [K s-1]
26 | character(len=512), intent(out) :: errmsg
27 | integer, intent(out) :: errflg
28 |
29 | errmsg = ''
30 | errflg = 0
31 |
32 | ttend_dp(:,:) = 0._kind_phys
33 |
34 | end subroutine save_ttend_from_convect_deep_timestep_init
35 |
36 | !> \section arg_table_save_ttend_from_convect_deep_run Argument Table
37 | !! \htmlinclude save_ttend_from_convect_deep_run.html
38 | subroutine save_ttend_from_convect_deep_run( &
39 | ncol, pver, &
40 | tend_s, cpair, &
41 | ttend_dp, &
42 | errmsg, errflg)
43 |
44 | ! Input arguments
45 | integer, intent(in) :: ncol
46 | integer, intent(in) :: pver
47 | real(kind_phys), intent(in) :: tend_s(:, :) ! Enthalpy tendency from deep convection [J kg-1 s-1]
48 | real(kind_phys), intent(in) :: cpair ! Specific heat of dry air at constant pressure [J kg-1 K-1]
49 |
50 | ! Input/output arguments
51 | real(kind_phys), intent(inout) :: ttend_dp(:, :) ! Temperature tendency from deep convection [K s-1] (accummulated)
52 |
53 | ! Output arguments
54 | character(len=512), intent(out) :: errmsg
55 | integer, intent(out) :: errflg
56 |
57 | ! Local variables
58 | integer :: i, k
59 |
60 | errmsg = ''
61 | errflg = 0
62 |
63 | ! Convert to temperature tendency
64 | do k = 1, pver
65 | do i = 1, ncol
66 | ttend_dp(i, k) = ttend_dp(i, k) + tend_s(i, k) / cpair
67 | end do
68 | end do
69 |
70 | end subroutine save_ttend_from_convect_deep_run
71 |
72 | end module save_ttend_from_convect_deep
73 |
--------------------------------------------------------------------------------
/test/musica/tuvx/test_tuvx_surface_albedo.F90:
--------------------------------------------------------------------------------
1 | ! Copyright (C) 2024-2025 University Corporation for Atmospheric Research
2 | ! SPDX-License-Identifier: Apache-2.0
3 | program test_tuvx_surface_albedo
4 |
5 | use musica_ccpp_tuvx_surface_albedo
6 |
7 | implicit none
8 |
9 | #define ASSERT(x) if (.not.(x)) then; write(*,*) "Assertion failed[", __FILE__, ":", __LINE__, "]: x"; stop 1; endif
10 | #define ASSERT_NEAR( a, b, abs_error ) if( (abs(a - b) >= abs_error) .and. (abs(a - b) /= 0.0) ) then; write(*,*) "Assertion failed[", __FILE__, ":", __LINE__, "]: a, b"; stop 1; endif
11 |
12 | call test_update_surface_albedo()
13 |
14 | contains
15 |
16 | subroutine test_update_surface_albedo()
17 | use musica_ccpp_tuvx_wavelength_grid, only: create_wavelength_grid
18 | use musica_util, only: error_t
19 | use musica_tuvx_grid, only: grid_t
20 | use musica_tuvx_profile, only: profile_t
21 | use ccpp_kinds, only: kind_phys
22 |
23 | integer, parameter :: NUM_WAVELENGTH_BINS = 4
24 | real, parameter :: ABS_ERROR = 1e-6
25 | real(kind_phys) :: wavelength_grid_interfaces(NUM_WAVELENGTH_BINS + 1) = &
26 | [200.0e-9_kind_phys, 210.0e-9_kind_phys, 240.0e-9_kind_phys, 300.0e-9_kind_phys, 400.0e-9_kind_phys]
27 | real(kind_phys) :: host_surface_albedo = 0.3_kind_phys
28 | real(kind_phys) :: expected_surface_albedo_interfaces(NUM_WAVELENGTH_BINS + 1) = 0.3_kind_phys
29 | real(kind_phys) :: surface_albedo_interfaces(NUM_WAVELENGTH_BINS + 1)
30 | type(grid_t), pointer :: wavelength_grid
31 | type(profile_t), pointer :: profile
32 | type(error_t) :: error
33 | character(len=512) :: errmsg
34 | integer :: errcode
35 | integer :: i
36 |
37 | wavelength_grid => create_wavelength_grid(wavelength_grid_interfaces, errmsg, errcode)
38 | ASSERT(errcode == 0)
39 | ASSERT(associated(wavelength_grid))
40 |
41 | profile => create_surface_albedo_profile( wavelength_grid, errmsg, errcode )
42 | ASSERT(errcode == 0)
43 | ASSERT(associated(profile))
44 |
45 | call set_surface_albedo_values( profile, host_surface_albedo, errmsg, errcode )
46 | ASSERT(errcode == 0)
47 |
48 | call profile%get_edge_values( surface_albedo_interfaces, error)
49 | ASSERT(error%is_success())
50 | do i = 1, size(surface_albedo_interfaces)
51 | ASSERT_NEAR(surface_albedo_interfaces(i), expected_surface_albedo_interfaces(i), ABS_ERROR)
52 | end do
53 |
54 | deallocate( profile )
55 | deallocate( wavelength_grid )
56 |
57 | end subroutine test_update_surface_albedo
58 |
59 | end program test_tuvx_surface_albedo
--------------------------------------------------------------------------------
/test/valgrind.supp:
--------------------------------------------------------------------------------
1 | ##############################################################
2 | #
3 | # MUSICA TUV-x suppressions
4 | #
5 | # TODO(jiwon) We are experiencing memory leak issues in certain
6 | # functions of TUV-x. It appears that these leaks occur only
7 | # occasionally during initialization. We believe it’s acceptable
8 | # to add a Valgrind suppression for now, and we will investigate
9 | # further if it becomes a significant concern.
10 | #
11 | ##############################################################
12 | {
13 | Suppress_MUSICA_TUV-x_Leak1
14 | Memcheck:Leak
15 | fun:malloc
16 | fun:__musica_config_MOD_get_string
17 | fun:__tuvx_radiator_aerosol_MOD_constructor
18 | fun:__tuvx_radiator_factory_MOD_radiator_builder
19 | fun:__tuvx_radiator_warehouse_MOD_constructor
20 | fun:__tuvx_radiative_transfer_MOD_constructor
21 | fun:__tuvx_core_MOD_constructor
22 | fun:InternalCreateTuvx
23 | ...
24 | }
25 | {
26 | Suppress_MUSICA_TUV-x_Leak2
27 | Memcheck:Leak
28 | fun:malloc
29 | fun:__musica_config_MOD_get_string
30 | fun:__tuvx_radiator_MOD_base_constructor
31 | fun:__tuvx_radiator_MOD_constructor
32 | fun:__tuvx_radiator_factory_MOD_radiator_builder
33 | fun:__tuvx_radiator_warehouse_MOD_constructor
34 | fun:__tuvx_radiative_transfer_MOD_constructor
35 | fun:__tuvx_core_MOD_constructor
36 | fun:InternalCreateTuvx
37 | ...
38 | }
39 | {
40 | Suppress_MUSICA_TUV-x_CreateRadiator
41 | Memcheck:Leak
42 | match-leak-kinds: definite
43 | fun:malloc
44 | fun:__musica_string_MOD_string_assign_char
45 | fun:__tuvx_radiator_from_host_MOD_constructor_char
46 | fun:__tuvx_radiator_from_host_MOD_constructor_string
47 | fun:InternalCreateRadiator
48 | ...
49 | }
50 | {
51 | Suppress_MUSICA_TUV-x_AddRadiator
52 | Memcheck:Leak
53 | match-leak-kinds: definite
54 | fun:malloc
55 | fun:__tuvx_radiator_from_host_MOD___copy_tuvx_radiator_from_host_Radiator_from_host_t
56 | fun:__tuvx_radiator_warehouse_MOD_add_radiator
57 | fun:InternalAddRadiator
58 | ...
59 | }
60 | {
61 | Suppress_MUSICA_TUV-x_GetRadiator
62 | Memcheck:Leak
63 | match-leak-kinds: definite
64 | fun:malloc
65 | fun:__tuvx_radiator_from_host_MOD___copy_tuvx_radiator_from_host_Radiator_from_host_t
66 | fun:InternalGetRadiator
67 | ...
68 | }
69 | {
70 | Suppress_MUSICA_TUV-x_CreateTuvx-RadiatorFromHost
71 | Memcheck:Leak
72 | match-leak-kinds: definite
73 | fun:malloc
74 | fun:__tuvx_radiator_from_host_MOD___copy_tuvx_radiator_from_host_Radiator_from_host_t
75 | fun:__tuvx_radiator_warehouse_MOD_add_radiator
76 | fun:__tuvx_radiator_warehouse_MOD_add_radiators
77 | fun:__tuvx_radiative_transfer_MOD_constructor
78 | fun:__tuvx_core_MOD_constructor
79 | fun:InternalCreateTuvx
80 | ...
81 | }
--------------------------------------------------------------------------------
/test/test_suites/suite_gw_cam7_se.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
24 |
25 |
26 | initialize_constituents
27 |
28 |
29 | gravity_wave_drag_common
30 |
31 |
32 | check_energy_zero_fluxes
33 | gravity_wave_drag_prepare_profiles
34 |
35 |
36 | gravity_wave_drag_top_taper
37 |
38 |
39 | gravity_wave_drag_moving_mountain
40 |
41 |
42 | gravity_wave_drag_convection_deep
43 |
44 |
45 | gravity_wave_drag_frontogenesis
46 |
47 |
48 | gravity_wave_drag_ridge
49 | gravity_wave_drag_ridge_beta
50 |
51 |
52 | convert_dry_constituent_tendencies_to_dry_air_basis
53 |
54 |
55 | gravity_wave_drag_common_diagnostics
56 |
57 |
58 | apply_tendency_of_eastward_wind
59 | apply_tendency_of_northward_wind
60 | apply_constituent_tendencies
61 | apply_heating_rate
62 | qneg
63 | geopotential_temp
64 | update_dry_static_energy
65 |
66 |
67 |
--------------------------------------------------------------------------------
/test/docker/Dockerfile.musica.no_install:
--------------------------------------------------------------------------------
1 | # This Dockerfile is designed for testing MUSICA CCPP functionality.
2 | # It includes:
3 | # - Unit tests for MUSICA utility functions
4 | # - Integration tests for MUSICA CCPP APIs
5 | #
6 | # No MUSICA library installation is required, as the CMake FetchContent module
7 | # retrieves the MUSICA library automatically.
8 |
9 | FROM ubuntu:22.04
10 |
11 | ARG MUSICA_GIT_TAG=25fff7ae42d146bf3f83ad5ac18b3caac8701ddd
12 | ARG CAM_SIMA_CHEMISTRY_DATA_TAG=1ea9d1b8b04980738894d30a864f9a000daf2e5c
13 | ARG USE_INSTALLED_MUSICA_LIB=OFF
14 | ARG BUILD_TYPE=Release
15 |
16 | RUN apt update \
17 | && apt install -y sudo \
18 | && useradd -m test_user \
19 | && echo "test_user ALL=(root) NOPASSWD: ALL" >> /etc/sudoers.d/test_user \
20 | && chmod 0440 /etc/sudoers.d/test_user
21 |
22 | USER test_user
23 | WORKDIR /home/test_user
24 |
25 | RUN sudo apt update \
26 | && sudo apt -y install \
27 | cmake \
28 | cmake-curses-gui \
29 | curl \
30 | g++ \
31 | gcc \
32 | gfortran \
33 | git \
34 | libblas-dev \
35 | liblapack-dev \
36 | lcov \
37 | libcurl4-openssl-dev \
38 | libhdf5-dev \
39 | libnetcdff-dev \
40 | libopenmpi-dev \
41 | m4 \
42 | make \
43 | openmpi-bin \
44 | python3 \
45 | tree \
46 | valgrind \
47 | vim \
48 | zlib1g-dev \
49 | && sudo apt clean
50 |
51 | ENV FC=mpif90
52 | ENV FFLAGS="-I/usr/include/"
53 |
54 | COPY . atmospheric_physics
55 | RUN sudo chown -R test_user:test_user atmospheric_physics
56 |
57 | # Clone the MUSICA chemistry data set repository
58 | RUN git clone https://github.com/NCAR/cam-sima-chemistry-data.git \
59 | && cd cam-sima-chemistry-data \
60 | && git checkout ${CAM_SIMA_CHEMISTRY_DATA_TAG}
61 |
62 | # Make ccpp-framework available before building test
63 | RUN cd atmospheric_physics/test \
64 | && mkdir lib \
65 | && cd lib \
66 | && git clone -b develop --depth 1 https://github.com/NCAR/ccpp-framework.git
67 | ENV CCPP_SRC_PATH="lib/ccpp-framework/src"
68 | ENV CCPP_FORTRAN_TOOLS_PATH="lib/ccpp-framework/scripts/fortran_tools"
69 |
70 | # Make the ESMStandardNames available
71 | RUN cd atmospheric_physics/test/lib \
72 | && git clone --depth 1 https://github.com/ESCOMP/ESMStandardNames.git
73 | ENV CCPP_STD_NAMES_PATH="lib/ESMStandardNames"
74 |
75 | RUN cd atmospheric_physics/test \
76 | && cmake -S . -B build \
77 | -D CMAKE_BUILD_TYPE=${BUILD_TYPE} \
78 | -D CCPP_ENABLE_MUSICA_TESTS=ON \
79 | -D CCPP_ENABLE_MEMCHECK=ON \
80 | && cmake --build ./build
81 |
82 | # Move the MUSICA configuration to the build root to make the data available for testing
83 | RUN mv /home/test_user/cam-sima-chemistry-data/mechanisms /home/test_user/atmospheric_physics/test/build/musica_configurations
84 |
85 | WORKDIR /home/test_user/atmospheric_physics/test/build
86 |
--------------------------------------------------------------------------------
/test/musica/tuvx/test_tuvx_temperature.F90:
--------------------------------------------------------------------------------
1 | ! Copyright (C) 2024-2025 University Corporation for Atmospheric Research
2 | ! SPDX-License-Identifier: Apache-2.0
3 | program test_tuvx_temperature
4 |
5 | use musica_ccpp_tuvx_temperature
6 |
7 | implicit none
8 |
9 | #define ASSERT(x) if (.not.(x)) then; write(*,*) "Assertion failed[", __FILE__, ":", __LINE__, "]: x"; stop 1; endif
10 | #define ASSERT_NEAR( a, b, abs_error ) if( (abs(a - b) >= abs_error) .and. (abs(a - b) /= 0.0) ) then; write(*,*) "Assertion failed[", __FILE__, ":", __LINE__, "]: a, b"; stop 1; endif
11 |
12 | call test_update_temperature()
13 |
14 | contains
15 |
16 | subroutine test_update_temperature()
17 | use musica_ccpp_tuvx_height_grid, only: create_height_grid
18 | use musica_util, only: error_t
19 | use musica_tuvx_grid, only: grid_t
20 | use musica_tuvx_profile, only: profile_t
21 | use ccpp_kinds, only: kind_phys
22 |
23 | integer, parameter :: NUM_HOST_MIDPOINTS = 5
24 | integer, parameter :: NUM_HOST_INTERFACES = 6
25 | real, parameter :: ABS_ERROR = 1e-4
26 | real(kind_phys) :: host_midpoint_temperature(NUM_HOST_MIDPOINTS) = &
27 | [800.8_kind_phys, 700.7_kind_phys, 600.6_kind_phys, 500.5_kind_phys, 400.4_kind_phys]
28 | real(kind_phys) :: host_surface_temperature = 300.3_kind_phys
29 | real(kind_phys) :: expected_temperature_interfaces(NUM_HOST_MIDPOINTS+2) = &
30 | [300.3_kind_phys, 400.4_kind_phys, 500.5_kind_phys, 600.6_kind_phys, 700.7_kind_phys, 800.8_kind_phys, 800.8_kind_phys]
31 | real(kind_phys) :: temperature_interfaces(NUM_HOST_MIDPOINTS+2)
32 | type(grid_t), pointer :: height_grid
33 | type(profile_t), pointer :: profile
34 | character(len=512) :: errmsg
35 | integer :: errcode
36 | type(error_t) :: error
37 | integer :: i
38 |
39 | height_grid => create_height_grid(NUM_HOST_MIDPOINTS, NUM_HOST_INTERFACES, errmsg, errcode)
40 | ASSERT(errcode == 0)
41 | ASSERT(associated(height_grid))
42 |
43 | profile => create_temperature_profile( height_grid, errmsg, errcode )
44 | ASSERT(errcode == 0)
45 | ASSERT(associated(profile))
46 |
47 | call set_temperature_values( profile, host_midpoint_temperature, &
48 | host_surface_temperature, errmsg, errcode )
49 | ASSERT(errcode == 0)
50 |
51 | call profile%get_edge_values( temperature_interfaces, error)
52 | ASSERT(error%is_success())
53 | do i = 1, size(temperature_interfaces)
54 | ASSERT_NEAR(temperature_interfaces(i), expected_temperature_interfaces(i), ABS_ERROR)
55 | end do
56 |
57 | deallocate( profile )
58 | deallocate( height_grid )
59 |
60 | end subroutine test_update_temperature
61 |
62 | end program test_tuvx_temperature
--------------------------------------------------------------------------------
/schemes/gravity_wave_drag/gravity_wave_drag_top_taper.F90:
--------------------------------------------------------------------------------
1 | module gravity_wave_drag_top_taper
2 | use ccpp_kinds, only: kind_phys
3 |
4 | implicit none
5 | private
6 |
7 | public :: gravity_wave_drag_top_taper_init
8 |
9 | contains
10 |
11 | ! Creates vertical ramp coefficients to taper gravity wave drag
12 | ! at the top levels of the model
13 | !> \section arg_table_gravity_wave_drag_top_taper_init Argument Table
14 | !! \htmlinclude gravity_wave_drag_top_taper_init.html
15 | subroutine gravity_wave_drag_top_taper_init( &
16 | pver, &
17 | amIRoot, iulog, &
18 | gw_top_taper, &
19 | nbot_gravity_wave_top_taper, &
20 | pref_edge, pref_mid, &
21 | vramp, &
22 | errmsg, errflg)
23 |
24 | ! Input arguments
25 | integer, intent(in) :: pver
26 | logical, intent(in) :: amIRoot
27 | integer, intent(in) :: iulog
28 |
29 | logical, intent(in) :: gw_top_taper ! Apply gravity wave top tapering [flag]
30 | integer, intent(in) :: nbot_gravity_wave_top_taper ! Bottom level to taper gravity waves at top of model [index]
31 | real(kind_phys), intent(in) :: pref_edge(:) ! Reference pressure at layer interfaces [Pa]
32 | real(kind_phys), intent(in) :: pref_mid(:) ! Reference pressure at layer midpoints [Pa]
33 |
34 | ! Output arguments
35 | real(kind_phys), intent(out) :: vramp(:) ! Gravity wave drag tapering coefficients [1]
36 |
37 | character(len=512), intent(out) :: errmsg
38 | integer, intent(out) :: errflg
39 |
40 | integer :: k ! Vertical level index
41 | integer :: topndx ! Top level index for tapering [index]
42 | integer :: botndx ! Bottom level index for tapering [index]
43 |
44 | errmsg = ''
45 | errflg = 0
46 |
47 | ! Initialize vramp to unity (no tapering by default)
48 | vramp(:pver) = 1._kind_phys
49 |
50 | if (gw_top_taper) then
51 | topndx = 1
52 | botndx = nbot_gravity_wave_top_taper
53 |
54 | if (botndx > 1) then
55 | ! Compute tapering coefficients from bottom index to top
56 | do k = botndx, topndx, -1
57 | vramp(k) = vramp(k + 1) / (pref_edge(k + 1) / pref_edge(k))
58 | end do
59 |
60 | if (amIRoot) then
61 | write(iulog, '(A)') 'gravity_wave_drag_top_taper_init: GW taper coef (vramp):'
62 | do k = 1, pver
63 | write(iulog, "('k: ',I4,' taper coef, press(Pa): ',F12.8,E12.4)") k, vramp(k), pref_mid(k)
64 | end do
65 | end if
66 | end if
67 | end if
68 | end subroutine gravity_wave_drag_top_taper_init
69 |
70 | end module gravity_wave_drag_top_taper
71 |
--------------------------------------------------------------------------------
/schemes/gravity_wave_drag/gw_utils.F90:
--------------------------------------------------------------------------------
1 | ! This module contains utility code for the gravity wave modules.
2 | module gw_utils
3 | use ccpp_kinds, only: kind_phys
4 |
5 | implicit none
6 | private
7 |
8 | public :: get_unit_vector
9 | public :: dot_2d
10 | public :: midpoint_interp
11 | public :: index_of_nearest
12 |
13 | contains
14 |
15 | ! Take two components of a vector, and find the unit vector components and
16 | ! total magnitude.
17 | subroutine get_unit_vector(u, v, u_n, v_n, mag)
18 | real(kind_phys), intent(in) :: u(:)
19 | real(kind_phys), intent(in) :: v(:)
20 | real(kind_phys), intent(out) :: u_n(:)
21 | real(kind_phys), intent(out) :: v_n(:)
22 | real(kind_phys), intent(out) :: mag(:)
23 |
24 | integer :: i
25 |
26 | mag = sqrt(u*u + v*v)
27 |
28 | ! Has to be a loop/if instead of a where, because floating point
29 | ! exceptions can trigger even on a masked divide-by-zero operation
30 | ! (especially on Intel).
31 | do i = 1, size(mag)
32 | if (mag(i) > 0._kind_phys) then
33 | u_n(i) = u(i)/mag(i)
34 | v_n(i) = v(i)/mag(i)
35 | else
36 | u_n(i) = 0._kind_phys
37 | v_n(i) = 0._kind_phys
38 | end if
39 | end do
40 |
41 | end subroutine get_unit_vector
42 |
43 | ! Vectorized version of a 2D dot product (since the intrinsic dot_product
44 | ! is more suitable for arrays of contiguous vectors).
45 | function dot_2d(u1, v1, u2, v2)
46 | real(kind_phys), intent(in) :: u1(:), v1(:)
47 | real(kind_phys), intent(in) :: u2(:), v2(:)
48 |
49 | real(kind_phys) :: dot_2d(size(u1))
50 |
51 | dot_2d = u1*u2 + v1*v2
52 |
53 | end function dot_2d
54 |
55 | ! Pure function that interpolates the values of the input array along
56 | ! dimension 2. This is obviously not a very generic routine, unlike, say,
57 | ! CAM's lininterp. But it's used often enough that it seems worth providing
58 | ! here.
59 | pure function midpoint_interp(arr) result(interp)
60 | real(kind_phys), intent(in) :: arr(:, :)
61 | real(kind_phys) :: interp(size(arr, 1), size(arr, 2) - 1)
62 |
63 | integer :: i
64 |
65 | do i = 1, size(interp, 2)
66 | interp(:, i) = 0.5_kind_phys*(arr(:, i) + arr(:, i + 1))
67 | end do
68 |
69 | end function midpoint_interp
70 |
71 | ! Short routine to get the indices of a set of values rounded to their
72 | ! nearest points on a grid.
73 | pure function index_of_nearest(x, grid) result(idx)
74 | real(kind_phys), intent(in) :: x(:)
75 | real(kind_phys), intent(in) :: grid(:)
76 |
77 | integer :: idx(size(x))
78 |
79 | real(kind_phys) :: interfaces(size(grid) - 1)
80 | integer :: i, n
81 |
82 | n = size(grid)
83 | interfaces = (grid(:n - 1) + grid(2:))/2._kind_phys
84 |
85 | idx = 1
86 | do i = 1, n - 1
87 | where (x > interfaces(i)) idx = i + 1
88 | end do
89 |
90 | end function index_of_nearest
91 |
92 | end module gw_utils
93 |
--------------------------------------------------------------------------------
/schemes/rrtmgp/utils/rrtmgp_dry_static_energy_tendency.F90:
--------------------------------------------------------------------------------
1 | module rrtmgp_dry_static_energy_tendency
2 | !-----------------------------------------------------------------------
3 | !
4 | ! Purpose: Provide an interface to convert shortwave and longwave
5 | ! radiative heating terms into net heating.
6 | !
7 | ! This module provides a hook to allow incorporating additional
8 | ! radiative terms (eUV heating and nonLTE longwave cooling).
9 | !
10 | ! Original version: B.A. Boville
11 | !-----------------------------------------------------------------------
12 |
13 | implicit none
14 | private
15 |
16 | ! Public interfaces
17 | public :: rrtmgp_dry_static_energy_tendency_run
18 |
19 | !===============================================================================
20 | contains
21 | !===============================================================================
22 |
23 | !> \section arg_table_rrtmgp_dry_static_energy_tendency_run Argument Table
24 | !! \htmlinclude rrtmgp_dry_static_energy_tendency_run.html
25 | !!
26 | subroutine rrtmgp_dry_static_energy_tendency_run(pdel, calc_sw_heat, calc_lw_heat, &
27 | qrs, qrl, qrs_prime, qrl_prime, errmsg, errflg)
28 | !-----------------------------------------------------------------------
29 | ! Compute net radiative heating from qrs and qrl, and the associated net
30 | ! boundary flux.
31 | !-----------------------------------------------------------------------
32 | use ccpp_kinds, only: kind_phys
33 |
34 | ! Arguments
35 | real(kind_phys), dimension(:,:), intent(in) :: pdel ! Layer thickness
36 | logical, intent(in) :: calc_sw_heat ! Flag to calculate net shortwave heating
37 | logical, intent(in) :: calc_lw_heat ! Flag to calculate net longwave heating
38 | real(kind_phys), dimension(:,:), intent(in) :: qrs ! shortwave heating rate adjusted by air pressure thickness (J Pa kg-1 s-1)
39 | real(kind_phys), dimension(:,:), intent(in) :: qrl ! longwave heating rate adjusted by air pressure thickness (J Pa kg-1 s-1)
40 | real(kind_phys), dimension(:,:), intent(out) :: qrs_prime ! shortwave heating rate (J kg-1 s-1)
41 | real(kind_phys), dimension(:,:), intent(out) :: qrl_prime ! longwave heating rate (J kg-1 s-1)
42 | character(len=*), intent(out) :: errmsg
43 | integer, intent(out) :: errflg
44 |
45 |
46 | !-----------------------------------------------------------------------
47 | ! Set error variables
48 | errmsg = ''
49 | errflg = 0
50 |
51 | if (calc_sw_heat) then
52 | qrs_prime(:,:) = qrs(:,:) / pdel(:,:)
53 | end if
54 |
55 | if (calc_lw_heat) then
56 | qrl_prime(:,:) = qrl(:,:) / pdel(:,:)
57 | end if
58 |
59 | end subroutine rrtmgp_dry_static_energy_tendency_run
60 |
61 | !================================================================================================
62 | end module rrtmgp_dry_static_energy_tendency
63 |
--------------------------------------------------------------------------------
/to_be_ccppized/ccpp_tuvx_utils.F90:
--------------------------------------------------------------------------------
1 | ! Copyright (C) 2024-2025 University Corporation for Atmospheric Research
2 | ! SPDX-License-Identifier: Apache-2.0
3 | module ccpp_tuvx_utils
4 |
5 | implicit none
6 |
7 | private
8 | public :: rebin, read_extraterrestrial_flux
9 |
10 | contains
11 |
12 | !> Regrids normalized flux data to match a specified wavelength grid
13 | ! This function is copied from CAM/src/chemistry/utils/mo_util.F90
14 | subroutine rebin( source_dimension, target_dimension, source_coordinates, &
15 | target_coordinates, source, target )
16 | use ccpp_kinds, only: kind_phys
17 |
18 | integer, intent(in) :: source_dimension
19 | integer, intent(in) :: target_dimension
20 | real(kind_phys), intent(in) :: source_coordinates(source_dimension+1)
21 | real(kind_phys), intent(in) :: target_coordinates(target_dimension+1)
22 | real(kind_phys), intent(in) :: source(source_dimension)
23 | real(kind_phys), intent(out) :: target(target_dimension)
24 |
25 | ! local variables
26 | integer :: i, si, si1, sil, siu
27 | real(kind_phys) :: y, sl, su, tl, tu
28 |
29 | do i = 1, target_dimension
30 | tl = target_coordinates(i)
31 | if( tl < source_coordinates( source_dimension + 1) ) then
32 | do sil = 1, source_dimension + 1
33 | if( tl <= source_coordinates( sil ) ) then
34 | exit
35 | end if
36 | end do
37 | tu = target_coordinates( i + 1 )
38 | do siu = 1, source_dimension + 1
39 | if( tu <= source_coordinates( siu ) ) then
40 | exit
41 | end if
42 | end do
43 | y = 0._kind_phys
44 | sil = max( sil, 2 )
45 | siu = min( siu, source_dimension + 1 )
46 | do si = sil, siu
47 | si1 = si - 1
48 | sl = max( tl, source_coordinates( si1 ) )
49 | su = min( tu, source_coordinates( si ) )
50 | y = y + ( su - sl ) * source( si1 )
51 | end do
52 | target(i) = y / (target_coordinates( i + 1 ) - target_coordinates( i ) )
53 | else
54 | target(i) = 0._kind_phys
55 | end if
56 | end do
57 |
58 | end subroutine rebin
59 |
60 | !> Reads a data file to retrieve the extraterrestrial radiation flux values.
61 | ! This function is a temporary implementation and will be replaced in
62 | ! future versions of the code.
63 | subroutine read_extraterrestrial_flux()
64 | character(len=50), dimension(4) :: filepath_of_extraterrestrial_flux
65 |
66 | filepath_of_extraterrestrial_flux(1) = 'musica_configurations/chapman/tuvx/data/profiles/solar/susim_hi.flx'
67 | filepath_of_extraterrestrial_flux(2) = 'musica_configurations/chapman/tuvx/data/profiles/solar/atlas3_1994_317_a.dat'
68 | filepath_of_extraterrestrial_flux(3) = 'musica_configurations/chapman/tuvx/data/profiles/solar/sao2010.solref.converted'
69 | filepath_of_extraterrestrial_flux(4) = 'musica_configurations/chapman/tuvx/data/profiles/solar/neckel.flx'
70 |
71 | end subroutine read_extraterrestrial_flux
72 |
73 | end module ccpp_tuvx_utils
--------------------------------------------------------------------------------
/schemes/musica/tuvx/musica_ccpp_tuvx_temperature.F90:
--------------------------------------------------------------------------------
1 | ! Copyright (C) 2024-2025 University Corporation for Atmospheric Research
2 | ! SPDX-License-Identifier: Apache-2.0
3 | module musica_ccpp_tuvx_temperature
4 | implicit none
5 |
6 | private
7 | public :: create_temperature_profile, set_temperature_values
8 |
9 | !> Label for temperature in TUV-x
10 | character(len=*), parameter, public :: temperature_label = "temperature"
11 | !> Unit for temperature in TUV-x
12 | character(len=*), parameter, public :: temperature_unit = "K"
13 |
14 | contains
15 |
16 | !> Creates a TUV-x temperature profile
17 | function create_temperature_profile(height_grid, errmsg, errcode) &
18 | result(profile)
19 | use musica_ccpp_util, only: has_error_occurred
20 | use musica_tuvx_grid, only: grid_t
21 | use musica_tuvx_profile, only: profile_t
22 | use musica_util, only: error_t
23 |
24 | type(grid_t), intent(in) :: height_grid
25 | character(len=*), intent(out) :: errmsg
26 | integer, intent(out) :: errcode
27 | type(profile_t), pointer :: profile
28 |
29 | ! local variables
30 | type(error_t) :: error
31 |
32 | profile => profile_t( temperature_label, temperature_unit, &
33 | height_grid, error )
34 | if ( has_error_occurred( error, errmsg, errcode ) ) return
35 |
36 | end function create_temperature_profile
37 |
38 | !> Sets TUV-x temperature values from host-model temperatures
39 | !!
40 | !! See description of `musica_ccpp_tuvx_height_grid.F90` for
41 | !! CAM-SIMA <-> TUV-x height grid mapping
42 | subroutine set_temperature_values(profile, host_midpoint_temperatures, &
43 | host_surface_temperature, errmsg, errcode)
44 | use musica_ccpp_util, only: has_error_occurred
45 | use musica_tuvx_profile, only: profile_t
46 | use musica_util, only: error_t
47 | use ccpp_kinds, only: kind_phys
48 |
49 | type(profile_t), intent(inout) :: profile
50 | real(kind_phys), intent(in) :: host_midpoint_temperatures(:) ! K
51 | real(kind_phys), intent(in) :: host_surface_temperature ! K
52 | character(len=*), intent(out) :: errmsg
53 | integer, intent(out) :: errcode
54 |
55 | ! local variables
56 | type(error_t) :: error
57 | real(kind_phys) :: interfaces(size(host_midpoint_temperatures)+2)
58 | integer :: n_host_midpoint_temperatures
59 |
60 | n_host_midpoint_temperatures = size(host_midpoint_temperatures)
61 |
62 | interfaces(1) = host_surface_temperature
63 | interfaces(2:n_host_midpoint_temperatures+1) = host_midpoint_temperatures(n_host_midpoint_temperatures:1:-1)
64 | interfaces(n_host_midpoint_temperatures+2) = host_midpoint_temperatures(1)
65 |
66 | call profile%set_edge_values( interfaces, error )
67 | if ( has_error_occurred( error, errmsg, errcode ) ) return
68 |
69 | end subroutine set_temperature_values
70 |
71 | end module musica_ccpp_tuvx_temperature
--------------------------------------------------------------------------------