diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ec9277a10..c7d40c6b12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required( VERSION 3.19 ) +cmake_minimum_required( VERSION 3.20 ) project( WRF ) @@ -218,6 +218,13 @@ set( DWORDSIZE 8 ) set( LWORDSIZE 4 ) +# To limit the KPP generation to not consume copious amounts of RAM +if ( NOT DEFINED MAX_KPP_GEN_THREADS ) + # 1 thread takes about 4.75 GB + set( MAX_KPP_GEN_THREADS 2 ) +endif() + + ######################## ################################################################################ @@ -259,6 +266,7 @@ endif() if ( ${ENABLE_KPP} AND NOT ${ENABLE_CHEM} ) message( WARNING "ENABLE_KPP requires ENABLE_CHEM but is not set, ignoring" ) + set( ENABLE_KPP OFF CACHE BOOL "Force ignore by configuration" FORCE ) endif() @@ -477,6 +485,19 @@ if ( ${ENABLE_CTSM} ) # find_package( CTSM REQUIRED ) endif() +if ( ${ENABLE_KPP} ) + find_package( BISON REQUIRED ) + find_package( FLEX REQUIRED ) + if ( ${FLEX_FOUND} AND "${FLEX_LIBRARIES}" STREQUAL "FL_LIBRARY-NOTFOUND" ) + message( FATAL_ERROR + "Flex executable found, but libraries were not. Please provide a searchable path for both " + "\n" + "Refer to https://cmake.org/cmake/help/latest/command/find_package.html for more info " + "on providing a suitable path" + ) + endif() +endif() + # Will need our own finder # find_package( GPFS REQUIRED ) @@ -684,9 +705,9 @@ list( APPEND PROJECT_COMPILE_DEFINITIONS_OPTIONS # in code since cmake cannot handle basically any others :( # https://gitlab.kitware.com/cmake/cmake/-/issues/17398 if ( ${ENABLE_CHEM} ) - list( APPEND PROJECT_COMPILE_DEFINITIONS_OPTIONS WRF_CHEM=1 ) + list( APPEND PROJECT_COMPILE_DEFINITIONS_OPTIONS WRF_CHEM ) if ( ${ENABLE_KPP} ) - list( APPEND PROJECT_COMPILE_DEFINITIONS_OPTIONS WRF_KPP=1 ) + list( APPEND PROJECT_COMPILE_DEFINITIONS_OPTIONS WRF_KPP ) endif() endif() if ( ${ENABLE_CHEM} ) @@ -919,7 +940,7 @@ add_subdirectory( share ) add_subdirectory( frame ) add_subdirectory( inc ) -if ( ${WRF_CHEM} ) +if ( ${ENABLE_CHEM} ) add_subdirectory( chem ) endif() diff --git a/chem/CMakeLists.txt b/chem/CMakeLists.txt index 544b253256..8c329a1397 100644 --- a/chem/CMakeLists.txt +++ b/chem/CMakeLists.txt @@ -4,6 +4,11 @@ target_include_directories( PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) +if ( ${ENABLE_KPP} ) + add_compile_options ( "${PROJECT_COMPILE_OPTIONS}" ) + add_compile_definitions( "${PROJECT_COMPILE_DEFINITIONS}" ) + add_subdirectory( KPP ) +endif() ######################################################################################################################## # @@ -209,31 +214,47 @@ target_sources( aerosol_driver.F ) -######################################################################################################################## -# -# convert_emiss executable -# -######################################################################################################################## -add_executable( - convert_emiss - convert_emiss.F - ) - -target_link_libraries( - convert_emiss - PRIVATE - ${PROJECT_NAME}_Core - ) +#!TODO: I'm not entirely sure when this exec is supposed to be generated or if it +# is exclusive to the real test case +# ######################################################################################################################## +# # +# # convert_emiss executable +# # +# ######################################################################################################################## +# set( CONVERT_EMISS_TARGET convert_emiss ) +# add_executable( +# ${CONVERT_EMISS_TARGET} +# convert_emiss.F +# ) -target_compile_options( - convert_emiss - PRIVATE - ${PROJECT_COMPILE_OPTIONS} - ) +# target_link_libraries( +# ${CONVERT_EMISS_TARGET} +# PRIVATE +# ${PROJECT_NAME}_Core +# ) +# set_target_properties( +# ${CONVERT_EMISS_TARGET} +# PROPERTIES +# # Just dump everything in here +# Fortran_MODULE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/modules/${CONVERT_EMISS_TARGET}/ +# Fortran_FORMAT FREE +# ) +# target_compile_options( +# convert_emiss +# PRIVATE +# ${PROJECT_COMPILE_OPTIONS} +# ) -target_compile_definitions( - convert_emiss - PRIVATE - ${PROJECT_COMPILE_DEFINITIONS} - ) +# target_compile_definitions( +# convert_emiss +# PRIVATE +# ${PROJECT_COMPILE_DEFINITIONS} +# ) +# install( +# TARGETS ${CONVERT_EMISS_TARGET} +# EXPORT ${EXPORT_NAME}Targets +# RUNTIME DESTINATION bin/ +# ARCHIVE DESTINATION lib/ +# LIBRARY DESTINATION lib/ +# ) diff --git a/chem/KPP/CMakeLists.txt b/chem/KPP/CMakeLists.txt new file mode 100644 index 0000000000..91e65723f7 --- /dev/null +++ b/chem/KPP/CMakeLists.txt @@ -0,0 +1,302 @@ + +message( STATUS "[KPP] Starting preprocessing preparation..." ) +list(APPEND CMAKE_MESSAGE_INDENT " ") + +# These names will also be used by the registry_kpp +set( + MECHANISMS + cb05_sorg_aq + cb05_sorg_vbs_aq + cbm4 + cbmz_bb + cbmz_mosaic + crimech + cri_mosaic_4bin_aq + cri_mosaic_8bin_aq + gocartracm + mozart + mozart_mosaic_4bin + mozart_mosaic_4bin_aq + mozcart + nmhc9 + racm + racm_esrlsorg + racm_esrlsorg_aqchem + racm_mim + racmpm + racm_soa_vbs + racm_soa_vbs_aqchem + racm_soa_vbs_het + racmsorg + racmsorg_aqchem + radm2 + radm2sorg + saprc99 + saprc99_mosaic_4bin_vbs2 + saprc99_mosaic_8bin_vbs2_aq + t1_mozcart + ) + +add_subdirectory( kpp/kpp-2.1 ) +add_subdirectory( util/wkc ) +add_subdirectory( util/write_decomp ) + + +target_sources( + ${PROJECT_NAME}_Core + PRIVATE + module_wkppc_constants.F + ) + +target_include_directories( + ${PROJECT_NAME}_Core + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/inc + ) + +set( GEN_MECHD_INC u l b a ibu ib ia e ) +set( + GEN_RCONST_INC + extra_args_to_update_rconst + extra_args_update_rconst + extra_decls_update_rconst + ) + +message( STATUS "[KPP] Adding generation for mechanisms" ) + +# Some helper vars for grouping the kpp gen and tuv inc +set( KPP_GEN_GROUPS ) +set( KPP_CURRENT_GEN_GROUP 0 ) + +set( TUV_PHOTOLYSIS_GEN FALSE ) +set( TUV_PHOTOLYSIS_CMD ) +set( TUV_PHOTOLYSIS_OUT ) + +foreach ( MECH ${MECHANISMS} ) + + ###################################################################################################################### + ## + ## Generate any "missing" includes that are just empty + ## + if ( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/inc/${MECH} ) + file( COPY ${CMAKE_CURRENT_SOURCE_DIR}/inc/${MECH}/ DESTINATION ${CMAKE_BINARY_DIR}/inc ) + endif() + + foreach ( MECHD_INAME ${GEN_MECHD_INC} ) + set( GEN_MECHD_INC_FILENAME kpp_mechd_${MECHD_INAME}_${MECH}.inc ) + if ( NOT EXISTS ${CMAKE_BINARY_DIR}/inc/${GEN_MECHD_INC_FILENAME} ) + message( STATUS "[KPP] Touching empty include ${GEN_MECHD_INC_FILENAME}" ) + file( TOUCH ${CMAKE_BINARY_DIR}/inc/${GEN_MECHD_INC_FILENAME} ) + endif() + endforeach() + + foreach ( RCONST_INAME ${GEN_RCONST_INC} ) + set( GEN_RCONST_INC_FILENAME ${RCONST_INAME}_${MECH}.inc ) + if ( NOT EXISTS ${CMAKE_BINARY_DIR}/inc/${GEN_RCONST_INC_FILENAME} ) + message( STATUS "[KPP] Touching empty include ${GEN_RCONST_INC_FILENAME}" ) + file( TOUCH ${CMAKE_BINARY_DIR}/inc/${GEN_RCONST_INC_FILENAME} ) + endif() + endforeach() + ## + ## + ## + ###################################################################################################################### + + ###################################################################################################################### + ## + ## run kpp model, generates .F files + ## + # KPP_HOME must be set by this point + # often set to chem/KPP/kpp/kpp-2.1 in case you didn't know it was KPP + set( KPP_HOME ${CMAKE_CURRENT_SOURCE_DIR}/kpp/kpp-2.1 ) + + # I'm using the configure-time dir creation to simplify custom target/command usage + set( KPP_WORKING_DIR ${CMAKE_CURRENT_BINARY_DIR}/mechanisms/${MECH} ) + file( COPY ${CMAKE_CURRENT_SOURCE_DIR}/mechanisms/${MECH}/ DESTINATION ${KPP_WORKING_DIR} ) + set( + ${MECH}_KPP_SOURCES + ${KPP_WORKING_DIR}/${MECH}_Parameters.f90 + ${KPP_WORKING_DIR}/${MECH}_Precision.f90 + ${KPP_WORKING_DIR}/${MECH}_JacobianSP.f90 + ${KPP_WORKING_DIR}/${MECH}_Jacobian.f90 + ${KPP_WORKING_DIR}/${MECH}_Update_Rconst.f90 + ) + set( + ${MECH}_KPP_SOURCES_INTEGRATOR + ${KPP_WORKING_DIR}/${MECH}_Integrator.f90 + ) + + add_custom_command( + OUTPUT + ${${MECH}_KPP_SOURCES} + ${${MECH}_KPP_SOURCES_INTEGRATOR} + COMMAND ${CMAKE_COMMAND} -E env KPP_HOME=${KPP_HOME} $ ${MECH}.kpp > ${CMAKE_BINARY_DIR}/kpp_${MECH}.log 2>&1 + COMMAND ${CMAKE_COMMAND} -E compare_files ${KPP_WORKING_DIR}/${MECH}_Integrator.f90 ${KPP_WORKING_DIR}/${MECH}_Integrator.f90 + COMMAND ${CMAKE_COMMAND} -E compare_files ${KPP_WORKING_DIR}/${MECH}_Parameters.f90 ${KPP_WORKING_DIR}/${MECH}_Parameters.f90 + COMMAND ${CMAKE_COMMAND} -E compare_files ${KPP_WORKING_DIR}/${MECH}_Precision.f90 ${KPP_WORKING_DIR}/${MECH}_Precision.f90 + COMMAND ${CMAKE_COMMAND} -E compare_files ${KPP_WORKING_DIR}/${MECH}_JacobianSP.f90 ${KPP_WORKING_DIR}/${MECH}_JacobianSP.f90 + COMMAND ${CMAKE_COMMAND} -E compare_files ${KPP_WORKING_DIR}/${MECH}_Jacobian.f90 ${KPP_WORKING_DIR}/${MECH}_Jacobian.f90 + COMMAND ${CMAKE_COMMAND} -E compare_files ${KPP_WORKING_DIR}/${MECH}_Update_Rconst.f90 ${KPP_WORKING_DIR}/${MECH}_Update_Rconst.f90 + WORKING_DIRECTORY ${KPP_WORKING_DIR} + DEPENDS kpp + ) + add_custom_target( + ${MECH}_kpp + COMMENT "[KPP] Generating kpp files for ${MECH}" + DEPENDS + ${${MECH}_KPP_SOURCES} + ${${MECH}_KPP_SOURCES_INTEGRATOR} + ) + + add_dependencies( ${PROJECT_NAME}_Core ${MECH}_kpp ) + target_sources( ${PROJECT_NAME}_Core PRIVATE ${${MECH}_KPP_SOURCES} ) + ## + ## + ## + ###################################################################################################################### + + ###################################################################################################################### + ## + ## Special KPP generation logic to streamline parallel building without crashing + ## + # Assign target to a group to serialize based on maximum threads allowed as + # this consumes a ton of RAM + list( LENGTH KPP_GEN_GROUPS KPP_GEN_GROUPS_LEN ) + if ( ${KPP_GEN_GROUPS_LEN} GREATER ${KPP_CURRENT_GEN_GROUP} ) + list( GET KPP_GEN_GROUPS ${KPP_CURRENT_GEN_GROUP} KPP_PREVIOUS_GROUP_TARGET ) + endif() + + # This is the start point, add it into the list + list( INSERT KPP_GEN_GROUPS ${KPP_CURRENT_GEN_GROUP} ${MECH}_kpp ) + MATH( EXPR KPP_NEXT_IDX "${KPP_CURRENT_GEN_GROUP} + 1" ) + + if ( DEFINED KPP_PREVIOUS_GROUP_TARGET ) + # Add as a dependency + add_dependencies( ${KPP_PREVIOUS_GROUP_TARGET} ${MECH}_kpp ) + # Replace current listing - currently next index is actually pointing to old + list( REMOVE_AT KPP_GEN_GROUPS ${KPP_NEXT_IDX} ) + endif() + + # Now we have min( MAX_KPP_GEN_THREADS, KPP_CURRENT_GEN_GROUP ) in list, loop modulus to go back to zero + MATH( EXPR KPP_CURRENT_GEN_GROUP "${KPP_NEXT_IDX} % ${MAX_KPP_GEN_THREADS}" ) + ## + ## end grouping logic + ## + ###################################################################################################################### + + + # generate tuv photolysis inc file + if ( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/mechanisms/${MECH}/${MECH}.tuv.jmap ) + if ( NOT ${TUV_PHOTOLYSIS_GEN} ) + set( TUV_PHOTOLYSIS_GEN TRUE ) + endif() + + list( + APPEND TUV_PHOTOLYSIS_CMD + COMMAND ${CMAKE_COMMAND} -E chdir ${KPP_WORKING_DIR} $ ${MECH} ${CMAKE_BINARY_DIR}/inc/ >> ${CMAKE_BINARY_DIR}/tuv_photolysis_inc.log 2>&1 + COMMAND ${CMAKE_COMMAND} -E touch tuv_photolysis_${MECH} + ) + list( + APPEND TUV_PHOTOLYSIS_OUT + tuv_photolysis_${MECH} + ) + endif() + + ###################################################################################################################### + ## + ## Integrator decomp rewrite + ## + # Do decomp for all - easier to manually specify rather than greps + file( + WRITE ${KPP_WORKING_DIR}/decomp_uses.inc + "USE ${MECH}_Parameters\nUSE ${MECH}_JacobianSP\n" + ) + file( + WRITE ${KPP_WORKING_DIR}/mech.tmp + "${MECH}\n" + ) + + add_executable( + write_decomp_${MECH} + util/write_decomp/write_decomp.F + ${KPP_WORKING_DIR}/${MECH}_Parameters.f90 + ${KPP_WORKING_DIR}/${MECH}_Precision.f90 + ${KPP_WORKING_DIR}/${MECH}_JacobianSP.f90 + ) + target_include_directories( write_decomp_${MECH} PRIVATE ${KPP_WORKING_DIR} ) + set_target_properties( + write_decomp_${MECH} + PROPERTIES + Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/decomp/${MECH}/ + Fortran_FORMAT FREE + ) + add_dependencies( write_decomp_${MECH} ${MECH}_kpp ) + + + # Now that write_decomp is generated for this kpp mechanism, process it + add_custom_command( + OUTPUT + ${KPP_WORKING_DIR}/${MECH}_Integrator_decomp.f90 + ${KPP_WORKING_DIR}/decomp_${MECH}.inc + # ${CMAKE_COMMAND} -E chdir ${KPP_WORKING_DIR} + COMMAND $ > ${CMAKE_BINARY_DIR}/kpp_write_decomp_${MECH}.log 2>&1 + COMMAND ${CMAKE_COMMAND} -E compare_files ${KPP_WORKING_DIR}/decomp_${MECH}.inc ${KPP_WORKING_DIR}/decomp_${MECH}.inc + + COMMAND $ + ${MECH} ${MECH}_Integrator.f90 + decomp_${MECH}.inc + ${MECH}_Integrator_decomp.f90 > ${CMAKE_BINARY_DIR}/kpp_integrator_edit_${MECH}.log 2>&1 + COMMAND ${CMAKE_COMMAND} -E compare_files ${KPP_WORKING_DIR}/${MECH}_Integrator_decomp.f90 ${KPP_WORKING_DIR}/${MECH}_Integrator_decomp.f90 + + WORKING_DIRECTORY ${KPP_WORKING_DIR} + DEPENDS kpp + ) + add_custom_target( + ${MECH}_integrator_decomp + COMMENT "[KPP] Post-processing integrator decomposition for ${MECH}_Integrator.f90" + DEPENDS + ${KPP_WORKING_DIR}/${MECH}_Integrator_decomp.f90 + ${KPP_WORKING_DIR}/decomp_${MECH}.inc + ) + + add_dependencies( ${PROJECT_NAME}_Core ${MECH}_integrator_decomp ) + target_sources( ${PROJECT_NAME}_Core PRIVATE ${KPP_WORKING_DIR}/${MECH}_Integrator_decomp.f90 ) + ## + ## + ## + ###################################################################################################################### + +endforeach() + +# Group our aggregated tuv commands if it was specified +if ( ${TUV_PHOTOLYSIS_GEN} ) + add_custom_command( + OUTPUT + # Note: I am not setting output as + # inc/tuv2wrf_jvals.inc + # inc/tuvdef_jvals.inc + # Because I want each step to succeed and not just the start or stop + tuv_photolysis_start + ${TUV_PHOTOLYSIS_OUT} + tuv_photolysis_stop + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/inc/ + COMMAND $ FIRST ${CMAKE_BINARY_DIR}/inc/ > ${CMAKE_BINARY_DIR}/tuv_photolysis_inc.log 2>&1 + COMMAND ${CMAKE_COMMAND} -E touch tuv_photolysis_start + ${TUV_PHOTOLYSIS_CMD} + COMMAND $ LAST ${CMAKE_BINARY_DIR}/inc/ >> ${CMAKE_BINARY_DIR}/tuv_photolysis_inc.log 2>&1 + COMMAND ${CMAKE_COMMAND} -E touch tuv_photolysis_stop + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS tuv_kpp + ) + add_custom_target( + tuv_photolysis_inc # Naming this something different just to identify this is a target + COMMENT "[KPP] Generating tuv_photolysis include file" + DEPENDS + tuv_photolysis_start + ${TUV_PHOTOLYSIS_OUT} + tuv_photolysis_stop + ) + add_dependencies( ${PROJECT_NAME}_Core tuv_photolysis_inc ) +endif() + +list(POP_BACK CMAKE_MESSAGE_INDENT) diff --git a/chem/KPP/compile_wkc b/chem/KPP/compile_wkc index 1d0cdc190c..0695e772d3 100755 --- a/chem/KPP/compile_wkc +++ b/chem/KPP/compile_wkc @@ -118,10 +118,10 @@ echo $kdir # generate tuv photolysis inc files if( -e $model.tuv.jmap ) then if( $found == 0 ) then - $WKC_HOME/util/wkc/tuv_kpp FIRST + $WKC_HOME/util/wkc/tuv_kpp FIRST ../../inc/ set found = 1 endif - $WKC_HOME/util/wkc/tuv_kpp $model + $WKC_HOME/util/wkc/tuv_kpp $model ../../../../inc/ endif if ( `echo $WRFC_ROOT | awk '{print ( length ( $1 ) > 40 ) }' `) then @@ -139,7 +139,7 @@ end # finish tuv photolysis inc files if( $found == 1 ) then - $WKC_HOME/util/wkc/tuv_kpp LAST + $WKC_HOME/util/wkc/tuv_kpp LAST ../../inc/ endif echo "=========================================================" diff --git a/chem/KPP/kpp/kpp-2.1/CMakeLists.txt b/chem/KPP/kpp/kpp-2.1/CMakeLists.txt new file mode 100644 index 0000000000..47f85af88f --- /dev/null +++ b/chem/KPP/kpp/kpp-2.1/CMakeLists.txt @@ -0,0 +1,50 @@ +# Port of cflags.guess logic +# If the compiler starts with "cc" +if ( ${CMAKE_C_COMPILER} MATCHES "(/|\\\\)cc[A-Za-z0-9_]*$" ) + if ( ${CMAKE_SYSTEM_NAME} STREQUAL "SunOS" ) + message( FATAL_ERROR "KPP must be compiled with gcc on SunOS machines" ) + endif() + + set( + KPP_CC_FLAGS + "$<$,$>:-Aa;-D_HPUX_SOURCE>" #@ Hewlett Packard Unix + "$<$,$>:-Aa>" #@ IBM Unix operating system + ) +endif() + + +FLEX_TARGET( + kpp_lex + src/scan.l + ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.c + ) + +BISON_TARGET( + kpp_tab + src/scan.y + ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c + ) + +add_executable( + kpp + ${FLEX_kpp_lex_OUTPUTS} + ${BISON_kpp_tab_OUTPUTS} + src/scanner.c + src/scanutil.c + src/kpp.c + src/gen.c + src/code.c + src/code_c.c + src/code_f77.c + src/code_f90.c + src/code_matlab.c + src/debug.c + ) + +target_include_directories( + kpp + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_BINARY_DIR} + ) +target_link_libraries( kpp PRIVATE ${FLEX_LIBRARIES} ) diff --git a/chem/KPP/util/wkc/CMakeLists.txt b/chem/KPP/util/wkc/CMakeLists.txt new file mode 100644 index 0000000000..949c07c1f8 --- /dev/null +++ b/chem/KPP/util/wkc/CMakeLists.txt @@ -0,0 +1,139 @@ + + +set( FOLDER_COMPILE_TARGET registry_kpp ) + +add_executable( + ${FOLDER_COMPILE_TARGET} + ) + +set( GEN_COMMS ${PROJECT_SOURCE_DIR}/tools/gen_comms.stub ) +# if ( ${USE_RSL_LITE} ) +# message( STATUS "Setting gen_comms to RSL_LITE" ) +# set( GEN_COMMS ${PROJECT_SOURCE_DIR}/external/RSL_LITE/gen_comms.c ) +# else() +# # Account for the weird makefile nonsense of copying things around +# Apparently chem-kpp does not use the rsl_lite comms, but I'm leaving the logic +# here just in case it needs to change +set_source_files_properties( + ${GEN_COMMS} + TARGET_DIRECTORY ${FOLDER_COMPILE_TARGET} + PROPERTIES + LANGUAGE C + ) +# endif() + +target_sources( + ${FOLDER_COMPILE_TARGET} + PRIVATE + registry_kpp.c + ${PROJECT_SOURCE_DIR}/tools/my_strtok.c + ${PROJECT_SOURCE_DIR}/tools/reg_parse.c + ${PROJECT_SOURCE_DIR}/tools/data.c + ${PROJECT_SOURCE_DIR}/tools/type.c + ${PROJECT_SOURCE_DIR}/tools/misc.c + ${PROJECT_SOURCE_DIR}/tools/sym.c + ${PROJECT_SOURCE_DIR}/tools/symtab_gen.c + + gen_kpp.c + get_wrf_chem_specs.c + gen_kpp_mech_dr.c + gen_kpp_interface.c + get_kpp_chem_specs.c + compare_kpp_to_species.c + get_wrf_radicals.c + get_wrf_jvals.c + gen_kpp_utils.c + gen_kpp_interf_utils.c + gen_kpp_args_to_Update_Rconst.c + kpp_data.c + + ${GEN_COMMS} + ) + + +target_include_directories( ${FOLDER_COMPILE_TARGET} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/tools + ) + +# Make sure we don't do any weird in-place modification of files +target_compile_definitions( ${FOLDER_COMPILE_TARGET} PRIVATE NO_MODIFY_MAKEFILE ) + +# Should this be installed? Consider also removing regular registry from install... +# install( +# TARGETS ${FOLDER_COMPILE_TARGET} +# RUNTIME DESTINATION bin/ +# ARCHIVE DESTINATION lib/ +# LIBRARY DESTINATION lib/ +# ) + + +# Quickly add tuv_kpp exec as well +add_executable( tuv_kpp tuv_kpp.c ) + + +# Do registry_kpp generation of sources and include files +set( KPP_INTERFACE_SOURCES ) +set( KPP_INTERFACE_SOURCES_CMD_CHECK ) +foreach( MECH ${MECHANISMS} ) + set( KPP_INTERFACE_SOURCE ${CMAKE_BINARY_DIR}/chem/module_kpp_${MECH}_interface.F ) + list( APPEND KPP_INTERFACE_SOURCES ${KPP_INTERFACE_SOURCE} ) + list( + APPEND KPP_INTERFACE_SOURCES_CMD_CHECK + COMMAND ${CMAKE_COMMAND} -E compare_files ${KPP_INTERFACE_SOURCE} ${KPP_INTERFACE_SOURCE} + ) + +endforeach() + + +get_directory_property( DIR_DEFS DIRECTORY ${CMAKE_SOURCE_DIR} COMPILE_DEFINITIONS ) +wrf_expand_definitions( + RESULT_VAR REGISTRY_DEFS + DEFINITIONS ${DIR_DEFS} + ) + +add_custom_command( + OUTPUT + gen_${FOLDER_COMPILE_TARGET} + ${CMAKE_BINARY_DIR}/chem/kpp_mechanism_driver.F + ${KPP_INTERFACE_SOURCES} + WORKING_DIRECTORY + ${CMAKE_BINARY_DIR} + # Replicate what exists in project directory for registry + COMMAND + ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/Registry + COMMAND + ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/inc + COMMAND + ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/frame + COMMAND + $ ${REGISTRY_DEFS} ${REGISTRY_FILE} > ${CMAKE_BINARY_DIR}/${FOLDER_COMPILE_TARGET}.log 2>&1 + ${KPP_INTERFACE_SOURCES_CMD_CHECK} + COMMAND + ${CMAKE_COMMAND} -E compare_files ${CMAKE_BINARY_DIR}/chem/kpp_mechanism_driver.F ${CMAKE_BINARY_DIR}/chem/kpp_mechanism_driver.F + COMMAND + ${CMAKE_COMMAND} -E touch gen_${FOLDER_COMPILE_TARGET} + DEPENDS + ${FOLDER_COMPILE_TARGET} + ) + + + +add_custom_target( + registry_kpp_code + DEPENDS + ${KPP_INTERFACE_SOURCES} + ${CMAKE_BINARY_DIR}/chem/kpp_mechanism_driver.F + gen_${FOLDER_COMPILE_TARGET} + ) + + +add_dependencies( ${PROJECT_NAME}_Core registry_kpp_code ) +target_sources( + ${PROJECT_NAME}_Core + PRIVATE + ${KPP_INTERFACE_SOURCES} + ${CMAKE_BINARY_DIR}/chem/kpp_mechanism_driver.F + ) + diff --git a/chem/KPP/util/wkc/gen_kpp.c b/chem/KPP/util/wkc/gen_kpp.c index 63dcd2f853..ef1df7f110 100644 --- a/chem/KPP/util/wkc/gen_kpp.c +++ b/chem/KPP/util/wkc/gen_kpp.c @@ -225,12 +225,11 @@ gen_kpp ( char * inc_dirname, char * kpp_dirname ) check_all ( kpp_dirname ); - +#ifndef NO_MODIFY_MAKEFILE /* add the kpp generated modules to the Makefile in the chem directory */ if ( DEBUGR == 1 ) printf("next: change_chem_Makefile \n"); change_chem_Makefile ( ); - - +#endif /* write the mechanism driver */ diff --git a/chem/KPP/util/wkc/protos_kpp.h b/chem/KPP/util/wkc/protos_kpp.h index e1f6c41b65..8254a017d9 100644 --- a/chem/KPP/util/wkc/protos_kpp.h +++ b/chem/KPP/util/wkc/protos_kpp.h @@ -18,8 +18,9 @@ int compare_kpp_to_species ( char * kpp_dirname) ; int run_kpp( char * dirname , char * kpp_version ); +#ifndef NO_MODIFY_MAKEFILE void change_chem_Makefile( ); - +#endif void gen_kpp_mechanism_driver ( ); void gen_kpp_call_to_mech_dr ( ); diff --git a/chem/KPP/util/wkc/tuv_kpp.c b/chem/KPP/util/wkc/tuv_kpp.c index cd878c5df3..32b5de6ddc 100644 --- a/chem/KPP/util/wkc/tuv_kpp.c +++ b/chem/KPP/util/wkc/tuv_kpp.c @@ -31,6 +31,7 @@ int main( int argc, char *argv[], char *env[] ) { char squezzed[NAMELEN]; char *wrf_jname, *cwrk, *tuv_jspec, *token; char *tuv_jname; + char openMode[1] = "a"; FILE * fp_in, *fp_set, *fp_def; wrf_node *Wrf_node; wrf_node *Wrf_HEAD; @@ -46,22 +47,27 @@ int main( int argc, char *argv[], char *env[] ) { argv++; strcpy( mech,*argv ); + argv++; + strcpy( dir,*argv ); + fprintf(stderr,"tuv_kpp: Argument = %s\n",mech); // open and write inc files + strcpy( fname_inc, dir ); + strcat( fname_inc, "tuv2wrf_jvals.inc" ); - if( !strcmp(mech,"LAST") ) - strcpy(fname_inc,"../../inc/tuv2wrf_jvals.inc"); - else - strcpy(fname_inc,"../../../../inc/tuv2wrf_jvals.inc"); - if( (fp_set = fopen( fname_inc,"a" )) == NULL ) { + if( !strcmp(mech,"FIRST") ) { + strcpy( openMode, "w" ); + } + + if( (fp_set = fopen( fname_inc, openMode )) == NULL ) { fprintf(stderr,"Can not open %s\n",fname_inc ); return(-1); } - if( !strcmp(mech,"LAST") ) - strcpy(fname_inc,"../../inc/tuvdef_jvals.inc"); - else - strcpy(fname_inc,"../../../../inc/tuvdef_jvals.inc"); - if( (fp_def = fopen( fname_inc,"a" )) == NULL ) { + + strcpy( fname_inc, dir ); + strcat( fname_inc, "tuvdef_jvals.inc" ); + + if( (fp_def = fopen( fname_inc, openMode )) == NULL ) { fprintf(stderr,"Can not open %s\n",fname_inc ); return(-1); } diff --git a/chem/KPP/util/write_decomp/CMakeLists.txt b/chem/KPP/util/write_decomp/CMakeLists.txt new file mode 100644 index 0000000000..f80de45d35 --- /dev/null +++ b/chem/KPP/util/write_decomp/CMakeLists.txt @@ -0,0 +1,3 @@ +# Compile once and only ONCE +add_executable( integration_edit integr_edit.c ) +target_compile_definitions( integration_edit PRIVATE -DNO_COPY ) diff --git a/chem/KPP/util/write_decomp/Makefile b/chem/KPP/util/write_decomp/Makefile index 7be276bf72..f8f1ebbe6d 100644 --- a/chem/KPP/util/write_decomp/Makefile +++ b/chem/KPP/util/write_decomp/Makefile @@ -28,7 +28,7 @@ all: $(MAKE) comp ./write_decomp.exe $(MAKE) integr_edit - ./integr_edit.exe $(MECH) + ./integr_edit.exe $(MECH) module_kpp_$(MECH)_Integr.F decomp_$(MODEL).inc $(MODEL)_new $(MAKE) clean diff --git a/chem/KPP/util/write_decomp/integr_edit.c b/chem/KPP/util/write_decomp/integr_edit.c index 82faae53c4..dee009dce4 100644 --- a/chem/KPP/util/write_decomp/integr_edit.c +++ b/chem/KPP/util/write_decomp/integr_edit.c @@ -25,99 +25,84 @@ main( int argc, char *argv[] ) FILE * ofile; - argv++ ; + + if ( argc != 5 ) + { + printf("ERROR: USAGE: integr_edit mech_name integrator_file decomp_inc_file output_file\n"); + exit(11); + } - if ( *argv ) - { + argv++ ; strcpy( mechname, *argv ); - } - else - { - printf("ERROR: USAGE: integr_edit mech_name\n"); - exit(11); - } - - sprintf ( intfname, "module_kpp_%s_Integr.F", mechname); - sprintf ( incfname, "decomp_%s.inc", mechname); - sprintf ( tfname, "%s_new", intfname ); - + argv++; + strcpy( intfname, *argv ); + argv++; + strcpy( incfname, *argv ); + argv++; + strcpy( tfname, *argv ); - sprintf( cp_command,"cp %s %s",tfname, intfname); + sprintf( cp_command,"cp %s %s",tfname, intfname ); - intf = fopen( intfname , "r" ); - incf = fopen( incfname , "r" ); - ofile = fopen( tfname , "w" ); + intf = fopen( intfname, "r" ); + incf = fopen( incfname, "r" ); + ofile = fopen( tfname, "w" ); - sprintf ( callln , " CALL %s_KppDecomp\0", mechname ); - sprintf ( endln , "END MODULE"); - - /* loop over lines in Integr file */ - while ( fgets ( inln , 4096 , intf ) != NULL ){ - - copyit=1; - - - /* replace call to decomp routine */ - - if ( !strncmp (inln, callln, strlen(callln)-1) ) { - - printf(" integr_edit: replacing %s \n", inln); - - fprintf(ofile, "!!! use direct adressing in decomp \n"); - fprintf(ofile, "!!! %s", inln); - fprintf(ofile, "CALL decomp_%s ( A, ising )\n", mechname ); + sprintf( callln, " CALL %s_KppDecomp\0", mechname ); + sprintf( endln, "END MODULE" ); + /* loop over lines in Integr file */ + while ( fgets( inln , 4096 , intf ) != NULL ) { - add_sub=1; - copyit=0; - } + copyit = 1; - /* add decomp routine w. direct referncing */ + /* replace call to decomp routine */ + if ( !strncmp( inln, callln, strlen( callln ) - 1 ) ) { - if ( !strncmp (inln, endln, strlen(endln)-1) ) { + printf(" integr_edit: replacing %s \n", inln); + fprintf(ofile, "!!! use direct adressing in decomp \n"); + fprintf(ofile, "!!! %s", inln); + fprintf(ofile, "CALL decomp_%s ( A, ising )\n", mechname ); - if ( add_sub ){ - printf(" %s ", inln ); - while ( fgets ( incln , 4096 , incf ) != NULL ){ - - fprintf(ofile, "%s", incln); - - } - - fprintf(ofile, " \n\n\n"); - } - } - - - - - /* copy line from original file */ - if ( copyit ) { - - fprintf(ofile, "%s", inln); + add_sub = 1; + copyit = 0; + } - } + /* add decomp routine w. direct referncing */ + if ( !strncmp (inln, endln, strlen(endln)-1) ) { - } + if ( add_sub ) { + printf(" %s ", inln ); + while ( fgets ( incln , 4096 , incf ) != NULL ) { + fprintf( ofile, "%s", incln ); + } + fprintf(ofile, " \n\n\n"); + } + } - if ( ! add_sub ) { - printf(" integr_edit: Kept previous version. \n "); - } + /* copy line from original file */ + if ( copyit ) { + fprintf( ofile, "%s", inln ); + } + } + if ( ! add_sub ) { + printf( " integr_edit: Kept previous version. \n " ); + } fclose( intf ); fclose( incf ); fclose( ofile ); - - system(cp_command); +#ifndef NO_COPY + system(cp_command); +#endif exit (0); } diff --git a/chem/chem_driver.F b/chem/chem_driver.F index 8650b9444a..485574ffe6 100755 --- a/chem/chem_driver.F +++ b/chem/chem_driver.F @@ -43,11 +43,12 @@ subroutine chem_driver ( grid , config_flags & USE module_wetdep_ls, only:wetdep_ls USE module_uoc_dustwd ! Claudia, 3 April 2014 [mklose 03082015] USE module_input_chem_data, only: last_chem_time, & + mozcart_lbc_set, & + bdy_chem_value_top_pv, & + PVS #if (defined(CHEM_DBG_I) && defined(CHEM_DBG_J) && defined(CHEM_DBG_K)) - chem_dbg, & + USE module_input_chem_data, only: chem_dbg #endif - mozcart_lbc_set, & - bdy_chem_value_top_pv,PVS USE module_chem_share, only: get_last_gas USE module_upper_bc_driver, only: upper_bc_driver USE module_tropopause, only: tropopause_driver diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index c858d2e281..92dd562378 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -119,6 +119,9 @@ foreach( n RANGE 0 31 ) ) endforeach() +# Make sure this exists at the top level - I'm avoiding using cache variables deliberately +set( REGISTRY_FILE ${REGISTRY_FILE} PARENT_SCOPE ) + wrf_expand_definitions( RESULT_VAR REGISTRY_DEFS DEFINITIONS ${PROJECT_COMPILE_DEFINITIONS} diff --git a/tools/data.h b/tools/data.h index 081ece8616..c6171e4c22 100644 --- a/tools/data.h +++ b/tools/data.h @@ -103,6 +103,8 @@ EXTERN char sw_commpath[NAMELEN] ; EXTERN int sw_new_bdys ; /* 20070207 JM support decomposed boundary arrays */ EXTERN int sw_unidir_shift_halo ; /* 20100210 JM assume that halo to shift is same in both directions and only gen one of them */ EXTERN int sw_new_with_old_bdys ; /* 20070207 JM for debugging interim phase, new comms w/ old data structs */ +EXTERN int sw_chem ; +EXTERN int sw_kpp ; EXTERN node_t * Type ; EXTERN node_t * Dim ; diff --git a/tools/registry.c b/tools/registry.c index b2dd0a5f6a..7919492cf9 100644 --- a/tools/registry.c +++ b/tools/registry.c @@ -54,6 +54,8 @@ main( int argc, char *argv[], char *env[] ) other data streams are written to file per process */ sw_new_bdys = 0 ; sw_unidir_shift_halo = 0 ; + sw_chem = 0; + sw_kpp = 0; strcpy( fname_in , "" ) ; @@ -127,6 +129,12 @@ main( int argc, char *argv[], char *env[] ) fprintf(stderr,"Usage: %s [-DDEREF_KLUDGE] [-DDM_PARALLEL] [-DDISTRIB_IO_LAYER] [-DDM_SERIAL_IN_ONLY] [-DD3VAR_IRY_KLUDGE] registryfile\n",thisprog) ; exit(1) ; } + if (!strcmp(*argv,"-DWRF_CHEM")) { + sw_chem = 1 ; + } + if (!strcmp(*argv,"-DWRF_KPP")) { + sw_kpp = 1 ; + } } else /* consider it an input file */ { @@ -144,10 +152,8 @@ main( int argc, char *argv[], char *env[] ) // possible IRR diagnostcis? // do_irr_diag = 0; - env_val = getenv( "WRF_CHEM" ); - if( env_val != NULL && !strncmp( env_val, "1", 1 ) ) { - env_val = getenv( "WRF_KPP" ); - if( env_val != NULL && !strncmp( env_val, "1", 1 ) ) do_irr_diag = 1; + if( sw_chem == 1 ) { + if( sw_kpp == 1 ) do_irr_diag = 1; } if( do_irr_diag ) { if( access( fname_in,F_OK ) ) {