diff --git a/applications/lfric_atm/build/fortran/crayftn.mk b/applications/lfric_atm/build/fortran/crayftn.mk index 49286c047..98e77d011 100644 --- a/applications/lfric_atm/build/fortran/crayftn.mk +++ b/applications/lfric_atm/build/fortran/crayftn.mk @@ -10,4 +10,4 @@ $(info Project specials for Cray compiler) export FFLAGS_UM_PHYSICS = -s real64 -include $(PROJECT_DIR)/build/fortran/crayftn/$(PROFILE).mk \ No newline at end of file +include $(PROJECT_DIR)/build/fortran/crayftn/$(PROFILE).mk diff --git a/applications/linear_model/Makefile b/applications/linear_model/Makefile index 7ad66520d..6b99b2116 100644 --- a/applications/linear_model/Makefile +++ b/applications/linear_model/Makefile @@ -1,15 +1,19 @@ ############################################################################## -# (c) Crown copyright 2023-2024 Met Office. All rights reserved. +# (c) Crown copyright 2017-2026 Met Office. All rights reserved. # The file LICENCE, distributed with this code, contains details of the terms # under which the code may be used. ############################################################################## PROJECT_NAME = linear_model + export PROFILE ?= fast-debug # Select option for PSyclone transformation. Select "none" for no transformation. export PSYCLONE_TRANSFORMATION ?= minimum +# This makefile is almost identical to the lfric_atm makefile, but with +# additions for the linear code. + # This top level makefile is very order sensitive. Source code extraction and # generation must happen in a certain order. Due to this we turn off # multithreading for this file only. Any called recursively (i.e. with $(MAKE)) @@ -19,24 +23,51 @@ export PSYCLONE_TRANSFORMATION ?= minimum export PROJECT_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) +# The lfric_atm application project directory is used for the +# optimisation options. +# This is because it must be possible for the linear_model code to be in +# the same exectuable as the nonlinear lfric_atm code, as is done in jedi. +# Therefore the linear_model uses exactly the same optimisation +# options as lfric_atm. Pointing to the lfric_atm options +# means that the linear_model is always aligned with lfric_atm, even +# if the lfric_atm options are updated. +export LFRIC_ATM_DIR := $(APPS_ROOT_DIR)/applications/lfric_atm + +export EXTERNAL_DYNAMIC_LIBRARIES = shum + +# List of functions from shumlib that may be used by developers during debugging +export IGNORE_DEPENDENCIES = c_shum_byteswap \ + f_shum_field_mod \ + f_shum_file_mod \ + f_shum_is_nan_mod \ + f_shum_is_inf_mod \ + f_shum_is_denormal_mod + export EXTRA_ROSE_META = jules export META_DIR = $(WORKING_DIR)/../rose-meta export ROSE_META_DIRS = $(APPS_ROOT_DIR)/rose-meta $(META_DIR) +# The physics components are extracted and built, even though they are not +# actually used by the linear_model app. This is to ensure that the code runs +# with the #ifdef UM_PHYSICS set to true, hence enabling both the linear +# and nonlinear lfric_atm code to be run in the same executable. +# Note - socrates_interface must come before jules_interface as there are dependencies on each other. export INTERNAL_DEPENDENCIES = $(CORE_ROOT_DIR)/infrastructure \ $(CORE_ROOT_DIR)/components/driver \ $(CORE_ROOT_DIR)/components/science \ $(CORE_ROOT_DIR)/components/inventory \ $(CORE_ROOT_DIR)/components/lfric-xios \ - $(APPS_ROOT_DIR)/science/gungho \ - $(APPS_ROOT_DIR)/science/linear + $(APPS_ROOT_DIR)/science/shared \ + $(APPS_ROOT_DIR)/interfaces/socrates_interface \ + $(APPS_ROOT_DIR)/interfaces/jules_interface \ + $(APPS_ROOT_DIR)/interfaces/physics_schemes_interface -META_VN ?= HEAD -META_FILE_DIR = $(PROJECT_DIR)/rose-meta/lfric-$(PROJECT_NAME)/$(META_VN) +META_VN ?= HEAD +export META_FILE_DIR = $(PROJECT_DIR)/rose-meta/lfric-$(PROJECT_NAME)/$(META_VN) # Check PSyclone transformation option is valid ifneq ("$(PSYCLONE_TRANSFORMATION)","none") - export OPTIMISATION_PATH ?= $(wildcard optimisation/$(PSYCLONE_TRANSFORMATION)) + export OPTIMISATION_PATH ?= $(wildcard $(LFRIC_ATM_DIR)/optimisation/$(PSYCLONE_TRANSFORMATION)) ifeq ("$(wildcard $(OPTIMISATION_PATH)/psykal/global.py)","") $(error PSyclone transformation dir "$(PSYCLONE_TRANSFORMATION)" does not have a global.py script) endif @@ -44,38 +75,34 @@ endif .PHONY: default default: build - -.PHONY: documentation doc docs -documentation doc docs: document-api + $(Q)echo > /dev/null include $(CORE_ROOT_DIR)/infrastructure/build/lfric.mk include $(INTERNAL_DEPENDENCIES:=/build/import.mk) +include build/project.mk -############################################################################## -# Documentation -# -.PHONY: document-api -document-api: PROJECT = linear_model -document-api: DOCUMENT_DIR ?= $(PROJECT_DIR)/documents/api -document-api: CONFIG_DIR = documentation -document-api: SOURCE_DIR = source -document-api: WORKING_DIR := $(WORKING_DIR)/api -document-api: api-documentation +# Include transmute list only if not using minimum or no transformations +ifeq ($(filter "$(PSYCLONE_TRANSFORMATION)", "none" "minimum"),) + include build/psyclone_transmute_file_list.mk +endif ############################################################################## # Build # .PHONY: build build: export BIN_DIR ?= $(PROJECT_DIR)/bin -build: export CXX_LINK = TRUE -build: export PROGRAMS := $(basename $(notdir $(shell find source -maxdepth 1 -name '*.[Ff]90' -print))) +build: export CXX_LINK = YES +build: export PROGRAMS := $(basename $(notdir $(shell find source -maxdepth 1 -name '*.[Ff]90' -exec egrep -l "^\s*program" {} \;))) +build: export PROJECT = $(PROJECT_NAME) +build: export SCRATCH_DIR := $(WORKING_DIR)/.. build: export WORKING_DIR := $(WORKING_DIR) build: export LDFLAGS_GROUPS = OPENMP ifeq "$(PROFILE)" "full-debug" -build: export FFLAG_GROUPS = OPENMP DEBUG WARNINGS INIT RUNTIME NO_OPTIMISATION FORTRAN_STANDARD +build: export FFLAG_GROUPS = OPENMP DEBUG WARNINGS INIT RUNTIME NO_OPTIMISATION else ifeq "$(PROFILE)" "fast-debug" -build: export FFLAG_GROUPS = OPENMP DEBUG WARNINGS FASTD_INIT FASTD_RUNTIME SAFE_OPTIMISATION FORTRAN_STANDARD +# Use fast-debug environment vars from build/fortran/*.mk configs +build: export FFLAG_GROUPS = OPENMP DEBUG WARNINGS FASTD_INIT FASTD_RUNTIME SAFE_OPTIMISATION else ifeq "$(PROFILE)" "production" build: export FFLAG_GROUPS = OPENMP DEBUG WARNINGS RISKY_OPTIMISATION else @@ -88,6 +115,25 @@ build: ALWAYS $(Q)for SUBPROJECT in $(INTERNAL_DEPENDENCIES) ; do \ $(MAKE) $(QUIET_ARG) -f $$SUBPROJECT/build/import.mk ; done $(call MESSAGE,========================================) + $(call MESSAGE,Extracting coupled_interface component) + $(call MESSAGE,========================================) + $Q$(MAKE) $(QUIET_ARG) -f $(LFRIC_BUILD)/extract.mk \ + SOURCE_DIR=$(APPS_ROOT_DIR)/interfaces/coupled_interface/source + $(call MESSAGE,========================================) + $(call MESSAGE,Extracting Gungho dynamical core) + $(call MESSAGE,========================================) + $Q$(MAKE) $(QUIET_ARG) -f $(LFRIC_BUILD)/extract.mk \ + SOURCE_DIR=$(APPS_ROOT_DIR)/science/gungho/source + $(call MESSAGE,========================================) + $(call MESSAGE,Extracting Linear) + $(call MESSAGE,========================================) + $Q$(MAKE) $(QUIET_ARG) -f $(LFRIC_BUILD)/extract.mk \ + SOURCE_DIR=$(APPS_ROOT_DIR)/science/linear/source + $(call MESSAGE,========================================) + $(call MESSAGE,Extracting UM physics ) + $(call MESSAGE,========================================) + $Q$(MAKE) $(QUIET_ARG) -f $(APPS_ROOT_DIR)/build/extract/extract_physics.mk + $(call MESSAGE,========================================) $(call MESSAGE,Extracting $(PROJECT_NAME)) $(call MESSAGE,========================================) $Q$(MAKE) $(QUIET_ARG) -f $(LFRIC_BUILD)/extract.mk \ @@ -96,19 +142,59 @@ build: ALWAYS $(call MESSAGE,Extracting External Rose Metadata) $(call MESSAGE,========================================) $Q$(MAKE) $(QUIET_ARG) -f $(APPS_ROOT_DIR)/build/extract/extract_meta.mk - $(call MESSAGE,=========================================================) + $(call MESSAGE,========================================) $(call MESSAGE,Generating $(PROJECT) namelist loaders) - $(call MESSAGE,=========================================================) + $(call MESSAGE,========================================) $Q$(MAKE) $(QUIET_ARG) -f $(LFRIC_BUILD)/configuration.mk \ - PROJECT=$(PROJECT) \ - SOURCE_DIR=source \ + SOURCE_DIR=$(APPS_ROOT_DIR)/science/gungho/source \ META_FILE_DIR=$(META_FILE_DIR) $(call MESSAGE,========================================) + $(call MESSAGE,PSycloning interface components) + $(call MESSAGE,========================================) + $Q$(MAKE) $(QUIET_ARG) -f $(LFRIC_BUILD)/psyclone/psyclone_psykal.mk \ + SOURCE_DIR=$(APPS_ROOT_DIR)/interfaces/coupled_interface/source + $Q$(MAKE) $(QUIET_ARG) -f $(LFRIC_BUILD)/psyclone/psyclone_psykal.mk \ + SOURCE_DIR=$(APPS_ROOT_DIR)/interfaces/jules_interface/source + $Q$(MAKE) $(QUIET_ARG) -f $(LFRIC_BUILD)/psyclone/psyclone_psykal.mk \ + SOURCE_DIR=$(APPS_ROOT_DIR)/interfaces/socrates_interface/source + $Q$(MAKE) $(QUIET_ARG) -f $(LFRIC_BUILD)/psyclone/psyclone_psykal.mk \ + SOURCE_DIR=$(APPS_ROOT_DIR)/interfaces/physics_schemes_interface/source + $(call MESSAGE,========================================) + $(call MESSAGE,PSycloning Gungho dynamical core) + $(call MESSAGE,========================================) + $Q$(MAKE) $(QUIET_ARG) -f $(LFRIC_BUILD)/psyclone/psyclone_psykal.mk \ + SOURCE_DIR=$(APPS_ROOT_DIR)/science/gungho/source + $(call MESSAGE,========================================) + $(call MESSAGE,PSycloning Linear) + $(call MESSAGE,========================================) + $Q$(MAKE) $(QUIET_ARG) -f $(LFRIC_BUILD)/psyclone/psyclone_psykal.mk \ + SOURCE_DIR=$(APPS_ROOT_DIR)/science/linear/source + $(call MESSAGE,========================================) $(call MESSAGE,PSycloning $(PROJECT_NAME)) $(call MESSAGE,========================================) $Q$(MAKE) $(QUIET_ARG) -f $(LFRIC_BUILD)/psyclone/psyclone_psykal.mk \ - SOURCE_DIR=source \ - OPTIMISATION_PATH=$(OPTIMISATION_PATH) + SOURCE_DIR=source + $(call MESSAGE,========================================) + $(call MESSAGE,Preprocess and PSyclone Transmute) + $(call MESSAGE,========================================) +# Note depending on site target requirements, either all source or specific source will be affected +# See application overrides and files exported there + $Q$(MAKE) $(QUIET_ARG) -f $(APPS_ROOT_DIR)/interfaces/build/pre_process_phys.mk \ + SOURCE_DIR=$(WORKING_DIR) \ + PSYCLONE_PHYSICS_FILES="$(PSYCLONE_PHYSICS_FILES)" \ + PSYCLONE_DIRECTORIES="$(PSYCLONE_DIRECTORIES)" \ + PSYCLONE_PHYSICS_EXCEPTION="$(PSYCLONE_PHYSICS_EXCEPTION)" + $Q$(MAKE) $(QUIET_ARG) -f $(APPS_ROOT_DIR)/interfaces/build/psyclone_transmute_pass.mk \ + SOURCE_DIR=$(WORKING_DIR) \ + OPTIMISATION_PATH_PSY=$(OPTIMISATION_PATH) \ + PSYCLONE_PASS_NO_SCRIPT="$(PSYCLONE_PASS_NO_SCRIPT)" + $Q$(MAKE) $(QUIET_ARG) -f $(APPS_ROOT_DIR)/interfaces/build/psyclone_transmute.mk \ + SOURCE_DIR=$(WORKING_DIR) \ + OPTIMISATION_PATH_PSY=$(OPTIMISATION_PATH) \ + PSYCLONE_PHYSICS_FILES="$(PSYCLONE_PHYSICS_FILES)" \ + PSYCLONE_PASS_NO_SCRIPT="$(PSYCLONE_PASS_NO_SCRIPT)" \ + PSYCLONE_DIRECTORIES="$(PSYCLONE_DIRECTORIES)" \ + PSYCLONE_PHYSICS_EXCEPTION="$(PSYCLONE_PHYSICS_EXCEPTION)" $(call MESSAGE,=========================================================) $(call MESSAGE,Analysing $(PROJECT) build dependencies) $(call MESSAGE,=========================================================) @@ -118,15 +204,45 @@ build: ALWAYS $(call MESSAGE,=========================================================) $Q$(MAKE) $(QUIET_ARG) -C $(WORKING_DIR) -f $(LFRIC_BUILD)/compile.mk + +############################################################################## +# Pat_build step - This runs after the build step as relies on exe + +# Pass $(PROJECT_NAME) which is exe name linear_model which pat_report needs +pat_build: build + $(call MESSAGE,=========================================================) + $(call MESSAGE, Begin Pat Build of $(PROJECT_NAME) executable) + $(call MESSAGE,=========================================================) + bash $(PAT_BUILD_PATH) $(PROJECT_NAME) + $(call MESSAGE,=========================================================) + $(call MESSAGE, Pat Build of $(PROJECT_NAME) complete as $(PROJECT_NAME)+pat) + $(call MESSAGE,=========================================================) + +############################################################################## +# Unit tests +# +unit-tests: + $(call MESSAGE,Testing,"There are no unit tests.") + + +############################################################################## +# Integration tests +# +integration-tests: + $(call MESSAGE,Testing,"There are no integration tests.") + + ############################################################################## # Clean # .PHONY: clean -clean: ALWAYS - $(call MESSAGE,Removing,"$(PROJECT_NAME) work space") - $(Q)-if [ $(WORKING_DIR) != *[\*]* ] && [ -d $(WORKING_DIR) ] ; then rm -r $(WORKING_DIR) ; fi - $(call MESSAGE,Removing,"$(PROJECT_NAME) documents") - $(Q)if [ -d documents ] ; then rm -r documents; fi - $(call MESSAGE,Removing,"$(PROJECT_NAME) binaries") +clean: partial-clean + $(call MESSAGE,Removing,"UM work space") + $(Q)-rm -r $(WORKING_DIR) + +.PHONY: partial-clean pclean +partial-clean pclean: ALWAYS + $(call MESSAGE,Removing,"LFRic atmosphere workspace") + $(Q)-rm -r $(WORKING_DIR) + $(call MESSAGE,Removing,"LFRic atmosphere binaries") $(Q)-if [ -d bin ] ; then rm -r bin ; fi - $(Q)-if [ -d test ] ; then rm -r test ; fi diff --git a/applications/linear_model/build/compile_options.mk b/applications/linear_model/build/compile_options.mk new file mode 100644 index 000000000..e4de43248 --- /dev/null +++ b/applications/linear_model/build/compile_options.mk @@ -0,0 +1,45 @@ +############################################################################## +# (c) Crown copyright 2017-2026 Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +############################################################################## + +# NOTE: Import of compile options from LFRic infrastructure is temporarily +# suspended here as a workaround for #2340 in which application of the +# -qoverride-limits option was preventing compilation of a UKCA module. +# include $(LFRIC_BUILD)/compile_options.mk + +$(info UM physics specific compile options) + +include $(PROJECT_DIR)/build/fortran/$(FORTRAN_COMPILER).mk + +casim/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +ukca/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +jules/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +socrates/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +legacy/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +AC_assimilation/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +aerosols/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +atmosphere_service/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +boundary_layer/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +carbon/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +convection/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +diffusion_and_filtering/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +dynamics/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +dynamics_advection/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +electric/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +free_tracers/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +gravity_wave_drag/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +idealised/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +large_scale_cloud/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +large_scale_precipitation/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +PWS_diagnostics/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +radiation_control/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +stochastic_physics/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +tracer_advection/%.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) +%/limited_area_constants_mod.o: private FFLAGS_EXTRA = $(FFLAGS_INTEL_FIX_ARG) + +$(info Disable warnings-turned-error caused by undeclared external functions - see ifort.mk) +%mpi_mod.o: private FFLAGS_EXTRA = $(FFLAGS_INTEL_EXTERNALS) +socrates/src/radiance_core/%.o: private FFLAGS_EXTRA = $(FFLAGS_INTEL_EXTERNALS) +socrates/src/interface_core/%.o: private FFLAGS_EXTRA = $(FFLAGS_INTEL_EXTERNALS) diff --git a/applications/linear_model/build/fortran/crayftn.mk b/applications/linear_model/build/fortran/crayftn.mk new file mode 100644 index 000000000..98e77d011 --- /dev/null +++ b/applications/linear_model/build/fortran/crayftn.mk @@ -0,0 +1,13 @@ +############################################################################## +# (c) Crown copyright 2017 Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +############################################################################## +# Various things specific to the Cray Fortran compiler. +############################################################################## + +$(info Project specials for Cray compiler) + +export FFLAGS_UM_PHYSICS = -s real64 + +include $(PROJECT_DIR)/build/fortran/crayftn/$(PROFILE).mk diff --git a/applications/linear_model/build/fortran/crayftn/fast-debug.mk b/applications/linear_model/build/fortran/crayftn/fast-debug.mk new file mode 100644 index 000000000..a627d2556 --- /dev/null +++ b/applications/linear_model/build/fortran/crayftn/fast-debug.mk @@ -0,0 +1,55 @@ +############################################################################## +# (c) Crown copyright 2025 Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +############################################################################## +############################################################################## +# Various things specific to fast-debug lfric_atm when using the +# Cray Fortran compiler. +# To override flags specified in LFRic Core, use +# FFLAGS_SAFE_OPTIMISATION, to add an additional flag to what is specified +# in Core, use FFLAGS_EXTRA. If you need to add debugging flags to a module, +# modify FFLAGS_DEBUG for the target module. +# All flag modification should be `private` so they are not inherited by +# submodules. +############################################################################## + +# ========================================================================== +# NON-DEBUG FLAGS +# ========================================================================== +# UKCA +%ukca_emiss_mode_mod.o: private FFLAGS_SAFE_OPTIMISATION = -O0 +%ukca_step_control_mod.o: private FFLAGS_SAFE_OPTIMISATION = -O0 + +# UM +%parcel_ascent_5a.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) -hvector0 + +# LFRic Apps +%aerosol_ukca_alg_mod_psy.o: private FFLAGS_SAFE_OPTIMISATION = -O0 +%bl_exp_alg_mod_psy.o: private FFLAGS_SAFE_OPTIMISATION = -O0 +%bl_imp_alg_mod_psy.o: private FFLAGS_SAFE_OPTIMISATION = -O0 +%conv_comorph_alg_mod_psy.o: private FFLAGS_SAFE_OPTIMISATION = -O0 +%conv_comorph_kernel_mod.o: private FFLAGS_SAFE_OPTIMISATION = -O0 +%conv_gr_alg_mod_psy.o: private FFLAGS_SAFE_OPTIMISATION = -O0 +%gungho_model_mod.o: private FFLAGS_SAFE_OPTIMISATION = -O0 +%init_aerosol_fields_alg_mod_psy.o: private FFLAGS_SAFE_OPTIMISATION = -O0 +%jules_extra_kernel_mod.o: private FFLAGS_SAFE_OPTIMISATION = -O0 +large_scale_precipitation/%.o: private FFLAGS_SAFE_OPTIMISATION = -O2 -hfp0 -hflex_mp=strict + +# ========================================================================== +# DEBUG FLAGS +# ========================================================================== +# UKCA +%ukca_emiss_mode_mod.o: private FFLAGS_DEBUG = -G0 +%ukca_step_control_mod.o: private FFLAGS_DEBUG = -G0 + +# LFRic Apps +%aerosol_ukca_alg_mod_psy.o: private FFLAGS_DEBUG = -G0 +%bl_exp_alg_mod_psy.o: private FFLAGS_DEBUG = -G0 +%bl_imp_alg_mod_psy.o: private FFLAGS_DEBUG = -G0 +%conv_comorph_alg_mod_psy.o: private FFLAGS_DEBUG = -G0 +%conv_comorph_kernel_mod.o: private FFLAGS_DEBUG = -G0 +%conv_gr_alg_mod_psy.o: private FFLAGS_DEBUG = -G0 +%gungho_model_mod.o: private FFLAGS_DEBUG = -G0 +%init_aerosol_fields_alg_mod_psy.o: private FFLAGS_DEBUG = -G0 +%jules_extra_kernel_mod.o: private FFLAGS_DEBUG = -G0 diff --git a/applications/linear_model/build/fortran/crayftn/full-debug.mk b/applications/linear_model/build/fortran/crayftn/full-debug.mk new file mode 100644 index 000000000..a5b3d45a3 --- /dev/null +++ b/applications/linear_model/build/fortran/crayftn/full-debug.mk @@ -0,0 +1,17 @@ +############################################################################## +# (c) Crown copyright 2025 Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +############################################################################## +############################################################################## +# Various things specific to full-debug lfric_atm when using the +# Cray Fortran compiler. +############################################################################## + +# ========================================================================== +# NON-DEBUG FLAGS +# ========================================================================== + +# ========================================================================== +# DEBUG FLAGS +# ========================================================================== diff --git a/applications/linear_model/build/fortran/crayftn/production.mk b/applications/linear_model/build/fortran/crayftn/production.mk new file mode 100644 index 000000000..ddf5ca86c --- /dev/null +++ b/applications/linear_model/build/fortran/crayftn/production.mk @@ -0,0 +1,36 @@ +############################################################################## +# (c) Crown copyright 2025 Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +############################################################################## +############################################################################## +# Various things specific to production lfric_atm when using the +# Cray Fortran compiler. +############################################################################## + +# ========================================================================== +# DIRECTORIES +# ========================================================================== +gravity_wave_drag/%.o: private FFLAGS_RISKY_OPTIMISATION = -O2 -hflex_mp=strict + +# ========================================================================== +# MODULES +# ========================================================================== +# UKCA +%ukca_emiss_mode_mod.o: private FFLAGS_RISKY_OPTIMISATION = -O0 +%ukca_step_control_mod.o: private FFLAGS_RISKY_OPTIMISATION = -O0 + +# UM +%parcel_ascent_5a.o: private FFLAGS_EXTRA = $(FFLAGS_UM_PHYSICS) -hvector0 + +# LFRic Apps +%aerosol_ukca_alg_mod_psy.o: private FFLAGS_RISKY_OPTIMISATION = -O0 +%bl_exp_alg_mod_psy.o: private FFLAGS_RISKY_OPTIMISATION = -O0 +%bl_imp_alg_mod_psy.o: private FFLAGS_RISKY_OPTIMISATION = -O0 +%conv_comorph_alg_mod_psy.o: private FFLAGS_RISKY_OPTIMISATION = -O0 +%conv_comorph_kernel_mod.o: private FFLAGS_RISKY_OPTIMISATION = -O0 +%conv_gr_alg_mod_psy.o: private FFLAGS_RISKY_OPTIMISATION = -O0 +%gungho_model_mod.o: private FFLAGS_RISKY_OPTIMISATION = -O0 +%init_aerosol_fields_alg_mod_psy.o: private FFLAGS_RISKY_OPTIMISATION = -O0 +%jules_extra_kernel_mod.o: private FFLAGS_RISKY_OPTIMISATION = -O0 +large_scale_precipitation/%.o: private FFLAGS_SAFE_OPTIMISATION = -O3 -hipa3 -hflex_mp=conservative diff --git a/applications/linear_model/build/fortran/gfortran.mk b/applications/linear_model/build/fortran/gfortran.mk new file mode 100644 index 000000000..79f02dc5a --- /dev/null +++ b/applications/linear_model/build/fortran/gfortran.mk @@ -0,0 +1,40 @@ +############################################################################## +# (c) Crown copyright 2017 Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +############################################################################## +# Various things specific to the GNU Fortran compiler. +############################################################################## + +$(info Project specials for GNU compiler) + +export FFLAGS_UM_PHYSICS = -fdefault-real-8 -fdefault-double-8 +# Most lfric_atm dependencies contain code with implicit lossy conversions and +# unused variables. +# We reset the FFLAGS_WARNINGS variable here in order to prevent +# -Werror induced build failures. +FFLAGS_WARNINGS = -Wall -Werror=character-truncation -Werror=unused-value \ + -Werror=tabs +# But, we can apply some more lfric infrastructure checking to socrates +FFLAGS_SOCRATES_WARNINGS = -Werror=unused-variable + +science/src/socrates/%.o science/src/socrates/%.mod: private FFLAGS_EXTRA = $(FFLAGS_SOCRATES_WARNINGS) + +# We remove bounds checking (applied by -fcheck=all) and underflow checking. The +# latter is due to regular permitting of exponents going to zero for small numbers +# to imply total extinction of radiation passing through a medium +FFLAGS_RUNTIME = -fcheck=all,no-bounds -ffpe-trap=invalid,zero,overflow + +# The lfric_atm app defines an extra set of debug flags for +# fast-debug which are the same as the full-debug settings +# except for some platforms +ifdef CRAY_ENVIRONMENT +# On the EXZ these options are switched off for fast-debug +# due to an unexpected FPE in the NetCDF library +FFLAGS_FASTD_INIT = +FFLAGS_FASTD_RUNTIME = +else +# Otherwise, use the same as the default full-debug settings +FFLAGS_FASTD_INIT = $(FFLAGS_INIT) +FFLAGS_FASTD_RUNTIME = $(FFLAGS_RUNTIME) +endif diff --git a/applications/linear_model/build/fortran/ifort.mk b/applications/linear_model/build/fortran/ifort.mk new file mode 100644 index 000000000..dc9b4513c --- /dev/null +++ b/applications/linear_model/build/fortran/ifort.mk @@ -0,0 +1,65 @@ +############################################################################## +# (c) Crown copyright 2017 Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +############################################################################## +# Various things specific to the Intel Fortran compiler. +############################################################################## + +$(info Project specials for Intel compiler) + +export FFLAGS_UM_PHYSICS = -r8 + +# Set fast-debug and full-debug options for lfric_atm Intel that +# differ from the setup in infrastructure used by other LFRic apps. +# First, the -check all option is removed from all configurations as +# it results in excessive numbers of warnings from UM code running +# within LFRic +FFLAGS_RUNTIME = -fpe0 +# Second, certain fast-debug options cause XIOS failures on the Cray +# in jobs that write diagnostic so they are removed. Note: the +# full-debug test can still use these options as it avoids such XIOS +# use. +ifdef CRAY_ENVIRONMENT +# On the Cray these options are switched off for fast-debug +FFLAGS_FASTD_INIT = +FFLAGS_FASTD_RUNTIME = +else +# Otherwise, use the same as the default full-debug settings +FFLAGS_FASTD_INIT = $(FFLAGS_INIT) +FFLAGS_FASTD_RUNTIME = $(FFLAGS_RUNTIME) +endif + +# NOTE: The -qoverride-limits option contained in $(FFLAGS_INTEL_FIX_ARG) is +# not currently applied here. This is a temporary workaround for #3465 +# which it was found to be inadvertently preventing compilation +# openMP has also been removed from this routine via the optimisation script +%bl_imp_alg_mod_psy.o %bl_imp_alg_mod_psy.mod: private FFLAGS_EXTRA = +%aerosol_ukca_alg_mod_psy.o %aerosol_ukca_alg_mod_psy.mod: private FFLAGS_EXTRA = +%conv_comorph_alg_mod_psy.o %conv_comorph_alg_mod_psy.mod: private FFLAGS_EXTRA = + +$(info LFRic compile options required for files with OpenMP - see Ticket 1490) +%psy.o %psy.mod: private FFLAGS_EXTRA = $(FFLAGS_INTEL_FIX_ARG) +# NOTE: The -qoverride-limits option contained in $(FFLAGS_INTEL_FIX_ARG) is +# not currently applied here. This is a temporary workaround for #3205 +# which it was found to be inadvertently preventing compilation +# psy/%.o psy/%.mod: private FFLAGS_EXTRA = $(FFLAGS_INTEL_FIX_ARG) + + +# -warn noexternals applied to code that imports lfric_mpi_mod to avoid +# a warning-turned-error about missing interfaces for MPI calls in +# mpi.mod, such as MPI_Allreduce - switching to mpi_f08.mod resolves +# this via polymorphic interface declarations. Some SOCRATES functions +# do not currently declare interfaces either. Flag was introduced in +# Intel Fortran v19.1.0 according to Intel release notes. +ifeq ($(shell test "$(IFORT_VERSION)" -ge 0190100; echo $$?), 0) + $(info ** Activating externals warning override for selected source files) + export FFLAGS_INTEL_EXTERNALS = -warn noexternals +else + export FFLAGS_INTEL_EXTERNALS = +endif + +ifeq ($(shell test "$(IFORT_VERSION)" -ge 0190103; echo $$?), 0) + $(info ** Disabling OpenMP due to a compiler bug for intel-compiler newer than 2020.3.304 - see Ticket 3853) + %ls_ppnc.o %ls_ppnc.mod: FFLAGS:=${FFLAGS} -qno-openmp +endif diff --git a/applications/linear_model/build/fortran/ifx.mk b/applications/linear_model/build/fortran/ifx.mk new file mode 100644 index 000000000..ff6251cde --- /dev/null +++ b/applications/linear_model/build/fortran/ifx.mk @@ -0,0 +1,58 @@ +############################################################################## +# (c) Crown copyright 2025 Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +############################################################################## +# Various things specific to the Intel oneAPI Fortran compiler. +############################################################################## + +$(info Project specials for Intel oneAPI compiler) + +export FFLAGS_UM_PHYSICS = -r8 + +# Set fast-debug and full-debug options for lfric_atm Intel that +# differ from the setup in infrastructure used by other LFRic apps. +# First, the -check all option is removed from all configurations as +# it results in excessive numbers of warnings from UM code running +# within LFRic +FFLAGS_RUNTIME = -fpe0 +# Second, certain fast-debug options cause XIOS failures on the Cray +# in jobs that write diagnostic so they are removed. Note: the +# full-debug test can still use these options as it avoids such XIOS +# use. +ifdef CRAY_ENVIRONMENT +# On the Cray these options are switched off for fast-debug +FFLAGS_FASTD_INIT = +FFLAGS_FASTD_RUNTIME = +else +# Otherwise, use the same as the default full-debug settings +FFLAGS_FASTD_INIT = $(FFLAGS_INIT) +FFLAGS_FASTD_RUNTIME = $(FFLAGS_RUNTIME) +endif + +# NOTE: The -qoverride-limits option contained in $(FFLAGS_INTEL_FIX_ARG) is +# not currently applied here. This is a temporary workaround for #3465 +# which it was found to be inadvertently preventing compilation +# openMP has also been removed from this routine via the optimisation script +%bl_imp_alg_mod_psy.o %bl_imp_alg_mod_psy.mod: private FFLAGS_EXTRA = +%aerosol_ukca_alg_mod_psy.o %aerosol_ukca_alg_mod_psy.mod: private FFLAGS_EXTRA = +%conv_comorph_alg_mod_psy.o %conv_comorph_alg_mod_psy.mod: private FFLAGS_EXTRA = + +$(info LFRic compile options required for files with OpenMP - see Ticket 1490) +%psy.o %psy.mod: private FFLAGS_EXTRA = $(FFLAGS_INTEL_FIX_ARG) +# NOTE: The -qoverride-limits option contained in $(FFLAGS_INTEL_FIX_ARG) is +# not currently applied here. This is a temporary workaround for #3205 +# which it was found to be inadvertently preventing compilation +# psy/%.o psy/%.mod: private FFLAGS_EXTRA = $(FFLAGS_INTEL_FIX_ARG) + + +# -warn noexternals applied to code that imports mpi_mod to avoid +# a warning-turned-error about missing interfaces for MPI calls in +# mpi.mod, such as MPI_Allreduce - switching to mpi_f08.mod resolves +# this via polymorphic interface declarations. Some SOCRATES functions +# do not currently declare interfaces either. Flag was introduced in +# Intel Fortran v19.1.0 according to Intel release notes. +export FFLAGS_INTEL_EXTERNALS = -warn noexternals + +$(info ** Disabling OpenMP due to a compiler bug for intel-compiler newer than 2020.3.304 - see Ticket 3853) +%ls_ppnc.o %ls_ppnc.mod: FFLAGS:=${FFLAGS} -qno-openmp diff --git a/applications/linear_model/build/fortran/nvfortran.mk b/applications/linear_model/build/fortran/nvfortran.mk new file mode 100644 index 000000000..e4a25fe13 --- /dev/null +++ b/applications/linear_model/build/fortran/nvfortran.mk @@ -0,0 +1,17 @@ +############################################################################# +#(c) Crown copyright 2024 Met Office. All rights reserved. +#The file LICENCE, distributed with this code, contains details of the terms +#under which the code may be used. +############################################################################# +# Various things specific to the NVIDIA Fortran compiler. +############################################################################# + +$(info Project specials for NVIDIA compiler) + +export FFLAGS_UM_PHYSICS = -r8 + +# The lfric_atm app defines an extra set of debug flags for +# fast-debug. For this compiler use the same as the full-debug +# settings +FFLAGS_FASTD_INIT = $(FFLAGS_INIT) +FFLAGS_FASTD_RUNTIME = $(FFLAGS_RUNTIME) diff --git a/applications/linear_model/build/fortran/pgfortran.mk b/applications/linear_model/build/fortran/pgfortran.mk new file mode 100644 index 000000000..e95afff35 --- /dev/null +++ b/applications/linear_model/build/fortran/pgfortran.mk @@ -0,0 +1,17 @@ +############################################################################## +# (c) Crown copyright 2017 Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +############################################################################## +# Various things specific to the Portland Fortran compiler. +############################################################################## + +$(info Project specials for Portland compiler) + +export FFLAGS_UM_PHYSICS = -r8 + +# The lfric_atm app defines an extra set of debug flags for +# fast-debug. For this compiler use the same as the full-debug +# settings +FFLAGS_FASTD_INIT = $(FFLAGS_INIT) +FFLAGS_FASTD_RUNTIME = $(FFLAGS_RUNTIME) diff --git a/applications/linear_model/build/project.mk b/applications/linear_model/build/project.mk new file mode 100644 index 000000000..e4a05cfed --- /dev/null +++ b/applications/linear_model/build/project.mk @@ -0,0 +1,15 @@ +############################################################################## +# (c) Crown copyright 2017 Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +############################################################################## + +$(info UM physics project specials) + +export PRE_PROCESS_INCLUDE_DIRS = \ + $(WORKING_DIR)/atmosphere_service/include \ + $(WORKING_DIR)/boundary_layer/include \ + $(WORKING_DIR)/large_scale_precipitation/include \ + $(WORKING_DIR)/free_tracers/include + +export PRE_PROCESS_MACROS += UM_PHYSICS LFRIC USSPPREC_32B LSPREC_32B UM_JULES diff --git a/applications/linear_model/build/psyclone_transmute_file_list.mk b/applications/linear_model/build/psyclone_transmute_file_list.mk new file mode 100644 index 000000000..90e2556c0 --- /dev/null +++ b/applications/linear_model/build/psyclone_transmute_file_list.mk @@ -0,0 +1,70 @@ +############################################################################## +# (c) Crown copyright 2025 Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +############################################################################## + +# File lists provided will use the transmute PSyclone method. +# https://code.metoffice.gov.uk/trac/lfric_apps/ticket/724 + + +##### TRANSMUTE_INCLUDE_METHOD specify_include ##### +# For CPU OMP, we want to choose which files get run through PSyclone, +# and preserve existing hand coded optimisations. + +# Choose which files to Pre-proccess and PSyclone from physics_schemes / other source (e.g. UKCA) + +export PSYCLONE_PHYSICS_FILES = \ + bl_lsp \ + bm_tau_kernel_mod \ + btq_int \ + conv_gr_kernel_mod \ + ex_flux_tq \ + ex_flux_uv \ + fm_drag \ + gw_ussp_mod \ + imp_mix \ + jules_exp_kernel_mod \ + jules_extra_kernel_mod \ + jules_imp_kernel_mod \ + kmkh \ + kmkhz_9c_wtrac \ + lw_kernel_mod \ + mphys_kernel_mod \ + pc2_bl_forced_cu \ + pc2_bm_initiate \ + pc2_initiation_ctl \ + pc2_initiation_kernel_mod \ + pc2_conv_coupling_kernel_mod \ + sw_kernel_mod \ + ukca_aero_ctl \ + ukca_abdulrazzak_ghan \ + ukca_chemistry_ctl_full_mod \ + ukca_main1-ukca_main1 \ + sw_rad_tile_kernel_mod \ + jules_imp_kernel_mod \ + jules_exp_kernel_mod \ + jules_extra_kernel_mod + +##### TRANSMUTE_INCLUDE_METHOD specify_include ##### + +# List to use PSyclone explicitly without any opt script +# This will remove hand written (OMP) directives in the source +# Used by both methods, specify_include and specify_exclude +export PSYCLONE_PASS_NO_SCRIPT = ukca_abdulrazzak_ghan + + +##### TRANSMUTE_INCLUDE_METHOD specify_exclude ##### +# For GPU, we may want to use more generic local.py transformation scripts and psyclone by directory. +# Advise which directories to pass to PSyclone. +# All files in these directories will be run through PSyclone using the transmute method. +# Also provide an optional exception list. +# These files will be filtered, and will NOT be run through PSyclone. + +# Directories to psyclone +export PSYCLONE_DIRECTORIES = + +# A general file exception list +export PSYCLONE_PHYSICS_EXCEPTION = + +##### TRANSMUTE_INCLUDE_METHOD specify_exclude ##### diff --git a/applications/linear_model/example/configuration.nml b/applications/linear_model/example/configuration.nml index 40697eb6c..76dd2e7bd 100644 --- a/applications/linear_model/example/configuration.nml +++ b/applications/linear_model/example/configuration.nml @@ -13,8 +13,24 @@ transport_overwrite_freq='final' limit_cfl=.false., / §ion_choice +aerosol='none', +boundary_layer='none' +chemistry='none', +cloud='none', +convection='none', dynamics='gungho', +electric='none', external_forcing=.false., +iau=.false., +iau_sst=.false., +iau_surf=.false., +methane_oxidation=.false., +microphysics='none', +orographic_drag='none', +radiation='none', +spectral_gwd='none', +stochastic_physics='none', +surface='none' / &departure_points horizontal_limit='none', @@ -285,3 +301,4 @@ vertical_sl_order='cubic' wind_mono_top=.false. wind_mono_top_depth=5 / + diff --git a/applications/linear_model/optimisation/esnz-cascade/psykal/global.py b/applications/linear_model/optimisation/esnz-cascade/psykal/global.py deleted file mode 100644 index 125a77f40..000000000 --- a/applications/linear_model/optimisation/esnz-cascade/psykal/global.py +++ /dev/null @@ -1,32 +0,0 @@ -############################################################################## -# Copyright (c) 2017, Met Office, on behalf of HMSO and Queen's Printer -# For further details please refer to the file LICENCE.original which you -# should have received as part of this distribution. -############################################################################## - - -''' -PSyclone transformation script for the LFRic (Dynamo0p3) API to apply -colouring, OpenMP and redundant computation to the level-1 halo for -the initialisation built-ins generically. - -''' - -from psyclone_tools import (redundant_computation_setval, colour_loops, - openmp_parallelise_loops, - view_transformed_schedule) - - -def trans(psyir): - ''' - Applies PSyclone colouring, OpenMP and redundant computation - transformations. - - :param psyir: the PSyIR of the PSyIR-layer. - :type psyir: :py:class:`psyclone.psyir.nodes.FileContainer` - - ''' - redundant_computation_setval(psyir) - colour_loops(psyir) - openmp_parallelise_loops(psyir) - view_transformed_schedule(psyir) diff --git a/applications/linear_model/optimisation/meto-azspice b/applications/linear_model/optimisation/meto-azspice deleted file mode 120000 index 146775380..000000000 --- a/applications/linear_model/optimisation/meto-azspice +++ /dev/null @@ -1 +0,0 @@ -meto-ex1a/ \ No newline at end of file diff --git a/applications/linear_model/optimisation/meto-ex1a/psykal/global.py b/applications/linear_model/optimisation/meto-ex1a/psykal/global.py deleted file mode 100644 index 125a77f40..000000000 --- a/applications/linear_model/optimisation/meto-ex1a/psykal/global.py +++ /dev/null @@ -1,32 +0,0 @@ -############################################################################## -# Copyright (c) 2017, Met Office, on behalf of HMSO and Queen's Printer -# For further details please refer to the file LICENCE.original which you -# should have received as part of this distribution. -############################################################################## - - -''' -PSyclone transformation script for the LFRic (Dynamo0p3) API to apply -colouring, OpenMP and redundant computation to the level-1 halo for -the initialisation built-ins generically. - -''' - -from psyclone_tools import (redundant_computation_setval, colour_loops, - openmp_parallelise_loops, - view_transformed_schedule) - - -def trans(psyir): - ''' - Applies PSyclone colouring, OpenMP and redundant computation - transformations. - - :param psyir: the PSyIR of the PSyIR-layer. - :type psyir: :py:class:`psyclone.psyir.nodes.FileContainer` - - ''' - redundant_computation_setval(psyir) - colour_loops(psyir) - openmp_parallelise_loops(psyir) - view_transformed_schedule(psyir) diff --git a/applications/linear_model/optimisation/minimum/psykal/global.py b/applications/linear_model/optimisation/minimum/psykal/global.py deleted file mode 100644 index 5ea0bf84d..000000000 --- a/applications/linear_model/optimisation/minimum/psykal/global.py +++ /dev/null @@ -1,31 +0,0 @@ -############################################################################## -# (c) Crown copyright 2023 Met Office. All rights reserved. -# The file LICENCE, distributed with this code, contains details of the terms -# under which the code may be used. -############################################################################## - - -''' -PSyclone transformation script for the LFRic (Dynamo0p3) API to apply -the minumum set of transformations required to permit the application -to run safely in debug mode on all supported platforms. - -Applying the 'redundant_computation_setval' transformation for the -initialisation built-ins permits developers to set safe values in halos. - -''' -from psyclone_tools import (redundant_computation_setval, - view_transformed_schedule) - - -def trans(psyir): - ''' - Applies PSyclone redundant computation transformations on - initialisation built-ins only. - - :param psyir: the PSyIR of the PSyIR-layer. - :type psyir: :py:class:`psyclone.psyir.nodes.FileContainer` - - ''' - redundant_computation_setval(psyir) - view_transformed_schedule(psyir) diff --git a/applications/linear_model/optimisation/nci-gadi/psykal/global.py b/applications/linear_model/optimisation/nci-gadi/psykal/global.py deleted file mode 120000 index 7246d03a8..000000000 --- a/applications/linear_model/optimisation/nci-gadi/psykal/global.py +++ /dev/null @@ -1 +0,0 @@ -./../../meto-ex1a/psykal/global.py \ No newline at end of file diff --git a/rose-stem/flow.cylc b/rose-stem/flow.cylc index de38992a1..02b40dfc6 100644 --- a/rose-stem/flow.cylc +++ b/rose-stem/flow.cylc @@ -91,6 +91,7 @@ # Check if running physics - don't extract these if not {% if "lfric_atm" in requested_applications or "jules" in requested_applications + or "linear_model" in requested_applications or "ngarch" in requested_applications or "lfric_coupled" in requested_applications %} diff --git a/rose-stem/site/meto/common/default_directives.cylc b/rose-stem/site/meto/common/default_directives.cylc index f861939eb..21a2f8fb7 100644 --- a/rose-stem/site/meto/common/default_directives.cylc +++ b/rose-stem/site/meto/common/default_directives.cylc @@ -18,6 +18,9 @@ "lfric_atm": { "build_wallclock": 45, }, + "linear_model": { + "build_wallclock": 45, + }, "jules": { "build_wallclock": 35, }, @@ -45,6 +48,9 @@ "lfric_atm": { "build_wallclock": 60, }, + "linear_model": { + "build_wallclock": 60, + }, "lfric_coupled": { "build_wallclock": 60, }, diff --git a/science/gungho/source/algorithm/initialisation/init_physics_prognostics_alg_mod.X90 b/science/gungho/source/algorithm/initialisation/init_physics_prognostics_alg_mod.X90 index f43c0e5a0..9a116271c 100644 --- a/science/gungho/source/algorithm/initialisation/init_physics_prognostics_alg_mod.X90 +++ b/science/gungho/source/algorithm/initialisation/init_physics_prognostics_alg_mod.X90 @@ -22,9 +22,25 @@ module init_physics_prognostics_alg_mod use init_aerosol_fields_alg_mod, only : init_aerosol_fields_alg use init_stph_fields_alg_mod, only : init_stph_fields_alg - use section_choice_config_mod, only: surface, surface_jules, & - aerosol, aerosol_um, & - electric, electric_um + use section_choice_config_mod, only: surface, surface_jules, & + surface_none, & + aerosol, aerosol_um, & + aerosol_none, & + cloud, cloud_none, & + microphysics, & + microphysics_none, & + radiation, & + radiation_none, & + convection, & + convection_none, & + orographic_drag, & + orographic_drag_none, & + boundary_layer, & + boundary_layer_none, & + stochastic_physics, & + stochastic_physics_none, & + electric, electric_um, & + electric_none use aerosol_config_mod, only: glomap_mode, & glomap_mode_dust_and_clim, & @@ -87,37 +103,44 @@ contains #ifdef UM_PHYSICS - ! Only actually initialise the fields if we're using the external code - ! Most things need calling regardless of whether the scheme is on, - ! because we initialise fields used by other schemes if the scheme - ! is off. Jules however can only be initialised if it is switched on - ! as it uses things from the surface namelist which is not read if - ! it is switched off. - call init_radiation_fields_alg(radiation_fields) - call init_microphysics_fields_alg(microphysics_fields) - if (electric == electric_um) then - call init_electric_fields_alg(electric_fields) + if ( surface /= surface_none .or. & + radiation /= radiation_none .or. & + orographic_drag /= orographic_drag_none .or. & + stochastic_physics /= stochastic_physics_none .or. & + boundary_layer /= boundary_layer_none ) then + + ! Only actually initialise the fields if we're using the external code + ! Most things need calling regardless of whether the scheme is on, + ! because we initialise fields used by other schemes if the scheme + ! is off. Jules however can only be initialised if it is switched on + ! as it uses things from the surface namelist which is not read if + ! it is switched off. + call init_radiation_fields_alg(radiation_fields) + call init_microphysics_fields_alg(microphysics_fields) + if (electric == electric_um) then + call init_electric_fields_alg(electric_fields) + end if + call init_orography_fields_alg(orography_fields) + call init_turbulence_fields_alg(turbulence_fields) + call init_convection_fields_alg(convection_fields) + call init_cloud_fields_alg(cloud_fields) + call init_surface_fields_alg(surface_fields) + if (surface == surface_jules) then + call init_soil_fields_alg(soil_fields) + call init_snow_fields_alg(snow_fields) + end if + if ( ( aerosol == aerosol_um .and. & + ( glomap_mode == glomap_mode_ukca .or. & + glomap_mode == glomap_mode_dust_and_clim ) ) .or. & + ( chem_scheme == chem_scheme_flexchem ) ) then + call init_chemistry_fields_alg(chemistry_fields) + end if + call init_aerosol_fields_alg(aerosol_fields) + + call init_stph_fields_alg(stph_fields) + + call log_event( 'Physics field collections initialised', LOG_LEVEL_INFO ) end if - call init_orography_fields_alg(orography_fields) - call init_turbulence_fields_alg(turbulence_fields) - call init_convection_fields_alg(convection_fields) - call init_cloud_fields_alg(cloud_fields) - call init_surface_fields_alg(surface_fields) - if (surface == surface_jules) then - call init_soil_fields_alg(soil_fields) - call init_snow_fields_alg(snow_fields) - end if - if ( ( aerosol == aerosol_um .and. & - ( glomap_mode == glomap_mode_ukca .or. & - glomap_mode == glomap_mode_dust_and_clim ) ) .or. & - ( chem_scheme == chem_scheme_flexchem ) ) then - call init_chemistry_fields_alg(chemistry_fields) - end if - call init_aerosol_fields_alg(aerosol_fields) - - call init_stph_fields_alg(stph_fields) - - call log_event( 'Physics field collections initialised', LOG_LEVEL_INFO ) #endif diff --git a/science/gungho/source/driver/create_physics_prognostics_mod.F90 b/science/gungho/source/driver/create_physics_prognostics_mod.F90 index 6e6545f72..cc4e98025 100644 --- a/science/gungho/source/driver/create_physics_prognostics_mod.F90 +++ b/science/gungho/source/driver/create_physics_prognostics_mod.F90 @@ -52,18 +52,29 @@ module create_physics_prognostics_mod easyaerosol_sw, easyaerosol_lw, & murk_prognostic, murk use section_choice_config_mod, only : cloud, cloud_um, & + cloud_none, & aerosol, aerosol_um, & + aerosol_none, & radiation, radiation_socrates, & + radiation_none, & boundary_layer, & boundary_layer_um, & + boundary_layer_none, & electric, electric_um, & + electric_none, & iau_sst, & surface, surface_jules, & + surface_none, & orographic_drag, & orographic_drag_um, & + orographic_drag_none, & convection, convection_um, & + convection_none, & + microphysics, & + microphysics_none, & stochastic_physics, & - stochastic_physics_um + stochastic_physics_um, & + stochastic_physics_none use cloud_config_mod, only : scheme, & scheme_pc2 use convection_config_mod, only : cv_scheme, cv_scheme_comorph @@ -209,6 +220,13 @@ subroutine process_physics_prognostics(processor) end if #ifdef UM_PHYSICS + + if ( surface /= surface_none .or. & + radiation /= radiation_none .or. & + orographic_drag /= orographic_drag_none .or. & + stochastic_physics /= stochastic_physics_none .or. & + boundary_layer /= boundary_layer_none ) then + !======================================================================== ! Fields owned by the radiation scheme !======================================================================== @@ -1882,6 +1900,8 @@ subroutine process_physics_prognostics(processor) twod=.true., is_int=.true., ckp=checkpoint_flag, empty=is_empty)) end if + end if + #endif diff --git a/science/gungho/source/driver/gungho_driver_mod.F90 b/science/gungho/source/driver/gungho_driver_mod.F90 index cb77b425d..2aa6193e3 100644 --- a/science/gungho/source/driver/gungho_driver_mod.F90 +++ b/science/gungho/source/driver/gungho_driver_mod.F90 @@ -18,9 +18,10 @@ module gungho_driver_mod use gungho_diagnostics_driver_mod, & only : gungho_diagnostics_driver use iau_time_control_mod, only : calc_iau_ts_end - use gungho_init_fields_mod, only : create_model_data, & - initialise_model_data, & - output_model_data, & + use gungho_init_fields_mod, only : create_model_data, & + create_physics_model_data, & + initialise_model_data, & + output_model_data, & finalise_model_data use driver_modeldb_mod, only : modeldb_type use gungho_model_mod, only : initialise_infrastructure, & @@ -229,6 +230,9 @@ subroutine initialise( program_name, modeldb ) call create_model_data( modeldb, & mesh, twod_mesh, & aerosol_mesh, aerosol_twod_mesh ) + call create_physics_model_data( modeldb, & + mesh, twod_mesh, & + aerosol_mesh, aerosol_twod_mesh ) ! Set up io for multifile reading if ( multifile_io ) then diff --git a/science/gungho/source/driver/gungho_init_fields_mod.X90 b/science/gungho/source/driver/gungho_init_fields_mod.X90 index 829eaf802..f37186a85 100644 --- a/science/gungho/source/driver/gungho_init_fields_mod.X90 +++ b/science/gungho/source/driver/gungho_init_fields_mod.X90 @@ -158,7 +158,7 @@ module gungho_init_fields_mod ! Set these to select how to initialize model prognostic fields integer(i_def) :: prognostic_init_choice, ancil_choice - public create_model_data, finalise_model_data, & + public create_model_data, create_physics_model_data, finalise_model_data, & initialise_model_data, output_model_data contains @@ -321,11 +321,11 @@ contains !> @param[in] twod_mesh The current 2d mesh !> @param[in] aerosol_mesh Aerosol 3d mesh !> @param[in] aerosol_twod_mesh Aerosol 2d mesh -subroutine create_model_data( modeldb, & - mesh, & - twod_mesh, & - aerosol_mesh, & - aerosol_twod_mesh ) + subroutine create_model_data( modeldb, & + mesh, & + twod_mesh, & + aerosol_mesh, & + aerosol_twod_mesh ) implicit none @@ -521,7 +521,45 @@ subroutine create_model_data( modeldb, & call create_physics_prognostics( mesh, twod_mesh, aerosol_mesh, aerosol_twod_mesh, field_mapper, & modeldb%clock ) + end if + + end subroutine create_model_data + + !------------------------------------------------------------------------------ + !> @brief Create the additional fields contained in model_data that are + !! only required by runs that use physics. + !> @param[inout] modeldb The working data set for a model run + !> @param[in] mesh The current 3d mesh + !> @param[in] twod_mesh The current 2d mesh + !> @param[in] aerosol_mesh Aerosol 3d mesh + !> @param[in] aerosol_twod_mesh Aerosol 2d mesh + subroutine create_physics_model_data( modeldb, & + mesh, & + twod_mesh, & + aerosol_mesh, & + aerosol_twod_mesh ) + + + implicit none + + type( modeldb_type ), intent(inout) :: modeldb + type( mesh_type ), intent(in), pointer :: mesh + type( mesh_type ), intent(in), pointer :: twod_mesh + type( mesh_type ), intent(in), pointer :: aerosol_mesh + type( mesh_type ), intent(in), pointer :: aerosol_twod_mesh + + type(field_collection_type), pointer :: depository + type(field_collection_type), pointer :: fd_fields + type(field_collection_type), pointer :: ancil_fields + type(gungho_time_axes_type), pointer :: model_axes + + model_axes => get_time_axes_from_collection(modeldb%values, "model_axes" ) + depository => modeldb%fields%get_field_collection("depository") + fd_fields => modeldb%fields%get_field_collection("fd_fields") + ancil_fields => modeldb%fields%get_field_collection("ancil_fields") + #ifdef UM_PHYSICS + if (use_physics) then ! Create FD prognostic fields select case ( prognostic_init_choice ) case ( init_option_fd_start_dump ) @@ -544,10 +582,10 @@ subroutine create_model_data( modeldb, & ancil_fields, & mesh, twod_mesh ) end select -#endif end if +#endif - end subroutine create_model_data + end subroutine create_physics_model_data !------------------------------------------------------------------------------ !> @brief Initialises the working data set dependent of namelist diff --git a/science/linear/source/driver/linear_diagnostics_driver_mod.F90 b/science/linear/source/driver/linear_diagnostics_driver_mod.F90 index 287724c3b..fadbaa713 100644 --- a/science/linear/source/driver/linear_diagnostics_driver_mod.F90 +++ b/science/linear/source/driver/linear_diagnostics_driver_mod.F90 @@ -8,65 +8,166 @@ module linear_diagnostics_driver_mod - use constants_mod, only : i_def, str_def + use constants_mod, only : i_def, str_def, l_def + use diagnostic_alg_mod, only : column_total_diagnostics_alg, & + calc_wbig_diagnostic_alg, & + pressure_diag_alg use diagnostics_io_mod, only : write_scalar_diagnostic, & write_vector_diagnostic use field_collection_mod, only : field_collection_type + use field_collection_iterator_mod, & + only : field_collection_iterator_type use driver_modeldb_mod, only : modeldb_type use field_array_mod, only : field_array_type use field_mod, only : field_type - use formulation_config_mod, only : moisture_formulation, & + use field_parent_mod, only : field_parent_type, write_interface + use formulation_config_mod, only : use_physics, & + moisture_formulation, & moisture_formulation_dry + use fs_continuity_mod, only : W3, Wtheta use mesh_mod, only : mesh_type use mr_indices_mod, only : nummr, mr_names use initialization_config_mod, only : ls_option, & ls_option_file + use initialise_diagnostics_mod, & + only : diagnostic_to_be_sampled + use io_value_mod, only : io_value_type, get_io_value + use io_config_mod, only : use_xios_io, write_fluxes, & + write_diag use log_mod, only : log_event, & LOG_LEVEL_INFO use linear_config_mod, only : ls_read_w2h + use lfric_xios_write_mod, only : write_field_generic + use sci_geometric_constants_mod, & + only : get_panel_id implicit none private - public linear_diagnostics_driver + public linear_write_initial_output, & + linear_diagnostics_driver contains - !> @brief Outputs simple diagnostics from Linear model - !> @param[in] mesh The primary mesh - !> @param[in] modeldb The working data set for the model run - !> @param[in] nodal_output_on_w3 Flag that determines if vector fields + + !> @brief Outputs simple diagnostics from Gungho/LFRic + !> + !> @param[in,out] modeldb Working data set of model. + !> @param[in] mesh The primary mesh + !> @param[in] twod_mesh The 2d mesh + !> @param[in] io_context_name The name of the IO context for writing + !> @param[in] nodal_output_on_w3 Flag that determines if vector fields !> should be projected to W3 for nodal output - subroutine linear_diagnostics_driver( mesh, & - modeldb, & + !> + subroutine linear_write_initial_output( modeldb, mesh, twod_mesh, & + io_context_name, nodal_output_on_w3 ) + +#ifdef USE_XIOS + !>@todo This will be removed by #3321 + use lfric_xios_context_mod, only : lfric_xios_context_type + use lfric_xios_action_mod, only : advance +#endif + + implicit none + + class(modeldb_type), intent(inout) :: modeldb + type(mesh_type), pointer, intent(in) :: mesh + type(mesh_type), pointer, intent(in) :: twod_mesh + character(*), intent(in) :: io_context_name + logical(l_def), intent(in) :: nodal_output_on_w3 +#ifdef USE_XIOS + type(lfric_xios_context_type), pointer :: io_context + ! Call clock initial step before initial conditions output + if (modeldb%clock%is_initialisation() .and. use_xios_io) then + call modeldb%io_contexts%get_io_context(io_context_name, io_context) + call advance(io_context, modeldb%clock) + end if +#endif + + if (modeldb%clock%is_initialisation() .and. write_diag) then + ! Calculation and output of initial conditions + call linear_diagnostics_driver( modeldb, & + mesh, & + twod_mesh, & + nodal_output_on_w3 ) + + end if + + end subroutine linear_write_initial_output + + !> @brief Outputs simple diagnostics from linear model + !> @param[in,out] modeldb Working data set of model run. + !> @param[in] mesh The primary mesh + !> @param[in] twod_mesh The 2d mesh + !> @param[in] nodal_output_on_w3 Flag that determines if vector fields + !> should be projected to W3 for nodal output + subroutine linear_diagnostics_driver( modeldb, & + mesh, & + twod_mesh, & nodal_output_on_w3 ) implicit none type(mesh_type), intent(in), pointer :: mesh + type(mesh_type), intent(in), pointer :: twod_mesh type(modeldb_type), intent(in), target :: modeldb logical, intent(in) :: nodal_output_on_w3 + + type(field_collection_type), pointer :: prognostic_fields type(field_collection_type), pointer :: moisture_fields => null() - type(field_array_type), pointer :: ls_mr_array => null() + type(field_type), pointer :: mr(:) + type(field_collection_type), pointer :: derived_fields + type(field_array_type), pointer :: ls_mr_array => null() + type(field_collection_type), pointer :: ls_fields + type(field_type), pointer :: ls_mr(:) => null() + + type(field_type), pointer :: theta + type(field_type), pointer :: u + type(field_type), pointer :: rho + type(field_type), pointer :: exner + type(field_type), pointer :: panel_id + type(field_type), pointer :: u_in_w2h + type(field_type), pointer :: v_in_w2h + type(field_type), pointer :: w_in_wth + type(field_type), pointer :: exner_in_wth + + type(field_array_type), pointer :: mr_array + + type(field_type), pointer :: ls_theta => null() + type(field_type), pointer :: ls_u => null() + type(field_type), pointer :: ls_rho => null() + type(field_type), pointer :: ls_exner => null() + type(field_type), pointer :: ls_v_u => null() + type(field_type), pointer :: ls_h_u => null() - type( field_collection_type ), pointer :: ls_fields - type( field_type ), pointer :: ls_mr(:) => null() + ! Iterator for field collection + type(field_collection_iterator_type) :: iterator - type( field_type), pointer :: ls_theta => null() - type( field_type), pointer :: ls_u => null() - type( field_type), pointer :: ls_rho => null() - type( field_type), pointer :: ls_exner => null() - type( field_type), pointer :: ls_v_u => null() - type( field_type), pointer :: ls_h_u => null() + ! A pointer used for retrieving fields from collections + ! when iterating over them + class(field_parent_type), pointer :: field_ptr + procedure(write_interface), pointer :: tmp_write_ptr + type(io_value_type), pointer :: temp_corr_io_value - integer :: i + integer :: i, fs + character(len=str_def) :: name call log_event("Linear: writing diagnostic output", LOG_LEVEL_INFO) + prognostic_fields => modeldb%fields%get_field_collection("prognostic_fields") ls_fields => modeldb%fields%get_field_collection("ls_fields") moisture_fields => modeldb%fields%get_field_collection("moisture_fields") + call moisture_fields%get_field("mr", mr_array) + mr => mr_array%bundle call moisture_fields%get_field("ls_mr", ls_mr_array) ls_mr => ls_mr_array%bundle + derived_fields => modeldb%fields%get_field_collection("derived_fields") + panel_id => get_panel_id(mesh%get_id()) + + call prognostic_fields%get_field('theta', theta) + call prognostic_fields%get_field('u', u) + call prognostic_fields%get_field('rho', rho) + call prognostic_fields%get_field('exner', exner) call ls_fields%get_field('ls_theta', ls_theta) call ls_fields%get_field('ls_u', ls_u) @@ -74,6 +175,12 @@ subroutine linear_diagnostics_driver( mesh, & call ls_fields%get_field('ls_exner', ls_exner) ! Scalar fields + call write_scalar_diagnostic('rho', rho, & + modeldb%clock, mesh, nodal_output_on_w3) + call write_scalar_diagnostic('theta', theta, & + modeldb%clock, mesh, nodal_output_on_w3) + call write_scalar_diagnostic('exner', exner, & + modeldb%clock, mesh, nodal_output_on_w3) call write_scalar_diagnostic('ls_rho', ls_rho, & modeldb%clock, mesh, nodal_output_on_w3) call write_scalar_diagnostic('ls_theta', ls_theta, & @@ -82,6 +189,40 @@ subroutine linear_diagnostics_driver( mesh, & modeldb%clock, mesh, nodal_output_on_w3) ! Vector fields + if (use_physics .and. use_xios_io .and. .not. write_fluxes) then + ! These have already been calculated, so no need to recalculate them + call derived_fields%get_field('u_in_w2h', u_in_w2h) + call derived_fields%get_field('v_in_w2h', v_in_w2h) + call derived_fields%get_field('w_in_wth', w_in_wth) + tmp_write_ptr => write_field_generic + call u_in_w2h%set_write_behaviour(tmp_write_ptr) + call v_in_w2h%set_write_behaviour(tmp_write_ptr) + if (modeldb%clock%is_initialisation()) then + if (diagnostic_to_be_sampled("init_u_in_w2h")) then + call u_in_w2h%write_field("init_u_in_w2h") + end if + if (diagnostic_to_be_sampled("init_v_in_w2h")) then + call v_in_w2h%write_field("init_v_in_w2h") + end if + if (diagnostic_to_be_sampled("init_w_in_wth")) then + call w_in_wth%write_field("init_w_in_wth") + end if + else + if (diagnostic_to_be_sampled("u_in_w2h")) then + call u_in_w2h%write_field("u_in_w2h") + end if + if (diagnostic_to_be_sampled("v_in_w2h")) then + call v_in_w2h%write_field("v_in_w2h") + end if + if (diagnostic_to_be_sampled("w_in_wth")) then + call w_in_wth%write_field("w_in_wth") + end if + end if + else + call write_vector_diagnostic('u', u, & + modeldb%clock, mesh, nodal_output_on_w3) + end if + call write_vector_diagnostic('ls_u', ls_u, & modeldb%clock, mesh, nodal_output_on_w3) @@ -107,6 +248,43 @@ subroutine linear_diagnostics_driver( mesh, & end do end if + ! Derived physics fields (only those on W3 or Wtheta) + if (use_physics .and. use_xios_io .and. .not. modeldb%clock%is_initialisation()) then + field_ptr => null() + call iterator%initialise(derived_fields) + do + if ( .not.iterator%has_next() ) exit + field_ptr => iterator%next() + select type(field_ptr) + type is (field_type) + fs = field_ptr%which_function_space() + if ( fs == W3 .or. fs == Wtheta ) then + name = trim(adjustl( field_ptr%get_name() )) + if (diagnostic_to_be_sampled(trim(name))) & + call field_ptr%write_field(trim(name)) + end if + end select + end do + field_ptr => null() + + ! Get w_in_wth for WBig calculation + call derived_fields%get_field('w_in_wth', w_in_wth) + call calc_wbig_diagnostic_alg(w_in_wth, mesh) + + ! Pressure diagnostics + call prognostic_fields%get_field('exner', exner) + call pressure_diag_alg(exner) + + call derived_fields%get_field('exner_in_wth', exner_in_wth) + call pressure_diag_alg(exner_in_wth) + + temp_corr_io_value => get_io_value( modeldb%values, 'temperature_correction_io_value') + call column_total_diagnostics_alg(rho, mr, derived_fields, exner, & + mesh, twod_mesh, & + temp_corr_io_value%data(1)) + + end if + end subroutine linear_diagnostics_driver end module linear_diagnostics_driver_mod diff --git a/science/linear/source/driver/linear_driver_mod.f90 b/science/linear/source/driver/linear_driver_mod.f90 index aac98282d..e4164e273 100644 --- a/science/linear/source/driver/linear_driver_mod.f90 +++ b/science/linear/source/driver/linear_driver_mod.f90 @@ -15,8 +15,6 @@ module linear_driver_mod use io_value_mod, only : io_value_type use section_choice_config_mod, only : stochastic_physics, & stochastic_physics_um - use gungho_diagnostics_driver_mod, & - only : gungho_diagnostics_driver use gungho_model_mod, only : initialise_infrastructure, & initialise_model, & finalise_infrastructure, & @@ -31,7 +29,6 @@ module linear_driver_mod use gungho_time_axes_mod, only : gungho_time_axes_type, & get_time_axes_from_collection use init_fd_prognostics_mod, only : init_fd_prognostics_dump - use initial_output_mod, only : write_initial_output use initialization_config_mod, only : init_option_fd_start_dump, & ls_option_file use io_context_mod, only : io_context_type @@ -45,7 +42,8 @@ module linear_driver_mod use linear_model_mod, only : initialise_linear_model, & finalise_linear_model use linear_diagnostics_driver_mod, & - only : linear_diagnostics_driver + only : linear_diagnostics_driver, & + linear_write_initial_output use linear_step_mod, only : linear_step use linear_data_algorithm_mod, only : update_ls_file_alg use mesh_mod, only : mesh_type @@ -188,8 +186,8 @@ subroutine initialise( program_name, modeldb ) nodal_output_on_w3 = modeldb%config%io%nodal_output_on_w3() ! Initial output - call write_initial_output( modeldb, mesh, twod_mesh, & - io_context_name, nodal_output_on_w3 ) + call linear_write_initial_output( modeldb, mesh, twod_mesh, & + io_context_name, nodal_output_on_w3 ) ! Linear model configuration initialisation call initialise_linear_model( mesh, & @@ -259,11 +257,10 @@ subroutine step( modeldb ) .and. ( write_diag ) ) then ! Calculation and output diagnostics - call gungho_diagnostics_driver( modeldb, mesh, twod_mesh, & - nodal_output_on_w3 ) - call linear_diagnostics_driver( mesh, & - modeldb, & + call linear_diagnostics_driver( modeldb, & + mesh, & + twod_mesh, & nodal_output_on_w3 ) end if