From 527d96f629276893e02bd8d700c2622ab21474be Mon Sep 17 00:00:00 2001 From: Dom Heinzeller Date: Wed, 9 May 2018 14:06:37 -0600 Subject: [PATCH] Nemsfv3gfs master ccpp integration (#63) This PR enables the integration of ccpp-framework (and ccpp-physics) in the current trunk of FV3 in directories ccpp/{framework,physics}. Most changes are required for the build system so that it can be used with the existing SCM and with FV3 (current trunk). For the FV3-current trunk, the cmake configuration is cleaner and streamlined between the different CMakeLists.txt (and with ccpp-physics). To avoid introducing all these changes for SCM at the same time, the current - to be improved - cmake config for SCM is retained. A new variable PROJECT is introduced that allows to distinguish between different builds (currently 'CCPP-FV3' for FV3-current trunk and default='unknown' for SCM). The cmake build system needs to be reworked, best would be to introduce project 'CCPP-SCM' for the SCM build and use 'unknown' for building the CCPP standalone. A new attribute 'initialized' is introduced for type ccpp_t (cdata structure) to test the initialization state of cdata. This is required for calling fast physics in FV3 dynamics through CCPP. For FV3-current trunk, the list of schemes and their dependencies and their caps is written to makefile and cmakefile snippets and used during the cmake build of ccpp-physics (as opposed to FV3v0, where only the auto-generated list of caps is used, or SCM where all of it is hardcoded). This requires minor changes to the Python prebuild script and configs. This PR is related to several others listed in a follow-up comment. Results are bit-for-bit identical with FV3v0 and SCM. --- CMakeLists.txt | 51 ++-- doc/CMakeLists.txt | 4 - examples/suite_FV3_test.xml | 11 + examples/suite_scm_GFS_test.xml | 2 +- schemes/CMakeLists.txt | 7 + schemes/check/CMakeLists.txt | 36 ++- scripts/ccpp_prebuild.py | 34 ++- ...g_FV3.py => ccpp_prebuild_config_FV3v0.py} | 15 +- scripts/ccpp_prebuild_config_FV3v1.py | 230 ++++++++++++++++++ scripts/ccpp_prebuild_config_SCM.py | 11 +- scripts/mkcap.py | 84 +++++++ src/CMakeLists.txt | 62 +++-- src/ccpp.F90 | 29 ++- src/ccpp_api.F90 | 6 +- src/ccpp_types.F90 | 1 + 15 files changed, 506 insertions(+), 77 deletions(-) create mode 100644 examples/suite_FV3_test.xml rename scripts/{ccpp_prebuild_config_FV3.py => ccpp_prebuild_config_FV3v0.py} (93%) create mode 100755 scripts/ccpp_prebuild_config_FV3v1.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c0eef4d..a4ff9319 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,23 @@ +# Set default project to unknown +if(NOT PROJECT) + message(STATUS "Setting CCPP project to 'unknown' as none was specified.") + set(PROJECT "Unknown") +endif (NOT PROJECT) + +#------------------------------------------------------------------------------ cmake_minimum_required(VERSION 2.8.11) +# Use rpaths on MacOSX +set(CMAKE_MACOSX_RPATH 1) + if(POLICY CMP0048) cmake_policy(SET CMP0048 NEW) - project(ccpp VERSION 0.1.0) + project(ccpp VERSION 1.0.0) else(POLICY CMP0048) project(ccpp) - set(PROJECT_VERSION 0.1.0) - set(PROJECT_VERSION_MAJOR 0) - set(PROJECT_VERSION_MINOR 1) + set(PROJECT_VERSION 1.0.0) + set(PROJECT_VERSION_MAJOR 1) + set(PROJECT_VERSION_MINOR 0) set(PROJECT_VERSION_PATCH 0) endif(POLICY CMP0048) @@ -21,19 +31,10 @@ enable_language(Fortran) #------------------------------------------------------------------------------ # Set package definitions -set(PACKAGE "CCPP") -set(AUTHORS "Timothy Brown" "David Gill" "Dom Heinzeller") +set(PACKAGE "ccpp-framework") +set(AUTHORS "Dom Heinzeller" "Timothy Brown" "David Gill") string(TIMESTAMP YEAR "%Y") -#------------------------------------------------------------------------------ -# The PGI compiler can not find any cap routines in their library. -# This is due to how it labels subroutines within a modules. -# For example the subroutine b() in the moduel a(), gets named a_b. -# GCC and Intel do NOT do this, it is name simply as b. -if ("${CMAKE_Fortran_COMPILER_ID}" STREQUAL "PGI") - message(STATUS "WARNING: PGI compiler is not fully ISO_C compliant; working solution involves a hack pgifix.py") -endif() - #------------------------------------------------------------------------------ # CMake Modules # Set the CMake module path @@ -72,8 +73,16 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" - "MinSizeRel" "RelWithDebInfo") + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "Coverage") +endif() + +#------------------------------------------------------------------------------ +# The PGI compiler can not find any cap routines in their library. +# This is due to how it labels subroutines within a modules. +# For example the subroutine b() in the moduel a(), gets named a_b. +# GCC and Intel do NOT do this, it is name simply as b. +if ("${CMAKE_Fortran_COMPILER_ID}" MATCHES "PGI") + message(STATUS "WARNING: PGI compiler is not fully ISO_C compliant; working solution involves a hack pgifix.py") endif() #------------------------------------------------------------------------------ @@ -82,7 +91,7 @@ option(BUILD_SHARED_LIBS "Build a shared library" ON) #------------------------------------------------------------------------------ # Enable code coverage -if(CMAKE_COMPILER_IS_GNUCC AND (CMAKE_BUILD_TYPE STREQUAL "Coverage")) +if ("${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU" AND (CMAKE_BUILD_TYPE STREQUAL "Coverage")) include(code_coverage) list(APPEND LIBS "gcov") endif() @@ -102,8 +111,8 @@ add_subdirectory(schemes) #------------------------------------------------------------------------------ # Configure and enable packaging -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Common Community Phyics Package") -set(CPACK_PACKAGE_VENDOR "DTC NCAR") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Common Community Physics Package - Framework") +set(CPACK_PACKAGE_VENDOR "GMTB NOAA/NCAR") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) @@ -115,7 +124,5 @@ set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") set(CPACK_SOURCE_GENERATOR "TBZ2") set(CPACK_GENERATOR "TBZ2") -#set(CPACK_GENERATOR "DEB") -#set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Timothy Brown") include(CPack) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index d77e0491..b5005ed9 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -23,9 +23,5 @@ if(BUILD_DOCUMENTATION) WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM) - -# Define where to install the documentation - install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html - DESTINATION share/doc/${PROJECT_NAME}) endif() diff --git a/examples/suite_FV3_test.xml b/examples/suite_FV3_test.xml new file mode 100644 index 00000000..14ad4bce --- /dev/null +++ b/examples/suite_FV3_test.xml @@ -0,0 +1,11 @@ + + + + FV3_test_init + + + FV3_test_run + + + FV3_test_finalize + diff --git a/examples/suite_scm_GFS_test.xml b/examples/suite_scm_GFS_test.xml index f1fe8a71..14959224 100644 --- a/examples/suite_scm_GFS_test.xml +++ b/examples/suite_scm_GFS_test.xml @@ -1,6 +1,6 @@ - + GFS_initialize_scm_run diff --git a/schemes/CMakeLists.txt b/schemes/CMakeLists.txt index 41b39d94..c1443451 100644 --- a/schemes/CMakeLists.txt +++ b/schemes/CMakeLists.txt @@ -1,3 +1,9 @@ +# Set default project to unknown +if(NOT PROJECT) + message(STATUS "Setting CCPP project to 'unknown' as none was specified.") + set(PROJECT "Unknown") +endif (NOT PROJECT) + #------------------------------------------------------------------------------ # Add all the physics schemes in their own sub-directory (a.k.a repos) #------------------------------------------------------------------------------ @@ -16,6 +22,7 @@ ExternalProject_Add( INSTALL_COMMAND "" CMAKE_ARGS -DCCPP_INCLUDE_DIRS=${CCPP_INCLUDE_DIRS} -DCCPP_LIB_DIRS=${CCPP_LIB_DIRS} + -DPROJECT=${PROJECT} -DCCPP_MKCAP=${CMAKE_CURRENT_SOURCE_DIR}/mkcap.py -DCMAKE_Fortran_FLAGS=${CMAKE_Fortran_FLAGS} -DCMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS=${CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS} diff --git a/schemes/check/CMakeLists.txt b/schemes/check/CMakeLists.txt index 4a5d4b34..6a1502ff 100644 --- a/schemes/check/CMakeLists.txt +++ b/schemes/check/CMakeLists.txt @@ -1,6 +1,16 @@ +# Set default project to unknown +if(NOT PROJECT) + message(STATUS "Setting CCPP project to 'unknown' as none was specified.") + set(PROJECT "Unknown") +endif (NOT PROJECT) + # Use rpaths on MacOSX set(CMAKE_MACOSX_RPATH 1) +message (INFO "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}") +message (INFO "CMAKE_CURRENT_BINARY_DIR: ${CMAKE_CURRENT_BINARY_DIR}") +#message (FATAL_ERROR "BLA") + #------------------------------------------------------------------------------ cmake_minimum_required(VERSION 2.8.11) @@ -34,15 +44,23 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake") option(BUILD_SHARED_LIBS "Build a shared library" ON) #------------------------------------------------------------------------------ -# Add the CCPP include/module directory -set(CCPP_INCLUDE_DIRS "" CACHE FILEPATH "Path to ccpp includes") -set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES ${CCPP_INCLUDE_DIRS}) - -#------------------------------------------------------------------------------ -# Add the CCPP library -set(CCPP_LIB_DIRS "" CACHE FILEPATH "Path to ccpp library") -link_directories(${CCPP_LIB_DIRS}) -list(APPEND LIBS "ccpp") +# Add the CCPP include/module directory and libraries, currently depends on build +# see FV3_current_trunk/ccpp/CMakeLists.txt on how to set CCPP_INCLUDE_DIRS etc. +if (PROJECT MATCHES "CCPP-FV3") + # Add the CCPP include/module directory + set(CCPP_INCLUDE_DIRS "" CACHE FILEPATH "Path to ccpp includes") + set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES ${CCPP_INCLUDE_DIRS}) + # Add the CCPP library + set(CCPP_LIB_DIRS "" CACHE FILEPATH "Path to ccpp library") + link_directories(${CCPP_LIB_DIRS}) + list(APPEND LIBS "ccpp") +else (PROJECT MATCHES "CCPP-FV3") + # Add the CCPP include/module directory + INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/../../../../src") + # Add the CCPP library + LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/../../../../src") + list(APPEND LIBS "ccpp") +endif (PROJECT MATCHES "CCPP-FV3") #------------------------------------------------------------------------------ # Set the sources diff --git a/scripts/ccpp_prebuild.py b/scripts/ccpp_prebuild.py index 6072f4a9..688034e3 100755 --- a/scripts/ccpp_prebuild.py +++ b/scripts/ccpp_prebuild.py @@ -15,7 +15,7 @@ # Local modules from common import encode_container, execute from metadata_parser import merge_metadata_dicts, parse_scheme_tables, parse_variable_tables -from mkcap import Cap, CapsMakefile, SchemesMakefile +from mkcap import Cap, CapsMakefile, CapsCMakefile, SchemesMakefile, SchemesCMakefile from mkdoc import metadata_to_html, metadata_to_latex ############################################################################### @@ -23,7 +23,7 @@ ############################################################################### # List of configured host models -HOST_MODELS = ["FV3", "SCM"] +HOST_MODELS = ["FV3v0", "FV3v1", "SCM"] ############################################################################### # Set up the command line argument parser and other global variables # @@ -60,9 +60,12 @@ def import_config(host_model): # Definitions in host-model dependent CCPP prebuild config script config['variable_definition_files'] = ccpp_prebuild_config.VARIABLE_DEFINITION_FILES config['scheme_files'] = ccpp_prebuild_config.SCHEME_FILES + config['scheme_files_dependencies'] = ccpp_prebuild_config.SCHEME_FILES_DEPENDENCIES config['schemes_makefile'] = ccpp_prebuild_config.SCHEMES_MAKEFILE + config['schemes_cmakefile'] = ccpp_prebuild_config.SCHEMES_CMAKEFILE config['target_files'] = ccpp_prebuild_config.TARGET_FILES config['caps_makefile'] = ccpp_prebuild_config.CAPS_MAKEFILE + config['caps_cmakefile'] = ccpp_prebuild_config.CAPS_CMAKEFILE config['caps_dir'] = ccpp_prebuild_config.CAPS_DIR config['optional_arguments'] = ccpp_prebuild_config.OPTIONAL_ARGUMENTS config['module_include_file'] = ccpp_prebuild_config.MODULE_INCLUDE_FILE @@ -327,11 +330,13 @@ def generate_scheme_caps(metadata, arguments, caps_dir, module_use_template_sche os.chdir(BASEDIR) return (success, scheme_caps) -def generate_schemes_makefile(schemes, schemes_makefile): - logging.info('Generating schemes makefile snippet ...') +def generate_schemes_makefile(schemes, schemes_makefile, schemes_cmakefile): + logging.info('Generating schemes makefile/cmakefile snippet ...') success = True makefile = SchemesMakefile() makefile.filename = schemes_makefile + cmakefile = SchemesCMakefile() + cmakefile.filename = schemes_cmakefile # Adjust relative file path to schemes from caps makefile schemes_with_path = [] schemes_makefile_dir = os.path.split(os.path.abspath(schemes_makefile))[0] @@ -340,20 +345,26 @@ def generate_schemes_makefile(schemes, schemes_makefile): relative_path = './{0}'.format(os.path.relpath(scheme_filepath, schemes_makefile_dir)) schemes_with_path.append(os.path.join(relative_path, scheme_filename)) makefile.write(schemes_with_path) - logging.info('Added {0} schemes to makefile {1}'.format(len(schemes_with_path), makefile.filename)) + cmakefile.write(schemes_with_path) + logging.info('Added {0} schemes to makefile/cmakefile {1}/{2}'.format( + len(schemes_with_path), makefile.filename, cmakefile.filename)) return success -def generate_caps_makefile(caps, caps_makefile, caps_dir): - logging.info('Generating caps makefile snippet ...') +def generate_caps_makefile(caps, caps_makefile, caps_cmakefile, caps_dir): + logging.info('Generating caps makefile/cmakefile snippet ...') success = True makefile = CapsMakefile() makefile.filename = caps_makefile + cmakefile = CapsCMakefile() + cmakefile.filename = caps_cmakefile # Adjust relative file path to schemes from caps makefile caps_makefile_dir = os.path.split(os.path.abspath(caps_makefile))[0] relative_path = './{0}'.format(os.path.relpath(caps_dir, caps_makefile_dir)) caps_with_path = [ os.path.join(relative_path, cap) for cap in caps] makefile.write(caps_with_path) - logging.info('Added {0} auto-generated caps to makefile {1}'.format(len(caps_with_path), makefile.filename)) + cmakefile.write(caps_with_path) + logging.info('Added {0} auto-generated caps to makefile/cmakefile {1}/{2}'.format( + len(caps_with_path), makefile.filename, cmakefile.filename)) return success def main(): @@ -423,13 +434,14 @@ def main(): if not success: raise Exception('Call to generate_scheme_caps failed.') - # Add filenames of schemes to makefile - success = generate_schemes_makefile(config['scheme_files'], config['schemes_makefile']) + # Add filenames of schemes to makefile - add dependencies for schemes + success = generate_schemes_makefile(config['scheme_files_dependencies'] + config['scheme_files'], + config['schemes_makefile'], config['schemes_cmakefile']) if not success: raise Exception('Call to generate_schemes_makefile failed.') # Add filenames of scheme caps to makefile - success = generate_caps_makefile(scheme_caps, config['caps_makefile'], config['caps_dir']) + success = generate_caps_makefile(scheme_caps, config['caps_makefile'], config['caps_cmakefile'], config['caps_dir']) if not success: raise Exception('Call to generate_caps_makefile failed.') diff --git a/scripts/ccpp_prebuild_config_FV3.py b/scripts/ccpp_prebuild_config_FV3v0.py similarity index 93% rename from scripts/ccpp_prebuild_config_FV3.py rename to scripts/ccpp_prebuild_config_FV3v0.py index 072e20c8..34af9c5a 100755 --- a/scripts/ccpp_prebuild_config_FV3.py +++ b/scripts/ccpp_prebuild_config_FV3v0.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# CCPP prebuild config for GFDL Finite-Volume Cubed-Sphere Model (FV3) v0.0 +# CCPP prebuild config for GFDL Finite-Volume Cubed-Sphere Model (FV3) v0 ############################################################################### @@ -14,6 +14,11 @@ 'FV3/gfsphysics/physics/physcons.f90', ] +# Can be empty, since all physics schemes and their +# dependencies are hardcoded in the makefile in +# FV3/gfsphysics - will be fixed in FV3 v1 +SCHEME_FILES_DEPENDENCIES = [] + # Add all physics scheme files relative to basedir SCHEME_FILES = [ 'FV3/gfsphysics/physics/GFS_DCNV_generic.f90', @@ -22,7 +27,7 @@ 'FV3/gfsphysics/physics/GFS_PBL_generic.f90', 'FV3/gfsphysics/physics/GFS_SCNV_generic.f90', 'FV3/gfsphysics/physics/GFS_calpreciptype.f90', - 'FV3/gfsphysics/physics/GFS_debug.f90', + 'FV3/gfsphysics/physics/GFS_debug.F90', 'FV3/gfsphysics/physics/GFS_rrtmg_post.F90', 'FV3/gfsphysics/physics/GFS_rrtmg_pre.F90', 'FV3/gfsphysics/physics/GFS_stochastics.f90', @@ -55,8 +60,9 @@ 'FV3/gfsphysics/physics/sfc_sice.f', ] -# Auto-generated makefile snippet that contains all schemes +# Auto-generated makefile/cmakefile snippets that contain all schemes SCHEMES_MAKEFILE = 'FV3/gfsphysics/CCPP_SCHEMES.mk' +SCHEMES_CMAKEFILE = 'FV3/gfsphysics/CCPP_SCHEMES.cmake' # CCPP host cap in which to insert the ccpp_field_add statements; # determines the directory to place ccpp_{modules,fields}.inc @@ -64,8 +70,9 @@ 'FV3/gfsphysics/IPD_layer/IPD_CCPP_Driver.F90', ] -# Auto-generated makefile snippet that contains all caps +# Auto-generated makefile/cmakefile snippets that contain all caps CAPS_MAKEFILE = 'FV3/gfsphysics/CCPP_CAPS.mk' +CAPS_CMAKEFILE = 'FV3/gfsphysics/CCPP_CAPS.cmake' # Directory where to put all auto-generated physics caps CAPS_DIR = 'FV3/gfsphysics/physics' diff --git a/scripts/ccpp_prebuild_config_FV3v1.py b/scripts/ccpp_prebuild_config_FV3v1.py new file mode 100755 index 00000000..e56293d3 --- /dev/null +++ b/scripts/ccpp_prebuild_config_FV3v1.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python + +# CCPP prebuild config for GFDL Finite-Volume Cubed-Sphere Model (FV3) v1 + + +############################################################################### +# Definitions # +############################################################################### + +# DH* THIS ENTIRE BLOCK COMPILES, but remove for initial integration in FV3v1 +### # Add all files with metadata tables on the host model side, +### # relative to basedir = top-level directory of host model +### VARIABLE_DEFINITION_FILES = [ +### 'FV3/gfsphysics/GFS_layer/GFS_typedefs.F90', +### # DH* NEED TO CHANGE - THESE MUST BE IN FV3 CODEBASE, NOT IN CCPP! (DOES NOT APPLY TO PHYSCONS?) +### 'ccpp/physics/GFS_layer/GFS_typedefs.F90', +### # *DH +### 'ccpp/physics/physics/physcons.f90', +### ] +### +### # Add all physics scheme dependencies relative to basedir - note that these are all violations +### # of the CCPP requirement to not use any external modules except Fortran standard modules! +### SCHEME_FILES_DEPENDENCIES = [ +### 'ccpp/physics/physics/GFDL_parse_tracers.F90', +### 'ccpp/physics/physics/date_def.f', +### 'ccpp/physics/physics/funcphys.f90', +### 'ccpp/physics/physics/gfs_phy_tracer_config.f', +### 'ccpp/physics/physics/gocart_tracer_config_stub.f', +### 'ccpp/physics/physics/h2o_def.f', +### 'ccpp/physics/physics/iounitdef.f', +### 'ccpp/physics/physics/machine.F', +### 'ccpp/physics/physics/mersenne_twister.f', +### 'ccpp/physics/physics/mfpbl.f', +### 'ccpp/physics/physics/module_bfmicrophysics.f', +### 'ccpp/physics/physics/module_nst_model.f90', +### 'ccpp/physics/physics/module_nst_parameters.f90', +### 'ccpp/physics/physics/module_nst_water_prop.f90', +### 'ccpp/physics/physics/namelist_soilveg.f', +### 'ccpp/physics/physics/ozne_def.f', +### 'ccpp/physics/physics/physcons.f90', +### 'ccpp/physics/physics/physparam.f', +### 'ccpp/physics/physics/radcons.f90', +### 'ccpp/physics/physics/radiation_aerosols.f', +### 'ccpp/physics/physics/radiation_astronomy.f', +### 'ccpp/physics/physics/radiation_clouds.f', +### 'ccpp/physics/physics/radiation_gases.f', +### 'ccpp/physics/physics/radiation_surface.f', +### 'ccpp/physics/physics/radlw_datatb.f', +### 'ccpp/physics/physics/radlw_param.f', +### 'ccpp/physics/physics/radsw_datatb.f', +### 'ccpp/physics/physics/radsw_param.f', +### 'ccpp/physics/physics/rascnvv2.f', +### 'ccpp/physics/physics/sflx.f', +### 'ccpp/physics/physics/tridi.f', +### 'ccpp/physics/physics/wam_f107_kp_mod.f90', +### # DH* NEED TO CHANGE - THIS MUST BE IN FV3 CODEBASE, NOT IN CCPP! *DH +### #'FV3/gfsphysics/GFS_layer/GFS_typedefs.F90', +### 'ccpp/physics/GFS_layer/GFS_typedefs.F90', +### ] +### +### # Add all physics scheme files relative to basedir +### SCHEME_FILES = [ +### 'ccpp/physics/physics/FV3_test.F90', +### 'ccpp/physics/physics/GFS_DCNV_generic.f90', +### 'ccpp/physics/physics/GFS_MP_generic_post.f90', +### 'ccpp/physics/physics/GFS_MP_generic_pre.f90', +### 'ccpp/physics/physics/GFS_PBL_generic.f90', +### 'ccpp/physics/physics/GFS_SCNV_generic.f90', +### 'ccpp/physics/physics/GFS_calpreciptype.f90', +### 'ccpp/physics/physics/GFS_debug.F90', +### 'ccpp/physics/physics/GFS_rrtmg_post.F90', +### 'ccpp/physics/physics/GFS_rrtmg_pre.F90', +### 'ccpp/physics/physics/GFS_stochastics.f90', +### 'ccpp/physics/physics/GFS_suite_interstitial.ccpp.f90', +### 'ccpp/physics/physics/GFS_surface_generic.f90', +### 'ccpp/physics/physics/GFS_surface_loop_control.f', +### 'ccpp/physics/physics/GFS_zhao_carr_pre.f90', +### 'ccpp/physics/physics/cnvc90.f', +### 'ccpp/physics/physics/dcyc2.f', +### 'ccpp/physics/physics/get_prs_fv3.f90', +### 'ccpp/physics/physics/gscond.f', +### 'ccpp/physics/physics/gwdc.f', +### 'ccpp/physics/physics/gwdps.f', +### 'ccpp/physics/physics/mfdeepcnv.f', +### 'ccpp/physics/physics/mfshalcnv.f', +### 'ccpp/physics/physics/moninedmf.f', +### 'ccpp/physics/physics/ozphys.f', +### 'ccpp/physics/physics/precpd.f', +### 'ccpp/physics/physics/radlw_main.f', +### 'ccpp/physics/physics/radsw_main.f', +### 'ccpp/physics/physics/rayleigh_damp.f', +### 'ccpp/physics/physics/rrtmg_lw_post.F90', +### 'ccpp/physics/physics/rrtmg_lw_pre.F90', +### 'ccpp/physics/physics/rrtmg_sw_post.F90', +### 'ccpp/physics/physics/rrtmg_sw_pre.F90', +### 'ccpp/physics/physics/sfc_diag.f', +### 'ccpp/physics/physics/sfc_diff.f', +### 'ccpp/physics/physics/sfc_drv.f', +### 'ccpp/physics/physics/sfc_nst.f', +### 'ccpp/physics/physics/sfc_sice.f', +### ] + +# Add all files with metadata tables on the host model side, +# relative to basedir = top-level directory of host model +VARIABLE_DEFINITION_FILES = [ + 'FV3/gfsphysics/GFS_layer/GFS_typedefs.F90', + ] + +# Add all physics scheme dependencies relative to basedir - note that these are all violations +# of the CCPP requirement to not use any external modules except Fortran standard modules! +SCHEME_FILES_DEPENDENCIES = [ + 'ccpp/physics/physics/machine.F', + 'ccpp/physics/physics/radlw_param.f', + 'ccpp/physics/physics/radsw_param.f', + 'ccpp/physics/physics/physparam.f', + ] + +# Add all physics scheme files relative to basedir +SCHEME_FILES = [ + 'ccpp/physics/physics/FV3_test.F90', + ] +# *DH + +# Auto-generated makefile/cmakefile snippets that contain all schemes +SCHEMES_MAKEFILE = 'ccpp/physics/CCPP_SCHEMES.mk' +SCHEMES_CMAKEFILE = 'ccpp/physics/CCPP_SCHEMES.cmake' + +# CCPP host cap in which to insert the ccpp_field_add statements; +# determines the directory to place ccpp_{modules,fields}.inc +TARGET_FILES = [ + 'FV3/ipd/IPD_CCPP_Driver.F90', + #'ccpp/physics/physics/IPD_layer/IPD_CCPP_Driver.F90', + ] + +# Auto-generated makefile/cmakefile snippets that contain all caps +CAPS_MAKEFILE = 'ccpp/physics/CCPP_CAPS.mk' +CAPS_CMAKEFILE = 'ccpp/physics/CCPP_CAPS.cmake' + +# Directory where to put all auto-generated physics caps +CAPS_DIR = 'ccpp/physics/physics' + +# Optional arguments - only required for schemes that use +# optional arguments. ccpp_prebuild.py will throw an exception +# if it encounters a scheme subroutine with optional arguments +# if no entry is made here. Possible values are: 'all', 'none', +# or a list of standard_names: [ 'var1', 'var3' ]. +OPTIONAL_ARGUMENTS = { + 'rrtmg_sw' : { + 'rrtmg_sw_run' : [ + 'tendency_of_air_temperature_due_to_shortwave_heating_assuming_clear_sky_on_radiation_time_step', + 'components_of_surface_downward_shortwave_fluxes', + 'cloud_liquid_water_path', + 'mean_effective_radius_for_liquid_cloud', + 'cloud_ice_water_path', + 'mean_effective_radius_for_ice_cloud', + 'cloud_rain_water_path', + 'mean_effective_radius_for_rain_drop', + 'cloud_snow_water_path', + 'mean_effective_radius_for_snow_flake', + ], + }, + 'rrtmg_lw' : { + 'rrtmg_lw_run' : [ + 'tendency_of_air_temperature_due_to_longwave_heating_assuming_clear_sky_on_radiation_time_step', + 'cloud_liquid_water_path', + 'mean_effective_radius_for_liquid_cloud', + 'cloud_ice_water_path', + 'mean_effective_radius_for_ice_cloud', + 'cloud_rain_water_path', + 'mean_effective_radius_for_rain_drop', + 'cloud_snow_water_path', + 'mean_effective_radius_for_snow_flake', + ], + }, + #'subroutine_name_1' : 'all', + #'subroutine_name_2' : 'none', + #'subroutine_name_2' : [ 'var1', 'var3'], + } + +# Names of Fortran include files in the host model cap (do not change); +# both files will be written to the directory of each target file +MODULE_INCLUDE_FILE = 'ccpp_modules.inc' +FIELDS_INCLUDE_FILE = 'ccpp_fields.inc' + +# HTML document containing the model-defined CCPP variables +HTML_VARTABLE_FILE = 'ccpp/physics/CCPP_VARIABLES_FV3.html' + +# LaTeX document containing the provided vs requested CCPP variables +LATEX_VARTABLE_FILE = 'ccpp/framework/doc/DevelopersGuide/CCPP_VARIABLES_FV3.tex' + + +############################################################################### +# Template code to generate include files # +############################################################################### + +# Name of the CCPP data structure in the host model cap; +# in the case of FV3, this is a 2-dimensional array with +# the number of blocks as the first and the number of +# OpenMP threads as the second dimension; nb is the loop +# index for the current block, nt for the current thread +CCPP_DATA_STRUCTURE = 'cdata' + +# Modules to load for auto-generated ccpp_field_add code +# in the host model cap (e.g. error handling) +MODULE_USE_TEMPLATE_HOST_CAP = \ +''' +use ccpp_api, only: ccpp_error +''' + +## Modules to load for auto-generated ccpp_field_get code +## in the physics scheme cap (e.g. derived data types) +#MODULE_USE_TEMPLATE_SCHEME_CAP = \ +#''' +# use machine, only: kind_phys +# use module_radlw_parameters, only: sfcflw_type, topflw_type +# use module_radsw_parameters, only: cmpfsw_type, sfcfsw_type, topfsw_type +# use GFS_typedefs, only: GFS_statein_type, GFS_stateout_type, & +# GFS_sfcprop_type, GFS_coupling_type, & +# GFS_control_type, GFS_grid_type, & +# GFS_tbd_type, GFS_cldprop_type, & +# GFS_radtend_type, GFS_diag_type, & +# GFS_interstitial_type +#''' + +# Modules to load for auto-generated ccpp_field_get code +# in the physics scheme cap (e.g. derived data types) +MODULE_USE_TEMPLATE_SCHEME_CAP = \ +''' + use machine, only: kind_phys +''' \ No newline at end of file diff --git a/scripts/ccpp_prebuild_config_SCM.py b/scripts/ccpp_prebuild_config_SCM.py index 38bce749..16e9b3c5 100755 --- a/scripts/ccpp_prebuild_config_SCM.py +++ b/scripts/ccpp_prebuild_config_SCM.py @@ -14,6 +14,11 @@ 'scm/src/gmtb_scm_physical_constants.f90' ] +# Can be empty, since all physics schemes and their +# dependencies are hardcoded in CMakeLists in +# ccpp-physics - to fix, c.f. FV3 v1 +SCHEME_FILES_DEPENDENCIES = [] + # Add all physics scheme files relative to basedir SCHEME_FILES = [ 'ccpp-physics/GFS_layer/GFS_initialize_scm.F90', @@ -57,8 +62,9 @@ 'ccpp-physics/physics/sfc_sice.f', ] -# Auto-generated makefile snippet that contains all schemes +# Auto-generated makefile/cmakefile snippets that contain all schemes SCHEMES_MAKEFILE = 'ccpp-physics/CCPP_SCHEMES.mk' +SCHEMES_CMAKEFILE = 'ccpp-physics/CCPP_SCHEMES.cmake' # CCPP host cap in which to insert the ccpp_field_add statements; # determines the directory to place ccpp_{modules,fields}.inc @@ -66,8 +72,9 @@ 'scm/src/gmtb_scm.f90', ] -# Auto-generated makefile snippet that contains all caps +# Auto-generated makefile/cmakefile snippets that contain all caps CAPS_MAKEFILE = 'ccpp-physics/CCPP_CAPS.mk' +CAPS_CMAKEFILE = 'ccpp-physics/CCPP_CAPS.cmake' # Directory where to put all auto-generated physics caps CAPS_DIR = 'ccpp-physics/physics' diff --git a/scripts/mkcap.py b/scripts/mkcap.py index 2bab0d74..2a864a86 100755 --- a/scripts/mkcap.py +++ b/scripts/mkcap.py @@ -552,6 +552,48 @@ def filename(self): def filename(self, value): self._filename = value +class CapsCMakefile(object): + + header=''' +# All CCPP caps are defined here. +# +# This file is auto-generated using ccpp_prebuild.py +# at compile time, do not edit manually. +# +set(CAPS +''' + footer=''') +''' + + def __init__(self, **kwargs): + self._filename = 'sys.stdout' + for key, value in kwargs.items(): + setattr(self, "_"+key, value) + + def write(self, schemes): + if (self.filename is not sys.stdout): + f = open(self.filename, 'w') + else: + f = sys.stdout + + contents = self.header + for scheme in schemes: + contents += ' {0}\n'.format(scheme) + contents += self.footer + f.write(contents) + + if (f is not sys.stdout): + f.close() + + @property + def filename(self): + '''Get the filename of write the output to.''' + return self._filename + + @filename.setter + def filename(self, value): + self._filename = value + class SchemesMakefile(object): header=''' @@ -611,6 +653,48 @@ def filename(self): def filename(self, value): self._filename = value +class SchemesCMakefile(object): + + header=''' +# All CCPP schemes are defined here. +# +# This file is auto-generated using ccpp_prebuild.py +# at compile time, do not edit manually. +# +set(SCHEMES +''' + footer=''') +''' + + def __init__(self, **kwargs): + self._filename = 'sys.stdout' + for key, value in kwargs.items(): + setattr(self, "_"+key, value) + + def write(self, schemes): + if (self.filename is not sys.stdout): + f = open(self.filename, 'w') + else: + f = sys.stdout + + contents = self.header + for scheme in schemes: + contents += ' {0}\n'.format(scheme) + contents += self.footer + f.write(contents) + + if (f is not sys.stdout): + f.close() + + @property + def filename(self): + '''Get the filename of write the output to.''' + return self._filename + + @filename.setter + def filename(self, value): + self._filename = value + ############################################################################### if __name__ == "__main__": main() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 44608420..985709ad 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,25 +1,38 @@ +# Set default project to unknown +if(NOT PROJECT) + message(STATUS "Setting CCPP project to 'unknown' as none was specified.") + set(PROJECT "Unknown") +endif (NOT PROJECT) + #------------------------------------------------------------------------------ # Set the sources -set(SOURCES - ccpp.F90 +set(SOURCES_C ccpp_dl.h ccpp_dl.c + ccpp_fields_idx.h + ccpp_fields_idx.c + ccpp_utils.h + ccpp_utils.c + ccpp_xml.h + ccpp_xml.c +) +set(SOURCES_F90 + ccpp.F90 ccpp_dl.F90 ccpp_errors.F90 ccpp_fcall.F90 ccpp_fields.F90 - ccpp_fields_idx.h - ccpp_fields_idx.c ccpp_strings.F90 ccpp_suite.F90 ccpp_types.F90 - ccpp_utils.h - ccpp_utils.c ccpp_xml.F90 - ccpp_xml.h - ccpp_xml.c ccpp_api.F90 ) +# Generate list of Fortran modules from defined sources +foreach(source_f90 ${SOURCES_F90}) + string(REGEX REPLACE ".F90" ".mod" module_f90 ${source_f90}) + list(APPEND MODULES_F90 ${CMAKE_CURRENT_BINARY_DIR}/${module_f90}) +endforeach() #------------------------------------------------------------------------------ # Find libXML2 @@ -87,11 +100,10 @@ add_subdirectory(tests) #------------------------------------------------------------------------------ # Define the executable and what to link -add_library(ccpp ${SOURCES}) +add_library(ccpp ${SOURCES_C} ${SOURCES_F90}) target_link_libraries(ccpp LINK_PUBLIC ${LIBS} ${CMAKE_DL_LIBS}) set_target_properties(ccpp PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} - COMPILE_FLAGS ${CMAKE_Fortran_FLAGS} LINK_FLAGS ${CMAKE_Fortran_FLAGS}) #------------------------------------------------------------------------------ @@ -99,15 +111,21 @@ set_target_properties(ccpp PROPERTIES VERSION ${PROJECT_VERSION} # # Find all the C headers and Fortran modules -file(GLOB headers +file(GLOB HEADERS_C "${CMAKE_CURRENT_SOURCE_DIR}/ccpp*.h" - "${CMAKE_CURRENT_BINARY_DIR}/ccpp*.mod" ) -target_include_directories(ccpp PUBLIC - $ - $ -) +if (PROJECT MATCHES "CCPP-FV3") + target_include_directories(ccpp PUBLIC + $ + $ + ) +else (PROJECT MATCHES "CCPP-FV3") + target_include_directories(ccpp PUBLIC + $ + $ + ) +endif (PROJECT MATCHES "CCPP-FV3") # Define where to install the library install(TARGETS ccpp @@ -123,6 +141,12 @@ install(EXPORT ccpp-targets DESTINATION lib/cmake ) -# Define where to install the modules -install(FILES ${headers} DESTINATION include/${PROJECT_NAME}) - +if (PROJECT MATCHES "CCPP-FV3") + # Define where to install the C headers and Fortran modules + install(FILES ${HEADERS_C} DESTINATION include) + install(FILES ${MODULES_F90} DESTINATION include) +else (PROJECT MATCHES "CCPP-FV3") + # Define where to install the C headers and Fortran modules + install(FILES ${HEADERS_C} DESTINATION include/${PROJECT_NAME}) + install(FILES ${MODULES_F90} DESTINATION include/${PROJECT_NAME}) +endif (PROJECT MATCHES "CCPP-FV3") diff --git a/src/ccpp.F90 b/src/ccpp.F90 index fb62f922..ef96ae18 100644 --- a/src/ccpp.F90 +++ b/src/ccpp.F90 @@ -32,7 +32,8 @@ module ccpp private public :: ccpp_init, & - ccpp_finalize + ccpp_finalize, & + ccpp_initialized contains @@ -51,7 +52,7 @@ subroutine ccpp_init(filename, cdata, ierr, suite) ierr = 0 - !call ccpp_debug('Called ccpp_init') + call ccpp_debug('Called ccpp_init') if (present(suite)) then cdata%suite = suite @@ -72,6 +73,9 @@ subroutine ccpp_init(filename, cdata, ierr, suite) return end if + ! Set flag indicating initialization state of cdata + cdata%initialized = .true. + end subroutine ccpp_init !> @@ -86,7 +90,7 @@ subroutine ccpp_finalize(cdata, ierr) ierr = 0 - !call ccpp_debug('Called ccpp_finalize') + call ccpp_debug('Called ccpp_finalize') ! Finalize the suite call ccpp_suite_finalize(cdata%suite, ierr) @@ -102,6 +106,25 @@ subroutine ccpp_finalize(cdata, ierr) return end if + ! Set flag indicating initialization state of cdata + cdata%initialized = .false. + end subroutine ccpp_finalize + !> + !! CCPP test initialization routine + !! + !! @param[in] cdata The ccpp_t type data + !! @return initialized .true. or .false. + ! + function ccpp_initialized(cdata) result(initialized) + type(ccpp_t), intent(in) :: cdata + logical :: initialized + + call ccpp_debug('Called ccpp_initialized') + + initialized = cdata%initialized + + end function ccpp_initialized + end module ccpp diff --git a/src/ccpp_api.F90 b/src/ccpp_api.F90 index 016f93c8..9c338121 100644 --- a/src/ccpp_api.F90 +++ b/src/ccpp_api.F90 @@ -23,7 +23,8 @@ module ccpp_api use ccpp_errors, only: ccpp_error, & ccpp_debug use ccpp, only: ccpp_init, & - ccpp_finalize + ccpp_finalize, & + ccpp_initialized use ccpp_fcall, only: ccpp_physics_init, & ccpp_physics_run, & ccpp_physics_finalize @@ -41,6 +42,7 @@ module ccpp_api ccpp_physics_init, & ccpp_physics_run, & ccpp_physics_finalize, & - ccpp_field_add + ccpp_field_add, & + ccpp_initialized end module ccpp_api diff --git a/src/ccpp_types.F90 b/src/ccpp_types.F90 index 9bcfdc94..b6a11c56 100644 --- a/src/ccpp_types.F90 +++ b/src/ccpp_types.F90 @@ -120,6 +120,7 @@ module ccpp_types type(c_ptr) :: fields_idx type(ccpp_field_t), allocatable, dimension(:) :: fields type(ccpp_suite_t) :: suite + logical :: initialized = .false. end type ccpp_t end module ccpp_types