From 6663aef70cf3d406d708527fb6c07c949009e8ad Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Wed, 13 Nov 2024 19:58:21 +1100 Subject: [PATCH 01/31] Copied CMakeLists.txt from COSIMA/access-om3/MOM6 --- cmake/CMakeLists.txt | 388 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 388 insertions(+) create mode 100644 cmake/CMakeLists.txt diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt new file mode 100644 index 0000000000..1842cbfdcf --- /dev/null +++ b/cmake/CMakeLists.txt @@ -0,0 +1,388 @@ +cmake_minimum_required(VERSION 3.18) + + +project(MOM6 DESCRIPTION "MOM6" LANGUAGES C Fortran) + + +# Common compiler flags and definitions +if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fbacktrace -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none") + if(${CMAKE_Fortran_COMPILER_VERSION} VERSION_GREATER_EQUAL 10) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fallow-argument-mismatch") + endif() + set(CMAKE_Fortran_FLAGS_RELEASE "-O") + set(CMAKE_Fortran_FLAGS_DEBUG "-g -Wall -Og -ffpe-trap=zero,overflow -fcheck=bounds") +elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Intel") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qno-opt-dynamic-align -convert big_endian -assume byterecl -ftz -traceback -assume realloc_lhs -fp-model source") + set(CMAKE_Fortran_FLAGS_RELEASE "-O2 -debug minimal") + set(CMAKE_Fortran_FLAGS_DEBUG "-O0 -g -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created") +else() + message(WARNING "Fortran compiler with ID ${CMAKE_Fortran_COMPILER_ID} will be used with CMake default options") +endif() + +if(CMAKE_C_COMPILER_ID MATCHES "GNU") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") + set(CMAKE_C_FLAGS_RELEASE "-O") + set(CMAKE_C_FLAGS_DEBUG "-g -Wall -Og -fbacktrace -ffpe-trap=invalid,zero,overflow -fcheck=bounds") +elseif(CMAKE_C_COMPILER_ID MATCHES "Intel") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -traceback -qno-opt-dynamic-align -fp-model precise -std=gnu99") + set(CMAKE_C_FLAGS_RELEASE "-O2 -debug minimal") + set(CMAKE_C_FLAGS_DEBUG "-O0 -g") +else() + message(WARNING "C compiler with ID ${CMAKE_C_COMPILER_ID} will be used with CMake default options") +endif() + +add_compile_definitions( + _USE_GENERIC_TRACER + _USE_MOM6_DIAG +) + +### Targets + +set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/../src") +set(CONFIG_SRC "${CMAKE_CURRENT_SOURCE_DIR}/../config_src") + +## MOM6 library +add_fortran_library(OM3_mom6 mod STATIC) +add_library(AccessOM3::mom6 ALIAS OM3_mom6) +target_include_directories(OM3_mom6 PRIVATE $) +if(OM3_MOM_SYMMETRIC) + target_include_directories(OM3_mom6 PRIVATE $) +else() + target_include_directories(OM3_mom6 PRIVATE $) +endif() +target_compile_options(OM3_mom6 PRIVATE "$<$:${fortran_compile_flags}>") +target_link_libraries(OM3_mom6 + PUBLIC esmf + PRIVATE AccessOM3::nuopc_cap_share AccessOM3::share FMS::fms_r8 +) + + +target_sources(OM3_mom6 PRIVATE + ${SRC}/ALE/coord_adapt.F90 + ${SRC}/ALE/coord_hycom.F90 + ${SRC}/ALE/coord_rho.F90 + ${SRC}/ALE/coord_sigma.F90 + ${SRC}/ALE/coord_zlike.F90 + ${SRC}/ALE/MOM_ALE.F90 + ${SRC}/ALE/MOM_hybgen_regrid.F90 + ${SRC}/ALE/MOM_hybgen_remap.F90 + ${SRC}/ALE/MOM_hybgen_unmix.F90 + ${SRC}/ALE/MOM_regridding.F90 + ${SRC}/ALE/MOM_remapping.F90 + ${SRC}/ALE/P1M_functions.F90 + ${SRC}/ALE/P3M_functions.F90 + ${SRC}/ALE/PCM_functions.F90 + ${SRC}/ALE/PLM_functions.F90 + ${SRC}/ALE/polynomial_functions.F90 + ${SRC}/ALE/PPM_functions.F90 + ${SRC}/ALE/PQM_functions.F90 + ${SRC}/ALE/regrid_consts.F90 + ${SRC}/ALE/regrid_edge_values.F90 + ${SRC}/ALE/regrid_interp.F90 + ${SRC}/ALE/regrid_solvers.F90 + ${SRC}/ALE/remapping_attic.F90 + + ${SRC}/core/MOM_barotropic.F90 + ${SRC}/core/MOM_boundary_update.F90 + ${SRC}/core/MOM_check_scaling.F90 + ${SRC}/core/MOM_checksum_packages.F90 + ${SRC}/core/MOM_continuity.F90 + ${SRC}/core/MOM_continuity_PPM.F90 + ${SRC}/core/MOM_CoriolisAdv.F90 + ${SRC}/core/MOM_density_integrals.F90 + ${SRC}/core/MOM_dynamics_split_RK2.F90 + ${SRC}/core/MOM_dynamics_unsplit.F90 + ${SRC}/core/MOM_dynamics_unsplit_RK2.F90 + ${SRC}/core/MOM.F90 + ${SRC}/core/MOM_grid.F90 + ${SRC}/core/MOM_interface_heights.F90 + ${SRC}/core/MOM_isopycnal_slopes.F90 + ${SRC}/core/MOM_open_boundary.F90 + ${SRC}/core/MOM_porous_barriers.F90 + ${SRC}/core/MOM_PressureForce.F90 + ${SRC}/core/MOM_PressureForce_FV.F90 + ${SRC}/core/MOM_PressureForce_Montgomery.F90 + ${SRC}/core/MOM_stoch_eos.F90 + ${SRC}/core/MOM_transcribe_grid.F90 + ${SRC}/core/MOM_unit_tests.F90 + ${SRC}/core/MOM_variables.F90 + ${SRC}/core/MOM_verticalGrid.F90 + + ${SRC}/diagnostics/MOM_debugging.F90 + ${SRC}/diagnostics/MOM_diagnostics.F90 + ${SRC}/diagnostics/MOM_obsolete_diagnostics.F90 + ${SRC}/diagnostics/MOM_obsolete_params.F90 + ${SRC}/diagnostics/MOM_PointAccel.F90 + ${SRC}/diagnostics/MOM_spatial_means.F90 + ${SRC}/diagnostics/MOM_sum_output.F90 + ${SRC}/diagnostics/MOM_wave_speed.F90 + + ${SRC}/equation_of_state/MOM_EOS.F90 + ${SRC}/equation_of_state/MOM_EOS_Jackett06.F90 + ${SRC}/equation_of_state/MOM_EOS_linear.F90 + ${SRC}/equation_of_state/MOM_EOS_Roquet_rho.F90 + ${SRC}/equation_of_state/MOM_EOS_Roquet_SpV.F90 + ${SRC}/equation_of_state/MOM_EOS_TEOS10.F90 + ${SRC}/equation_of_state/MOM_EOS_UNESCO.F90 + ${SRC}/equation_of_state/MOM_EOS_Wright.F90 + ${SRC}/equation_of_state/MOM_EOS_Wright_full.F90 + ${SRC}/equation_of_state/MOM_EOS_Wright_red.F90 + ${SRC}/equation_of_state/MOM_temperature_convert.F90 + ${SRC}/equation_of_state/MOM_TFreeze.F90 + + ${SRC}/equation_of_state/TEOS10/gsw_chem_potential_water_t_exact.f90 + ${SRC}/equation_of_state/TEOS10/gsw_ct_freezing_exact.f90 + ${SRC}/equation_of_state/TEOS10/gsw_ct_freezing_poly.f90 + ${SRC}/equation_of_state/TEOS10/gsw_ct_from_pt.f90 + ${SRC}/equation_of_state/TEOS10/gsw_ct_from_t.f90 + ${SRC}/equation_of_state/TEOS10/gsw_entropy_part.f90 + ${SRC}/equation_of_state/TEOS10/gsw_entropy_part_zerop.f90 + ${SRC}/equation_of_state/TEOS10/gsw_gibbs.f90 + ${SRC}/equation_of_state/TEOS10/gsw_gibbs_ice.f90 + ${SRC}/equation_of_state/TEOS10/gsw_gibbs_pt0_pt0.f90 + ${SRC}/equation_of_state/TEOS10/gsw_mod_error_functions.f90 + ${SRC}/equation_of_state/TEOS10/gsw_mod_freezing_poly_coefficients.f90 + ${SRC}/equation_of_state/TEOS10/gsw_mod_gibbs_ice_coefficients.f90 + ${SRC}/equation_of_state/TEOS10/gsw_mod_kinds.f90 + ${SRC}/equation_of_state/TEOS10/gsw_mod_specvol_coefficients.f90 + ${SRC}/equation_of_state/TEOS10/gsw_mod_teos10_constants.f90 + ${SRC}/equation_of_state/TEOS10/gsw_mod_toolbox.f90 + ${SRC}/equation_of_state/TEOS10/gsw_pt0_from_t.f90 + ${SRC}/equation_of_state/TEOS10/gsw_pt_from_ct.f90 + ${SRC}/equation_of_state/TEOS10/gsw_pt_from_t.f90 + ${SRC}/equation_of_state/TEOS10/gsw_rho.f90 + ${SRC}/equation_of_state/TEOS10/gsw_rho_first_derivatives.f90 + ${SRC}/equation_of_state/TEOS10/gsw_rho_second_derivatives.f90 + ${SRC}/equation_of_state/TEOS10/gsw_sp_from_sr.f90 + ${SRC}/equation_of_state/TEOS10/gsw_sr_from_sp.f90 + ${SRC}/equation_of_state/TEOS10/gsw_specvol.f90 + ${SRC}/equation_of_state/TEOS10/gsw_specvol_first_derivatives.f90 + ${SRC}/equation_of_state/TEOS10/gsw_specvol_second_derivatives.f90 + ${SRC}/equation_of_state/TEOS10/gsw_t_deriv_chem_potential_water_t_exact.f90 + ${SRC}/equation_of_state/TEOS10/gsw_t_freezing_exact.f90 + ${SRC}/equation_of_state/TEOS10/gsw_t_freezing_poly.f90 + ${SRC}/equation_of_state/TEOS10/gsw_t_from_ct.f90 + + ${SRC}/framework/MOM_array_transform.F90 + ${SRC}/framework/MOM_checksums.F90 + ${SRC}/framework/MOM_coms.F90 + ${SRC}/framework/MOM_cpu_clock.F90 + ${SRC}/framework/MOM_data_override.F90 + ${SRC}/framework/MOM_diag_mediator.F90 + ${SRC}/framework/MOM_diag_remap.F90 + ${SRC}/framework/MOM_document.F90 + ${SRC}/framework/MOM_domains.F90 + ${SRC}/framework/MOM_dyn_horgrid.F90 + ${SRC}/framework/MOM_ensemble_manager.F90 + ${SRC}/framework/MOM_error_handler.F90 + ${SRC}/framework/MOM_file_parser.F90 + ${SRC}/framework/MOM_get_input.F90 + ${SRC}/framework/MOM_hor_index.F90 + ${SRC}/framework/MOM_horizontal_regridding.F90 + ${SRC}/framework/MOM_interpolate.F90 + ${SRC}/framework/MOM_intrinsic_functions.F90 + ${SRC}/framework/MOM_io.F90 + ${SRC}/framework/MOM_io_file.F90 + ${SRC}/framework/MOM_memory_macros.h + ${SRC}/framework/MOM_netcdf.F90 + ${SRC}/framework/MOM_random.F90 + ${SRC}/framework/MOM_restart.F90 + ${SRC}/framework/MOM_safe_alloc.F90 + ${SRC}/framework/MOM_string_functions.F90 + ${SRC}/framework/MOM_unique_scales.F90 + ${SRC}/framework/MOM_unit_scaling.F90 + ${SRC}/framework/MOM_write_cputime.F90 + ${SRC}/framework/posix.F90 + + ${SRC}/ice_shelf/MOM_ice_shelf_diag_mediator.F90 + ${SRC}/ice_shelf/MOM_ice_shelf_dynamics.F90 + ${SRC}/ice_shelf/MOM_ice_shelf.F90 + ${SRC}/ice_shelf/MOM_ice_shelf_initialize.F90 + ${SRC}/ice_shelf/MOM_ice_shelf_state.F90 + ${SRC}/ice_shelf/MOM_marine_ice.F90 + ${SRC}/ice_shelf/user_shelf_init.F90 + + ${SRC}/initialization/MOM_coord_initialization.F90 + ${SRC}/initialization/MOM_fixed_initialization.F90 + ${SRC}/initialization/MOM_grid_initialize.F90 + ${SRC}/initialization/MOM_shared_initialization.F90 + ${SRC}/initialization/MOM_state_initialization.F90 + ${SRC}/initialization/MOM_tracer_initialization_from_Z.F90 + + ${SRC}/ocean_data_assim/MOM_oda_driver.F90 + ${SRC}/ocean_data_assim/MOM_oda_incupd.F90 + + ${SRC}/parameterizations/CVmix/cvmix_background.F90 + ${SRC}/parameterizations/CVmix/cvmix_convection.F90 + ${SRC}/parameterizations/CVmix/cvmix_ddiff.F90 + ${SRC}/parameterizations/CVmix/cvmix_kinds_and_types.F90 + ${SRC}/parameterizations/CVmix/cvmix_kpp.F90 + ${SRC}/parameterizations/CVmix/cvmix_math.F90 + ${SRC}/parameterizations/CVmix/cvmix_put_get.F90 + ${SRC}/parameterizations/CVmix/cvmix_shear.F90 + ${SRC}/parameterizations/CVmix/cvmix_tidal.F90 + ${SRC}/parameterizations/CVmix/cvmix_utils.F90 + + ${SRC}/parameterizations/lateral/MOM_hor_visc.F90 + ${SRC}/parameterizations/lateral/MOM_interface_filter.F90 + ${SRC}/parameterizations/lateral/MOM_internal_tides.F90 + ${SRC}/parameterizations/lateral/MOM_lateral_mixing_coeffs.F90 + ${SRC}/parameterizations/lateral/MOM_load_love_numbers.F90 + ${SRC}/parameterizations/lateral/MOM_MEKE.F90 + ${SRC}/parameterizations/lateral/MOM_MEKE_types.F90 + ${SRC}/parameterizations/lateral/MOM_mixed_layer_restrat.F90 + ${SRC}/parameterizations/lateral/MOM_spherical_harmonics.F90 + ${SRC}/parameterizations/lateral/MOM_thickness_diffuse.F90 + ${SRC}/parameterizations/lateral/MOM_tidal_forcing.F90 + ${SRC}/parameterizations/lateral/MOM_Zanna_Bolton.F90 + + ${SRC}/parameterizations/stochastic/MOM_stochastics.F90 + + ${SRC}/parameterizations/vertical/MOM_ALE_sponge.F90 + ${SRC}/parameterizations/vertical/MOM_bkgnd_mixing.F90 + ${SRC}/parameterizations/vertical/MOM_bulk_mixed_layer.F90 + ${SRC}/parameterizations/vertical/MOM_CVMix_conv.F90 + ${SRC}/parameterizations/vertical/MOM_CVMix_ddiff.F90 + ${SRC}/parameterizations/vertical/MOM_CVMix_KPP.F90 + ${SRC}/parameterizations/vertical/MOM_CVMix_shear.F90 + ${SRC}/parameterizations/vertical/MOM_diabatic_aux.F90 + ${SRC}/parameterizations/vertical/MOM_diabatic_driver.F90 + ${SRC}/parameterizations/vertical/MOM_diapyc_energy_req.F90 + ${SRC}/parameterizations/vertical/MOM_energetic_PBL.F90 + ${SRC}/parameterizations/vertical/MOM_entrain_diffusive.F90 + ${SRC}/parameterizations/vertical/MOM_full_convection.F90 + ${SRC}/parameterizations/vertical/MOM_geothermal.F90 + ${SRC}/parameterizations/vertical/MOM_internal_tide_input.F90 + ${SRC}/parameterizations/vertical/MOM_kappa_shear.F90 + ${SRC}/parameterizations/vertical/MOM_opacity.F90 + ${SRC}/parameterizations/vertical/MOM_regularize_layers.F90 + ${SRC}/parameterizations/vertical/MOM_set_diffusivity.F90 + ${SRC}/parameterizations/vertical/MOM_set_viscosity.F90 + ${SRC}/parameterizations/vertical/MOM_sponge.F90 + ${SRC}/parameterizations/vertical/MOM_tidal_mixing.F90 + ${SRC}/parameterizations/vertical/MOM_vert_friction.F90 + + ${SRC}/tracer/advection_test_tracer.F90 + ${SRC}/tracer/boundary_impulse_tracer.F90 + ${SRC}/tracer/DOME_tracer.F90 + ${SRC}/tracer/dyed_obc_tracer.F90 + ${SRC}/tracer/dye_example.F90 + ${SRC}/tracer/ideal_age_example.F90 + ${SRC}/tracer/ISOMIP_tracer.F90 + ${SRC}/tracer/MOM_CFC_cap.F90 + ${SRC}/tracer/MOM_hor_bnd_diffusion.F90 + ${SRC}/tracer/MOM_neutral_diffusion.F90 + ${SRC}/tracer/MOM_OCMIP2_CFC.F90 + ${SRC}/tracer/MOM_offline_aux.F90 + ${SRC}/tracer/MOM_offline_main.F90 + ${SRC}/tracer/MOM_tracer_advect.F90 + ${SRC}/tracer/MOM_tracer_diabatic.F90 + ${SRC}/tracer/MOM_tracer_flow_control.F90 + ${SRC}/tracer/MOM_tracer_hor_diff.F90 + ${SRC}/tracer/MOM_tracer_registry.F90 + ${SRC}/tracer/MOM_tracer_types.F90 + ${SRC}/tracer/MOM_tracer_Z_init.F90 + ${SRC}/tracer/nw2_tracers.F90 + ${SRC}/tracer/oil_tracer.F90 + ${SRC}/tracer/pseudo_salt_tracer.F90 + ${SRC}/tracer/RGC_tracer.F90 + ${SRC}/tracer/tracer_example.F90 + + ${SRC}/user/adjustment_initialization.F90 + ${SRC}/user/baroclinic_zone_initialization.F90 + ${SRC}/user/basin_builder.F90 + ${SRC}/user/benchmark_initialization.F90 + ${SRC}/user/BFB_initialization.F90 + ${SRC}/user/BFB_surface_forcing.F90 + ${SRC}/user/circle_obcs_initialization.F90 + ${SRC}/user/dense_water_initialization.F90 + ${SRC}/user/DOME2d_initialization.F90 + ${SRC}/user/DOME_initialization.F90 + ${SRC}/user/dumbbell_initialization.F90 + ${SRC}/user/dumbbell_surface_forcing.F90 + ${SRC}/user/dyed_channel_initialization.F90 + ${SRC}/user/dyed_obcs_initialization.F90 + ${SRC}/user/external_gwave_initialization.F90 + ${SRC}/user/Idealized_Hurricane.F90 + ${SRC}/user/ISOMIP_initialization.F90 + ${SRC}/user/Kelvin_initialization.F90 + ${SRC}/user/lock_exchange_initialization.F90 + ${SRC}/user/MOM_controlled_forcing.F90 + ${SRC}/user/MOM_wave_interface.F90 + ${SRC}/user/Neverworld_initialization.F90 + ${SRC}/user/Phillips_initialization.F90 + ${SRC}/user/RGC_initialization.F90 + ${SRC}/user/Rossby_front_2d_initialization.F90 + ${SRC}/user/SCM_CVMix_tests.F90 + ${SRC}/user/seamount_initialization.F90 + ${SRC}/user/shelfwave_initialization.F90 + ${SRC}/user/sloshing_initialization.F90 + ${SRC}/user/soliton_initialization.F90 + ${SRC}/user/supercritical_initialization.F90 + ${SRC}/user/tidal_bay_initialization.F90 + ${SRC}/user/user_change_diffusivity.F90 + ${SRC}/user/user_initialization.F90 + ${SRC}/user/user_revise_forcing.F90 + + ${CONFIG_SRC}/external/database_comms/MOM_database_comms.F90 + ${CONFIG_SRC}/external/database_comms/database_client_interface.F90 + + ${CONFIG_SRC}/external/drifters/MOM_particles.F90 + ${CONFIG_SRC}/external/drifters/MOM_particles_types.F90 + + ${CONFIG_SRC}/external/ODA_hooks/kdtree.f90 + ${CONFIG_SRC}/external/ODA_hooks/ocean_da_core.F90 + ${CONFIG_SRC}/external/ODA_hooks/ocean_da_types.F90 + ${CONFIG_SRC}/external/ODA_hooks/write_ocean_obs.F90 + + ${CONFIG_SRC}/external/stochastic_physics/get_stochy_pattern.F90 + ${CONFIG_SRC}/external/stochastic_physics/stochastic_physics.F90 + + ${CONFIG_SRC}/infra/FMS2/MOM_coms_infra.F90 + ${CONFIG_SRC}/infra/FMS2/MOM_constants.F90 + ${CONFIG_SRC}/infra/FMS2/MOM_cpu_clock_infra.F90 + ${CONFIG_SRC}/infra/FMS2/MOM_data_override_infra.F90 + ${CONFIG_SRC}/infra/FMS2/MOM_diag_manager_infra.F90 + ${CONFIG_SRC}/infra/FMS2/MOM_domain_infra.F90 + ${CONFIG_SRC}/infra/FMS2/MOM_ensemble_manager_infra.F90 + ${CONFIG_SRC}/infra/FMS2/MOM_error_infra.F90 + ${CONFIG_SRC}/infra/FMS2/MOM_interp_infra.F90 + ${CONFIG_SRC}/infra/FMS2/MOM_io_infra.F90 + ${CONFIG_SRC}/infra/FMS2/MOM_time_manager.F90 + + ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap_time.F90 + ${CONFIG_SRC}/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 + ${CONFIG_SRC}/drivers/nuopc_cap/ocn_comp_NUOPC.F90 + ${CONFIG_SRC}/drivers/nuopc_cap/time_utils.F90 + + extra_sources/mom_cap_gtracer_flux.F90 +) + +### Install and Export + +## Library +if(OM3_LIB_INSTALL) + set_target_properties(OM3_mom6 PROPERTIES + OUTPUT_NAME access-mom6 + EXPORT_NAME mom6 + ) + install(TARGETS OM3_mom6 + EXPORT AccessOM3mom6_Targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_RunTime NAMELINK_COMPONENT AccessOM3_Development + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_Development + ) + # Fortran module files are a special case, as currently there is no standard + # way of handling them in CMake + target_include_directories(OM3_mom6 PUBLIC "$") + get_target_property(mom_moddir OM3_mom6 Fortran_MODULE_DIRECTORY) + install(FILES ${mom_moddir}/ocn_comp_nuopc.mod ${mom_moddir}/mom_cap_mod.mod + DESTINATION ${CMAKE_INSTALL_MODULEDIR}/access-mom6 + COMPONENT AccessOM3_Development + ) + install(EXPORT AccessOM3mom6_Targets + FILE AccessOM3mom6Targets.cmake + NAMESPACE AccessOM3:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AccessOM3 + ) +endif() From e371579e0f94fbfffe77c28b9801281a12f719e9 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Fri, 15 Nov 2024 12:20:24 +1100 Subject: [PATCH 02/31] update CMakeLists.txt --- cmake/CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 1842cbfdcf..7e54bd9438 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -1,5 +1,13 @@ cmake_minimum_required(VERSION 3.18) +function(add_fortran_library LIB MOD_DIR) + add_library(${LIB} ${ARGN}) + + get_target_property(LIB_DIR ${LIB} BINARY_DIR) + set_target_properties(${LIB} PROPERTIES Fortran_MODULE_DIRECTORY ${LIB_DIR}/${MOD_DIR}) + + target_include_directories(${LIB} INTERFACE "$") +endfunction(add_fortran_library) project(MOM6 DESCRIPTION "MOM6" LANGUAGES C Fortran) @@ -356,7 +364,7 @@ target_sources(OM3_mom6 PRIVATE ${CONFIG_SRC}/drivers/nuopc_cap/ocn_comp_NUOPC.F90 ${CONFIG_SRC}/drivers/nuopc_cap/time_utils.F90 - extra_sources/mom_cap_gtracer_flux.F90 + #extra_sources/mom_cap_gtracer_flux.F90 ) ### Install and Export From d656bbd1218ee62dd4562aea2a49fdc148fbff78 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Thu, 14 Nov 2024 14:49:29 +1100 Subject: [PATCH 03/31] Add add_fortran_library function. --- cmake/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 7e54bd9438..2d32497e79 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -11,7 +11,15 @@ endfunction(add_fortran_library) project(MOM6 DESCRIPTION "MOM6" LANGUAGES C Fortran) +function(add_fortran_library LIB MOD_DIR) + add_library(${LIB} ${ARGN}) + + get_target_property(LIB_DIR ${LIB} BINARY_DIR) + set_target_properties(${LIB} PROPERTIES Fortran_MODULE_DIRECTORY ${LIB_DIR}/${MOD_DIR}) + target_include_directories(${LIB} INTERFACE "$") + endfunction(add_fortran_library) + # Common compiler flags and definitions if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fbacktrace -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none") From 2cd94a2c7757ae18a5887bd5f77513a1fe217002 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Tue, 26 Nov 2024 16:22:58 +1100 Subject: [PATCH 04/31] Update cmake directory to enable MOM6 standalone build --- cmake/CMakeLists.txt | 76 +++++++--- cmake/FindNetCDF.cmake | 337 +++++++++++++++++++++++++++++++++++++++++ cmake/FindPIO.cmake | 210 +++++++++++++++++++++++++ cmake/Fortranlib.cmake | 8 + 4 files changed, 610 insertions(+), 21 deletions(-) create mode 100644 cmake/FindNetCDF.cmake create mode 100644 cmake/FindPIO.cmake create mode 100644 cmake/Fortranlib.cmake diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 2d32497e79..9f04beb18c 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -1,37 +1,36 @@ cmake_minimum_required(VERSION 3.18) -function(add_fortran_library LIB MOD_DIR) - add_library(${LIB} ${ARGN}) +#[==============================================================================[ +# Basic project definition # +#]==============================================================================] - get_target_property(LIB_DIR ${LIB} BINARY_DIR) - set_target_properties(${LIB} PROPERTIES Fortran_MODULE_DIRECTORY ${LIB_DIR}/${MOD_DIR}) +project(MOM6 VERSION "0.1.0" + PROJECT_HOMEPAGE_URL https://github.com/ACCESS-NRI/MOM6 + DESCRIPTION "MOM6" + LANGUAGES C Fortran) - target_include_directories(${LIB} INTERFACE "$") -endfunction(add_fortran_library) +#[==============================================================================[ +# Project configuration # +#]==============================================================================] -project(MOM6 DESCRIPTION "MOM6" LANGUAGES C Fortran) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}) +include(GNUInstallDirs) +include(FortranLib) -function(add_fortran_library LIB MOD_DIR) - add_library(${LIB} ${ARGN}) - - get_target_property(LIB_DIR ${LIB} BINARY_DIR) - set_target_properties(${LIB} PROPERTIES Fortran_MODULE_DIRECTORY ${LIB_DIR}/${MOD_DIR}) - - target_include_directories(${LIB} INTERFACE "$") - endfunction(add_fortran_library) - # Common compiler flags and definitions if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fbacktrace -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none") if(${CMAKE_Fortran_COMPILER_VERSION} VERSION_GREATER_EQUAL 10) set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fallow-argument-mismatch") endif() + set(CMAKE_Fortran_FLAGS "-fdefault-real-8 -fdefault-double-8") set(CMAKE_Fortran_FLAGS_RELEASE "-O") set(CMAKE_Fortran_FLAGS_DEBUG "-g -Wall -Og -ffpe-trap=zero,overflow -fcheck=bounds") elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Intel") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qno-opt-dynamic-align -convert big_endian -assume byterecl -ftz -traceback -assume realloc_lhs -fp-model source") set(CMAKE_Fortran_FLAGS_RELEASE "-O2 -debug minimal") set(CMAKE_Fortran_FLAGS_DEBUG "-O0 -g -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created") + set(CMAKE_Fortran_FLAGS "-r8") else() message(WARNING "Fortran compiler with ID ${CMAKE_Fortran_COMPILER_ID} will be used with CMake default options") endif() @@ -51,16 +50,33 @@ endif() add_compile_definitions( _USE_GENERIC_TRACER _USE_MOM6_DIAG + #CESMCOUPLED +) + +## Fortran modules path; currently this is simply set to be the include dir +set(CMAKE_INSTALL_MODULEDIR ${CMAKE_INSTALL_INCLUDEDIR} + CACHE STRING + "Fortran module installation path (Not a cmake native variable)" ) +#[==============================================================================[ +# External packages # +#]==============================================================================] + +find_package(NetCDF REQUIRED Fortran) +find_package(fms COMPONENTS R8 REQUIRED) +find_package(PIO 2.5.3 REQUIRED COMPONENTS C Fortran) +#find_package(FoX 4.1.2 REQUIRED) + ### Targets +## MOM6 library + set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/../src") set(CONFIG_SRC "${CMAKE_CURRENT_SOURCE_DIR}/../config_src") -## MOM6 library add_fortran_library(OM3_mom6 mod STATIC) -add_library(AccessOM3::mom6 ALIAS OM3_mom6) + target_include_directories(OM3_mom6 PRIVATE $) if(OM3_MOM_SYMMETRIC) target_include_directories(OM3_mom6 PRIVATE $) @@ -69,8 +85,9 @@ else() endif() target_compile_options(OM3_mom6 PRIVATE "$<$:${fortran_compile_flags}>") target_link_libraries(OM3_mom6 - PUBLIC esmf - PRIVATE AccessOM3::nuopc_cap_share AccessOM3::share FMS::fms_r8 + #PUBLIC esmf + PRIVATE FMS::fms_r8 + #PRIVATE AccessOM3::nuopc_cap_share AccessOM3::share FMS::fms_r8 ) @@ -124,6 +141,8 @@ target_sources(OM3_mom6 PRIVATE ${SRC}/core/MOM_unit_tests.F90 ${SRC}/core/MOM_variables.F90 ${SRC}/core/MOM_verticalGrid.F90 + ${SRC}/core/MOM_forcing_type.F90 #add_patched_sources + ${SRC}/core/MOM_dynamics_split_RK2b.F90 #ml ${SRC}/diagnostics/MOM_debugging.F90 ${SRC}/diagnostics/MOM_diagnostics.F90 @@ -147,6 +166,8 @@ target_sources(OM3_mom6 PRIVATE ${SRC}/equation_of_state/MOM_temperature_convert.F90 ${SRC}/equation_of_state/MOM_TFreeze.F90 + ${SRC}/equation_of_state/MOM_EOS_base_type.F90 # ml + ${SRC}/equation_of_state/TEOS10/gsw_chem_potential_water_t_exact.f90 ${SRC}/equation_of_state/TEOS10/gsw_ct_freezing_exact.f90 ${SRC}/equation_of_state/TEOS10/gsw_ct_freezing_poly.f90 @@ -210,6 +231,7 @@ target_sources(OM3_mom6 PRIVATE ${SRC}/framework/MOM_unit_scaling.F90 ${SRC}/framework/MOM_write_cputime.F90 ${SRC}/framework/posix.F90 + ${SRC}/framework/MOM_coupler_types.F90 #add_patched_sources ${SRC}/ice_shelf/MOM_ice_shelf_diag_mediator.F90 ${SRC}/ice_shelf/MOM_ice_shelf_dynamics.F90 @@ -252,6 +274,7 @@ target_sources(OM3_mom6 PRIVATE ${SRC}/parameterizations/lateral/MOM_thickness_diffuse.F90 ${SRC}/parameterizations/lateral/MOM_tidal_forcing.F90 ${SRC}/parameterizations/lateral/MOM_Zanna_Bolton.F90 + ${SRC}/parameterizations/lateral/MOM_self_attr_load.F90 # ml ${SRC}/parameterizations/stochastic/MOM_stochastics.F90 @@ -305,6 +328,8 @@ target_sources(OM3_mom6 PRIVATE ${SRC}/tracer/RGC_tracer.F90 ${SRC}/tracer/tracer_example.F90 + ${SRC}/tracer/MOM_generic_tracer.F90 #add_patched_sources + ${SRC}/user/adjustment_initialization.F90 ${SRC}/user/baroclinic_zone_initialization.F90 ${SRC}/user/basin_builder.F90 @@ -341,6 +366,7 @@ target_sources(OM3_mom6 PRIVATE ${SRC}/user/user_initialization.F90 ${SRC}/user/user_revise_forcing.F90 + ${CONFIG_SRC}/external/database_comms/MOM_database_comms.F90 ${CONFIG_SRC}/external/database_comms/database_client_interface.F90 @@ -355,6 +381,9 @@ target_sources(OM3_mom6 PRIVATE ${CONFIG_SRC}/external/stochastic_physics/get_stochy_pattern.F90 ${CONFIG_SRC}/external/stochastic_physics/stochastic_physics.F90 + ${CONFIG_SRC}/external/GFDL_ocean_BGC/generic_tracer_utils.F90 #ml + ${CONFIG_SRC}/external/GFDL_ocean_BGC/generic_tracer.F90 #ml + ${CONFIG_SRC}/infra/FMS2/MOM_coms_infra.F90 ${CONFIG_SRC}/infra/FMS2/MOM_constants.F90 ${CONFIG_SRC}/infra/FMS2/MOM_cpu_clock_infra.F90 @@ -367,12 +396,17 @@ target_sources(OM3_mom6 PRIVATE ${CONFIG_SRC}/infra/FMS2/MOM_io_infra.F90 ${CONFIG_SRC}/infra/FMS2/MOM_time_manager.F90 + ${CONFIG_SRC}/infra/FMS2/MOM_couplertype_infra.F90 #add_patched_sources + ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap_time.F90 ${CONFIG_SRC}/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 ${CONFIG_SRC}/drivers/nuopc_cap/ocn_comp_NUOPC.F90 ${CONFIG_SRC}/drivers/nuopc_cap/time_utils.F90 - #extra_sources/mom_cap_gtracer_flux.F90 + ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap.F90 #add_patched_sources + ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap_methods.F90 #add_patched_sources + ${CONFIG_SRC}/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 #add_patched_sources + ) ### Install and Export diff --git a/cmake/FindNetCDF.cmake b/cmake/FindNetCDF.cmake new file mode 100644 index 0000000000..1439ae8486 --- /dev/null +++ b/cmake/FindNetCDF.cmake @@ -0,0 +1,337 @@ +# (C) Copyright 2011- ECMWF. +# +# This software is licensed under the terms of the Apache Licence Version 2.0 +# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. +# In applying this licence, ECMWF does not waive the privileges and immunities +# granted to it by virtue of its status as an intergovernmental organisation nor +# does it submit to any jurisdiction. + +# Try to find NetCDF includes and library. +# Supports static and shared libaries and allows each component to be found in sepearte prefixes. +# +# This module defines +# +# - NetCDF_FOUND - System has NetCDF +# - NetCDF_INCLUDE_DIRS - the NetCDF include directories +# - NetCDF_VERSION - the version of NetCDF +# - NetCDF_CONFIG_EXECUTABLE - the netcdf-config executable if found +# - NetCDF_PARALLEL - Boolean True if NetCDF4 has parallel IO support via hdf5 and/or pnetcdf +# - NetCDF_HAS_PNETCDF - Boolean True if NetCDF4 has pnetcdf support +# +# Deprecated Defines +# - NetCDF_LIBRARIES - [Deprecated] Use NetCDF::NetCDF_ targets instead. +# +# +# Following components are available: +# +# - C - C interface to NetCDF (netcdf) +# - CXX - CXX4 interface to NetCDF (netcdf_c++4) +# - Fortran - Fortran interface to NetCDF (netcdff) +# +# For each component the following are defined: +# +# - NetCDF__FOUND - whether the component is found +# - NetCDF__LIBRARIES - the libraries for the component +# - NetCDF__LIBRARY_SHARED - Boolean is true if libraries for component are shared +# - NetCDF__INCLUDE_DIRS - the include directories for specified component +# - NetCDF::NetCDF_ - target of component to be used with target_link_libraries() +# +# The following paths will be searched in order if set in CMake (first priority) or environment (second priority) +# +# - NetCDF_ROOT - root of NetCDF installation +# - NetCDF_PATH - root of NetCDF installation +# +# The search process begins with locating NetCDF Include headers. If these are in a non-standard location, +# set one of the following CMake or environment variables to point to the location: +# +# - NetCDF_INCLUDE_DIR or NetCDF_${comp}_INCLUDE_DIR +# - NetCDF_INCLUDE_DIRS or NetCDF_${comp}_INCLUDE_DIR +# +# Notes: +# +# - Use "NetCDF::NetCDF_" targets only. NetCDF_LIBRARIES exists for backwards compatibility and should not be used. +# - These targets have all the knowledge of include directories and library search directories, and a single +# call to target_link_libraries will provide all these transitive properties to your target. Normally all that is +# needed to build and link against NetCDF is, e.g.: +# target_link_libraries(my_c_tgt PUBLIC NetCDF::NetCDF_C) +# - "NetCDF" is always the preferred naming for this package, its targets, variables, and environment variables +# - For compatibility, some variables are also set/checked using alternate names NetCDF4, NETCDF, or NETCDF4 +# - Environments relying on these older environment variable names should move to using a "NetCDF_ROOT" environment variable +# - Preferred component capitalization follows the CMake LANGUAGES variables: i.e., C, Fortran, CXX +# - For compatibility, alternate capitalizations are supported but should not be used. +# - If no components are defined, all components will be searched +# + +list( APPEND _possible_components C CXX Fortran ) + +## Include names for each component +set( NetCDF_C_INCLUDE_NAME netcdf.h ) +set( NetCDF_CXX_INCLUDE_NAME netcdf ) +set( NetCDF_Fortran_INCLUDE_NAME netcdf.mod ) + +## Library names for each component +set( NetCDF_C_LIBRARY_NAME netcdf ) +set( NetCDF_CXX_LIBRARY_NAME netcdf_c++4 ) +set( NetCDF_Fortran_LIBRARY_NAME netcdff ) + +## Enumerate search components +foreach( _comp ${_possible_components} ) + string( TOUPPER "${_comp}" _COMP ) + set( _arg_${_COMP} ${_comp} ) + set( _name_${_COMP} ${_comp} ) +endforeach() + +set( _search_components C) +foreach( _comp ${${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS} ) + string( TOUPPER "${_comp}" _COMP ) + set( _arg_${_COMP} ${_comp} ) + list( APPEND _search_components ${_name_${_COMP}} ) + if( NOT _name_${_COMP} ) + message(SEND_ERROR "Find${CMAKE_FIND_PACKAGE_NAME}: COMPONENT ${_comp} is not a valid component. Valid components: ${_possible_components}" ) + endif() +endforeach() +list( REMOVE_DUPLICATES _search_components ) + +## Search hints for finding include directories and libraries +foreach( _comp IN ITEMS "_" "_C_" "_Fortran_" "_CXX_" ) + foreach( _name IN ITEMS NetCDF4 NetCDF NETCDF4 NETCDF ) + foreach( _var IN ITEMS ROOT PATH ) + list(APPEND _search_hints ${${_name}${_comp}${_var}} $ENV{${_name}${_comp}${_var}} ) + list(APPEND _include_search_hints + ${${_name}${_comp}INCLUDE_DIR} $ENV{${_name}${_comp}INCLUDE_DIR} + ${${_name}${_comp}INCLUDE_DIRS} $ENV{${_name}${_comp}INCLUDE_DIRS} ) + endforeach() + endforeach() +endforeach() +#Old-school HPC module env variable names +foreach( _name IN ITEMS NetCDF4 NetCDF NETCDF4 NETCDF ) + foreach( _comp IN ITEMS "_C" "_Fortran" "_CXX" ) + list(APPEND _search_hints ${${_name}} $ENV{${_name}}) + list(APPEND _search_hints ${${_name}${_comp}} $ENV{${_name}${_comp}}) + endforeach() +endforeach() + +## Find headers for each component +set(NetCDF_INCLUDE_DIRS) +set(_new_search_components) +foreach( _comp IN LISTS _search_components ) + if(NOT ${PROJECT_NAME}_NetCDF_${_comp}_FOUND) + list(APPEND _new_search_components ${_comp}) + endif() + find_file(NetCDF_${_comp}_INCLUDE_FILE + NAMES ${NetCDF_${_comp}_INCLUDE_NAME} + DOC "NetCDF ${_comp} include directory" + HINTS ${_include_search_hints} ${_search_hints} + PATH_SUFFIXES include include/netcdf + ) + mark_as_advanced(NetCDF_${_comp}_INCLUDE_FILE) + message(DEBUG "NetCDF_${_comp}_INCLUDE_FILE: ${NetCDF_${_comp}_INCLUDE_FILE}") + if( NetCDF_${_comp}_INCLUDE_FILE ) + get_filename_component(NetCDF_${_comp}_INCLUDE_FILE ${NetCDF_${_comp}_INCLUDE_FILE} ABSOLUTE) + get_filename_component(NetCDF_${_comp}_INCLUDE_DIR ${NetCDF_${_comp}_INCLUDE_FILE} DIRECTORY) + list(APPEND NetCDF_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIR}) + endif() +endforeach() +if(NetCDF_INCLUDE_DIRS) + list(REMOVE_DUPLICATES NetCDF_INCLUDE_DIRS) +endif() +set(NetCDF_INCLUDE_DIRS "${NetCDF_INCLUDE_DIRS}" CACHE STRING "NetCDF Include directory paths" FORCE) + +## Find n*-config executables for search components +foreach( _comp IN LISTS _search_components ) + if( _comp MATCHES "^(C)$" ) + set(_conf "c") + elseif( _comp MATCHES "^(Fortran)$" ) + set(_conf "f") + elseif( _comp MATCHES "^(CXX)$" ) + set(_conf "cxx4") + endif() + find_program( NetCDF_${_comp}_CONFIG_EXECUTABLE + NAMES n${_conf}-config + HINTS ${NetCDF_INCLUDE_DIRS} ${_include_search_hints} ${_search_hints} + PATH_SUFFIXES bin Bin ../bin ../../bin + DOC "NetCDF n${_conf}-config helper" ) + message(DEBUG "NetCDF_${_comp}_CONFIG_EXECUTABLE: ${NetCDF_${_comp}_CONFIG_EXECUTABLE}") +endforeach() + +set(_C_libs_flag --libs) +set(_Fortran_libs_flag --flibs) +set(_CXX_libs_flag --libs) +set(_C_includes_flag --includedir) +set(_Fortran_includes_flag --includedir) +set(_CXX_includes_flag --includedir) +function(netcdf_config exec flag output_var) + set(${output_var} False PARENT_SCOPE) + if( exec ) + execute_process( COMMAND ${exec} ${flag} RESULT_VARIABLE _ret OUTPUT_VARIABLE _val) + if( _ret EQUAL 0 ) + string( STRIP ${_val} _val ) + set( ${output_var} ${_val} PARENT_SCOPE ) + endif() + endif() +endfunction() + +## Find libraries for each component +set( NetCDF_LIBRARIES ) +foreach( _comp IN LISTS _search_components ) + string( TOUPPER "${_comp}" _COMP ) + + find_library( NetCDF_${_comp}_LIBRARY + NAMES ${NetCDF_${_comp}_LIBRARY_NAME} + DOC "NetCDF ${_comp} library" + HINTS ${NetCDF_${_comp}_INCLUDE_DIRS} ${_search_hints} + PATH_SUFFIXES lib64 lib ../lib64 ../lib ../../lib64 ../../lib ) + mark_as_advanced( NetCDF_${_comp}_LIBRARY ) + get_filename_component(NetCDF_${_comp}_LIBRARY ${NetCDF_${_comp}_LIBRARY} ABSOLUTE) + set(NetCDF_${_comp}_LIBRARY ${NetCDF_${_comp}_LIBRARY} CACHE STRING "NetCDF ${_comp} library" FORCE) + message(DEBUG "NetCDF_${_comp}_LIBRARY: ${NetCDF_${_comp}_LIBRARY}") + + if( NetCDF_${_comp}_LIBRARY ) + if( NetCDF_${_comp}_LIBRARY MATCHES ".a$" ) + set( NetCDF_${_comp}_LIBRARY_SHARED FALSE ) + set( _library_type STATIC) + else() + list( APPEND NetCDF_LIBRARIES ${NetCDF_${_comp}_LIBRARY} ) + set( NetCDF_${_comp}_LIBRARY_SHARED TRUE ) + set( _library_type SHARED) + endif() + endif() + + #Use nc-config to set per-component LIBRARIES variable if possible + netcdf_config( ${NetCDF_${_comp}_CONFIG_EXECUTABLE} ${_${_comp}_libs_flag} _val ) + if( _val ) + set( NetCDF_${_comp}_LIBRARIES ${_val} ) + if(NOT NetCDF_${_comp}_LIBRARY_SHARED AND NOT NetCDF_${_comp}_FOUND) #Static targets should use nc_config to get a proper link line with all necessary static targets. + list( APPEND NetCDF_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) + endif() + else() + set( NetCDF_${_comp}_LIBRARIES ${NetCDF_${_comp}_LIBRARY} ) + if(NOT NetCDF_${_comp}_LIBRARY_SHARED) + message(SEND_ERROR "Unable to properly find NetCDF. Found static libraries at: ${NetCDF_${_comp}_LIBRARY} but could not run nc-config: ${NetCDF_CONFIG_EXECUTABLE}") + endif() + endif() + + #Use nc-config to set per-component INCLUDE_DIRS variable if possible + netcdf_config( ${NetCDF_${_comp}_CONFIG_EXECUTABLE} ${_${_comp}_includes_flag} _val ) + if( _val ) + string( REPLACE " " ";" _val ${_val} ) + set( NetCDF_${_comp}_INCLUDE_DIRS ${_val} ) + else() + set( NetCDF_${_comp}_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIR} ) + endif() + + if( NetCDF_${_comp}_LIBRARIES AND NetCDF_${_comp}_INCLUDE_DIRS ) + set( ${CMAKE_FIND_PACKAGE_NAME}_${_arg_${_COMP}}_FOUND TRUE ) + if (NOT TARGET NetCDF::NetCDF_${_comp}) + add_library(NetCDF::NetCDF_${_comp} ${_library_type} IMPORTED) + set_target_properties(NetCDF::NetCDF_${_comp} PROPERTIES + IMPORTED_LOCATION ${NetCDF_${_comp}_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES "${NetCDF_${_comp}_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) + endif() + endif() +endforeach() +if(NetCDF_LIBRARIES AND NetCDF_${_comp}_LIBRARY_SHARED) + list(REMOVE_DUPLICATES NetCDF_LIBRARIES) +endif() +set(NetCDF_LIBRARIES "${NetCDF_LIBRARIES}" CACHE STRING "NetCDF library targets" FORCE) + +## Find version via netcdf-config if possible +if (NetCDF_INCLUDE_DIRS) + if( NetCDF_C_CONFIG_EXECUTABLE ) + netcdf_config( ${NetCDF_C_CONFIG_EXECUTABLE} --version _vers ) + if( _vers ) + string(REGEX REPLACE ".* ((([0-9]+)\\.)+([0-9]+)).*" "\\1" NetCDF_VERSION "${_vers}" ) + endif() + else() + foreach( _dir IN LISTS NetCDF_INCLUDE_DIRS) + if( EXISTS "${_dir}/netcdf_meta.h" ) + file(STRINGS "${_dir}/netcdf_meta.h" _netcdf_version_lines + REGEX "#define[ \t]+NC_VERSION_(MAJOR|MINOR|PATCH|NOTE)") + string(REGEX REPLACE ".*NC_VERSION_MAJOR *\([0-9]*\).*" "\\1" _netcdf_version_major "${_netcdf_version_lines}") + string(REGEX REPLACE ".*NC_VERSION_MINOR *\([0-9]*\).*" "\\1" _netcdf_version_minor "${_netcdf_version_lines}") + string(REGEX REPLACE ".*NC_VERSION_PATCH *\([0-9]*\).*" "\\1" _netcdf_version_patch "${_netcdf_version_lines}") + string(REGEX REPLACE ".*NC_VERSION_NOTE *\"\([^\"]*\)\".*" "\\1" _netcdf_version_note "${_netcdf_version_lines}") + set(NetCDF_VERSION "${_netcdf_version_major}.${_netcdf_version_minor}.${_netcdf_version_patch}${_netcdf_version_note}") + unset(_netcdf_version_major) + unset(_netcdf_version_minor) + unset(_netcdf_version_patch) + unset(_netcdf_version_note) + unset(_netcdf_version_lines) + endif() + endforeach() + endif() +endif () + +## Detect additional package properties +netcdf_config(${NetCDF_C_CONFIG_EXECUTABLE} --has-parallel4 _val) +if( NOT _val MATCHES "^(yes|no)$" ) + netcdf_config(${NetCDF_C_CONFIG_EXECUTABLE} --has-parallel _val) +endif() +if( _val MATCHES "^(yes)$" ) + set(NetCDF_PARALLEL TRUE CACHE STRING "NetCDF has parallel IO capability via pnetcdf or hdf5." FORCE) +else() + set(NetCDF_PARALLEL FALSE CACHE STRING "NetCDF has no parallel IO capability." FORCE) +endif() + +## Finalize find_package +include(FindPackageHandleStandardArgs) + +if(NOT NetCDF_FOUND OR _new_search_components) + find_package_handle_standard_args( ${CMAKE_FIND_PACKAGE_NAME} + REQUIRED_VARS NetCDF_INCLUDE_DIRS NetCDF_LIBRARIES + VERSION_VAR NetCDF_VERSION + HANDLE_COMPONENTS ) +endif() + +foreach( _comp IN LISTS _search_components ) + if( NetCDF_${_comp}_FOUND ) + #Record found components to avoid duplication in NetCDF_LIBRARIES for static libraries + set(NetCDF_${_comp}_FOUND ${NetCDF_${_comp}_FOUND} CACHE BOOL "NetCDF ${_comp} Found" FORCE) + #Set a per-package, per-component found variable to communicate between multiple calls to find_package() + set(${PROJECT_NAME}_NetCDF_${_comp}_FOUND True) + endif() +endforeach() + +if( ${CMAKE_FIND_PACKAGE_NAME}_FOUND AND NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY AND _new_search_components) + message( STATUS "Find${CMAKE_FIND_PACKAGE_NAME} defines targets:" ) + message( STATUS " - NetCDF_VERSION [${NetCDF_VERSION}]") + message( STATUS " - NetCDF_PARALLEL [${NetCDF_PARALLEL}]") + foreach( _comp IN LISTS _new_search_components ) + string( TOUPPER "${_comp}" _COMP ) + message( STATUS " - NetCDF_${_comp}_CONFIG_EXECUTABLE [${NetCDF_${_comp}_CONFIG_EXECUTABLE}]") + if( ${CMAKE_FIND_PACKAGE_NAME}_${_arg_${_COMP}}_FOUND ) + get_filename_component(_root ${NetCDF_${_comp}_INCLUDE_DIR}/.. ABSOLUTE) + if( NetCDF_${_comp}_LIBRARY_SHARED ) + message( STATUS " - NetCDF::NetCDF_${_comp} [SHARED] [Root: ${_root}] Lib: ${NetCDF_${_comp}_LIBRARY} ") + else() + message( STATUS " - NetCDF::NetCDF_${_comp} [STATIC] [Root: ${_root}] Lib: ${NetCDF_${_comp}_LIBRARY} ") + endif() + endif() + endforeach() +endif() + +foreach( _prefix NetCDF NetCDF4 NETCDF NETCDF4 ${CMAKE_FIND_PACKAGE_NAME} ) + set( ${_prefix}_INCLUDE_DIRS ${NetCDF_INCLUDE_DIRS} ) + set( ${_prefix}_LIBRARIES ${NetCDF_LIBRARIES}) + set( ${_prefix}_VERSION ${NetCDF_VERSION} ) + set( ${_prefix}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_FOUND} ) + set( ${_prefix}_CONFIG_EXECUTABLE ${NetCDF_CONFIG_EXECUTABLE} ) + set( ${_prefix}_PARALLEL ${NetCDF_PARALLEL} ) + + foreach( _comp ${_search_components} ) + string( TOUPPER "${_comp}" _COMP ) + set( _arg_comp ${_arg_${_COMP}} ) + set( ${_prefix}_${_comp}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_${_arg_comp}_FOUND} ) + set( ${_prefix}_${_COMP}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_${_arg_comp}_FOUND} ) + set( ${_prefix}_${_arg_comp}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_${_arg_comp}_FOUND} ) + + set( ${_prefix}_${_comp}_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) + set( ${_prefix}_${_COMP}_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) + set( ${_prefix}_${_arg_comp}_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) + + set( ${_prefix}_${_comp}_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIRS} ) + set( ${_prefix}_${_COMP}_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIRS} ) + set( ${_prefix}_${_arg_comp}_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIRS} ) + endforeach() +endforeach() diff --git a/cmake/FindPIO.cmake b/cmake/FindPIO.cmake new file mode 100644 index 0000000000..cbbd89f793 --- /dev/null +++ b/cmake/FindPIO.cmake @@ -0,0 +1,210 @@ + +# FindPIO.cmake +# +# Copyright UCAR 2020 +# Copyright NOAA/NWS/NCEP/EMC 2020 +# +# Find PIO: A high-level Parallel I/O Library for structured grid applications +# https://github.com/NCAR/ParallelIO +# +# Components available for query: +# C - Has C support +# Fortran - Has Fortran support +# SHARED - Has shared targets +# STATIC - Has static targets +# +# Variables provided: +# PIO_FOUND - True if PIO was found +# PIO_C_FOUND - True if PIO C support was found +# PIO_Fortran_FOUND - True if PIO Fortran support was found +# PIO_VERSION - Version of installed PIO +# +# Targets provided: +# PIO::PIO_C - C interface target aliased to SHARED|STATIC as requested or to shared libraries if available else static libraries +# PIO::PIO_Fortran - Fortran interface target aliases to SHARED|STATIC as requested or to shared libraries if available else static libraries +# +# To control finding of this package, set PIO_ROOT environment variable to the full path to the prefix +# under which PIO was installed (e.g., /usr/local) + +set( _search_components ) +set( _search_library_type ) +foreach( _comp ${${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS} ) + if( _comp MATCHES "^(STATIC|SHARED)$" ) + list( APPEND _search_library_type ${_comp} ) + else() + list( APPEND _search_components ${_comp} ) + endif() +endforeach() +set( ${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS ${_search_components} ) + +# If no COMPONENTS are requested, seach both C and Fortran +if( NOT _search_components ) + list( APPEND _search_components C Fortran ) +endif() + +# Ensure there is only one type of library being requested +if( _search_library_type ) + list( LENGTH _search_library_type _len) + if( _len GREATER 1 ) + message(FATAL_ERROR "User requesting both STATIC and SHARED is not permissible") + endif() + unset(_len) +endif() + +## Find libraries and paths, and determine found components +find_path(PIO_INCLUDE_DIR NAMES pio.h HINTS "${PIO_PREFIX}" PATH_SUFFIXES include include/pio) +if(PIO_INCLUDE_DIR) + string(REGEX REPLACE "/include(/.+)?" "" PIO_PREFIX ${PIO_INCLUDE_DIR}) + set(PIO_PREFIX ${PIO_PREFIX} CACHE STRING "") + find_path(PIO_MODULE_DIR NAMES pio.mod PATHS "${PIO_PREFIX}" + PATH_SUFFIXES include include/pio lib/pio/module module module/pio NO_DEFAULT_PATH) + if(APPLE) + set(_SHARED_LIB_EXT dylib) + else() + set(_SHARED_LIB_EXT so) + endif() + find_library(PIO_C_STATIC_LIB libpioc.a PATHS "${PIO_PREFIX}" PATH_SUFFIXES lib lib64 NO_DEFAULT_PATH) + find_library(PIO_C_SHARED_LIB libpioc.${_SHARED_LIB_EXT} PATHS "${PIO_PREFIX}" PATH_SUFFIXES lib lib64 NO_DEFAULT_PATH) + find_library(PIO_Fortran_STATIC_LIB libpiof.a PATHS "${PIO_PREFIX}" PATH_SUFFIXES lib lib64 NO_DEFAULT_PATH) + find_library(PIO_Fortran_SHARED_LIB libpiof.${_SHARED_LIB_EXT} PATHS "${PIO_PREFIX}" PATH_SUFFIXES lib lib64 NO_DEFAULT_PATH) + unset(_SHARED_LIB_EXT) + #Check for Fortran components + if(PIO_MODULE_DIR) + if(PIO_Fortran_STATIC_LIB) + set(PIO_Fortran_STATIC_FOUND 1) + endif() + if(PIO_Fortran_SHARED_LIB) + set(PIO_Fortran_SHARED_FOUND 1) + endif() + endif() + #Check for C components + if(PIO_C_STATIC_LIB) + set(PIO_C_STATIC_FOUND 1) + endif() + if(PIO_C_SHARED_LIB) + set(PIO_C_SHARED_FOUND 1) + endif() +endif() +## Debugging output +message(DEBUG "[FindPIO] PIO_INCLUDE_DIR: ${PIO_INCLUDE_DIR}") +message(DEBUG "[FindPIO] PIO_PREFIX: ${PIO_PREFIX}") +message(DEBUG "[FindPIO] PIO_MODULE_DIR: ${PIO_MODULE_DIR}") +message(DEBUG "[FindPIO] PIO_C_STATIC_LIB: ${PIO_C_STATIC_LIB}") +message(DEBUG "[FindPIO] PIO_C_SHARED_LIB: ${PIO_C_SHARED_LIB}") +message(DEBUG "[FindPIO] PIO_C_SHARED_FOUND: ${PIO_C_SHARED_FOUND}") +message(DEBUG "[FindPIO] PIO_C_STATIC_FOUND: ${PIO_C_STATIC_FOUND}") +message(DEBUG "[FindPIO] PIO_Fortran_STATIC_LIB: ${PIO_Fortran_STATIC_LIB}") +message(DEBUG "[FindPIO] PIO_Fortran_SHARED_LIB: ${PIO_Fortran_SHARED_LIB}") +message(DEBUG "[FindPIO] PIO_Fortran_SHARED_FOUND: ${PIO_Fortran_SHARED_FOUND}") +message(DEBUG "[FindPIO] PIO_Fortran_STATIC_FOUND: ${PIO_Fortran_STATIC_FOUND}") + +## Create targets +set(_new_components) +# PIO_C_STATIC imported interface target +if(PIO_C_STATIC_FOUND AND NOT TARGET PIO_C_STATIC) + add_library(PIO_C_STATIC INTERFACE IMPORTED) + set_target_properties(PIO_C_STATIC PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${PIO_INCLUDE_DIR} + INTERFACE_LINK_LIBRARIES ${PIO_C_STATIC_LIB} + IMPORTED_GLOBAL True ) + set(_new_components 1) +endif() +# PIO_C_SHARED imported interface target +if(PIO_C_SHARED_FOUND AND NOT TARGET PIO_C_SHARED) + add_library(PIO_C_SHARED INTERFACE IMPORTED) + set_target_properties(PIO_C_SHARED PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${PIO_INCLUDE_DIR} + INTERFACE_LINK_LIBRARIES ${PIO_C_SHARED_LIB} + IMPORTED_GLOBAL True ) + set(_new_components 1) +endif() +# PIO_Fortran_STATIC imported interface target +if(PIO_Fortran_STATIC_FOUND AND NOT TARGET PIO_Fortran_STATIC) + add_library(PIO_Fortran_STATIC INTERFACE IMPORTED) + set_target_properties(PIO_Fortran_STATIC PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${PIO_INCLUDE_DIR} + INTERFACE_LINK_LIBRARIES ${PIO_Fortran_STATIC_LIB} + IMPORTED_GLOBAL True ) + if(PIO_MODULE_DIR AND NOT PIO_MODULE_DIR STREQUAL PIO_INCLUDE_DIR ) + set_property(TARGET PIO_Fortran_STATIC APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${PIO_MODULE_DIR}) + endif() + set(_new_components 1) + target_link_libraries(PIO_Fortran_STATIC INTERFACE PIO_C_STATIC) +endif() +# PIO_Fortran_SHARED imported interface target +if(PIO_Fortran_SHARED_FOUND AND NOT TARGET PIO_Fortran_SHARED) + add_library(PIO_Fortran_SHARED INTERFACE IMPORTED) + set_target_properties(PIO_Fortran_SHARED PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${PIO_INCLUDE_DIR} + INTERFACE_LINK_LIBRARIES ${PIO_Fortran_SHARED_LIB} + IMPORTED_GLOBAL True ) + if(PIO_MODULE_DIR AND NOT PIO_MODULE_DIR STREQUAL PIO_INCLUDE_DIR ) + set_property(TARGET PIO_Fortran_SHARED APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${PIO_MODULE_DIR}) + endif() + target_link_libraries(PIO_Fortran_SHARED INTERFACE PIO_C_SHARED) + set(_new_components 1) +endif() + +if( _search_library_type MATCHES "^(SHARED)$" ) + if( TARGET PIO_C_SHARED ) + add_library(PIO::PIO_C ALIAS PIO_C_SHARED) + set(PIO_C_FOUND 1) + endif() + if( TARGET PIO_Fortran_SHARED ) + add_library(PIO::PIO_Fortran ALIAS PIO_Fortran_SHARED) + set(PIO_Fortran_FOUND 1) + endif() +elseif( _search_library_type MATCHES "^(STATIC)$" ) + if( TARGET PIO_C_STATIC ) + add_library(PIO::PIO_C ALIAS PIO_C_STATIC) + set(PIO_C_FOUND 1) + endif() + if( TARGET PIO_Fortran_STATIC ) + add_library(PIO::PIO_Fortran ALIAS PIO_Fortran_STATIC) + set(PIO_Fortran_FOUND 1) + endif() +else() + if( TARGET PIO_C_SHARED ) + add_library(PIO::PIO_C ALIAS PIO_C_SHARED) + set(PIO_C_FOUND 1) + elseif( TARGET PIO_C_STATIC ) + add_library(PIO::PIO_C ALIAS PIO_C_STATIC) + set(PIO_C_FOUND 1) + endif() + if( TARGET PIO_Fortran_SHARED ) + add_library(PIO::PIO_Fortran ALIAS PIO_Fortran_SHARED) + set(PIO_Fortran_FOUND 1) + elseif( TARGET PIO_Fortran_STATIC ) + add_library(PIO::PIO_Fortran ALIAS PIO_Fortran_STATIC) + set(PIO_Fortran_FOUND 1) + endif() +endif() + +## Check package has been found correctly +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + PIO + REQUIRED_VARS + PIO_PREFIX + PIO_INCLUDE_DIR + HANDLE_COMPONENTS +) +message(DEBUG "[FindPIO] PIO_FOUND: ${PIO_FOUND}") + +## Print status +if(${CMAKE_FIND_PACKAGE_NAME}_FOUND AND NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY AND _new_components) + message( STATUS "Find${CMAKE_FIND_PACKAGE_NAME}:" ) + message( STATUS " - ${CMAKE_FIND_PACKAGE_NAME}_PREFIX [${${CMAKE_FIND_PACKAGE_NAME}_PREFIX}]") + set(_found_comps) + foreach( _comp ${_search_components} ) + if( ${CMAKE_FIND_PACKAGE_NAME}_${_comp}_FOUND ) + list(APPEND _found_comps ${_comp}) + endif() + endforeach() + message( STATUS " - ${CMAKE_FIND_PACKAGE_NAME} Components Found: ${_found_comps}") + unset(_found_comps) +endif() +unset(_new_components) +unset(_search_components) +unset(_search_library_type) +unset(_library_type) diff --git a/cmake/Fortranlib.cmake b/cmake/Fortranlib.cmake new file mode 100644 index 0000000000..08bcccbf8c --- /dev/null +++ b/cmake/Fortranlib.cmake @@ -0,0 +1,8 @@ +function(add_fortran_library LIB MOD_DIR) + add_library(${LIB} ${ARGN}) + + get_target_property(LIB_DIR ${LIB} BINARY_DIR) + set_target_properties(${LIB} PROPERTIES Fortran_MODULE_DIRECTORY ${LIB_DIR}/${MOD_DIR}) + + target_include_directories(${LIB} INTERFACE "$") + endfunction(add_fortran_library) From 8c4425cfdaa79a0beb968e51d2e45063fe09fbd1 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Mon, 9 Dec 2024 15:13:29 +1100 Subject: [PATCH 05/31] Switch PROJECT_HOMEPAGE_URL and DESCRIPTION --- cmake/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 9f04beb18c..ee527f1b92 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -5,9 +5,9 @@ cmake_minimum_required(VERSION 3.18) #]==============================================================================] project(MOM6 VERSION "0.1.0" - PROJECT_HOMEPAGE_URL https://github.com/ACCESS-NRI/MOM6 - DESCRIPTION "MOM6" - LANGUAGES C Fortran) + DESCRIPTION "MOM6" + PROJECT_HOMEPAGE_URL https://github.com/ACCESS-NRI/MOM6 + LANGUAGES C Fortran) #[==============================================================================[ # Project configuration # From 18135a0138d5e296f58c2ddb21de3c2e964d19e5 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Mon, 9 Dec 2024 15:19:10 +1100 Subject: [PATCH 06/31] Fix typos --- cmake/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index ee527f1b92..7c34ed81fa 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.18) project(MOM6 VERSION "0.1.0" DESCRIPTION "MOM6" - PROJECT_HOMEPAGE_URL https://github.com/ACCESS-NRI/MOM6 + HOMEPAGE_URL https://github.com/ACCESS-NRI/MOM6 LANGUAGES C Fortran) #[==============================================================================[ From e08c0811fd2fdd2f3f96c24bcedfb1bc4a661a99 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Mon, 9 Dec 2024 15:22:34 +1100 Subject: [PATCH 07/31] Rename Fortranlib.cmake to FortranLib.cmake --- cmake/{Fortranlib.cmake => FortranLib.cmake} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename cmake/{Fortranlib.cmake => FortranLib.cmake} (100%) diff --git a/cmake/Fortranlib.cmake b/cmake/FortranLib.cmake similarity index 100% rename from cmake/Fortranlib.cmake rename to cmake/FortranLib.cmake From 9ee3d634fdf60ab59a8fe627cbad948d30504150 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Mon, 9 Dec 2024 15:30:05 +1100 Subject: [PATCH 08/31] Comment PIO --- cmake/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 7c34ed81fa..82d45c8a5b 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -65,7 +65,7 @@ set(CMAKE_INSTALL_MODULEDIR ${CMAKE_INSTALL_INCLUDEDIR} find_package(NetCDF REQUIRED Fortran) find_package(fms COMPONENTS R8 REQUIRED) -find_package(PIO 2.5.3 REQUIRED COMPONENTS C Fortran) +#find_package(PIO 2.5.3 REQUIRED COMPONENTS C Fortran) #find_package(FoX 4.1.2 REQUIRED) ### Targets From 6b2a366391cafe9278c707d26781c4bd83aaf725 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Mon, 9 Dec 2024 15:47:01 +1100 Subject: [PATCH 09/31] uncomment esmf library link --- cmake/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 82d45c8a5b..9fb5057e98 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -85,7 +85,7 @@ else() endif() target_compile_options(OM3_mom6 PRIVATE "$<$:${fortran_compile_flags}>") target_link_libraries(OM3_mom6 - #PUBLIC esmf + PUBLIC esmf PRIVATE FMS::fms_r8 #PRIVATE AccessOM3::nuopc_cap_share AccessOM3::share FMS::fms_r8 ) From 021a7f74495e8bf88e5941896975f3e58a5c0174 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Mon, 9 Dec 2024 16:43:40 +1100 Subject: [PATCH 10/31] add esmf package --- cmake/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 9fb5057e98..5cd580dbf7 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -65,6 +65,7 @@ set(CMAKE_INSTALL_MODULEDIR ${CMAKE_INSTALL_INCLUDEDIR} find_package(NetCDF REQUIRED Fortran) find_package(fms COMPONENTS R8 REQUIRED) +find_package(ESMF 8.3.0 MODULE REQUIRED) #find_package(PIO 2.5.3 REQUIRED COMPONENTS C Fortran) #find_package(FoX 4.1.2 REQUIRED) From 27129b52177602cb5ebe1181c89be3add570725b Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Mon, 9 Dec 2024 17:13:30 +1100 Subject: [PATCH 11/31] add findesmf cmake file --- cmake/FindESMF.cmake | 135 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 cmake/FindESMF.cmake diff --git a/cmake/FindESMF.cmake b/cmake/FindESMF.cmake new file mode 100644 index 0000000000..c79c5d3a1e --- /dev/null +++ b/cmake/FindESMF.cmake @@ -0,0 +1,135 @@ +# - Try to find ESMF +# +# Requires setting ESMFMKFILE to the filepath of esmf.mk. If this is NOT set, +# then ESMF_FOUND will always be FALSE. If ESMFMKFILE exists, then ESMF_FOUND=TRUE +# and all ESMF makefile variables will be set in the global scope. Optionally, +# set ESMF_MKGLOBALS to a string list to filter makefile variables. For example, +# to globally scope only ESMF_LIBSDIR and ESMF_APPSDIR variables, use this CMake +# command in CMakeLists.txt: +# +# set(ESMF_MKGLOBALS "LIBSDIR" "APPSDIR") + + +# Add the ESMFMKFILE path to the cache if defined as system env variable +if(DEFINED ENV{ESMFMKFILE} AND NOT DEFINED ESMFMKFILE) + set(ESMFMKFILE $ENV{ESMFMKFILE} CACHE FILEPATH "Path to ESMF mk file") +endif() + +# If it's not explicitly set try to find esmf.mk file in default locations (ESMF_ROOT, CMAKE_PREFIX_PATH, etc) +if(NOT DEFINED ESMFMKFILE) + find_path(ESMFMKFILE_PATH esmf.mk PATH_SUFFIXES lib lib64) + if(ESMFMKFILE_PATH) + set(ESMFMKFILE ${ESMFMKFILE_PATH}/esmf.mk) + message(STATUS "Found esmf.mk file ${ESMFMKFILE}") + else() + message(STATUS "ESMFMKFILE not defined. This is the path to esmf.mk file. \ +Without this filepath, ESMF_FOUND will always be FALSE.") + endif() +endif() + +# Only parse the mk file if it is found +if(EXISTS ${ESMFMKFILE}) + # Read the mk file + file(STRINGS "${ESMFMKFILE}" esmfmkfile_contents) + # Parse each line in the mk file + foreach(str ${esmfmkfile_contents}) + # Only consider uncommented lines + string(REGEX MATCH "^[^#]" def ${str}) + # Line is not commented + if(def) + # Extract the variable name + string(REGEX MATCH "^[^=]+" esmf_varname ${str}) + # Extract the variable's value + string(REGEX MATCH "=.+$" esmf_vardef ${str}) + # Only for variables with a defined value + if(esmf_vardef) + # Get rid of the assignment string + string(SUBSTRING ${esmf_vardef} 1 -1 esmf_vardef) + # Remove whitespace + string(STRIP ${esmf_vardef} esmf_vardef) + # A string or single-valued list + if(NOT DEFINED ESMF_MKGLOBALS) + # Set in global scope + set(${esmf_varname} ${esmf_vardef}) + # Don't display by default in GUI + mark_as_advanced(esmf_varname) + else() # Need to filter global promotion + foreach(m ${ESMF_MKGLOBALS}) + string(FIND ${esmf_varname} ${m} match) + # Found the string + if(NOT ${match} EQUAL -1) + # Promote to global scope + set(${esmf_varname} ${esmf_vardef}) + # Don't display by default in the GUI + mark_as_advanced(esmf_varname) + # No need to search for the current string filter + break() + endif() + endforeach() + endif() + endif() + endif() + endforeach() + + # Construct ESMF_VERSION from ESMF_VERSION_STRING_GIT + # ESMF_VERSION_MAJOR and ESMF_VERSION_MINOR are defined in ESMFMKFILE + set(ESMF_VERSION 0) + set(ESMF_VERSION_PATCH ${ESMF_VERSION_REVISION}) + set(ESMF_BETA_RELEASE FALSE) + if(ESMF_VERSION_BETASNAPSHOT MATCHES "^('T')$") + set(ESMF_BETA_RELEASE TRUE) + string(REGEX REPLACE ".*beta_snapshot_*\([0-9]*\).*" "\\1" ESMF_BETA_SNAPSHOT "${ESMF_VERSION_STRING_GIT}") + message(STATUS "Detected ESMF Beta snapshot ${ESMF_BETA_SNAPSHOT}") + endif() + set(ESMF_VERSION "${ESMF_VERSION_MAJOR}.${ESMF_VERSION_MINOR}.${ESMF_VERSION_PATCH}") + + separate_arguments(ESMF_F90COMPILEPATHS NATIVE_COMMAND ${ESMF_F90COMPILEPATHS}) + foreach(ITEM ${ESMF_F90COMPILEPATHS}) + string(REGEX REPLACE "^-I" "" ITEM "${ITEM}") + list(APPEND tmp ${ITEM}) + endforeach() + set(ESMF_F90COMPILEPATHS ${tmp}) + + # Look for static library, if not found try dynamic library + find_library(esmf_lib NAMES libesmf.a PATHS ${ESMF_LIBSDIR}) + if(esmf_lib MATCHES "esmf_lib-NOTFOUND") + unset(esmf_lib) + message(STATUS "Static ESMF library not found, searching for dynamic library instead") + find_library(esmf_lib NAMES esmf_fullylinked libesmf.so PATHS ${ESMF_LIBSDIR}) + if(esmf_lib MATCHES "esmf_lib-NOTFOUND") + unset(esmf_lib) + message(STATUS "Neither the dynamic nor the static ESMF library was found") + else() + set(_library_type SHARED) + endif() + else() + set(_library_type STATIC) + endif() + + string(STRIP "${ESMF_F90ESMFLINKRPATHS} ${ESMF_F90ESMFLINKPATHS} ${ESMF_F90LINKPATHS} ${ESMF_F90LINKLIBS} ${ESMF_F90LINKOPTS}" ESMF_INTERFACE_LINK_LIBRARIES) + set(ESMF_LIBRARY_LOCATION ${esmf_lib}) + +else() + + message(WARNING "ESMFMKFILE ${ESMFMKFILE} does not exist") + +endif() + +## Finalize find_package +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args( + ${CMAKE_FIND_PACKAGE_NAME} + REQUIRED_VARS ESMF_LIBRARY_LOCATION + ESMF_INTERFACE_LINK_LIBRARIES + ESMF_F90COMPILEPATHS + VERSION_VAR ESMF_VERSION) + +## If ESMF is found create imported library target +if(ESMF_FOUND) + add_library(esmf ${_library_type} IMPORTED) + set_target_properties(esmf PROPERTIES + IMPORTED_LOCATION "${ESMF_LIBRARY_LOCATION}" + INTERFACE_INCLUDE_DIRECTORIES "${ESMF_F90COMPILEPATHS}" + INTERFACE_LINK_LIBRARIES "${ESMF_INTERFACE_LINK_LIBRARIES}") +endif() \ No newline at end of file From bea91461108b2055f21fdcefed1d97f6fdb0b944 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Wed, 11 Dec 2024 11:15:02 +1100 Subject: [PATCH 12/31] Add c precessor for cesmcoupled --- cmake/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 5cd580dbf7..957251f3a5 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -50,9 +50,15 @@ endif() add_compile_definitions( _USE_GENERIC_TRACER _USE_MOM6_DIAG - #CESMCOUPLED ) +# Conditionally define CESMCOUPLED +if (CESMCOUPLED) + add_compile_definitions( + CESMCOUPLED + ) +endif() + ## Fortran modules path; currently this is simply set to be the include dir set(CMAKE_INSTALL_MODULEDIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE STRING From d2112f8a983fb5ad9c1afda3ad74ac93ed8aeff5 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Tue, 21 Jan 2025 09:59:58 +1100 Subject: [PATCH 13/31] Enable MOM6 standalone exe and ACCESS3MOM6 library --- cmake/CMakeLists.txt | 181 ++++++++++++++++++++++---------------- cmake/CompilerFlags.cmake | 32 +++++++ 2 files changed, 137 insertions(+), 76 deletions(-) create mode 100644 cmake/CompilerFlags.cmake diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 957251f3a5..7db85161fa 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -3,7 +3,6 @@ cmake_minimum_required(VERSION 3.18) #[==============================================================================[ # Basic project definition # #]==============================================================================] - project(MOM6 VERSION "0.1.0" DESCRIPTION "MOM6" HOMEPAGE_URL https://github.com/ACCESS-NRI/MOM6 @@ -12,51 +11,41 @@ project(MOM6 VERSION "0.1.0" #[==============================================================================[ # Project configuration # #]==============================================================================] +# Configurations to build +list(APPEND KnownConfigurations MOM6 ACCESS-MOM6) +option(ENABLE_MOM6 "Building MOM6 executable standalone" OFF) +option(ENABLE_ACCESS_MOM6 "Building MOM6 library with Access3share" ON) -list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}) -include(GNUInstallDirs) -include(FortranLib) +message(STATUS "Configuration") +message(STATUS " Building MOM6 executable standalone " ${ENABLE_MOM6}) +message(STATUS " Building MOM6 library with Access3share " ${ENABLE_ACCESS_MOM6}) -# Common compiler flags and definitions -if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") - set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fbacktrace -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none") - if(${CMAKE_Fortran_COMPILER_VERSION} VERSION_GREATER_EQUAL 10) - set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fallow-argument-mismatch") - endif() - set(CMAKE_Fortran_FLAGS "-fdefault-real-8 -fdefault-double-8") - set(CMAKE_Fortran_FLAGS_RELEASE "-O") - set(CMAKE_Fortran_FLAGS_DEBUG "-g -Wall -Og -ffpe-trap=zero,overflow -fcheck=bounds") -elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Intel") - set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qno-opt-dynamic-align -convert big_endian -assume byterecl -ftz -traceback -assume realloc_lhs -fp-model source") - set(CMAKE_Fortran_FLAGS_RELEASE "-O2 -debug minimal") - set(CMAKE_Fortran_FLAGS_DEBUG "-O0 -g -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created") - set(CMAKE_Fortran_FLAGS "-r8") -else() - message(WARNING "Fortran compiler with ID ${CMAKE_Fortran_COMPILER_ID} will be used with CMake default options") -endif() +# build options +option(ENABLE_MOM_SYMMETRIC "Use MOM symmetric memory" ON ) +option(ENABLE_CESMCOUPLED "Use CESMCOUPLED" OFF) -if(CMAKE_C_COMPILER_ID MATCHES "GNU") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") - set(CMAKE_C_FLAGS_RELEASE "-O") - set(CMAKE_C_FLAGS_DEBUG "-g -Wall -Og -fbacktrace -ffpe-trap=invalid,zero,overflow -fcheck=bounds") -elseif(CMAKE_C_COMPILER_ID MATCHES "Intel") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -traceback -qno-opt-dynamic-align -fp-model precise -std=gnu99") - set(CMAKE_C_FLAGS_RELEASE "-O2 -debug minimal") - set(CMAKE_C_FLAGS_DEBUG "-O0 -g") -else() - message(WARNING "C compiler with ID ${CMAKE_C_COMPILER_ID} will be used with CMake default options") +if (ENABLE_CESMCOUPLED AND NOT ENABLE_ACCESS_MOM6) + message(FATAL_ERROR "ENABLE_CESMCOUPLED can only be set if ENABLE_ACCESS_MOM6 is ON.") endif() -add_compile_definitions( - _USE_GENERIC_TRACER - _USE_MOM6_DIAG -) +message(STATUS "Build options") +message(STATUS "MOM_SYMMETRIC ${ENABLE_MOM_SYMMETRIC}") +message(STATUS "CESMCOUPLED ${ENABLE_CESMCOUPLED}" ) -# Conditionally define CESMCOUPLED -if (CESMCOUPLED) - add_compile_definitions( - CESMCOUPLED - ) +#[==============================================================================[ +# Project configuration # +#]==============================================================================] +# include libraries +list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}) +include(GNUInstallDirs) +include(FortranLib) +include(CompilerFlags) + +# Precessor (macro) definitions +add_compile_definitions(_USE_GENERIC_TRACER _USE_MOM6_DIAG) + +if (ENABLE_CESMCOUPLED) + add_compile_definitions(CESMCOUPLED) endif() ## Fortran modules path; currently this is simply set to be the include dir @@ -68,37 +57,47 @@ set(CMAKE_INSTALL_MODULEDIR ${CMAKE_INSTALL_INCLUDEDIR} #[==============================================================================[ # External packages # #]==============================================================================] - find_package(NetCDF REQUIRED Fortran) find_package(fms COMPONENTS R8 REQUIRED) -find_package(ESMF 8.3.0 MODULE REQUIRED) -#find_package(PIO 2.5.3 REQUIRED COMPONENTS C Fortran) -#find_package(FoX 4.1.2 REQUIRED) +find_package(PIO 2.6.2 REQUIRED COMPONENTS C Fortran) + +if (ENABLE_ACCESS_MOM6) + find_package(ESMF 8.3.0 MODULE REQUIRED) + find_package(Access3Share REQUIRED cdeps timing share nuopc_cap_share) +endif() ### Targets ## MOM6 library -set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/../src") -set(CONFIG_SRC "${CMAKE_CURRENT_SOURCE_DIR}/../config_src") +# set paths for the source code and config source +set(SRC "${CMAKE_SOURCE_DIR}/../src") +set(CONFIG_SRC "${CMAKE_SOURCE_DIR}/../config_src") + +add_fortran_library(mom6lib mod STATIC) -add_fortran_library(OM3_mom6 mod STATIC) +target_include_directories(mom6lib PRIVATE $) # include version_variable.h -target_include_directories(OM3_mom6 PRIVATE $) -if(OM3_MOM_SYMMETRIC) - target_include_directories(OM3_mom6 PRIVATE $) +if(ENABLE_MOM_SYMMETRIC) + set(MOM_MEMORY_DIR $) # include MOM_memory.h else() - target_include_directories(OM3_mom6 PRIVATE $) + set(MOM_MEMORY_DIR $) # include MOM_memory.h endif() -target_compile_options(OM3_mom6 PRIVATE "$<$:${fortran_compile_flags}>") -target_link_libraries(OM3_mom6 +target_include_directories(mom6lib PRIVATE ${MOM_MEMORY_DIR}) + +target_compile_options(mom6lib PRIVATE "$<$:${fortran_compile_flags}>") + +# link libraries +target_link_libraries(mom6lib PRIVATE FMS::fms_r8) + +if(ENABLE_ACCESS_MOM6) +target_link_libraries(mom6lib PUBLIC esmf - PRIVATE FMS::fms_r8 - #PRIVATE AccessOM3::nuopc_cap_share AccessOM3::share FMS::fms_r8 + PRIVATE Access3::nuopc_cap_share Access3::share Access3::timing Access3::cdeps-common ) +endif() - -target_sources(OM3_mom6 PRIVATE +target_sources(mom6lib PRIVATE ${SRC}/ALE/coord_adapt.F90 ${SRC}/ALE/coord_hycom.F90 ${SRC}/ALE/coord_rho.F90 @@ -404,42 +403,72 @@ target_sources(OM3_mom6 PRIVATE ${CONFIG_SRC}/infra/FMS2/MOM_time_manager.F90 ${CONFIG_SRC}/infra/FMS2/MOM_couplertype_infra.F90 #add_patched_sources +) +if (ENABLE_ACCESS_MOM6) + target_sources(mom6lib PRIVATE ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap_time.F90 ${CONFIG_SRC}/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 ${CONFIG_SRC}/drivers/nuopc_cap/ocn_comp_NUOPC.F90 ${CONFIG_SRC}/drivers/nuopc_cap/time_utils.F90 - ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap.F90 #add_patched_sources ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap_methods.F90 #add_patched_sources ${CONFIG_SRC}/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 #add_patched_sources + ) +endif() -) - +if (ENABLE_MOM6) + target_sources(mom6lib PRIVATE + ${CONFIG_SRC}/drivers/solo_driver/MOM_surface_forcing.F90 + ${CONFIG_SRC}/drivers/solo_driver/MESO_surface_forcing.F90 + ${CONFIG_SRC}/drivers/solo_driver/user_surface_forcing.F90 + ) +endif() ### Install and Export ## Library -if(OM3_LIB_INSTALL) - set_target_properties(OM3_mom6 PROPERTIES - OUTPUT_NAME access-mom6 - EXPORT_NAME mom6 +if(ENABLE_ACCESS_MOM6) + set_target_properties(mom6lib PROPERTIES + OUTPUT_NAME access-mom6lib + EXPORT_NAME mom6lib ) - install(TARGETS OM3_mom6 - EXPORT AccessOM3mom6_Targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_RunTime NAMELINK_COMPONENT AccessOM3_Development - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_Development + install(TARGETS mom6lib + EXPORT MOM6libTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessMOM6Cmeps_runtime NAMELINK_COMPONENT AccessMOM6Cmeps_Development + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessMOM6Cmeps_Development ) # Fortran module files are a special case, as currently there is no standard # way of handling them in CMake - target_include_directories(OM3_mom6 PUBLIC "$") - get_target_property(mom_moddir OM3_mom6 Fortran_MODULE_DIRECTORY) + target_include_directories(mom6lib PUBLIC "$") + get_target_property(mom_moddir mom6lib Fortran_MODULE_DIRECTORY) install(FILES ${mom_moddir}/ocn_comp_nuopc.mod ${mom_moddir}/mom_cap_mod.mod - DESTINATION ${CMAKE_INSTALL_MODULEDIR}/access-mom6 - COMPONENT AccessOM3_Development + DESTINATION ${CMAKE_INSTALL_MODULEDIR}/mom6lib + COMPONENT AccessMOM6Cmeps_Development + ) + install(EXPORT MOM6libTargets + FILE MOM6libTargets.cmake + NAMESPACE Access3:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Mom6lib + ) +endif() + +# executable +if (ENABLE_MOM6) + add_executable(MOM6 ${CONFIG_SRC}/drivers/solo_driver/MOM_driver.F90) + target_link_libraries(MOM6 PRIVATE mom6lib) + + target_include_directories(MOM6 PRIVATE + ${SRC}/framework + ${MOM_MEMORY_DIR} + ${CONFIG_SRC}/drivers/solo_driver + ) + + set_target_properties(MOM6 PROPERTIES + LINKER_LANGUAGE Fortran + OUTPUT_NAME mom6 ) - install(EXPORT AccessOM3mom6_Targets - FILE AccessOM3mom6Targets.cmake - NAMESPACE AccessOM3:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AccessOM3 + + install(TARGETS MOM6 + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) endif() diff --git a/cmake/CompilerFlags.cmake b/cmake/CompilerFlags.cmake new file mode 100644 index 0000000000..1200cf5baf --- /dev/null +++ b/cmake/CompilerFlags.cmake @@ -0,0 +1,32 @@ +# Common compiler flags and definitions + +# Fortran compiler flags +if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fbacktrace -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none") + if(${CMAKE_Fortran_COMPILER_VERSION} VERSION_GREATER_EQUAL 10) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fallow-argument-mismatch") + endif() + set(CMAKE_Fortran_FLAGS "-fdefault-real-8 -fdefault-double-8") + set(CMAKE_Fortran_FLAGS_RELEASE "-O") + set(CMAKE_Fortran_FLAGS_DEBUG "-g -Wall -Og -ffpe-trap=zero,overflow -fcheck=bounds") +elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Intel") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qno-opt-dynamic-align -convert big_endian -assume byterecl -ftz -traceback -assume realloc_lhs -fp-model source") + set(CMAKE_Fortran_FLAGS_RELEASE "-O2 -debug minimal") + set(CMAKE_Fortran_FLAGS_DEBUG "-O0 -g -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created") + set(CMAKE_Fortran_FLAGS "-r8") +else() + message(WARNING "Fortran compiler with ID ${CMAKE_Fortran_COMPILER_ID} will be used with CMake default options") +endif() + +# C compiler flags +if(CMAKE_C_COMPILER_ID MATCHES "GNU") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") + set(CMAKE_C_FLAGS_RELEASE "-O") + set(CMAKE_C_FLAGS_DEBUG "-g -Wall -Og -fbacktrace -ffpe-trap=invalid,zero,overflow -fcheck=bounds") +elseif(CMAKE_C_COMPILER_ID MATCHES "Intel") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -traceback -qno-opt-dynamic-align -fp-model precise -std=gnu99") + set(CMAKE_C_FLAGS_RELEASE "-O2 -debug minimal") + set(CMAKE_C_FLAGS_DEBUG "-O0 -g") +else() + message(WARNING "C compiler with ID ${CMAKE_C_COMPILER_ID} will be used with CMake default options") +endif() \ No newline at end of file From 31b869f0594f29287bd7a5b1841780f70dd6e669 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Tue, 21 Jan 2025 10:02:26 +1100 Subject: [PATCH 14/31] Remove misleading comments --- cmake/CMakeLists.txt | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 7db85161fa..c5796d16e1 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -76,12 +76,12 @@ set(CONFIG_SRC "${CMAKE_SOURCE_DIR}/../config_src") add_fortran_library(mom6lib mod STATIC) -target_include_directories(mom6lib PRIVATE $) # include version_variable.h +target_include_directories(mom6lib PRIVATE $) if(ENABLE_MOM_SYMMETRIC) - set(MOM_MEMORY_DIR $) # include MOM_memory.h + set(MOM_MEMORY_DIR $) else() - set(MOM_MEMORY_DIR $) # include MOM_memory.h + set(MOM_MEMORY_DIR $) endif() target_include_directories(mom6lib PRIVATE ${MOM_MEMORY_DIR}) @@ -147,7 +147,7 @@ target_sources(mom6lib PRIVATE ${SRC}/core/MOM_unit_tests.F90 ${SRC}/core/MOM_variables.F90 ${SRC}/core/MOM_verticalGrid.F90 - ${SRC}/core/MOM_forcing_type.F90 #add_patched_sources + ${SRC}/core/MOM_forcing_type.F90 ${SRC}/core/MOM_dynamics_split_RK2b.F90 #ml ${SRC}/diagnostics/MOM_debugging.F90 @@ -172,7 +172,7 @@ target_sources(mom6lib PRIVATE ${SRC}/equation_of_state/MOM_temperature_convert.F90 ${SRC}/equation_of_state/MOM_TFreeze.F90 - ${SRC}/equation_of_state/MOM_EOS_base_type.F90 # ml + ${SRC}/equation_of_state/MOM_EOS_base_type.F90 ${SRC}/equation_of_state/TEOS10/gsw_chem_potential_water_t_exact.f90 ${SRC}/equation_of_state/TEOS10/gsw_ct_freezing_exact.f90 @@ -237,7 +237,7 @@ target_sources(mom6lib PRIVATE ${SRC}/framework/MOM_unit_scaling.F90 ${SRC}/framework/MOM_write_cputime.F90 ${SRC}/framework/posix.F90 - ${SRC}/framework/MOM_coupler_types.F90 #add_patched_sources + ${SRC}/framework/MOM_coupler_types.F90 ${SRC}/ice_shelf/MOM_ice_shelf_diag_mediator.F90 ${SRC}/ice_shelf/MOM_ice_shelf_dynamics.F90 @@ -334,7 +334,7 @@ target_sources(mom6lib PRIVATE ${SRC}/tracer/RGC_tracer.F90 ${SRC}/tracer/tracer_example.F90 - ${SRC}/tracer/MOM_generic_tracer.F90 #add_patched_sources + ${SRC}/tracer/MOM_generic_tracer.F90 ${SRC}/user/adjustment_initialization.F90 ${SRC}/user/baroclinic_zone_initialization.F90 @@ -387,8 +387,8 @@ target_sources(mom6lib PRIVATE ${CONFIG_SRC}/external/stochastic_physics/get_stochy_pattern.F90 ${CONFIG_SRC}/external/stochastic_physics/stochastic_physics.F90 - ${CONFIG_SRC}/external/GFDL_ocean_BGC/generic_tracer_utils.F90 #ml - ${CONFIG_SRC}/external/GFDL_ocean_BGC/generic_tracer.F90 #ml + ${CONFIG_SRC}/external/GFDL_ocean_BGC/generic_tracer_utils.F90 + ${CONFIG_SRC}/external/GFDL_ocean_BGC/generic_tracer.F90 ${CONFIG_SRC}/infra/FMS2/MOM_coms_infra.F90 ${CONFIG_SRC}/infra/FMS2/MOM_constants.F90 @@ -402,7 +402,7 @@ target_sources(mom6lib PRIVATE ${CONFIG_SRC}/infra/FMS2/MOM_io_infra.F90 ${CONFIG_SRC}/infra/FMS2/MOM_time_manager.F90 - ${CONFIG_SRC}/infra/FMS2/MOM_couplertype_infra.F90 #add_patched_sources + ${CONFIG_SRC}/infra/FMS2/MOM_couplertype_infra.F90 ) if (ENABLE_ACCESS_MOM6) @@ -411,9 +411,9 @@ if (ENABLE_ACCESS_MOM6) ${CONFIG_SRC}/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 ${CONFIG_SRC}/drivers/nuopc_cap/ocn_comp_NUOPC.F90 ${CONFIG_SRC}/drivers/nuopc_cap/time_utils.F90 - ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap.F90 #add_patched_sources - ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap_methods.F90 #add_patched_sources - ${CONFIG_SRC}/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 #add_patched_sources + ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap.F90 + ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap_methods.F90 + ${CONFIG_SRC}/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 ) endif() From c5f2b04795e72fd0da20ff85fe894504205ba592 Mon Sep 17 00:00:00 2001 From: dougiesquire Date: Thu, 23 Jan 2025 10:40:45 +1100 Subject: [PATCH 15/31] Replicate FMS cap initialize_ocean_public_type changes in NUOPC cap The NUOPC cap appears to have been written from the MCT cap, which does not include changes needed to successfully register restarts for FMS coupler type. See NCAR/MOM6@73304eb --- .../nuopc_cap/mom_ocean_model_nuopc.F90 | 47 ++++++------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 b/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 index 9ac40daaa4..b6cc4de0be 100644 --- a/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 +++ b/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 @@ -20,6 +20,7 @@ module MOM_ocean_model_nuopc use MOM_constants, only : CELSIUS_KELVIN_OFFSET, hlf use MOM_diag_mediator, only : diag_ctrl, enable_averages, disable_averaging use MOM_diag_mediator, only : diag_mediator_close_registration, diag_mediator_end +use MOM_domains, only : MOM_domain_type, domain2d, clone_MOM_domain, get_domain_extent use MOM_domains, only : pass_var, pass_vector, AGRID, BGRID_NE, CGRID_NE use MOM_domains, only : TO_ALL, Omit_Corners use MOM_error_handler, only : MOM_error, FATAL, WARNING, is_root_pe @@ -51,8 +52,6 @@ module MOM_ocean_model_nuopc use MOM_coupler_types, only : coupler_type_spawn, coupler_type_write_chksums use MOM_coupler_types, only : coupler_type_initialized, coupler_type_copy_data use MOM_coupler_types, only : coupler_type_set_diags, coupler_type_send_data -use mpp_domains_mod, only : domain2d, mpp_get_layout, mpp_get_global_domain -use mpp_domains_mod, only : mpp_define_domains, mpp_get_compute_domain, mpp_get_data_domain use MOM_io, only : stdout use MOM_EOS, only : gsw_sp_from_sr, gsw_pt_from_ct use MOM_wave_interface, only : wave_parameters_CS, MOM_wave_interface_init @@ -102,7 +101,7 @@ module MOM_ocean_model_nuopc !! points of the two velocity components. Valid entries !! include AGRID, BGRID_NE, CGRID_NE, BGRID_SW, and CGRID_SW, !! corresponding to the community-standard Arakawa notation. - !! (These are named integers taken from mpp_parameter_mod.) + !! (These are named integers taken from the MOM_domains module.) !! Following MOM5, stagger is BGRID_NE by default when the !! ocean is initialized, but here it is set to -999 so that !! a global max across ocean and non-ocean processors can be @@ -407,14 +406,7 @@ subroutine ocean_model_init(Ocean_sfc, OS, Time_init, Time_in, gas_fields_ocn, i ! it also initializes statistical waves. call MOM_wave_interface_init(OS%Time, OS%grid, OS%GV, OS%US, param_file, OS%Waves, OS%diag) - if (associated(OS%grid%Domain%maskmap)) then - call initialize_ocean_public_type(OS%grid%Domain%mpp_domain, Ocean_sfc, & - OS%diag, maskmap=OS%grid%Domain%maskmap, & - gas_fields_ocn=gas_fields_ocn) - else - call initialize_ocean_public_type(OS%grid%Domain%mpp_domain, Ocean_sfc, & - OS%diag, gas_fields_ocn=gas_fields_ocn) - endif + call initialize_ocean_public_type(OS%grid%Domain, Ocean_sfc, OS%diag, gas_fields_ocn=gas_fields_ocn) ! This call can only occur here if the coupler_bc_type variables have been ! initialized already using the information from gas_fields_ocn. @@ -529,8 +521,7 @@ subroutine update_ocean_model(Ice_ocean_boundary, OS, Ocean_sfc, & (/is,is,ie,ie/), (/js,js,je,je/), as_needed=.true.) ! Translate Ice_ocean_boundary into fluxes. - call mpp_get_compute_domain(Ocean_sfc%Domain, index_bnds(1), index_bnds(2), & - index_bnds(3), index_bnds(4)) + call get_domain_extent(Ocean_sfc%Domain, index_bnds(1), index_bnds(2), index_bnds(3), index_bnds(4)) weight = 1.0 @@ -792,7 +783,7 @@ end subroutine ocean_model_end subroutine ocean_model_save_restart(OS, Time, directory, filename_suffix) type(ocean_state_type), pointer :: OS !< A pointer to the structure containing the !! internal ocean state (in). - type(time_type), intent(in) :: Time !< The model time at this call, needed for mpp_write calls. + type(time_type), intent(in) :: Time !< The model time at this call, needed for writing files. character(len=*), optional, intent(in) :: directory !< An optional directory into which to !! write these restart files. character(len=*), optional, intent(in) :: filename_suffix !< An optional suffix (e.g., a time-stamp) @@ -823,16 +814,12 @@ subroutine ocean_model_save_restart(OS, Time, directory, filename_suffix) end subroutine ocean_model_save_restart !> Initialize the public ocean type -subroutine initialize_ocean_public_type(input_domain, Ocean_sfc, diag, maskmap, & - gas_fields_ocn) - type(domain2D), intent(in) :: input_domain !< The ocean model domain description +subroutine initialize_ocean_public_type(input_domain, Ocean_sfc, diag, gas_fields_ocn) + type(MOM_domain_type), intent(in) :: input_domain !< The ocean model domain description type(ocean_public_type), intent(inout) :: Ocean_sfc !< A structure containing various publicly - !! visible ocean surface properties after initialization, whose - !! elements are allocated here. - type(diag_ctrl), intent(in) :: diag !< A structure that regulates diagnsotic output - logical, dimension(:,:), & - optional, intent(in) :: maskmap !< A mask indicating which virtual processors - !! are actually in use. If missing, all are used. + !! visible ocean surface properties after + !! initialization, whose elements are allocated here. + type(diag_ctrl), intent(in) :: diag !< A structure that regulates diagnostic output type(coupler_1d_bc_type), & optional, intent(in) :: gas_fields_ocn !< If present, this type describes the !! ocean and surface-ice fields that will participate @@ -844,14 +831,9 @@ subroutine initialize_ocean_public_type(input_domain, Ocean_sfc, diag, maskmap, ! and have no halos. integer :: isc, iec, jsc, jec - call mpp_get_layout(input_domain,layout) - call mpp_get_global_domain(input_domain, xsize=xsz, ysize=ysz) - if (PRESENT(maskmap)) then - call mpp_define_domains((/1,xsz,1,ysz/),layout,Ocean_sfc%Domain, maskmap=maskmap) - else - call mpp_define_domains((/1,xsz,1,ysz/),layout,Ocean_sfc%Domain) - endif - call mpp_get_compute_domain(Ocean_sfc%Domain, isc, iec, jsc, jec) + call clone_MOM_domain(input_domain, Ocean_sfc%Domain, halo_size=0, symmetric=.false.) + + call get_domain_extent(Ocean_sfc%Domain, isc, iec, jsc, jec) allocate ( Ocean_sfc%t_surf (isc:iec,jsc:jec), & Ocean_sfc%s_surf (isc:iec,jsc:jec), & @@ -907,8 +889,7 @@ subroutine convert_state_to_ocean_type(sfc_state, Ocean_sfc, G, US, patm, press_ is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec call pass_vector(sfc_state%u, sfc_state%v, G%Domain) - call mpp_get_compute_domain(Ocean_sfc%Domain, isc_bnd, iec_bnd, & - jsc_bnd, jec_bnd) + call get_domain_extent(Ocean_sfc%Domain, isc_bnd, iec_bnd, jsc_bnd, jec_bnd) if (present(patm)) then ! Check that the inidicies in patm are (isc_bnd:iec_bnd,jsc_bnd:jec_bnd). if (.not.present(press_to_z)) call MOM_error(FATAL, & From c82b91a2c38de1fd9c2f99a8c8f893772cf5b0b1 Mon Sep 17 00:00:00 2001 From: dougiesquire Date: Thu, 23 Jan 2025 11:36:38 +1100 Subject: [PATCH 16/31] Allow generic tracers in NUOPC cap These changes provide an initial implementation to allow use of coupled generic tracers with NUOPC-coupled MOM6. This is a bit of a hack as coupling in generic tracers effectively assumes the use of FMScoupler. Broadly, the changes to the NUOPC cap in this commit do the following: - Initialisation phase: Initialise the FMS coupler type data structures used by generic tracers for handling surface fluxes. Register with NUOPC the additional import fields required by the generic tracer package being used. Export of additional fields is not currently handled. - Advance phase: Populate the relevant FMS coupler type data structure with fields received from the atmosphere. Calculate the surface fluxes using a modified version of the routine used by FMScoupler. Restart read/write for the FMS coupler types is also handled. Fields in the FMS coupler types can be overridden using the data_table --- config_src/drivers/nuopc_cap/mom_cap.F90 | 153 +++- .../nuopc_cap/mom_cap_gtracer_flux.F90 | 680 ++++++++++++++++++ .../drivers/nuopc_cap/mom_cap_methods.F90 | 60 +- .../infra/FMS1/MOM_couplertype_infra.F90 | 10 +- .../infra/FMS2/MOM_couplertype_infra.F90 | 10 +- src/framework/MOM_coupler_types.F90 | 10 +- 6 files changed, 912 insertions(+), 11 deletions(-) create mode 100644 config_src/drivers/nuopc_cap/mom_cap_gtracer_flux.F90 diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index fab6fe1f55..541d7f12cc 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -2,8 +2,9 @@ module MOM_cap_mod +use field_manager_mod, only: field_manager_init, field_manager_end use MOM_domains, only: get_domain_extent -use MOM_io, only: stdout, io_infra_end +use MOM_io, only: stdout, io_infra_end, slasher use mpp_domains_mod, only: mpp_get_compute_domains use mpp_domains_mod, only: mpp_get_ntile_count, mpp_get_pelist, mpp_get_global_domain use mpp_domains_mod, only: mpp_get_domain_npes @@ -30,6 +31,7 @@ module MOM_cap_mod use MOM_cap_methods, only: ChkErr use MOM_ensemble_manager, only: ensemble_manager_init use MOM_coms, only: sum_across_PEs +use MOM_coupler_types, only: coupler_1d_bc_type, coupler_2d_bc_type #ifdef CESMCOUPLED use shr_log_mod, only: shr_log_setLogUnit @@ -37,6 +39,15 @@ module MOM_cap_mod #endif use time_utils_mod, only: esmf2fms_time +#ifdef _USE_GENERIC_TRACER +use MOM_coupler_types, only: coupler_type_spawn, coupler_type_destructor +use MOM_coupler_types, only: coupler_type_set_diags, coupler_type_send_data, coupler_type_data_override +use MOM_data_override, only: data_override_init, data_override +use MOM_cap_gtracer_flux, only: gas_exchange_init, gas_fields_restore, gas_fields_restart +use MOM_cap_gtracer_flux, only: get_coupled_field_name, add_gas_fluxes_param, UNKNOWN_CMEPS_FIELD +use MOM_cap_gtracer_flux, only: atmos_ocean_fluxes_calc +#endif + use, intrinsic :: iso_fortran_env, only: output_unit use ESMF, only: ESMF_ClockAdvance, ESMF_ClockGet, ESMF_ClockPrint, ESMF_VMget @@ -96,11 +107,14 @@ module MOM_cap_mod public SetServices public SetVM -!> Internal state type with pointers to three types defined by MOM. +!> Internal state type with pointers to types defined by MOM. type ocean_internalstate_type type(ocean_public_type), pointer :: ocean_public_type_ptr type(ocean_state_type), pointer :: ocean_state_type_ptr type(ice_ocean_boundary_type), pointer :: ice_ocean_boundary_type_ptr +#ifdef _USE_GENERIC_TRACER + type(coupler_2d_bc_type), pointer :: coupler_2d_bc_type_ptr +#endif end type !> Wrapper-derived type required to associate an internal state instance @@ -416,6 +430,10 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) type (ocean_public_type), pointer :: ocean_public => NULL() type (ocean_state_type), pointer :: ocean_state => NULL() type(ice_ocean_boundary_type), pointer :: Ice_ocean_boundary => NULL() + type(coupler_1d_bc_type), pointer :: gas_fields_atm => NULL() + type(coupler_1d_bc_type), pointer :: gas_fields_ocn => NULL() + type(coupler_1d_bc_type), pointer :: gas_fluxes => NULL() + type(coupler_2d_bc_type), pointer :: atm_fields => NULL() type(ocean_internalstate_wrapper) :: ocean_internalstate type(ocean_grid_type), pointer :: ocean_grid => NULL() type(directories) :: dirs @@ -447,6 +465,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) character(len=512) :: restartfile ! Path/Name of restart file character(len=2048) :: restartfiles ! Path/Name of restart files ! (same as restartfile if single restart file) + character(240) :: additional_restart_dir character(len=*), parameter :: subname='(MOM_cap:InitializeAdvertise)' character(len=32) :: calendar character(len=:), allocatable :: rpointer_filename @@ -525,6 +544,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) if (chkerr(rc,__LINE__,u_FILE_u)) return call MOM_infra_init(mpi_comm_mom) + call field_manager_init + ! determine the calendar if (cesm_coupled) then call NUOPC_CompAttributeGet(gcomp, name="calendar", value=cvalue, & @@ -656,13 +677,44 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) endif + ! Set NUOPC attribute additional_restart_dir to RESTART/ if not defined + additional_restart_dir = "RESTART/" + call NUOPC_CompAttributeGet(gcomp, name="additional_restart_dir", value=cvalue, & + isPresent=isPresent, isSet=isSet, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (isPresent .and. isSet) then + additional_restart_dir = slasher(cvalue) + else + call ESMF_LogWrite('MOM_cap:additional_restart_dir unset. Defaulting to '//trim(additional_restart_dir), & + ESMF_LOGMSG_INFO) + endif + call NUOPC_CompAttributeSet(gcomp, name="additional_restart_dir", value=additional_restart_dir, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + ocean_public%is_ocean_pe = .true. +#ifdef _USE_GENERIC_TRACER + ! Initialise structures for extra tracer fluxes + call gas_exchange_init(gas_fields_atm=gas_fields_atm, gas_fields_ocn=gas_fields_ocn, gas_fluxes=gas_fluxes) + + if (cesm_coupled .and. len_trim(inst_suffix)>0) then + call ocean_model_init(ocean_public, ocean_state, time0, time_start, gas_fields_ocn=gas_fields_ocn, & + input_restart_file=trim(adjustl(restartfiles)), inst_index=inst_index) + else + call ocean_model_init(ocean_public, ocean_state, time0, time_start, gas_fields_ocn=gas_fields_ocn, & + input_restart_file=trim(adjustl(restartfiles))) + endif + + ! Enable data override via the data_table using the component name 'OCN' + call get_ocean_grid(ocean_state, ocean_grid) + call data_override_init(ocean_grid%Domain) +#else if (cesm_coupled .and. len_trim(inst_suffix)>0) then call ocean_model_init(ocean_public, ocean_state, time0, time_start, & input_restart_file=trim(adjustl(restartfiles)), inst_index=inst_index) else call ocean_model_init(ocean_public, ocean_state, time0, time_start, input_restart_file=trim(adjustl(restartfiles))) endif +#endif ! GMM, this call is not needed in CESM. Check with EMC if it can be deleted. call ocean_model_flux_init(ocean_state) @@ -729,6 +781,31 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) Ice_ocean_boundary%hcond = 0.0 endif +#ifdef _USE_GENERIC_TRACER + ! Allocate fields for extra tracer fluxes in Ice_ocean_boundary + ! Annoyingly, spawning doesn't copy param array, so add manually + call coupler_type_spawn(gas_fluxes, Ice_ocean_boundary%fluxes, (/isc,isc,iec,iec/), & + (/jsc,jsc,jec,jec/), suffix='_ice_ocn') + call add_gas_fluxes_param(Ice_ocean_boundary%fluxes) + + ! Initialise structure for atmos fields related to extra tracer fluxes + ! This is set in the ESMF Internal State to be accessed elsewhere + ! TODO: should we deallocate atm_fields in a finalise step? Ice_ocean_boundary is handled + ! in a similar way and does not appear to be deallocated. + allocate(atm_fields) + ocean_internalstate%ptr%coupler_2d_bc_type_ptr => atm_fields + call coupler_type_spawn(gas_fields_atm, atm_fields, (/isc,isc,iec,iec/), & + (/jsc,jsc,jec,jec/), suffix='_atm') + + ! Register diagnosics for extra tracer flux structures + call coupler_type_set_diags(Ice_ocean_boundary%fluxes, "ocean_flux", ocean_public%axes(1:2), time_start) + call coupler_type_set_diags(atm_fields, "atmos_sfc", ocean_public%axes(1:2), time_start) + + ! Restore ocean fields related to extra tracer fluxes from restart files + call get_MOM_input(dirs=dirs) + call gas_fields_restore(ocean_public%fields, ocean_public%domain, dirs%restart_input_dir) +#endif + call query_ocean_state(ocean_state, use_waves=use_waves, wave_method=wave_method) if (use_waves) then if (wave_method == "EFACTOR") then @@ -797,6 +874,15 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) endif endif +#ifdef _USE_GENERIC_TRACER + ! Add import fields required for extra tracer fluxes + do n = 1, gas_fluxes%num_bcs + stdname = get_coupled_field_name(gas_fluxes%bc(n)%name) + if (stdname /= UNKNOWN_CMEPS_FIELD) & + call fld_list_add(fldsToOcn_num, fldsToOcn, stdname, "will provide") + enddo +#endif + !--------- export fields ------------- call fld_list_add(fldsFrOcn_num, fldsFrOcn, "So_omask" , "will provide") call fld_list_add(fldsFrOcn_num, fldsFrOcn, "So_t" , "will provide") @@ -808,6 +894,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) call fld_list_add(fldsFrOcn_num, fldsFrOcn, "Fioo_q" , "will provide") call fld_list_add(fldsFrOcn_num, fldsFrOcn, "So_bldepth" , "will provide") + ! TODO: dts: How to handle export fields from generic tracers? + do n = 1,fldsToOcn_num call NUOPC_Advertise(importState, standardName=fldsToOcn(n)%stdname, name=fldsToOcn(n)%shortname, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return @@ -1619,11 +1707,14 @@ subroutine ModelAdvance(gcomp, rc) type (ocean_public_type), pointer :: ocean_public => NULL() type (ocean_state_type), pointer :: ocean_state => NULL() type(ice_ocean_boundary_type), pointer :: Ice_ocean_boundary => NULL() + type(coupler_2d_bc_type), pointer :: atm_fields => NULL() type(ocean_internalstate_wrapper) :: ocean_internalstate type(ocean_grid_type) , pointer :: ocean_grid type(time_type) :: Time + type(time_type) :: Time_import type(time_type) :: Time_step_coupled type(time_type) :: Time_restart_current + integer :: isc,iec,jsc,jec integer :: dth, dtm, dts integer :: nc type(ESMF_Time) :: MyTime @@ -1635,12 +1726,13 @@ subroutine ModelAdvance(gcomp, rc) integer :: writeunit integer :: localPet type(ESMF_VM) :: vm - integer :: n, i + integer :: m, n, i character(240) :: import_timestr, export_timestr character(len=128) :: fldname character(len=*),parameter :: subname='(MOM_cap:ModelAdvance)' character(len=8) :: suffix character(len=:), allocatable :: rpointer_filename + character(240) :: additional_restart_dir integer :: num_rest_files real(8) :: MPI_Wtime, timers logical :: write_restart @@ -1683,6 +1775,7 @@ subroutine ModelAdvance(gcomp, rc) Time_step_coupled = esmf2fms_time(timeStep) Time = esmf2fms_time(currTime) + Time_import = Time !--------------- ! Apply ocean lag for startup runs: @@ -1758,8 +1851,39 @@ subroutine ModelAdvance(gcomp, rc) ! Import data !--------------- +#ifdef _USE_GENERIC_TRACER + atm_fields => ocean_internalstate%ptr%coupler_2d_bc_type_ptr + + call mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, atm_fields=atm_fields, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Potentially override atm_fields from data_table. + call coupler_type_data_override('OCN', atm_fields, Time_import) + + ! Potentially override ice_ocean_boundary%fluxes from data_table. + ! Doing this before atmos_ocean_fluxes_calc call avoids unnecessary calculation of overridden fluxes. + ! However, we cannot use coupler_type_data_override here since it does not set the override flag on + ! overridden fields + do n = 1, ice_ocean_boundary%fluxes%num_bcs + do m = 1, ice_ocean_boundary%fluxes%bc(n)%num_fields + call data_override('OCN', ice_ocean_boundary%fluxes%bc(n)%field(m)%name, & + ice_ocean_boundary%fluxes%bc(n)%field(m)%values, Time_import, & + override=ice_ocean_boundary%fluxes%bc(n)%field(m)%override) + enddo + enddo + + ! Calculate the extra tracer fluxes + call get_domain_extent(ocean_public%domain, isc, iec, jsc, jec) + call atmos_ocean_fluxes_calc(atm_fields, ocean_public%fields, ice_ocean_boundary%fluxes, & + ice_ocean_boundary%ice_fraction, isc, iec, jsc, jec) + + ! Send diagnostics + call coupler_type_send_data(atm_fields, Time_import) + call coupler_type_send_data(ice_ocean_boundary%fluxes, Time_import) +#else call mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return +#endif !--------------- ! Update MOM6 @@ -1831,7 +1955,7 @@ subroutine ModelAdvance(gcomp, rc) ! determine restart filename call ESMF_ClockGetNextTime(clock, MyTime, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_TimeGet (MyTime, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc ) + call ESMF_TimeGet (MyTime, yy=year, mm=month, dd=day, s=seconds, rc=rc ) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (cesm_coupled) then @@ -1889,6 +2013,14 @@ subroutine ModelAdvance(gcomp, rc) endif +#ifdef _USE_GENERIC_TRACER + ! Write fields for extra tracer fluxes to their internally defined ocean restart file + call NUOPC_CompAttributeGet(gcomp, name="additional_restart_dir", value=additional_restart_dir, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + call gas_fields_restart(ocean_public%fields, ocean_public%domain, additional_restart_dir) +#endif + if (is_root_pe()) then write(stdout,*) subname//' writing restart file ',trim(restartname) endif @@ -2169,6 +2301,7 @@ subroutine ocean_model_finalize(gcomp, rc) integer :: alarmCount character(len=64) :: timestamp logical :: write_restart + character(240) :: additional_restart_dir character(len=*),parameter :: subname='(MOM_cap:ocean_model_finalize)' real(8) :: MPI_Wtime, timefs @@ -2202,6 +2335,18 @@ subroutine ocean_model_finalize(gcomp, rc) call ocean_model_end(ocean_public, ocean_State, Time, write_restart=write_restart) +#ifdef _USE_GENERIC_TRACER + if (write_restart) then + ! Write fields for extra tracer fluxes to their internally defined ocean restart file + call NUOPC_CompAttributeGet(gcomp, name="additional_restart_dir", value=additional_restart_dir, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + call gas_fields_restart(ocean_public%fields, ocean_public%domain, additional_restart_dir) + endif +#endif + + call field_manager_end() + call io_infra_end() call MOM_infra_end() diff --git a/config_src/drivers/nuopc_cap/mom_cap_gtracer_flux.F90 b/config_src/drivers/nuopc_cap/mom_cap_gtracer_flux.F90 new file mode 100644 index 0000000000..af1d886b37 --- /dev/null +++ b/config_src/drivers/nuopc_cap/mom_cap_gtracer_flux.F90 @@ -0,0 +1,680 @@ +!> Contains routines for handling FMS coupler_bc_type tracer flux structures +!! when using MOM generic tracers + +module MOM_cap_gtracer_flux + +use MOM_domains, only: domain2d +use MOM_coupler_types, only: coupler_1d_bc_type, coupler_2d_bc_type +use MOM_coupler_types, only: ind_flux, ind_deltap, ind_kw, ind_flux0 +use MOM_coupler_types, only: ind_pcair, ind_u10, ind_psurf +use MOM_coupler_types, only: ind_alpha, ind_csurf, ind_sc_no +use MOM_coupler_types, only: ind_runoff, ind_deposition +use MOM_ocean_model_nuopc, only: ocean_model_flux_init +use coupler_types_mod, only: coupler_type_register_restarts, coupler_type_restore_state +use atmos_ocean_fluxes_mod, only: atmos_ocean_type_fluxes_init, atmos_ocean_fluxes_init +use fms2_io_mod, only: FmsNetcdfDomainFile_t +use fms2_io_mod, only: fms2_check_if_open => check_if_open, fms2_close_file => close_file +use fms2_io_mod, only: fms2_write_data => write_data +use fms2_io_mod, only: fms2_read_restart => read_restart, fms2_write_restart => write_restart +use fms2_io_mod, only: fms2_get_global_io_domain_indices => get_global_io_domain_indices +use field_manager_mod, only: fm_field_name_len, fm_type_name_len, fm_loop_over_list, fm_change_list +use fm_util_mod, only: fm_util_get_real_array +use mpp_mod, only: mpp_error, FATAL +use FMSconstants, only: wtmair, rdgas, vonkarm + +implicit none; private + +! Public member functions +public :: gas_exchange_init +public :: gas_fields_restore +public :: gas_fields_restart +public :: add_gas_fluxes_param +public :: get_coupled_field_name +public :: atmos_ocean_fluxes_calc +public :: UNKNOWN_CMEPS_FIELD + +character(len=*), parameter :: mod_name = 'mom_cap_gtracer_flux' +character(len=*), parameter :: UNKNOWN_CMEPS_FIELD = "UNKNOWN_FIELD" +real, parameter :: epsln=1.0e-30 + +!> FMS coupler_bc_types for additional tracer fields when using generic tracers +logical :: gas_fluxes_initialized = .false. ! This is set to true when the following types are initialized. +type(coupler_1d_bc_type), target :: ex_gas_fields_atm ! tracer fields in atm + !< Structure containing atmospheric surface variables that are used in the + !! calculation of the atmosphere-ocean gas fluxes, as well as parameters + !! regulating these fluxes. The fields in this structure are never actually + !! set, but the structure is used for initialisation of components and to + !! spawn other structure whose fields are set. +type(coupler_1d_bc_type), target :: ex_gas_fields_ocn ! tracer fields atop the ocean + !< Structure containing ocean surface variables that are used in the + !! calculation of the atmosphere-ocean gas fluxes, as well as parameters + !! regulating these fluxes. The fields in this structure are never actually + !! set, but the structure is used for initialisation of components and to + !! spawn other structure whose fields are set. +type(coupler_1d_bc_type), target :: ex_gas_fluxes ! tracer fluxes between the atm and ocean + !< A structure for exchanging gas or tracer fluxes between the atmosphere and + !! ocean, defined by the field table, as well as a place holder of + !! intermediate calculations, such as piston velocities, and parameters that + !! impact the fluxes. The fields in this structure are never actually set, + !! but the structure is used for initialisation of components and to spawn + !! other structure whose fields are set. + +contains + +!> \brief Gas and tracer field initialization routine for running with MOM generic tracers. +!! Copied and adapted slightly from +!! https://github.com/NOAA-GFDL/FMScoupler/blob/7761886/full/flux_exchange.F90#L626. +subroutine gas_exchange_init (gas_fields_atm, gas_fields_ocn, gas_fluxes) + type(coupler_1d_bc_type), optional, pointer :: gas_fields_atm ! tracer fields in atm + !< Pointer to a structure containing atmospheric surface variables that + !! are used in the calculation of the atmosphere-ocean gas fluxes, as well + !! as parameters regulating these fluxes. + type(coupler_1d_bc_type), optional, pointer :: gas_fields_ocn ! tracer fields atop the ocean + !< Pointer to a structure containing ocean surface variables that are + !! used in the calculation of the atmosphere-ocean gas fluxes, as well as + !! parameters regulating these fluxes. + type(coupler_1d_bc_type), optional, pointer :: gas_fluxes ! tracer fluxes between the atm and ocean + !< Pointer to a structure for exchanging gas or tracer fluxes between the + !! atmosphere and ocean, defined by the field table, as well as a place holder + !! of intermediate calculations, such as piston velocities, and parameters + !! that impact the fluxes. + + if (.not.gas_fluxes_initialized) then + call atmos_ocean_type_fluxes_init( ) + call ocean_model_flux_init( ) + call atmos_ocean_fluxes_init(ex_gas_fluxes, ex_gas_fields_atm, ex_gas_fields_ocn) + gas_fluxes_initialized = .true. + endif + + if (present(gas_fields_atm)) gas_fields_atm => ex_gas_fields_atm + if (present(gas_fields_ocn)) gas_fields_ocn => ex_gas_fields_ocn + if (present(gas_fluxes)) gas_fluxes => ex_gas_fluxes + +end subroutine gas_exchange_init + +!> \brief Restore FMS coupler_bc_type state from ocean restart file +! See https://github.com/NOAA-GFDL/FMScoupler/blob/008399d/full/full_coupler_mod.F90#L1096 +subroutine gas_fields_restore(gas_fields, domain, directory) + type(coupler_2d_bc_type), intent(inout) :: gas_fields !< FMS coupler_bc_type to be registered for restarts + type(domain2D), intent(in) :: domain !< The FMS domain to use for this registration call + character(len=*), optional, intent(in) :: directory !< Directory containing the restart file + + ! local variables + type(FmsNetcdfDomainFile_t), dimension(:), pointer :: ocn_bc_restart => NULL() !< Structures describing + !! the restart files + integer :: num_ocn_bc_restart !< The number of restart + !! files to use + integer :: n + + call coupler_type_register_restarts(gas_fields, ocn_bc_restart, num_ocn_bc_restart, & + domain, to_read=.true., ocean_restart=.true., directory=directory) + + ! Restore the fields from the restart files + do n = 1, num_ocn_bc_restart + if (fms2_check_if_open(ocn_bc_restart(n))) then + call fms2_read_restart(ocn_bc_restart(n)) + endif + enddo + + ! Check whether the restarts were read successfully. + call coupler_type_restore_state(gas_fields, use_fms2_io=.true., test_by_field=.true.) + + do n = 1, num_ocn_bc_restart + if(fms2_check_if_open(ocn_bc_restart(n))) call fms2_close_file(ocn_bc_restart(n)) + enddo + +end subroutine gas_fields_restore + +!> \brief Write ocean restart file for FMS coupler_bc_type state +! See https://github.com/NOAA-GFDL/FMScoupler/blob/008399d/full/full_coupler_mod.F90#L1408 +subroutine gas_fields_restart(gas_fields, domain, directory) + type(coupler_2d_bc_type), intent(inout) :: gas_fields !< FMS coupler_bc_type to be registered for restarts + type(domain2D), intent(in) :: domain !< The FMS domain to use for this registration call + character(len=*), optional, intent(in) :: directory !< Directory containing the restart file + + ! local variables + type(FmsNetcdfDomainFile_t), dimension(:), pointer :: ocn_bc_restart => NULL() !< Structures describing + !! the restart files + integer :: num_ocn_bc_restart !< The number of restart + !! files to use + integer :: n + + call coupler_type_register_restarts(gas_fields, ocn_bc_restart, num_ocn_bc_restart, & + domain, to_read=.false., ocean_restart=.true., directory=directory) + + do n = 1, num_ocn_bc_restart + if (fms2_check_if_open(ocn_bc_restart(n))) then + call fms2_write_restart(ocn_bc_restart(n)) + call add_domain_dimension_data(ocn_bc_restart(n)) + call fms2_close_file(ocn_bc_restart(n)) + endif + enddo + +end subroutine gas_fields_restart + +!> Register the axis data as a variable in the netcdf file and add some dummy data. +!! This is needed so the combiner can work correctly when the io_layout is not 1,1. Copied from +!! https://github.com/NOAA-GFDL/FMScoupler/blob/008399d/full/full_coupler_mod.F90#L1328 +subroutine add_domain_dimension_data(fileobj) + type(FmsNetcdfDomainFile_t) :: fileobj !< Fms2io domain decomposed fileobj + + ! local variables + integer, dimension(:), allocatable :: buffer !< Buffer with axis data + integer :: is, ie !< Starting and Ending indices for data + + call fms2_get_global_io_domain_indices(fileobj, "xaxis_1", is, ie, indices=buffer) + call fms2_write_data(fileobj, "xaxis_1", buffer) + deallocate(buffer) + + call fms2_get_global_io_domain_indices(fileobj, "yaxis_1", is, ie, indices=buffer) + call fms2_write_data(fileobj, "yaxis_1", buffer) + deallocate(buffer) + +end subroutine add_domain_dimension_data + +!> Retrieve param array from field_manager and add to FMS coupler_bc_type. This is +!! needed because the coupler_type_spawn routine does not copy the param array into +!! the spawned type. Hopefully we can get rid of this. This routine is based on +!! https://github.com/NOAA-GFDL/FMS/blob/7f58528/coupler/atmos_ocean_fluxes.F90#L448 +subroutine add_gas_fluxes_param(gas_fluxes) + type(coupler_2d_bc_type), intent(inout) :: gas_fluxes !< FMS coupler_bc_type to add param to + + ! local variables + integer :: n + character(len=fm_field_name_len) :: name + character(len=fm_type_name_len) :: typ + integer :: ind + + character(len=*), parameter :: sub_name = 'add_gas_fluxes_param' + character(len=*), parameter :: error_header =& + '==>Error from ' // trim(mod_name) // '(' // trim(sub_name) // '):' + + n = 0 + do while (fm_loop_over_list('/coupler_mod/fluxes', name, typ, ind)) + if (typ .ne. 'list') then + call mpp_error(FATAL, trim(error_header) // ' ' // trim(name) // ' is not a list') + endif + + n = n + 1 + + if (.not. fm_change_list('/coupler_mod/fluxes/' // trim(name))) then + call mpp_error(FATAL, trim(error_header) // ' Problem changing to ' // trim(name)) + endif + + if (gas_fluxes%bc(n)%name .eq. name) then + gas_fluxes%bc(n)%param => fm_util_get_real_array('param') + else + call mpp_error(FATAL, trim(error_header) // ' Problem setting param array pointer') + endif + enddo +end subroutine add_gas_fluxes_param + +!> Return the CMEPS standard_name of the coupled field required for a given coupled +!! generic_tracer flux name. +function get_coupled_field_name(name) + character(len=64) :: get_coupled_field_name !< CMEPS standard_name + character(len=*), intent(in) :: name !< gtracer flux name + + ! Add other coupled field names here + select case(trim(name)) + case( 'co2_flux' ) + get_coupled_field_name = "Sa_co2prog" + case default + get_coupled_field_name = UNKNOWN_CMEPS_FIELD + end select +end function get_coupled_field_name + +!> \brief Calculate the FMS coupler_bc_type ocean tracer fluxes. Units should be mol/m^2/s. +!! Upward flux is positive. +!! +!! This routine was copied from FMScoupler at +!! https://github.com/NOAA-GFDL/FMScoupler/blob/6442d38/full/atmos_ocean_fluxes_calc.F90 +!! and subsequently modified in the following ways: +!! - Operate on 2D inputs, rather than 1D +!! - Add calculation for 'air_sea_deposition' taken from +!! https://github.com/NOAA-GFDL/FMScoupler/blob/6442d38/full/atmos_ocean_dep_fluxes_calc.F90 +!! - Multiply fluxes by ice_fraction input, rather than masking based on seawater input +!! - Use MOM over FMS modules where easy to do so +!! - Make tsurf input optional, as it is only used by a few implementations +!! - Use ind_runoff rather than ind_deposition in runoff flux calculation (note, their +!! values are equal) +!! - Rename gas_fields_ice to gas_fields_ocn +subroutine atmos_ocean_fluxes_calc(gas_fields_atm, gas_fields_ocn, gas_fluxes,& + ice_fraction, isc, iec, jsc, jec, tsurf, ustar, cd_m) + type(coupler_2d_bc_type), intent(in) :: gas_fields_atm ! fields in atm + !< Structure containing atmospheric surface variables that are used in the calculation + !! of the atmosphere-ocean tracer fluxes. + type(coupler_2d_bc_type), intent(in) :: gas_fields_ocn ! fields atop the ocean + !< Structure containing ocean surface variables that are used in the calculation of the + !! atmosphere-ocean tracer fluxes. + type(coupler_2d_bc_type), intent(inout) :: gas_fluxes ! fluxes between the atm and ocean + !< Structure containing the gas fluxes between the atmosphere and the ocean and + !! parameters related to the calculation of these fluxes. + real, intent(in) :: ice_fraction(isc:iec,jsc:jec) !< sea ice fraction + integer, intent(in) :: isc !< The start i-index of cell centers within + !! the computational domain + integer, intent(in) :: iec !< The end i-index of cell centers within the + !! computational domain + integer, intent(in) :: jsc !< The start j-index of cell centers within + !! the computational domain + integer, intent(in) :: jec !< The end j-index of cell centers within the + !! computational domain + real, intent(in), optional :: tsurf(isc:iec,jsc:jec) !< surface temperature + real, intent(in), optional :: ustar(isc:iec,jsc:jec) !< friction velocity, not + !! used + real, intent(in), optional :: cd_m (isc:iec,jsc:jec) !< drag coefficient, not + !! used + + ! local variables + character(len=*), parameter :: sub_name = 'atmos_ocean_fluxes_calc' + character(len=*), parameter :: error_header =& + & '==>Error from ' // trim(mod_name) // '(' // trim(sub_name) // '):' + real, parameter :: permeg=1.0e-6 + + integer :: n + integer :: i + integer :: j + real, dimension(:,:), allocatable :: kw + real, dimension(:,:), allocatable :: cair + character(len=128) :: error_string + + ! Return if no fluxes to be calculated + if (gas_fluxes%num_bcs .le. 0) return + + if (.not. associated(gas_fluxes%bc)) then + if (gas_fluxes%num_bcs .ne. 0) then + call mpp_error(FATAL, trim(error_header) // ' Number of gas fluxes not zero') + else + return + endif + endif + + do n = 1, gas_fluxes%num_bcs + ! only do calculations if the flux has not been overridden + if ( .not. gas_fluxes%bc(n)%field(ind_flux)%override) then + if (gas_fluxes%bc(n)%flux_type .eq. 'air_sea_gas_flux_generic') then + if (.not. allocated(kw)) then + allocate( kw(isc:iec,jsc:jec) ) + allocate ( cair(isc:iec,jsc:jec) ) + elseif ((size(kw(:,:), dim=1) .ne. iec-isc+1) .or. (size(kw(:,:), dim=2) .ne. jec-jsc+1)) then + call mpp_error(FATAL, trim(error_header) // ' Sizes of flux fields do not match') + endif + + if (gas_fluxes%bc(n)%implementation .eq. 'ocmip2') then + do j = jsc,jec + do i = isc,iec + gas_fluxes%bc(n)%field(ind_kw)%values(i,j) =& + & (1 - ice_fraction(i,j)) * gas_fluxes%bc(n)%param(1) * & + & gas_fields_atm%bc(n)%field(ind_u10)%values(i,j)**2 + cair(i,j) = & + gas_fields_ocn%bc(n)%field(ind_alpha)%values(i,j) * & + gas_fields_atm%bc(n)%field(ind_pcair)%values(i,j) * & + gas_fields_atm%bc(n)%field(ind_psurf)%values(i,j) * gas_fluxes%bc(n)%param(2) + gas_fluxes%bc(n)%field(ind_flux)%values(i,j) =& + & gas_fluxes%bc(n)%field(ind_kw)%values(i,j) *& + & sqrt(660. / (gas_fields_ocn%bc(n)%field(ind_sc_no)%values(i,j) + epsln)) *& + & (gas_fields_ocn%bc(n)%field(ind_csurf)%values(i,j) - cair(i,j)) + gas_fluxes%bc(n)%field(ind_flux0)%values(i,j) =& + & gas_fluxes%bc(n)%field(ind_kw)%values(i,j) *& + & sqrt(660. / (gas_fields_ocn%bc(n)%field(ind_sc_no)%values(i,j) + epsln)) *& + & gas_fields_ocn%bc(n)%field(ind_csurf)%values(i,j) + gas_fluxes%bc(n)%field(ind_deltap)%values(i,j) =& + & (gas_fields_ocn%bc(n)%field(ind_csurf)%values(i,j) - cair(i,j)) / & + (gas_fields_ocn%bc(n)%field(ind_alpha)%values(i,j) * permeg + epsln) + enddo + enddo + elseif (gas_fluxes%bc(n)%implementation .eq. 'duce') then + if (.not. present(tsurf)) then + call mpp_error(FATAL, trim(error_header) // ' Implementation ' //& + trim(gas_fluxes%bc(n)%implementation) // ' for ' // trim(gas_fluxes%bc(n)%name) //& + ' requires input tsurf') + endif + do j = jsc,jec + do i = isc,iec + gas_fluxes%bc(n)%field(ind_kw)%values(i,j) = & + & (1 - ice_fraction(i,j)) * gas_fields_atm%bc(n)%field(ind_u10)%values(i,j) /& + & (770.+45.*gas_fluxes%bc(n)%param(1)**(1./3.)) *& + & 101325./(rdgas*wtmair*1e-3*tsurf(i,j) *& + & max(gas_fields_ocn%bc(n)%field(ind_alpha)%values(i,j),epsln)) + !alpha: mol/m3/atm + cair(i,j) = & + gas_fields_ocn%bc(n)%field(ind_alpha)%values(i,j) * & + gas_fields_atm%bc(n)%field(ind_pcair)%values(i,j) * & + gas_fields_atm%bc(n)%field(ind_psurf)%values(i,j) * 9.86923e-6 + cair(i,j) = max(cair(i,j),0.) + gas_fluxes%bc(n)%field(ind_flux)%values(i,j) =& + & gas_fluxes%bc(n)%field(ind_kw)%values(i,j) *& + & (max(gas_fields_ocn%bc(n)%field(ind_csurf)%values(i,j),0.) - cair(i,j)) + gas_fluxes%bc(n)%field(ind_flux0)%values(i,j) =& + & gas_fluxes%bc(n)%field(ind_kw)%values(i,j) *& + & max(gas_fields_ocn%bc(n)%field(ind_csurf)%values(i,j),0.) + gas_fluxes%bc(n)%field(ind_deltap)%values(i,j) =& + & (max(gas_fields_ocn%bc(n)%field(ind_csurf)%values(i,j),0.) - cair(i,j)) /& + & (gas_fields_ocn%bc(n)%field(ind_alpha)%values(i,j) * permeg + epsln) + enddo + enddo + elseif (gas_fluxes%bc(n)%implementation .eq. 'johnson') then + if (.not. present(tsurf)) then + call mpp_error(FATAL, trim(error_header) // ' Implementation ' //& + trim(gas_fluxes%bc(n)%implementation) // ' for ' // trim(gas_fluxes%bc(n)%name) //& + ' requires input tsurf') + endif + !f1p: not sure how to pass salinity. For now, just force at 35. + do j = jsc,jec + do i = isc,iec + !calc_kw(tk,p,u10,h,vb,mw,sc_w,ustar,cd_m) + gas_fluxes%bc(n)%field(ind_kw)%values(i,j) =& + & (1 - ice_fraction(i,j)) * calc_kw(tsurf(i,j),& + & gas_fields_atm%bc(n)%field(ind_psurf)%values(i,j),& + & gas_fields_atm%bc(n)%field(ind_u10)%values(i,j),& + & 101325./(rdgas*wtmair*1e-3*tsurf(i,j)*& + & max(gas_fields_ocn%bc(n)%field(ind_alpha)%values(i,j),epsln)),& + & gas_fluxes%bc(n)%param(2),& + & gas_fluxes%bc(n)%param(1),& + & gas_fields_ocn%bc(n)%field(ind_sc_no)%values(i,j)) + cair(i,j) =& + & gas_fields_ocn%bc(n)%field(ind_alpha)%values(i,j) *& + & gas_fields_atm%bc(n)%field(ind_pcair)%values(i,j) *& + & gas_fields_atm%bc(n)%field(ind_psurf)%values(i,j) * 9.86923e-6 + cair(i,j) = max(cair(i,j),0.) + gas_fluxes%bc(n)%field(ind_flux)%values(i,j) =& + & gas_fluxes%bc(n)%field(ind_kw)%values(i,j) *& + & (max(gas_fields_ocn%bc(n)%field(ind_csurf)%values(i,j),0.) - cair(i,j)) + gas_fluxes%bc(n)%field(ind_flux0)%values(i,j) =& + & gas_fluxes%bc(n)%field(ind_kw)%values(i,j) *& + & max(gas_fields_ocn%bc(n)%field(ind_csurf)%values(i,j),0.) + gas_fluxes%bc(n)%field(ind_deltap)%values(i,j) =& + & (max(gas_fields_ocn%bc(n)%field(ind_csurf)%values(i,j),0.) - cair(i,j)) /& + & (gas_fields_ocn%bc(n)%field(ind_alpha)%values(i,j) * permeg + epsln) + enddo + enddo + else + call mpp_error(FATAL, ' Unknown implementation (' //& + & trim(gas_fluxes%bc(n)%implementation) // ') for ' // trim(gas_fluxes%bc(n)%name)) + endif + elseif (gas_fluxes%bc(n)%flux_type .eq. 'air_sea_gas_flux') then + if (.not. allocated(kw)) then + allocate( kw(isc:iec,jsc:jec) ) + allocate ( cair(isc:iec,jsc:jec) ) + elseif ((size(kw(:,:), dim=1) .ne. iec-isc+1) .or. (size(kw(:,:), dim=2) .ne. jec-jsc+1)) then + call mpp_error(FATAL, trim(error_header) // ' Sizes of flux fields do not match') + endif + + if (gas_fluxes%bc(n)%implementation .eq. 'ocmip2_data') then + do j = jsc,jec + do i = isc,iec + kw(i,j) = (1 - ice_fraction(i,j)) * gas_fluxes%bc(n)%param(1) *& + & gas_fields_atm%bc(n)%field(ind_u10)%values(i,j) + cair(i,j) =& + & gas_fields_ocn%bc(n)%field(ind_alpha)%values(i,j) *& + & gas_fields_atm%bc(n)%field(ind_pcair)%values(i,j) *& + & gas_fields_atm%bc(n)%field(ind_psurf)%values(i,j) * gas_fluxes%bc(n)%param(2) + gas_fluxes%bc(n)%field(ind_flux)%values(i,j) = kw(i,j) *& + & (gas_fields_ocn%bc(n)%field(ind_csurf)%values(i,j) - cair(i,j)) + enddo + enddo + elseif (gas_fluxes%bc(n)%implementation .eq. 'ocmip2') then + do j = jsc,jec + do i = isc,iec + kw(i,j) = (1 - ice_fraction(i,j)) * gas_fluxes%bc(n)%param(1) *& + & gas_fields_atm%bc(n)%field(ind_u10)%values(i,j)**2 + cair(i,j) =& + & gas_fields_ocn%bc(n)%field(ind_alpha)%values(i,j) *& + & gas_fields_atm%bc(n)%field(ind_pcair)%values(i,j) *& + & gas_fields_atm%bc(n)%field(ind_psurf)%values(i,j) * gas_fluxes%bc(n)%param(2) + gas_fluxes%bc(n)%field(ind_flux)%values(i,j) = kw(i,j) *& + & (gas_fields_ocn%bc(n)%field(ind_csurf)%values(i,j) - cair(i,j)) + enddo + enddo + elseif (gas_fluxes%bc(n)%implementation .eq. 'linear') then + do j = jsc,jec + do i = isc,iec + kw(i,j) = (1 - ice_fraction(i,j)) * gas_fluxes%bc(n)%param(1) *& + & max(0.0, gas_fields_atm%bc(n)%field(ind_u10)%values(i,j) - gas_fluxes%bc(n)%param(2)) + cair(i,j) =& + & gas_fields_ocn%bc(n)%field(ind_alpha)%values(i,j) *& + & gas_fields_atm%bc(n)%field(ind_pcair)%values(i,j) *& + & gas_fields_atm%bc(n)%field(ind_psurf)%values(i,j) * gas_fluxes%bc(n)%param(3) + gas_fluxes%bc(n)%field(ind_flux)%values(i,j) = kw(i,j) *& + & (gas_fields_ocn%bc(n)%field(ind_csurf)%values(i,j) - cair(i,j)) + enddo + enddo + else + call mpp_error(FATAL, ' Unknown implementation (' //& + & trim(gas_fluxes%bc(n)%implementation) // ') for ' // trim(gas_fluxes%bc(n)%name)) + endif + elseif (gas_fluxes%bc(n)%flux_type .eq. 'air_sea_deposition') then + if (gas_fluxes%bc(n)%param(1) .le. 0.0) then + write (error_string, '(1pe10.3)') gas_fluxes%bc(n)%param(1) + call mpp_error(FATAL, 'Bad parameter (' // trim(error_string) //& + & ') for air_sea_deposition for ' // trim(gas_fluxes%bc(n)%name)) + endif + + if (gas_fluxes%bc(n)%implementation .eq. 'dry') then + do j = jsc,jec + do i = isc,iec + gas_fluxes%bc(n)%field(ind_flux)%values(i,j) = (1 - ice_fraction(i,j)) *& + gas_fields_atm%bc(n)%field(ind_deposition)%values(i,j) / gas_fluxes%bc(n)%param(1) + enddo + enddo + elseif (gas_fluxes%bc(n)%implementation .eq. 'wet') then + do j = jsc,jec + do i = isc,iec + gas_fluxes%bc(n)%field(ind_flux)%values(i,j) = (1 - ice_fraction(i,j)) *& + gas_fields_atm%bc(n)%field(ind_deposition)%values(i,j) / gas_fluxes%bc(n)%param(1) + enddo + enddo + else + call mpp_error(FATAL, 'Unknown implementation (' //& + & trim(gas_fluxes%bc(n)%implementation) // ') for ' // trim(gas_fluxes%bc(n)%name)) + endif + elseif (gas_fluxes%bc(n)%flux_type .eq. 'land_sea_runoff') then + if (gas_fluxes%bc(n)%param(1) .le. 0.0) then + write (error_string, '(1pe10.3)') gas_fluxes%bc(n)%param(1) + call mpp_error(FATAL, ' Bad parameter (' // trim(error_string) //& + & ') for land_sea_runoff for ' // trim(gas_fluxes%bc(n)%name)) + endif + + if (gas_fluxes%bc(n)%implementation .eq. 'river') then + do j = jsc,jec + do i = isc,iec + gas_fluxes%bc(n)%field(ind_flux)%values(i,j) = (1 - ice_fraction(i,j)) *& + & gas_fields_atm%bc(n)%field(ind_runoff)%values(i,j) /& + & gas_fluxes%bc(n)%param(1) + enddo + enddo + else + call mpp_error(FATAL, ' Unknown implementation (' //& + & trim(gas_fluxes%bc(n)%implementation) // ') for ' // trim(gas_fluxes%bc(n)%name)) + endif + else + call mpp_error(FATAL, ' Unknown flux_type (' // trim(gas_fluxes%bc(n)%flux_type) //& + & ') for ' // trim(gas_fluxes%bc(n)%name)) + endif + endif + enddo + + if (allocated(kw)) then + deallocate(kw) + deallocate(cair) + endif +end subroutine atmos_ocean_fluxes_calc + +!> Calculate \f$k_w\f$ +!! +!! Taken from Johnson, Ocean Science, 2010. (http://doi.org/10.5194/os-6-913-2010) +!! +!! Uses equations defined in Liss[1974], +!! \f[ +!! F = K_g(c_g - H C_l) = K_l(c_g/H - C_l) +!! \f] +!! where \f$c_g\f$ and \f$C_l\f$ are the bulk gas and liquid concentrations, \f$H\f$ +!! is the Henry's law constant (\f$H = c_{sg}/C_{sl}\f$, where \f$c_{sg}\f$ is the +!! equilibrium concentration in gas phase (\f$g/cm^3\f$ of air) and \f$C_{sl}\f$ is the +!! equilibrium concentration of unionised dissolved gas in liquid phase (\f$g/cm^3\f$ +!! of water)), +!! \f[ +!! 1/K_g = 1/k_g + H/k_l +!! \f] +!! and +!! \f[ +!! 1/K_l = 1/k_l + 1/{Hk_g} +!! \f] +!! where \f$k_g\f$ and \f$k_l\f$ are the exchange constants for the gas and liquid +!! phases, respectively. +!! +!! This routine was copied from FMScoupler at +!! https://github.com/NOAA-GFDL/FMScoupler/blob/6442d38/full/atmos_ocean_fluxes_calc.F90 +real function calc_kw(tk, p, u10, h, vb, mw, sc_w, ustar, cd_m) + real, intent(in) :: tk !< temperature at surface in kelvin + real, intent(in) :: p !< pressure at surface in pa + real, intent(in) :: u10 !< wind speed at 10m above the surface in m/s + real, intent(in) :: h !< Henry's law constant (\f$H=c_sg/C_sl\f$) (unitless) + real, intent(in) :: vb !< Molar volume + real, intent(in) :: mw !< molecular weight (g/mol) + real, intent(in) :: sc_w + real, intent(in), optional :: ustar !< Friction velocity (m/s). If not provided, + !! ustar = \f$u_{10} \sqrt{C_D}\f$. + real, intent(in), optional :: cd_m !< Drag coefficient (\f$C_D\f$). Used only if + !! ustar is provided. + !! If ustar is not provided, + !! cd_m = \f$6.1 \times 10^{-4} + 0.63 \times 10^{-4} *u_10\f$ + + real :: ra,rl,tc + + tc = tk-273.15 + ra = 1./max(h*calc_ka(tc,p,mw,vb,u10,ustar,cd_m),epsln) + rl = 1./max(calc_kl(tc,u10,sc_w),epsln) + calc_kw = 1./max(ra+rl,epsln) +end function calc_kw + +!> Calculate \f$k_a\f$ +!! +!! See calc_kw +!! +!! This routine was copied from FMScoupler at +!! https://github.com/NOAA-GFDL/FMScoupler/blob/6442d38/full/atmos_ocean_fluxes_calc.F90 +real function calc_ka(t, p, mw, vb, u10, ustar, cd_m) + real, intent(in) :: t !< temperature at surface in C + real, intent(in) :: p !< pressure at surface in pa + real, intent(in) :: mw !< molecular weight (g/mol) + real, intent(in) :: vb !< molar volume + real, intent(in) :: u10 !< wind speed at 10m above the surface in m/s + real, intent(in), optional :: ustar !< Friction velocity (m/s). If not provided, + !! ustar = \f$u_{10} \sqrt{C_D}\f$. + real, intent(in), optional :: cd_m !< Drag coefficient (\f$C_D\f$). Used only if + !! ustar is provided. + !! If ustar is not provided, + !! cd_m = \f$6.1 \times 10^{-4} + 0.63 \times 10^{-4} *u_10\f$ + + real :: sc + real :: ustar_t, cd_m_t + + if (.not. present(ustar)) then + !drag coefficient + cd_m_t = 6.1e-4 +0.63e-4*u10 + !friction velocity + ustar_t = u10*sqrt(cd_m_t) + else + cd_m_t = cd_m + ustar_t = ustar + end if + sc = schmidt_g(t,p,mw,vb) + calc_ka = 1e-3+ustar_t/(13.3*sqrt(sc)+1/sqrt(cd_m_t)-5.+log(sc)/(2.*vonkarm)) +end function calc_ka + +!> Calculate \f$k_l\f$ +!! +!! See calc_kw, and Nightingale, Global Biogeochemical Cycles, 2000 +!! (https://doi.org/10.1029/1999GB900091) +!! +!! This routine was copied from FMScoupler at +!! https://github.com/NOAA-GFDL/FMScoupler/blob/6442d38/full/atmos_ocean_fluxes_calc.F90 +real function calc_kl(t, v, sc) + real, intent(in) :: t !< temperature at surface in C + real, intent(in) :: v !< wind speed at surface in m/s + real, intent(in) :: sc + + calc_kl = (((0.222*v**2)+0.333*v)*(max(sc,epsln)/600.)**(-0.5))/(100.*3600.) +end function calc_kl + +!> Schmidt number of the gas in air +!! +!! This routine was copied from FMScoupler at +!! https://github.com/NOAA-GFDL/FMScoupler/blob/6442d38/full/atmos_ocean_fluxes_calc.F90 +real function schmidt_g(t, p, mw, vb) + real, intent(in) :: t !< temperature at surface in C + real, intent(in) :: p !< pressure at surface in pa + real, intent(in) :: mw !< molecular weight (g/mol) + real, intent(in) :: vb !< molar volume + + real :: d,v + + d = d_air(t,p,mw,vb) + v = v_air(t) + schmidt_g = v / d +end function schmidt_g + +!> From Fuller, Industrial & Engineering Chemistry (https://doi.org/10.1021/ie50677a007) +!! +!! This routine was copied from FMScoupler at +!! https://github.com/NOAA-GFDL/FMScoupler/blob/6442d38/full/atmos_ocean_fluxes_calc.F90 +real function d_air(t, p, mw, vb) + real, intent(in) :: t !< temperature in c + real, intent(in) :: p !< pressure in pa + real, intent(in) :: mw !< molecular weight (g/mol) + real, intent(in) :: vb !< diffusion coefficient (\f$cm3/mol\f$) + + real, parameter :: ma = 28.97d0 !< molecular weight air in g/mol + real, parameter :: va = 20.1d0 !< diffusion volume for air (\f$cm^3/mol\f$) + + real :: pa + + ! convert p to atm + pa = 9.8692d-6*p + d_air = 1d-3 *& + & (t+273.15d0)**(1.75d0)*sqrt(1d0/ma + 1d0/mw)/(pa*(va**(1d0/3d0)+vb**(1d0/3d0))**2d0) + ! d_air is in cm2/s convert to m2/s + d_air = d_air * 1d-4 +end function d_air + +!> kinematic viscosity in air +!! +!! This routine was copied from FMScoupler at +!! https://github.com/NOAA-GFDL/FMScoupler/blob/6442d38/full/atmos_ocean_fluxes_calc.F90 +real function p_air(t) + real, intent(in) :: t + + real, parameter :: sd_0 = 1.293393662d0,& + & sd_1 = -5.538444326d-3,& + & sd_2 = 3.860201577d-5,& + & sd_3 = -5.2536065d-7 + p_air = sd_0+(sd_1*t)+(sd_2*t**2)+(sd_3*t**3) +end function p_air + +!> Kinematic viscosity in air (\f$m^2/s\f$ +!! +!! This routine was copied from FMScoupler at +!! https://github.com/NOAA-GFDL/FMScoupler/blob/6442d38/full/atmos_ocean_fluxes_calc.F90 +real function v_air(t) + real, intent(in) :: t !< temperature in C + v_air = n_air(t)/p_air(t) +end function v_air + +!> dynamic viscosity in air +!! +!! This routine was copied from FMScoupler at +!! https://github.com/NOAA-GFDL/FMScoupler/blob/6442d38/full/atmos_ocean_fluxes_calc.F90 +real function n_air(t) + real, intent(in) :: t !< temperature in C + + real, parameter :: sv_0 = 1.715747771d-5,& + & sv_1 = 4.722402075d-8,& + & sv_2 = -3.663027156d-10,& + & sv_3 = 1.873236686d-12,& + & sv_4 = -8.050218737d-14 + ! in n.s/m^2 (pa.s) + n_air = sv_0+(sv_1*t)+(sv_2*t**2)+(sv_3*t**3)+(sv_4*t**4) +end function n_air + +end module MOM_cap_gtracer_flux \ No newline at end of file diff --git a/config_src/drivers/nuopc_cap/mom_cap_methods.F90 b/config_src/drivers/nuopc_cap/mom_cap_methods.F90 index 125bae5748..3f81f6aa7e 100644 --- a/config_src/drivers/nuopc_cap/mom_cap_methods.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap_methods.F90 @@ -20,8 +20,15 @@ module MOM_cap_methods use MOM_surface_forcing_nuopc, only: ice_ocean_boundary_type use MOM_grid, only: ocean_grid_type use MOM_domains, only: pass_var +use MOM_coupler_types, only: coupler_2d_bc_type use mpp_domains_mod, only: mpp_get_compute_domain +#ifdef _USE_GENERIC_TRACER +use MOM_coupler_types, only: set_coupler_type_data +use MOM_coupler_types, only: ind_pcair, ind_u10, ind_psurf, ind_runoff, ind_deposition +use MOM_cap_gtracer_flux, only: get_coupled_field_name, UNKNOWN_CMEPS_FIELD +#endif + ! By default make data private implicit none; private @@ -72,11 +79,17 @@ end subroutine mom_set_geomtype !> This function has a few purposes: !! (1) it imports surface fluxes using data from the mediator; and !! (2) it can apply restoring in SST and SSS. -subroutine mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, rc) +!! (3) optional: if atm_fields is provided, it imports and sets the fields in atm_fields required +!! for the calculation of coupled generic tracer fluxes +subroutine mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, atm_fields, rc) type(ocean_public_type) , intent(in) :: ocean_public !< Ocean surface state type(ocean_grid_type) , intent(in) :: ocean_grid !< Ocean model grid type(ESMF_State) , intent(inout) :: importState !< incoming data from mediator type(ice_ocean_boundary_type) , intent(inout) :: ice_ocean_boundary !< Ocean boundary forcing + type(coupler_2d_bc_type), optional, intent(inout) :: atm_fields !< If present, this type + !! describes the atmospheric tracer fields to + !! be imported for the calculation of generic + !! tracer fluxes. integer , intent(inout) :: rc !< Return code ! Local Variables @@ -88,7 +101,10 @@ subroutine mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, real(ESMF_KIND_R8), allocatable :: tauy(:,:) real(ESMF_KIND_R8), allocatable :: stkx(:,:,:) real(ESMF_KIND_R8), allocatable :: stky(:,:,:) + real(ESMF_KIND_R8), allocatable :: work(:,:) character(len=*) , parameter :: subname = '(mom_import)' + character(len=256) :: stdname + integer :: field_index rc = ESMF_SUCCESS @@ -364,6 +380,48 @@ subroutine mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, deallocate(stkx,stky) endif + !--- + ! Tracer flux fields for generic tracers + !--- +#ifdef _USE_GENERIC_TRACER + if (present(atm_fields)) then + ! Set fields in atm_fields from coupler + allocate (work(isc:iec,jsc:jec)) + do n = 1, atm_fields%num_bcs + if (atm_fields%bc(n)%flux_type .eq. 'air_sea_deposition') then + field_index = ind_deposition + elseif (atm_fields%bc(n)%flux_type .eq. 'land_sea_runoff') then + field_index = ind_runoff + else + ! This is a gas flux - set ind_u10 and ind_psurf + ! Note, we set these fields even though the pcair field may not be set below. This + ! is to allow flux calculation with overridden pcair fields + field_index = ind_pcair + call set_coupler_type_data(sqrt(ice_ocean_boundary%u10_sqr), n, atm_fields, & + idim=(/isc,isc,iec,iec/), jdim=(/jsc,jsc,jec,jec/), field_index=ind_u10) + call set_coupler_type_data(ice_ocean_boundary%p, n, atm_fields, & + idim=(/isc,isc,iec,iec/), jdim=(/jsc,jsc,jec,jec/), field_index=ind_psurf) + endif + + stdname = get_coupled_field_name(atm_fields%bc(n)%name) + if (stdname /= UNKNOWN_CMEPS_FIELD) then + call ESMF_LogWrite(trim(subname)//': generic_tracer flux, '//trim(atm_fields%bc(n)%name)//& + ': setting field index '//CHAR(48+field_index)//' to '//trim(stdname)//' if provided '//& + 'by coupler, otherwise defaulting to zero', ESMF_LOGMSG_INFO) + work(:,:) = 0._ESMF_KIND_R8 + call state_getimport(importState, trim(stdname), isc, iec, jsc, jec, work, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call set_coupler_type_data(work, n, atm_fields, & + idim=(/isc,isc,iec,iec/), jdim=(/jsc,jsc,jec,jec/), field_index=field_index) + else + call ESMF_LogWrite(trim(subname)//': generic_tracer flux, '//trim(atm_fields%bc(n)%name)//& + ': no fields set from coupler', ESMF_LOGMSG_INFO) + endif + enddo + deallocate(work) + endif +#endif + end subroutine mom_import !> Maps outgoing ocean data to ESMF State diff --git a/config_src/infra/FMS1/MOM_couplertype_infra.F90 b/config_src/infra/FMS1/MOM_couplertype_infra.F90 index 637f2b5ebf..0fb57c991a 100644 --- a/config_src/infra/FMS1/MOM_couplertype_infra.F90 +++ b/config_src/infra/FMS1/MOM_couplertype_infra.F90 @@ -9,7 +9,10 @@ module MOM_couplertype_infra use coupler_types_mod, only : coupler_type_increment_data, coupler_type_rescale_data use coupler_types_mod, only : coupler_type_extract_data, coupler_type_set_data use coupler_types_mod, only : coupler_type_data_override -use coupler_types_mod, only : ind_flux, ind_alpha, ind_csurf +use coupler_types_mod, only : ind_flux, ind_deltap, ind_kw, ind_flux0 +use coupler_types_mod, only : ind_pcair, ind_u10, ind_psurf +use coupler_types_mod, only : ind_alpha, ind_csurf, ind_sc_no +use coupler_types_mod, only : ind_runoff, ind_deposition use coupler_types_mod, only : coupler_1d_bc_type, coupler_2d_bc_type, coupler_3d_bc_type use atmos_ocean_fluxes_mod, only : aof_set_coupler_flux use MOM_domain_infra, only : domain2D @@ -22,7 +25,10 @@ module MOM_couplertype_infra public :: CT_set_data, CT_increment_data, CT_rescale_data public :: CT_copy_data, CT_extract_data, CT_redistribute_data public :: atmos_ocn_coupler_flux -public :: ind_flux, ind_alpha, ind_csurf +public :: ind_flux, ind_deltap, ind_kw, ind_flux0 +public :: ind_pcair, ind_u10, ind_psurf +public :: ind_alpha, ind_csurf, ind_sc_no +public :: ind_runoff, ind_deposition public :: coupler_1d_bc_type, coupler_2d_bc_type, coupler_3d_bc_type !> This is the interface to spawn one coupler_bc_type into another. diff --git a/config_src/infra/FMS2/MOM_couplertype_infra.F90 b/config_src/infra/FMS2/MOM_couplertype_infra.F90 index 3bcccc1dc7..50fd5b09cd 100644 --- a/config_src/infra/FMS2/MOM_couplertype_infra.F90 +++ b/config_src/infra/FMS2/MOM_couplertype_infra.F90 @@ -9,7 +9,10 @@ module MOM_couplertype_infra use coupler_types_mod, only : coupler_type_increment_data, coupler_type_rescale_data use coupler_types_mod, only : coupler_type_extract_data, coupler_type_set_data use coupler_types_mod, only : coupler_type_data_override -use coupler_types_mod, only : ind_flux, ind_alpha, ind_csurf +use coupler_types_mod, only : ind_flux, ind_deltap, ind_kw, ind_flux0 +use coupler_types_mod, only : ind_pcair, ind_u10, ind_psurf +use coupler_types_mod, only : ind_alpha, ind_csurf, ind_sc_no +use coupler_types_mod, only : ind_runoff, ind_deposition use coupler_types_mod, only : coupler_1d_bc_type, coupler_2d_bc_type, coupler_3d_bc_type use atmos_ocean_fluxes_mod, only : aof_set_coupler_flux use MOM_domain_infra, only : domain2D @@ -22,7 +25,10 @@ module MOM_couplertype_infra public :: CT_set_data, CT_increment_data, CT_rescale_data public :: CT_copy_data, CT_extract_data, CT_redistribute_data public :: atmos_ocn_coupler_flux -public :: ind_flux, ind_alpha, ind_csurf +public :: ind_flux, ind_deltap, ind_kw, ind_flux0 +public :: ind_pcair, ind_u10, ind_psurf +public :: ind_alpha, ind_csurf, ind_sc_no +public :: ind_runoff, ind_deposition public :: coupler_1d_bc_type, coupler_2d_bc_type, coupler_3d_bc_type !> This is the interface to spawn one coupler_bc_type into another. diff --git a/src/framework/MOM_coupler_types.F90 b/src/framework/MOM_coupler_types.F90 index b931a2ddd2..cac9309b5e 100644 --- a/src/framework/MOM_coupler_types.F90 +++ b/src/framework/MOM_coupler_types.F90 @@ -9,7 +9,10 @@ module MOM_coupler_types use MOM_couplertype_infra, only : CT_copy_data, CT_increment_data, CT_rescale_data use MOM_couplertype_infra, only : CT_set_data, CT_extract_data, CT_redistribute_data use MOM_couplertype_infra, only : coupler_1d_bc_type, coupler_2d_bc_type, coupler_3d_bc_type -use MOM_couplertype_infra, only : ind_flux, ind_alpha, ind_csurf +use MOM_couplertype_infra, only : ind_flux, ind_deltap, ind_kw, ind_flux0 +use MOM_couplertype_infra, only : ind_pcair, ind_u10, ind_psurf +use MOM_couplertype_infra, only : ind_alpha, ind_csurf, ind_sc_no +use MOM_couplertype_infra, only : ind_runoff, ind_deposition use MOM_domain_infra, only : domain2D use MOM_time_manager, only : time_type @@ -23,7 +26,10 @@ module MOM_coupler_types public :: coupler_1d_bc_type, coupler_2d_bc_type, coupler_3d_bc_type ! These are encoding constant parameters that indicate whether a flux, solubility or ! surface ocean concentration are being set or accessed with an inquiry. -public :: ind_flux, ind_alpha, ind_csurf +public :: ind_flux, ind_deltap, ind_kw, ind_flux0 +public :: ind_pcair, ind_u10, ind_psurf +public :: ind_alpha, ind_csurf, ind_sc_no +public :: ind_runoff, ind_deposition !> This is the interface to spawn one coupler_bc_type into another. interface coupler_type_spawn From 62da2a0608771af46ad82fdfb8d932fb4d8d34a2 Mon Sep 17 00:00:00 2001 From: dougiesquire Date: Thu, 23 Jan 2025 13:36:06 +1100 Subject: [PATCH 17/31] Accumulate fluxes%salt_flux_added and pass to new generic_tracer_update_from_coupler routine This allows virtual flux corrections in generic tracer packages --- config_src/external/GFDL_ocean_BGC/generic_tracer.F90 | 9 +++++++++ src/core/MOM_forcing_type.F90 | 5 +++++ src/tracer/MOM_generic_tracer.F90 | 7 ++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/config_src/external/GFDL_ocean_BGC/generic_tracer.F90 b/config_src/external/GFDL_ocean_BGC/generic_tracer.F90 index 42c386497a..90e7d795ff 100644 --- a/config_src/external/GFDL_ocean_BGC/generic_tracer.F90 +++ b/config_src/external/GFDL_ocean_BGC/generic_tracer.F90 @@ -21,6 +21,7 @@ module generic_tracer public generic_tracer_vertdiff_G public generic_tracer_get_diag_list public generic_tracer_coupler_accumulate + public generic_tracer_update_from_coupler !> Turn on generic tracers (note dangerous use of module data) logical :: do_generic_tracer = .true. @@ -65,6 +66,14 @@ subroutine generic_tracer_coupler_accumulate(IOB_struc, weight, model_time) type(time_type), optional,intent(in) :: model_time !< Time end subroutine generic_tracer_coupler_accumulate + !> Modify the values obtained from the coupler + subroutine generic_tracer_update_from_coupler(ilb, jlb, salt_flux_added) + integer, intent(in) :: ilb !< Lower bounds of x extent of input arrays on data domain + integer, intent(in) :: jlb !< Lower bounds of y extent of input arrays on data domain + real, dimension(ilb:,jlb:), intent(in) :: salt_flux_added !< Surface salt flux into ocean from restoring + !! or flux adjustment [g/m^2/sec] + end subroutine generic_tracer_update_from_coupler + !> Calls the corresponding generic_X_update_from_source routine for each package X subroutine generic_tracer_source(Temp,Salt,rho_dzt,dzt,hblt_depth,ilb,jlb,tau,dtts,& grid_dat,model_time,nbands,max_wavelength_band,sw_pen_band,opacity_band,internal_heat,& diff --git a/src/core/MOM_forcing_type.F90 b/src/core/MOM_forcing_type.F90 index 998713d1f1..a2efcaac7d 100644 --- a/src/core/MOM_forcing_type.F90 +++ b/src/core/MOM_forcing_type.F90 @@ -2280,6 +2280,11 @@ subroutine fluxes_accumulate(flux_tmp, fluxes, G, wt2, forces) fluxes%salt_flux(i,j) = wt1*fluxes%salt_flux(i,j) + wt2*flux_tmp%salt_flux(i,j) enddo ; enddo + if (associated(fluxes%salt_flux_added) .and. associated(flux_tmp%salt_flux_added)) then + do j=js,je ; do i=is,ie + fluxes%salt_flux_added(i,j) = wt1*fluxes%salt_flux_added(i,j) + wt2*flux_tmp%salt_flux_added(i,j) + enddo ; enddo + endif if (associated(fluxes%heat_added) .and. associated(flux_tmp%heat_added)) then do j=js,je ; do i=is,ie fluxes%heat_added(i,j) = wt1*fluxes%heat_added(i,j) + wt2*flux_tmp%heat_added(i,j) diff --git a/src/tracer/MOM_generic_tracer.F90 b/src/tracer/MOM_generic_tracer.F90 index 6b10d15e2f..e092aa7d6d 100644 --- a/src/tracer/MOM_generic_tracer.F90 +++ b/src/tracer/MOM_generic_tracer.F90 @@ -21,7 +21,7 @@ module MOM_generic_tracer use generic_tracer, only: generic_tracer_coupler_get, generic_tracer_coupler_set use generic_tracer, only: generic_tracer_end, generic_tracer_get_list, do_generic_tracer use generic_tracer, only: generic_tracer_update_from_bottom,generic_tracer_vertdiff_G - use generic_tracer, only: generic_tracer_coupler_accumulate + use generic_tracer, only: generic_tracer_coupler_accumulate, generic_tracer_update_from_coupler use g_tracer_utils, only: g_tracer_get_name,g_tracer_set_values,g_tracer_set_common,g_tracer_get_common use g_tracer_utils, only: g_tracer_get_next,g_tracer_type,g_tracer_is_prog,g_tracer_flux_init @@ -527,6 +527,11 @@ subroutine MOM_generic_tracer_column_physics(h_old, h_new, ea, eb, fluxes, Hml, ! the fluxes without coming into this subroutine. ! MOM5 has to modified to conform. + ! + !Call the generic_tracer's update_from_coupler routine (convert salt_flux_added to g/m^2/sec) + ! + call generic_tracer_update_from_coupler(G%isd, G%jsd, 1000*(US%RZ_T_to_kg_m2s*fluxes%salt_flux_added)) + ! !Add contribution of river to surface flux ! From a0b022641f79d117c984920aead63b22df63f27c Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Thu, 23 Jan 2025 14:39:09 +1100 Subject: [PATCH 18/31] Small tweaks --- cmake/CMakeLists.txt | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index c5796d16e1..421c6e611b 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -12,7 +12,6 @@ project(MOM6 VERSION "0.1.0" # Project configuration # #]==============================================================================] # Configurations to build -list(APPEND KnownConfigurations MOM6 ACCESS-MOM6) option(ENABLE_MOM6 "Building MOM6 executable standalone" OFF) option(ENABLE_ACCESS_MOM6 "Building MOM6 library with Access3share" ON) @@ -21,16 +20,16 @@ message(STATUS " Building MOM6 executable standalone " ${ENABLE_MOM6}) message(STATUS " Building MOM6 library with Access3share " ${ENABLE_ACCESS_MOM6}) # build options -option(ENABLE_MOM_SYMMETRIC "Use MOM symmetric memory" ON ) -option(ENABLE_CESMCOUPLED "Use CESMCOUPLED" OFF) +option(ENABLE_MOM_SYMMETRIC "Use MOM symmetric memory" ON ) +option(ENABLE_CESMCOUPLED "Use CESMCOUPLED" OFF) if (ENABLE_CESMCOUPLED AND NOT ENABLE_ACCESS_MOM6) message(FATAL_ERROR "ENABLE_CESMCOUPLED can only be set if ENABLE_ACCESS_MOM6 is ON.") endif() message(STATUS "Build options") -message(STATUS "MOM_SYMMETRIC ${ENABLE_MOM_SYMMETRIC}") -message(STATUS "CESMCOUPLED ${ENABLE_CESMCOUPLED}" ) +message(STATUS "MOM_SYMMETRIC ${ENABLE_MOM_SYMMETRIC}" ) +message(STATUS "CESMCOUPLED ${ENABLE_CESMCOUPLED}" ) #[==============================================================================[ # Project configuration # @@ -66,6 +65,8 @@ if (ENABLE_ACCESS_MOM6) find_package(Access3Share REQUIRED cdeps timing share nuopc_cap_share) endif() + + ### Targets ## MOM6 library @@ -148,7 +149,6 @@ target_sources(mom6lib PRIVATE ${SRC}/core/MOM_variables.F90 ${SRC}/core/MOM_verticalGrid.F90 ${SRC}/core/MOM_forcing_type.F90 - ${SRC}/core/MOM_dynamics_split_RK2b.F90 #ml ${SRC}/diagnostics/MOM_debugging.F90 ${SRC}/diagnostics/MOM_diagnostics.F90 @@ -172,8 +172,6 @@ target_sources(mom6lib PRIVATE ${SRC}/equation_of_state/MOM_temperature_convert.F90 ${SRC}/equation_of_state/MOM_TFreeze.F90 - ${SRC}/equation_of_state/MOM_EOS_base_type.F90 - ${SRC}/equation_of_state/TEOS10/gsw_chem_potential_water_t_exact.f90 ${SRC}/equation_of_state/TEOS10/gsw_ct_freezing_exact.f90 ${SRC}/equation_of_state/TEOS10/gsw_ct_freezing_poly.f90 @@ -280,7 +278,6 @@ target_sources(mom6lib PRIVATE ${SRC}/parameterizations/lateral/MOM_thickness_diffuse.F90 ${SRC}/parameterizations/lateral/MOM_tidal_forcing.F90 ${SRC}/parameterizations/lateral/MOM_Zanna_Bolton.F90 - ${SRC}/parameterizations/lateral/MOM_self_attr_load.F90 # ml ${SRC}/parameterizations/stochastic/MOM_stochastics.F90 @@ -334,8 +331,6 @@ target_sources(mom6lib PRIVATE ${SRC}/tracer/RGC_tracer.F90 ${SRC}/tracer/tracer_example.F90 - ${SRC}/tracer/MOM_generic_tracer.F90 - ${SRC}/user/adjustment_initialization.F90 ${SRC}/user/baroclinic_zone_initialization.F90 ${SRC}/user/basin_builder.F90 @@ -372,7 +367,6 @@ target_sources(mom6lib PRIVATE ${SRC}/user/user_initialization.F90 ${SRC}/user/user_revise_forcing.F90 - ${CONFIG_SRC}/external/database_comms/MOM_database_comms.F90 ${CONFIG_SRC}/external/database_comms/database_client_interface.F90 @@ -403,6 +397,8 @@ target_sources(mom6lib PRIVATE ${CONFIG_SRC}/infra/FMS2/MOM_time_manager.F90 ${CONFIG_SRC}/infra/FMS2/MOM_couplertype_infra.F90 + + ${SRC}/tracer/MOM_generic_tracer.F90 ) if (ENABLE_ACCESS_MOM6) @@ -450,6 +446,7 @@ if(ENABLE_ACCESS_MOM6) NAMESPACE Access3:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Mom6lib ) + endif() # executable From 079e53b5ce0c31e98cd3bdcd6495e657f310847e Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Thu, 23 Jan 2025 14:42:25 +1100 Subject: [PATCH 19/31] Configure MOM6 package --- cmake/CMakeLists.txt | 13 ++++++++++++- cmake/MOM6libConfig.cmake.in | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 cmake/MOM6libConfig.cmake.in diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 421c6e611b..ebe7184e14 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -39,6 +39,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}) include(GNUInstallDirs) include(FortranLib) include(CompilerFlags) +include(CMakePackageConfigHelpers) # Precessor (macro) definitions add_compile_definitions(_USE_GENERIC_TRACER _USE_MOM6_DIAG) @@ -444,9 +445,19 @@ if(ENABLE_ACCESS_MOM6) install(EXPORT MOM6libTargets FILE MOM6libTargets.cmake NAMESPACE Access3:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Mom6lib + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MOM6lib ) + configure_package_config_file( + MOM6libConfig.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/MOM6libConfig.cmake" + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MOM6lib + ) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/MOM6libConfig.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MOM6lib + COMPONENT AccessMOM6Cmeps_Development + ) endif() # executable diff --git a/cmake/MOM6libConfig.cmake.in b/cmake/MOM6libConfig.cmake.in new file mode 100644 index 0000000000..bc1758eefc --- /dev/null +++ b/cmake/MOM6libConfig.cmake.in @@ -0,0 +1,20 @@ +@PACKAGE_INIT@ + +if(NOT MOM6_FIND_QUIETLY) + message(STATUS "Found MOM6: ${PACKAGE_PREFIX_DIR}") +endif() + +include(CMakeFindDependencyMacro) + +# Request components +set(_required_components ${MOM6lib_FIND_COMPONENTS}) + +find_dependency(fms COMPONENTS R8 REQUIRED) + +# Run the normal Targets.cmake +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) +include("${CMAKE_CURRENT_LIST_DIR}/MOM6libTargets.cmake") +list(REMOVE_ITEM CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +# Check the requested components are valid +check_required_components(_required_components) \ No newline at end of file From 1fbf957e470a06c9dfc6bddea916233468c191a1 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Thu, 23 Jan 2025 14:59:08 +1100 Subject: [PATCH 20/31] fix package name --- cmake/MOM6libConfig.cmake.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/MOM6libConfig.cmake.in b/cmake/MOM6libConfig.cmake.in index bc1758eefc..e7235f6477 100644 --- a/cmake/MOM6libConfig.cmake.in +++ b/cmake/MOM6libConfig.cmake.in @@ -1,7 +1,7 @@ @PACKAGE_INIT@ -if(NOT MOM6_FIND_QUIETLY) - message(STATUS "Found MOM6: ${PACKAGE_PREFIX_DIR}") +if(NOT MOM6lib_FIND_QUIETLY) + message(STATUS "Found MOM6lib: ${PACKAGE_PREFIX_DIR}") endif() include(CMakeFindDependencyMacro) From 8d0d525b511be98f2cadd069af5a12227c790d25 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Thu, 23 Jan 2025 15:57:00 +1100 Subject: [PATCH 21/31] remove option mom6 standalone and rename ENABLE_ACCESS_MOM6 to ACCESS3_MOM6, consistent with ACCESS3_CICE --- cmake/CMakeLists.txt | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index ebe7184e14..8acd8bd0f8 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 3.18) #[==============================================================================[ # Basic project definition # #]==============================================================================] -project(MOM6 VERSION "0.1.0" - DESCRIPTION "MOM6" +project(MOM6 + DESCRIPTION "Modular Ocean Model6" HOMEPAGE_URL https://github.com/ACCESS-NRI/MOM6 LANGUAGES C Fortran) @@ -12,19 +12,17 @@ project(MOM6 VERSION "0.1.0" # Project configuration # #]==============================================================================] # Configurations to build -option(ENABLE_MOM6 "Building MOM6 executable standalone" OFF) -option(ENABLE_ACCESS_MOM6 "Building MOM6 library with Access3share" ON) +option(ACCESS3_MOM6 "Building MOM6 library with Access3share" ON) message(STATUS "Configuration") -message(STATUS " Building MOM6 executable standalone " ${ENABLE_MOM6}) -message(STATUS " Building MOM6 library with Access3share " ${ENABLE_ACCESS_MOM6}) +message(STATUS " Building MOM6 library with Access3share " ${ACCESS3_MOM6}) # build options option(ENABLE_MOM_SYMMETRIC "Use MOM symmetric memory" ON ) option(ENABLE_CESMCOUPLED "Use CESMCOUPLED" OFF) -if (ENABLE_CESMCOUPLED AND NOT ENABLE_ACCESS_MOM6) - message(FATAL_ERROR "ENABLE_CESMCOUPLED can only be set if ENABLE_ACCESS_MOM6 is ON.") +if (ENABLE_CESMCOUPLED AND NOT ACCESS3_MOM6) + message(FATAL_ERROR "ENABLE_CESMCOUPLED can only be set if ACCESS3_MOM6 is ON.") endif() message(STATUS "Build options") @@ -61,7 +59,7 @@ find_package(NetCDF REQUIRED Fortran) find_package(fms COMPONENTS R8 REQUIRED) find_package(PIO 2.6.2 REQUIRED COMPONENTS C Fortran) -if (ENABLE_ACCESS_MOM6) +if (ACCESS3_MOM6) find_package(ESMF 8.3.0 MODULE REQUIRED) find_package(Access3Share REQUIRED cdeps timing share nuopc_cap_share) endif() @@ -92,7 +90,7 @@ target_compile_options(mom6lib PRIVATE "$<$:${fortran_ # link libraries target_link_libraries(mom6lib PRIVATE FMS::fms_r8) -if(ENABLE_ACCESS_MOM6) +if(ACCESS3_MOM6) target_link_libraries(mom6lib PUBLIC esmf PRIVATE Access3::nuopc_cap_share Access3::share Access3::timing Access3::cdeps-common @@ -402,7 +400,7 @@ target_sources(mom6lib PRIVATE ${SRC}/tracer/MOM_generic_tracer.F90 ) -if (ENABLE_ACCESS_MOM6) +if (ACCESS3_MOM6) target_sources(mom6lib PRIVATE ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap_time.F90 ${CONFIG_SRC}/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 @@ -412,9 +410,7 @@ if (ENABLE_ACCESS_MOM6) ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap_methods.F90 ${CONFIG_SRC}/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 ) -endif() - -if (ENABLE_MOM6) +else() target_sources(mom6lib PRIVATE ${CONFIG_SRC}/drivers/solo_driver/MOM_surface_forcing.F90 ${CONFIG_SRC}/drivers/solo_driver/MESO_surface_forcing.F90 @@ -424,7 +420,7 @@ endif() ### Install and Export ## Library -if(ENABLE_ACCESS_MOM6) +if(ACCESS3_MOM6) set_target_properties(mom6lib PROPERTIES OUTPUT_NAME access-mom6lib EXPORT_NAME mom6lib @@ -458,10 +454,10 @@ if(ENABLE_ACCESS_MOM6) DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MOM6lib COMPONENT AccessMOM6Cmeps_Development ) -endif() + +else() # executable -if (ENABLE_MOM6) add_executable(MOM6 ${CONFIG_SRC}/drivers/solo_driver/MOM_driver.F90) target_link_libraries(MOM6 PRIVATE mom6lib) From 80a36614eae10d3be15cbbcc466a2744d77c35a5 Mon Sep 17 00:00:00 2001 From: minghangli-uni Date: Thu, 23 Jan 2025 16:08:01 +1100 Subject: [PATCH 22/31] Add dependency for MOM6 configuration --- cmake/CMakeLists.txt | 2 -- cmake/MOM6libConfig.cmake.in | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 8acd8bd0f8..92cb76cfb1 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -57,7 +57,6 @@ set(CMAKE_INSTALL_MODULEDIR ${CMAKE_INSTALL_INCLUDEDIR} #]==============================================================================] find_package(NetCDF REQUIRED Fortran) find_package(fms COMPONENTS R8 REQUIRED) -find_package(PIO 2.6.2 REQUIRED COMPONENTS C Fortran) if (ACCESS3_MOM6) find_package(ESMF 8.3.0 MODULE REQUIRED) @@ -65,7 +64,6 @@ if (ACCESS3_MOM6) endif() - ### Targets ## MOM6 library diff --git a/cmake/MOM6libConfig.cmake.in b/cmake/MOM6libConfig.cmake.in index e7235f6477..723498dde6 100644 --- a/cmake/MOM6libConfig.cmake.in +++ b/cmake/MOM6libConfig.cmake.in @@ -10,6 +10,7 @@ include(CMakeFindDependencyMacro) set(_required_components ${MOM6lib_FIND_COMPONENTS}) find_dependency(fms COMPONENTS R8 REQUIRED) +find_dependency(NetCDF REQUIRED Fortran) # Run the normal Targets.cmake list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) From 50473e3e4e7f4d4e6187a9c17e27276658ede355 Mon Sep 17 00:00:00 2001 From: anton-seaice Date: Thu, 23 Jan 2025 16:44:17 +1100 Subject: [PATCH 23/31] name tweaks and missing files --- cmake/CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 92cb76cfb1..2816168292 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -19,15 +19,15 @@ message(STATUS " Building MOM6 library with Access3share " ${ACCESS3_MOM6}) # build options option(ENABLE_MOM_SYMMETRIC "Use MOM symmetric memory" ON ) -option(ENABLE_CESMCOUPLED "Use CESMCOUPLED" OFF) +option(CESMCOUPLED "Use CESMCOUPLED" OFF) -if (ENABLE_CESMCOUPLED AND NOT ACCESS3_MOM6) +if (CESMCOUPLED AND NOT ACCESS3_MOM6) message(FATAL_ERROR "ENABLE_CESMCOUPLED can only be set if ACCESS3_MOM6 is ON.") endif() message(STATUS "Build options") message(STATUS "MOM_SYMMETRIC ${ENABLE_MOM_SYMMETRIC}" ) -message(STATUS "CESMCOUPLED ${ENABLE_CESMCOUPLED}" ) +message(STATUS "CESMCOUPLED ${CESMCOUPLED}" ) #[==============================================================================[ # Project configuration # @@ -42,7 +42,7 @@ include(CMakePackageConfigHelpers) # Precessor (macro) definitions add_compile_definitions(_USE_GENERIC_TRACER _USE_MOM6_DIAG) -if (ENABLE_CESMCOUPLED) +if (CESMCOUPLED) add_compile_definitions(CESMCOUPLED) endif() @@ -129,6 +129,7 @@ target_sources(mom6lib PRIVATE ${SRC}/core/MOM_CoriolisAdv.F90 ${SRC}/core/MOM_density_integrals.F90 ${SRC}/core/MOM_dynamics_split_RK2.F90 + ${SRC}/core/MOM_dynamics_split_RK2b.F90 ${SRC}/core/MOM_dynamics_unsplit.F90 ${SRC}/core/MOM_dynamics_unsplit_RK2.F90 ${SRC}/core/MOM.F90 @@ -157,6 +158,7 @@ target_sources(mom6lib PRIVATE ${SRC}/diagnostics/MOM_wave_speed.F90 ${SRC}/equation_of_state/MOM_EOS.F90 + ${SRC}/equation_of_state/MOM_EOS_base_type.F90 ${SRC}/equation_of_state/MOM_EOS_Jackett06.F90 ${SRC}/equation_of_state/MOM_EOS_linear.F90 ${SRC}/equation_of_state/MOM_EOS_Roquet_rho.F90 @@ -272,6 +274,7 @@ target_sources(mom6lib PRIVATE ${SRC}/parameterizations/lateral/MOM_MEKE_types.F90 ${SRC}/parameterizations/lateral/MOM_mixed_layer_restrat.F90 ${SRC}/parameterizations/lateral/MOM_spherical_harmonics.F90 + ${SRC}/parameterizations/lateral/MOM_self_attr_load.F90 ${SRC}/parameterizations/lateral/MOM_thickness_diffuse.F90 ${SRC}/parameterizations/lateral/MOM_tidal_forcing.F90 ${SRC}/parameterizations/lateral/MOM_Zanna_Bolton.F90 From b648a63ba2ad030ac31a495c9dd42310b78ba9e8 Mon Sep 17 00:00:00 2001 From: "minghang.li" Date: Thu, 23 Jan 2025 17:13:18 +1100 Subject: [PATCH 24/31] fix typo --- cmake/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 2816168292..8ff10198cc 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -436,7 +436,7 @@ if(ACCESS3_MOM6) target_include_directories(mom6lib PUBLIC "$") get_target_property(mom_moddir mom6lib Fortran_MODULE_DIRECTORY) install(FILES ${mom_moddir}/ocn_comp_nuopc.mod ${mom_moddir}/mom_cap_mod.mod - DESTINATION ${CMAKE_INSTALL_MODULEDIR}/mom6lib + DESTINATION ${CMAKE_INSTALL_MODULEDIR}/MOM6lib COMPONENT AccessMOM6Cmeps_Development ) install(EXPORT MOM6libTargets From dd52c5f8a0f1936d8822d3eb5a91de8e5aecdf88 Mon Sep 17 00:00:00 2001 From: anton-seaice Date: Fri, 24 Jan 2025 08:42:35 +1100 Subject: [PATCH 25/31] typo --- cmake/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 8ff10198cc..83ff7c5f50 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -433,7 +433,7 @@ if(ACCESS3_MOM6) ) # Fortran module files are a special case, as currently there is no standard # way of handling them in CMake - target_include_directories(mom6lib PUBLIC "$") + target_include_directories(mom6lib PUBLIC "$") get_target_property(mom_moddir mom6lib Fortran_MODULE_DIRECTORY) install(FILES ${mom_moddir}/ocn_comp_nuopc.mod ${mom_moddir}/mom_cap_mod.mod DESTINATION ${CMAKE_INSTALL_MODULEDIR}/MOM6lib From ff3823373ef36399ed009c19cb3c28584ef32dd0 Mon Sep 17 00:00:00 2001 From: anton-seaice Date: Mon, 3 Feb 2025 13:57:14 +1100 Subject: [PATCH 26/31] Check for Netcdf parallel --- cmake/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 83ff7c5f50..3492912074 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -56,6 +56,11 @@ set(CMAKE_INSTALL_MODULEDIR ${CMAKE_INSTALL_INCLUDEDIR} # External packages # #]==============================================================================] find_package(NetCDF REQUIRED Fortran) + +if (NOT NetCDF_PARALLEL) + message(FATAL_ERROR "NetCDF does not have parallel I/O support!") +endif() + find_package(fms COMPONENTS R8 REQUIRED) if (ACCESS3_MOM6) From 12631b3e975c9e1edb62860de68130e4a0b6cc30 Mon Sep 17 00:00:00 2001 From: anton-seaice Date: Wed, 5 Feb 2025 16:05:04 +1100 Subject: [PATCH 27/31] extra checks for Netcdf parallel --- cmake/MOM6libConfig.cmake.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/MOM6libConfig.cmake.in b/cmake/MOM6libConfig.cmake.in index 723498dde6..531a90cb4c 100644 --- a/cmake/MOM6libConfig.cmake.in +++ b/cmake/MOM6libConfig.cmake.in @@ -11,6 +11,9 @@ set(_required_components ${MOM6lib_FIND_COMPONENTS}) find_dependency(fms COMPONENTS R8 REQUIRED) find_dependency(NetCDF REQUIRED Fortran) +if (NOT NetCDF_PARALLEL) + message(FATAL_ERROR "NetCDF does not have parallel I/O support!") +endif() # Run the normal Targets.cmake list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) From b62e6179a5495dca77bef33b9197266a20a0e750 Mon Sep 17 00:00:00 2001 From: anton-seaice Date: Thu, 6 Feb 2025 10:13:36 +1100 Subject: [PATCH 28/31] possibly better deps handling --- cmake/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 3492912074..0e825c5712 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -456,7 +456,7 @@ if(ACCESS3_MOM6) INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MOM6lib ) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/MOM6libConfig.cmake + install(FILES ${CMAKE_SOURCE_DIR}/FindNetCDF.cmake ${CMAKE_CURRENT_BINARY_DIR}/MOM6libConfig.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MOM6lib COMPONENT AccessMOM6Cmeps_Development ) From 5e1f917b9ae132fe124d022cfbb534387955ee46 Mon Sep 17 00:00:00 2001 From: Dougie Squire <42455466+dougiesquire@users.noreply.github.com> Date: Fri, 14 Feb 2025 06:48:24 +1100 Subject: [PATCH 29/31] Fix bug in setting Fortran compiler flags --- cmake/CompilerFlags.cmake | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmake/CompilerFlags.cmake b/cmake/CompilerFlags.cmake index 1200cf5baf..b41ff46a15 100644 --- a/cmake/CompilerFlags.cmake +++ b/cmake/CompilerFlags.cmake @@ -10,10 +10,9 @@ if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") set(CMAKE_Fortran_FLAGS_RELEASE "-O") set(CMAKE_Fortran_FLAGS_DEBUG "-g -Wall -Og -ffpe-trap=zero,overflow -fcheck=bounds") elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Intel") - set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qno-opt-dynamic-align -convert big_endian -assume byterecl -ftz -traceback -assume realloc_lhs -fp-model source") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qno-opt-dynamic-align -convert big_endian -assume byterecl -ftz -traceback -assume realloc_lhs -fp-model source -r8") set(CMAKE_Fortran_FLAGS_RELEASE "-O2 -debug minimal") set(CMAKE_Fortran_FLAGS_DEBUG "-O0 -g -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created") - set(CMAKE_Fortran_FLAGS "-r8") else() message(WARNING "Fortran compiler with ID ${CMAKE_Fortran_COMPILER_ID} will be used with CMake default options") endif() @@ -29,4 +28,4 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Intel") set(CMAKE_C_FLAGS_DEBUG "-O0 -g") else() message(WARNING "C compiler with ID ${CMAKE_C_COMPILER_ID} will be used with CMake default options") -endif() \ No newline at end of file +endif() From 02bd2ae7fcd20c0deceeab70ec0c6e71e80ef0bd Mon Sep 17 00:00:00 2001 From: Dougie Squire <42455466+dougiesquire@users.noreply.github.com> Date: Fri, 14 Feb 2025 10:41:07 +1100 Subject: [PATCH 30/31] Fix bug in setting Fortran compiler flags --- cmake/CompilerFlags.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/CompilerFlags.cmake b/cmake/CompilerFlags.cmake index b41ff46a15..112340a560 100644 --- a/cmake/CompilerFlags.cmake +++ b/cmake/CompilerFlags.cmake @@ -2,11 +2,10 @@ # Fortran compiler flags if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") - set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fbacktrace -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fbacktrace -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none -fdefault-real-8 -fdefault-double-8") if(${CMAKE_Fortran_COMPILER_VERSION} VERSION_GREATER_EQUAL 10) set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fallow-argument-mismatch") endif() - set(CMAKE_Fortran_FLAGS "-fdefault-real-8 -fdefault-double-8") set(CMAKE_Fortran_FLAGS_RELEASE "-O") set(CMAKE_Fortran_FLAGS_DEBUG "-g -Wall -Og -ffpe-trap=zero,overflow -fcheck=bounds") elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Intel") From dbc5f95258a4c39faec89bf9e66ce679190ef345 Mon Sep 17 00:00:00 2001 From: anton-seaice Date: Fri, 28 Feb 2025 16:00:11 +1100 Subject: [PATCH 31/31] fix CMakeLists --- cmake/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 0e825c5712..cdd8e8017e 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -154,7 +154,9 @@ target_sources(mom6lib PRIVATE ${SRC}/core/MOM_forcing_type.F90 ${SRC}/diagnostics/MOM_debugging.F90 + ${SRC}/diagnostics/MOM_diagnose_MLD.F90 ${SRC}/diagnostics/MOM_diagnostics.F90 + ${SRC}/diagnostics/MOM_harmonic_analysis.F90 ${SRC}/diagnostics/MOM_obsolete_diagnostics.F90 ${SRC}/diagnostics/MOM_obsolete_params.F90 ${SRC}/diagnostics/MOM_PointAccel.F90 @@ -279,6 +281,7 @@ target_sources(mom6lib PRIVATE ${SRC}/parameterizations/lateral/MOM_MEKE_types.F90 ${SRC}/parameterizations/lateral/MOM_mixed_layer_restrat.F90 ${SRC}/parameterizations/lateral/MOM_spherical_harmonics.F90 + ${SRC}/parameterizations/lateral/MOM_streaming_filter.F90 ${SRC}/parameterizations/lateral/MOM_self_attr_load.F90 ${SRC}/parameterizations/lateral/MOM_thickness_diffuse.F90 ${SRC}/parameterizations/lateral/MOM_tidal_forcing.F90 @@ -409,6 +412,7 @@ target_sources(mom6lib PRIVATE if (ACCESS3_MOM6) target_sources(mom6lib PRIVATE ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap_time.F90 + ${CONFIG_SRC}/drivers/nuopc_cap/mom_cap_gtracer_flux.F90 ${CONFIG_SRC}/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 ${CONFIG_SRC}/drivers/nuopc_cap/ocn_comp_NUOPC.F90 ${CONFIG_SRC}/drivers/nuopc_cap/time_utils.F90