diff --git a/src/core_atmosphere/Makefile b/src/core_atmosphere/Makefile index 966027bc77..48a1262273 100644 --- a/src/core_atmosphere/Makefile +++ b/src/core_atmosphere/Makefile @@ -2,12 +2,13 @@ # # To build a dycore-only MPAS-Atmosphere model, comment-out or delete -# the definition of PHYSICS, below +# the definition of PHYSICS and CHEMISTRY, below # -# If MPAS_CAM_DYCORE is found in CPPFLAGS, PHYSICS will become undefined automatically +# If MPAS_CAM_DYCORE is found in CPPFLAGS, PHYSICS and CHEMISTRY will become undefined automatically # ifeq ($(findstring MPAS_CAM_DYCORE,$(CPPFLAGS)),) PHYSICS = -DDO_PHYSICS + CHEMISTRY = -DDO_CHEMISTRY endif ifdef PHYSICS @@ -15,16 +16,21 @@ ifdef PHYSICS PHYS_OBJS = libphys/*.o endif +ifdef CHEMISTRY + CHEMCORE = chemcore + CHEM_OBJS = libchem/*.o +endif + OBJS = mpas_atm_core.o \ mpas_atm_core_interface.o \ mpas_atm_dimensions.o \ mpas_atm_threading.o \ mpas_atm_halos.o -all: $(PHYSCORE) dycore diagcore atmcore utilities +all: $(PHYSCORE) $(CHEMCORE) dycore diagcore atmcore utilities core_reg: - $(CPP) $(CPPFLAGS) $(CPPINCLUDES) $(PHYSICS) Registry.xml > Registry_processed.xml + $(CPP) $(CPPFLAGS) $(CPPINCLUDES) $(PHYSICS) $(CHEMISTRY) Registry.xml > Registry_processed.xml core_input_gen: if [ ! -e default_inputs ]; then mkdir default_inputs; fi @@ -47,17 +53,21 @@ physcore: mpas_atm_dimensions.o ( cd ../..; ln -sf ./src/core_atmosphere/physics/physics_wrf/files/*DATA* .) ( cd ../..; ln -sf ./src/core_atmosphere/physics/physics_noahmp/parameters/*TBL .) -dycore: mpas_atm_dimensions.o $(PHYSCORE) - ( cd dynamics; $(MAKE) all PHYSICS="$(PHYSICS)" ) +chemcore: mpas_atm_dimensions.o + ( cd chemistry; $(MAKE) all ) + ( mkdir libchem; cd libchem; ar -x ../chemistry/libchem.a ) + +dycore: mpas_atm_dimensions.o $(PHYSCORE) $(CHEMCORE) + ( cd dynamics; $(MAKE) all PHYSICS="$(PHYSICS)"; $(MAKE) all CHEMISTRY="$(CHEMISTRY)" ) -diagcore: $(PHYSCORE) dycore - ( cd diagnostics; $(MAKE) all PHYSICS="$(PHYSICS)" ) +diagcore: $(PHYSCORE) $(CHEMCORE) dycore + ( cd diagnostics; $(MAKE) all PHYSICS="$(PHYSICS)"; $(MAKE) all CHEMISTRY="$(CHEMISTRY)" ) -utilities: $(PHYSCORE) - ( cd utils; $(MAKE) all PHYSICS="$(PHYSICS)" ) +utilities: $(PHYSCORE) $(CHEMCORE) + ( cd utils; $(MAKE) all PHYSICS="$(PHYSICS)"; $(MAKE) all CHEMISTRY="$(CHEMISTRY)" ) -atmcore: $(PHYSCORE) dycore diagcore $(OBJS) - ar -ru libdycore.a $(OBJS) dynamics/*.o $(PHYS_OBJS) diagnostics/*.o +atmcore: $(PHYSCORE) $(CHEMCORE) dycore diagcore $(OBJS) + ar -ru libdycore.a $(OBJS) dynamics/*.o $(PHYS_OBJS) $(CHEM_OBJS) diagnostics/*.o mpas_atm_core_interface.o: mpas_atm_core.o @@ -67,6 +77,7 @@ mpas_atm_dimensions.o: clean: ( cd physics; $(MAKE) clean ) + ( cd chemistry; $(MAKE) clean ) ( cd dynamics; $(MAKE) clean ) ( cd diagnostics; $(MAKE) clean ) ( cd utils; $(MAKE) clean ) diff --git a/src/core_atmosphere/Registry.xml b/src/core_atmosphere/Registry.xml index bdf47ec7b4..b66ebb3217 100644 --- a/src/core_atmosphere/Registry.xml +++ b/src/core_atmosphere/Registry.xml @@ -1672,7 +1672,18 @@ + packages="mp_thompson_aers_in"/> + + + + + + + + #endif @@ -2023,7 +2034,18 @@ + packages="mp_thompson_aers_in"/> + + + + + + + + #endif diff --git a/src/core_atmosphere/chemistry/Makefile b/src/core_atmosphere/chemistry/Makefile new file mode 100644 index 0000000000..f5b4bde970 --- /dev/null +++ b/src/core_atmosphere/chemistry/Makefile @@ -0,0 +1,41 @@ +.SUFFIXES: .F .o + +ifeq ($(CORE),atmosphere) +COREDEF = -Dmpas +endif + +all: + ./../tools/manage_externals/checkout_externals --externals ./../Externals.cfg + $(MAKE) core_mpas_musica core_chemistry + +dummy: + echo "****** compiling chemistry ******" + +OBJS = \ + mpas_atmchem_control.o + +core_mpas_musica: + (cd musica; $(MAKE) all COREDEF="$(COREDEF)") + +core_chemistry: core_mpas_musica + ($(MAKE) chem_interface COREDEF="$(COREDEF)") + ar -ru libchem.a $(OBJS) + ($(MAKE) -C ./musica mpas_musica_lib) + +chem_interface: $(OBJS) + +clean: + $(RM) *.o *.mod *.f90 libchem.a + ( cd musica; $(MAKE) clean ) + @# Certain systems with intel compilers generate *.i files + @# This removes them during the clean process + $(RM) *.i + +.F.o: + $(RM) $@ $*.mod +ifeq "$(GEN_F90)" "true" + $(CPP) $(CPPFLAGS) $(COREDEF) $(HYDROSTATIC) $(CPPINCLUDES) $< > $*.f90 + $(FC) $(FFLAGS) -c $*.f90 $(FCINCLUDES) -I./musica -I.. -I../../../framework -I../../../external/esmf_time_f90 +else + $(FC) $(CPPFLAGS) $(COREDEF) $(HYDROSTATIC) $(FFLAGS) -c $*.F $(CPPINCLUDES) $(FCINCLUDES) -I./musica -I.. -I../../../framework -I../../../external/esmf_time_f90 +endif diff --git a/src/core_atmosphere/chemistry/mpas_atmchem_control.F b/src/core_atmosphere/chemistry/mpas_atmchem_control.F new file mode 100644 index 0000000000..2f022edaa7 --- /dev/null +++ b/src/core_atmosphere/chemistry/mpas_atmchem_control.F @@ -0,0 +1,37 @@ +! Copyright (c) 2025, Los Alamos National Security, LLC (LANS) +! and the University Corporation for Atmospheric Research (UCAR). +! +! Unless noted otherwise source code is licensed under the BSD license. +! Additional copyright and license information can be found in the LICENSE file +! distributed with this code, or at http://mpas-dev.github.com/license.html +! +!================================================================================================================= +module mpas_atmchem_control + + + implicit none + private + public:: chemistry_setup_packages + +!MPAS chemistry package configuration routines. +!ACOM Software Engineering Team 2025 +! +! subroutines in mpas_atmchem_init: +! --------------------------------- +! chemistry_setup_packages : identifies available chemistry packages + +contains + + +!================================================================================================================= + subroutine chemistry_setup_packages() +!================================================================================================================= + use mpas_musica, only : log_musica_support + + call log_musica_support() + + end subroutine chemistry_setup_packages + +!================================================================================================================= +end module mpas_atmchem_control +!================================================================================================================= \ No newline at end of file diff --git a/src/core_atmosphere/chemistry/musica/Makefile b/src/core_atmosphere/chemistry/musica/Makefile new file mode 100644 index 0000000000..4e30424426 --- /dev/null +++ b/src/core_atmosphere/chemistry/musica/Makefile @@ -0,0 +1,30 @@ +.SUFFIXES: .F .o + +.PHONY: mpas_musica mpas_musica_lib + +all: dummy mpas_musica + +dummy: + echo "****** compiling mpas_musica ******" + +OBJS = \ + mpas_musica.o + +mpas_musica: $(OBJS) + +mpas_musica_lib: + ar -ru ./../libchem.a $(OBJS) + +clean: + $(RM) *.f90 *.o *.mod + @# Certain systems with intel compilers generate *.i files + @# This removes them during the clean process + $(RM) *.i + +.F.o: +ifeq "$(GEN_F90)" "true" + $(CPP) $(CPPFLAGS) $(COREDEF) $(CPPINCLUDES) $< > $*.f90 + $(FC) $(FFLAGS) -c $*.f90 $(FCINCLUDES) -I.. -I../../../framework -I../../../external/esmf_time_f90 +else + $(FC) $(CPPFLAGS) $(COREDEF) $(FFLAGS) -c $*.F $(CPPINCLUDES) $(FCINCLUDES) -I.. -I../../../framework -I../../../external/esmf_time_f90 +endif \ No newline at end of file diff --git a/src/core_atmosphere/chemistry/musica/mpas_musica.F b/src/core_atmosphere/chemistry/musica/mpas_musica.F new file mode 100644 index 0000000000..aa755e4f7a --- /dev/null +++ b/src/core_atmosphere/chemistry/musica/mpas_musica.F @@ -0,0 +1,49 @@ +! Copyright (c) 2025 University Corporation for Atmospheric Research +! +! Unless noted otherwise, this software is licensed under the BSD license. +! Additional copyright and license information can be found in the LICENSE file +! distributed with this code, or at http://mpas-dev.github.com/license.html +! +!================================================================================================================= +module mpas_musica +#ifdef MPAS_USE_MUSICA + use musica_micm, only : get_micm_version + use musica_util, only : string_t +#endif +use mpas_log, only: mpas_log_write + +implicit none +private +public:: log_musica_support + +!The MUSICA library must also be compiled and linked to the MPAS executable, This is +!typically done by first installing the MUSICA and then including the `MUSICA=true` option +!when building the MPAS atmosphere model. +! +!CURRENTLY UNDER DEVELOPMENT +! +!ACOM Software Engineering Team 2025 + + + contains + + +!================================================================================================================= + subroutine log_musica_support() +!================================================================================================================= +#ifdef MPAS_USE_MUSICA + +!local variables + type(string_t) :: version_string + + version_string = get_micm_version() + call mpas_log_write("MUSICA support is available. MICM version: "//version_string%value_) +#else + call mpas_log_write("MUSICA support not available.") +#endif + end subroutine log_musica_support + +!================================================================================================================= +end module mpas_musica +!================================================================================================================= + diff --git a/src/core_atmosphere/mpas_atm_core_interface.F b/src/core_atmosphere/mpas_atm_core_interface.F index 21c651905e..e5a8d8c352 100644 --- a/src/core_atmosphere/mpas_atm_core_interface.F +++ b/src/core_atmosphere/mpas_atm_core_interface.F @@ -110,6 +110,10 @@ function atm_setup_packages(configs, streamInfo, packages, iocontext) result(ier use mpas_atmphys_packages #endif +#ifdef DO_CHEMISTRY + use mpas_atmchem_control, only : chemistry_setup_packages +#endif + implicit none type (mpas_pool_type), intent(inout) :: configs @@ -259,6 +263,10 @@ function atm_setup_packages(configs, streamInfo, packages, iocontext) result(ier #endif +#ifdef DO_CHEMISTRY + call chemistry_setup_packages() +#endif + end function atm_setup_packages diff --git a/src/core_init_atmosphere/Registry.xml b/src/core_init_atmosphere/Registry.xml index 40b1c144ee..87cf1ac5c8 100644 --- a/src/core_init_atmosphere/Registry.xml +++ b/src/core_init_atmosphere/Registry.xml @@ -1171,6 +1171,15 @@ + + + + + + diff --git a/src/core_init_atmosphere/mpas_init_atm_cases.F b/src/core_init_atmosphere/mpas_init_atm_cases.F index 5ab57e4194..d4cec87782 100644 --- a/src/core_init_atmosphere/mpas_init_atm_cases.F +++ b/src/core_init_atmosphere/mpas_init_atm_cases.F @@ -259,7 +259,11 @@ subroutine init_atm_setup_case(domain, stream_manager) call init_atm_case_gfs(block_ptr, mesh, nCells, nEdges, nVertLevels, fg, state, & diag, diag_physics, block_ptr % dimensions, block_ptr % configs) - + +#ifdef DO_CHEMISTRY + call init_chem(mesh, state) +#endif + if (config_met_interp) then call init_atm_thompson_aerosols(block_ptr, mesh, block_ptr % configs, diag, state) call physics_initialize_real(mesh, fg, domain % dminfo, block_ptr % dimensions, block_ptr % configs) @@ -7522,5 +7526,38 @@ function read_text_array(dminfo, filename, xarray) result(ierr) end function read_text_array + subroutine init_chem(mesh, state) + + implicit none + + type (mpas_pool_type), intent(in) :: mesh + type (mpas_pool_type), intent(inout) :: state + + integer, pointer :: index_o3 + integer, pointer :: index_no + integer, pointer :: index_no2 + integer, pointer :: nCells + integer, pointer :: nVertLevels + + integer :: k, iCell + + real (kind=RKIND), dimension(:,:,:), pointer :: scalars + + call mpas_log_write('====== Handling Chemistry initialization ======') + + call mpas_pool_get_dimension(mesh, 'nCells', nCells) + call mpas_pool_get_dimension(mesh, 'nVertLevels', nVertLevels) + + call mpas_pool_get_dimension(state, 'index_o3', index_o3) + call mpas_pool_get_dimension(state, 'index_no', index_no) + call mpas_pool_get_dimension(state, 'index_no2', index_no2) + + call mpas_pool_get_array(state, 'scalars', scalars) + + scalars(index_o3,:,:) = 0.1 + scalars(index_no,:,:) = 0.01 + scalars(index_no2,:,:) = 0.03 + + end subroutine init_chem end module init_atm_cases