├── .github ├── ISSUE_TEMPLATE │ └── parameter-testing.yml └── workflows │ └── compilation.yml ├── .gitignore ├── .gitmodules ├── CDEPS ├── CMakeLists.txt ├── extra_sources │ └── datm_datamode_jra55do_mod.F90 └── patches │ └── atm_comp_nuopc.F90.patch ├── CICE └── CMakeLists.txt ├── CMEPS └── CMakeLists.txt ├── CMakeLists.txt ├── CMakePresets.json ├── ChangeLog.md ├── MOM6 ├── CMakeLists.txt ├── extra_sources │ └── mom_cap_gtracer_flux.F90 └── patches │ ├── MOM_PointAccel.F90.patch │ ├── MOM_coupler_types.F90.patch │ ├── MOM_couplertype_infra.F90.patch │ ├── MOM_forcing_type.F90.patch │ ├── MOM_generic_tracer.F90.patch │ ├── MOM_io_infra.F90.patch │ ├── mom_cap.F90.patch │ ├── mom_cap_methods.F90.patch │ └── mom_ocean_model_nuopc.F90.patch ├── README.md ├── WW3 ├── CMakeLists.txt ├── cmake │ └── check_switches.cmake └── patches │ ├── w3iorsmd.F90.patch │ └── w3srcemd.F90.patch ├── build.sh ├── cmake ├── AccessOM3Config.cmake.in ├── AddPatchedSource.cmake ├── CMakePresets-compilers.json ├── CMakePresets-defaults.json ├── CMakePresets-machines.json ├── FindESMF.cmake ├── FindFoX.cmake ├── FindNetCDF.cmake ├── FindPIO.cmake ├── FortranLib.cmake └── PatchFile.cmake └── share ├── CMakeLists.txt ├── patches ├── nuopc_shr_methods.F90.patch └── shr_const_mod.F90.patch ├── src ├── dtypes.h ├── shr_assert_mod.F90 ├── shr_frz_mod.F90 └── shr_infnan_mod.F90 ├── stubs └── mct_mod.F90 └── timing ├── COPYING ├── ChangeLog ├── GPTLget_memusage.c ├── GPTLprint_memusage.c ├── GPTLutil.c ├── README ├── f_wrappers.c ├── gptl.c ├── gptl.h ├── gptl.inc ├── gptl_papi.c ├── perf_mod.F90 ├── perf_utils.F90 └── private.h /.github/ISSUE_TEMPLATE/parameter-testing.yml: -------------------------------------------------------------------------------- 1 | name: Parameter Testing 2 | description: Template for tracking parameter testing issues 3 | title: "[Parameter Testing] " 4 | labels: "Parameter-testing" 5 | assignees: [optional-assignee] 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Please fill out the sections below to clearly and concisely describe: 11 | 1. the parameter(s) tested, 12 | 2. the exact version of the test tool (Expts_manager) used. 13 | 14 | - type: textarea 15 | attributes: 16 | label: Parameter Tests Description 17 | placeholder: "including a short description and Parameter Name(s): Value(s) Tested" 18 | validations: 19 | required: true 20 | 21 | - type: input 22 | attributes: 23 | label: Expts_manager Version 24 | placeholder: Git URL including commit hash 25 | validations: 26 | required: true 27 | 28 | - type: textarea 29 | attributes: 30 | label: YAML input file 31 | placeholder: | 32 | ```yaml 33 | Copy the yaml input file used 34 | ``` 35 | validations: 36 | required: true 37 | 38 | - type: textarea 39 | attributes: 40 | label: Additional Information 41 | placeholder: Any other relevant information... 42 | -------------------------------------------------------------------------------- /.github/workflows/compilation.yml: -------------------------------------------------------------------------------- 1 | name: compilation 2 | 3 | on: 4 | push: 5 | 6 | jobs: 7 | compilation: 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | compiler: [gcc] 14 | build_type: [Debug, Release] 15 | 16 | container: 17 | image: ghcr.io/cosima/access-om3-ci-images/${{matrix.compiler}}:main 18 | 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v3 22 | with: 23 | submodules: recursive 24 | 25 | - name: Configure CMake 26 | env: 27 | FC: mpifort 28 | CC: mpicc 29 | run: . /etc/profile && cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DCMAKE_VERBOSE_MAKEFILE=ON 30 | 31 | - name: Build 32 | # Build your program with the given configuration 33 | run: . /etc/profile && cmake --build ${{github.workspace}}/build --config ${{matrix.build_type}} 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | bin/* 3 | Debug/* 4 | Release/* 5 | CMakeUserPresets.json 6 | **/make_patches.sh 7 | .fortls 8 | spack-* 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "MOM6/MOM6"] 2 | path = MOM6/MOM6 3 | url = https://github.com/ACCESS-NRI/MOM6 4 | [submodule "CICE6/CICE6"] 5 | path = CICE/CICE 6 | url = https://github.com/ACCESS-NRI/CICE 7 | [submodule "CMEPS/CMEPS"] 8 | path = CMEPS/CMEPS 9 | url = https://github.com/ESCOMP/CMEPS 10 | [submodule "CDEPS/CDEPS"] 11 | path = CDEPS/CDEPS 12 | url = https://github.com/ESCOMP/CDEPS 13 | [submodule "share/CESM_share"] 14 | path = share/CESM_share 15 | url = https://github.com/ESCOMP/CESM_share.git 16 | [submodule "WW3/WW3"] 17 | path = WW3/WW3 18 | url = https://github.com/ESCOMP/WW3 19 | [submodule "MOM6/GFDL_generic_tracers"] 20 | path = MOM6/GFDL_generic_tracers 21 | url = https://github.com/ACCESS-NRI/GFDL-generic-tracers.git 22 | -------------------------------------------------------------------------------- /CDEPS/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ### Targets 2 | 3 | ## Common library 4 | add_fortran_library(OM3_cdeps_common mod/common STATIC) 5 | add_library(AccessOM3::cdeps_common ALIAS OM3_cdeps_common) 6 | target_include_directories(OM3_cdeps_common PRIVATE $) 7 | target_link_libraries(OM3_cdeps_common 8 | PUBLIC esmf 9 | PRIVATE AccessOM3::share AccessOM3::cmeps AccessOM3::nuopc_cap_share FoX::FoX PIO::PIO_Fortran 10 | ) 11 | target_sources(OM3_cdeps_common PRIVATE 12 | CDEPS/streams/dshr_methods_mod.F90 13 | CDEPS/streams/dshr_strdata_mod.F90 14 | CDEPS/streams/dshr_stream_mod.F90 15 | CDEPS/streams/dshr_tinterp_mod.F90 16 | 17 | CDEPS/dshr/dshr_mod.F90 18 | CDEPS/dshr/dshr_dfield_mod.F90 19 | CDEPS/dshr/dshr_fldlist_mod.F90 20 | ) 21 | 22 | ## DATM 23 | add_fortran_library(OM3_cdeps_datm mod/datm STATIC) 24 | add_library(AccessOM3::cdeps_datm ALIAS OM3_cdeps_datm) 25 | target_include_directories(OM3_cdeps_datm PRIVATE $) 26 | target_link_libraries(OM3_cdeps_datm 27 | PUBLIC esmf 28 | PRIVATE AccessOM3::cdeps_common AccessOM3::share 29 | ) 30 | target_sources(OM3_cdeps_datm PRIVATE 31 | CDEPS/datm/datm_datamode_cfsr_mod.F90 32 | CDEPS/datm/datm_datamode_clmncep_mod.F90 33 | CDEPS/datm/datm_datamode_core2_mod.F90 34 | CDEPS/datm/datm_datamode_cplhist_mod.F90 35 | CDEPS/datm/datm_datamode_era5_mod.F90 36 | CDEPS/datm/datm_datamode_gefs_mod.F90 37 | CDEPS/datm/datm_datamode_jra_mod.F90 38 | CDEPS/datm/datm_datamode_simple_mod.F90 39 | extra_sources/datm_datamode_jra55do_mod.F90 40 | ) 41 | add_patched_source(OM3_cdeps_datm CDEPS/datm/atm_comp_nuopc.F90) 42 | 43 | ## DOCN 44 | add_fortran_library(OM3_cdeps_docn mod/docn STATIC) 45 | add_library(AccessOM3::cdeps_docn ALIAS OM3_cdeps_docn) 46 | target_include_directories(OM3_cdeps_docn PRIVATE $) 47 | target_link_libraries(OM3_cdeps_docn 48 | PUBLIC esmf 49 | PRIVATE AccessOM3::cdeps_common AccessOM3::share 50 | ) 51 | target_sources(OM3_cdeps_docn PRIVATE 52 | CDEPS/docn/docn_datamode_aquaplanet_mod.F90 53 | CDEPS/docn/docn_datamode_copyall_mod.F90 54 | CDEPS/docn/docn_datamode_cplhist_mod.F90 55 | CDEPS/docn/docn_datamode_multilev_mod.F90 56 | CDEPS/docn/docn_datamode_multilev_dom_mod.F90 57 | CDEPS/docn/docn_datamode_iaf_mod.F90 58 | CDEPS/docn/docn_datamode_som_mod.F90 59 | CDEPS/docn/docn_import_data_mod.F90 60 | CDEPS/docn/ocn_comp_nuopc.F90 61 | ) 62 | 63 | ## DICE 64 | add_fortran_library(OM3_cdeps_dice mod/dice STATIC) 65 | add_library(AccessOM3::cdeps_dice ALIAS OM3_cdeps_dice) 66 | target_include_directories(OM3_cdeps_dice PRIVATE $) 67 | target_link_libraries(OM3_cdeps_dice 68 | PUBLIC esmf 69 | PRIVATE AccessOM3::cdeps_common AccessOM3::share 70 | ) 71 | target_sources(OM3_cdeps_dice PRIVATE 72 | CDEPS/dice/dice_datamode_ssmi_mod.F90 73 | CDEPS/dice/dice_flux_atmice_mod.F90 74 | CDEPS/dice/ice_comp_nuopc.F90 75 | ) 76 | 77 | ## DWAV 78 | add_fortran_library(OM3_cdeps_dwav mod/dwav STATIC) 79 | add_library(AccessOM3::cdeps_dwav ALIAS OM3_cdeps_dwav) 80 | target_include_directories(OM3_cdeps_dwav PRIVATE $) 81 | target_link_libraries(OM3_cdeps_dwav 82 | PUBLIC esmf 83 | PRIVATE AccessOM3::cdeps_common AccessOM3::share 84 | ) 85 | target_sources(OM3_cdeps_dwav PRIVATE 86 | CDEPS/dwav/wav_comp_nuopc.F90 87 | ) 88 | 89 | ## DROF 90 | add_fortran_library(OM3_cdeps_drof mod/drof STATIC) 91 | add_library(AccessOM3::cdeps_drof ALIAS OM3_cdeps_drof) 92 | target_include_directories(OM3_cdeps_drof PRIVATE $) 93 | target_link_libraries(OM3_cdeps_drof 94 | PUBLIC esmf 95 | PRIVATE AccessOM3::cdeps_common AccessOM3::share 96 | ) 97 | target_sources(OM3_cdeps_drof PRIVATE 98 | CDEPS/drof/rof_comp_nuopc.F90 99 | ) 100 | 101 | ### Install and Export 102 | 103 | ## Library 104 | if(OM3_LIB_INSTALL) 105 | # cdeps_common 106 | set_target_properties(OM3_cdeps_common PROPERTIES 107 | OUTPUT_NAME access-cdeps-common 108 | EXPORT_NAME cdeps-common 109 | ) 110 | install(TARGETS OM3_cdeps_common 111 | EXPORT AccessOM3cdeps_Targets 112 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_RunTime NAMELINK_COMPONENT AccessOM3_Development 113 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_Development 114 | ) 115 | # components 116 | foreach(LIB atm ocn ice wav rof) 117 | set_target_properties(OM3_cdeps_d${LIB} PROPERTIES 118 | OUTPUT_NAME access-cdeps-d${LIB} 119 | EXPORT_NAME cdeps-d${LIB} 120 | ) 121 | install(TARGETS OM3_cdeps_d${LIB} 122 | EXPORT AccessOM3cdeps_Targets 123 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_RunTime NAMELINK_COMPONENT AccessOM3_Development 124 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_Development 125 | ) 126 | # Fortran module files are a special case, as currently there is no standard 127 | # way of handling them in CMake 128 | target_include_directories(OM3_cdeps_d${LIB} PUBLIC "$") 129 | get_target_property(d${LIB}_moddir OM3_cdeps_d${LIB} Fortran_MODULE_DIRECTORY) 130 | install(FILES ${d${LIB}_moddir}/${LIB}_comp_nuopc.mod 131 | DESTINATION ${CMAKE_INSTALL_MODULEDIR}/access-cdeps-d${LIB} 132 | COMPONENT AccessOM3_Development 133 | ) 134 | endforeach() 135 | install(EXPORT AccessOM3cdeps_Targets 136 | FILE AccessOM3cdepsTargets.cmake 137 | NAMESPACE AccessOM3:: 138 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AccessOM3 139 | ) 140 | endif() 141 | -------------------------------------------------------------------------------- /CDEPS/extra_sources/datm_datamode_jra55do_mod.F90: -------------------------------------------------------------------------------- 1 | module datm_datamode_jra55do_mod 2 | 3 | use ESMF , only : ESMF_State, ESMF_StateGet, ESMF_SUCCESS, ESMF_LogWrite, ESMF_LOGMSG_INFO 4 | use ESMF , only : ESMF_MeshGet 5 | use ESMF , only : ESMF_StateItem_Flag, ESMF_STATEITEM_NOTFOUND, operator(/=) 6 | use NUOPC , only : NUOPC_Advertise 7 | use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs 8 | use shr_sys_mod , only : shr_sys_abort 9 | use shr_cal_mod , only : shr_cal_date2julian 10 | use shr_const_mod , only : shr_const_tkfrz, shr_const_pi, shr_const_rdair 11 | use dshr_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_type 12 | use dshr_methods_mod , only : dshr_state_getfldptr, dshr_fldbun_getfldptr, dshr_fldbun_regrid, chkerr 13 | use dshr_strdata_mod , only : shr_strdata_type 14 | use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add 15 | 16 | implicit none 17 | private ! except 18 | 19 | public :: datm_datamode_jra55do_advertise 20 | public :: datm_datamode_jra55do_init_pointers 21 | public :: datm_datamode_jra55do_advance 22 | 23 | 24 | ! export state pointers 25 | real(r8), pointer :: Sa_z(:) => null() 26 | real(r8), pointer :: Sa_tbot(:) => null() 27 | real(r8), pointer :: Sa_ptem(:) => null() 28 | real(r8), pointer :: Sa_shum(:) => null() 29 | real(r8), pointer :: Sa_dens(:) => null() 30 | real(r8), pointer :: Sa_pbot(:) => null() 31 | real(r8), pointer :: Sa_pslv(:) => null() 32 | real(r8), pointer :: Faxa_rainc(:) => null() 33 | real(r8), pointer :: Faxa_rainl(:) => null() 34 | real(r8), pointer :: Faxa_snowc(:) => null() 35 | real(r8), pointer :: Faxa_snowl(:) => null() 36 | real(r8), pointer :: Faxa_swndr(:) => null() 37 | real(r8), pointer :: Faxa_swndf(:) => null() 38 | real(r8), pointer :: Faxa_swvdr(:) => null() 39 | real(r8), pointer :: Faxa_swvdf(:) => null() 40 | real(r8), pointer :: Faxa_swnet(:) => null() 41 | real(r8), pointer :: Faxa_ndep(:,:) => null() 42 | 43 | ! stream data 44 | real(r8), pointer :: strm_prrn(:) => null() ! Rainfall flux 45 | real(r8), pointer :: strm_prsn(:) => null() ! Snowfall flux 46 | real(r8), pointer :: strm_swdn(:) => null() 47 | 48 | ! othe module arrays 49 | real(R8), pointer :: yc(:) ! array of model latitudes 50 | 51 | ! constants 52 | real(R8) , parameter :: tKFrz = SHR_CONST_TKFRZ 53 | real(R8) , parameter :: rdair = SHR_CONST_RDAIR ! dry air gas constant ~ J/K/kg 54 | real(R8) , parameter :: degtorad = SHR_CONST_PI/180.0_R8 55 | real(R8) , parameter :: phs_c0 = 0.298_R8 56 | real(R8) , parameter :: dLWarc = -5.000_R8 57 | 58 | character(*), parameter :: nullstr = 'null' 59 | character(*), parameter :: rpfile = 'rpointer.atm' 60 | character(*), parameter :: u_FILE_u = & 61 | __FILE__ 62 | 63 | !=============================================================================== 64 | contains 65 | !=============================================================================== 66 | 67 | subroutine datm_datamode_jra55do_advertise(exportState, fldsexport, flds_scalar_name, & 68 | flds_co2, flds_wiso, flds_presaero, flds_presndep, rc) 69 | 70 | ! input/output variables 71 | type(esmf_State) , intent(inout) :: exportState 72 | type(fldlist_type) , pointer :: fldsexport 73 | character(len=*) , intent(in) :: flds_scalar_name 74 | logical , intent(in) :: flds_co2 75 | logical , intent(in) :: flds_wiso 76 | logical , intent(in) :: flds_presaero 77 | logical , intent(in) :: flds_presndep 78 | integer , intent(out) :: rc 79 | 80 | ! local variables 81 | type(fldlist_type), pointer :: fldList 82 | !------------------------------------------------------------------------------- 83 | 84 | rc = ESMF_SUCCESS 85 | 86 | call dshr_fldList_add(fldsExport, trim(flds_scalar_name)) 87 | call dshr_fldList_add(fldsExport, 'Sa_z' ) 88 | call dshr_fldList_add(fldsExport, 'Sa_u' ) 89 | call dshr_fldList_add(fldsExport, 'Sa_v' ) 90 | call dshr_fldList_add(fldsExport, 'Sa_ptem' ) 91 | call dshr_fldList_add(fldsExport, 'Sa_dens' ) 92 | call dshr_fldList_add(fldsExport, 'Sa_pslv' ) 93 | call dshr_fldList_add(fldsExport, 'Sa_tbot' ) 94 | call dshr_fldList_add(fldsExport, 'Sa_pbot' ) 95 | call dshr_fldList_add(fldsExport, 'Sa_shum' ) 96 | call dshr_fldList_add(fldsExport, 'Faxa_rainc' ) 97 | call dshr_fldList_add(fldsExport, 'Faxa_rainl' ) 98 | call dshr_fldList_add(fldsExport, 'Faxa_snowc' ) 99 | call dshr_fldList_add(fldsExport, 'Faxa_snowl' ) 100 | call dshr_fldList_add(fldsExport, 'Faxa_swndr' ) 101 | call dshr_fldList_add(fldsExport, 'Faxa_swvdr' ) 102 | call dshr_fldList_add(fldsExport, 'Faxa_swndf' ) 103 | call dshr_fldList_add(fldsExport, 'Faxa_swvdf' ) 104 | call dshr_fldList_add(fldsExport, 'Faxa_swnet' ) 105 | call dshr_fldList_add(fldsExport, 'Faxa_lwdn' ) 106 | call dshr_fldList_add(fldsExport, 'Faxa_swdn' ) 107 | 108 | if (flds_co2) then 109 | call dshr_fldList_add(fldsExport, 'Sa_co2prog') 110 | call dshr_fldList_add(fldsExport, 'Sa_co2diag') 111 | end if 112 | if (flds_presaero) then 113 | call dshr_fldList_add(fldsExport, 'Faxa_bcph' , ungridded_lbound=1, ungridded_ubound=3) 114 | call dshr_fldList_add(fldsExport, 'Faxa_ocph' , ungridded_lbound=1, ungridded_ubound=3) 115 | call dshr_fldList_add(fldsExport, 'Faxa_dstwet' , ungridded_lbound=1, ungridded_ubound=4) 116 | call dshr_fldList_add(fldsExport, 'Faxa_dstdry' , ungridded_lbound=1, ungridded_ubound=4) 117 | end if 118 | if (flds_presndep) then 119 | call dshr_fldList_add(fldsExport, 'Faxa_ndep', ungridded_lbound=1, ungridded_ubound=2) 120 | end if 121 | if (flds_wiso) then 122 | call dshr_fldList_add(fldsExport, 'Faxa_rainc_wiso', ungridded_lbound=1, ungridded_ubound=3) 123 | call dshr_fldList_add(fldsExport, 'Faxa_rainl_wiso', ungridded_lbound=1, ungridded_ubound=3) 124 | call dshr_fldList_add(fldsExport, 'Faxa_snowc_wiso', ungridded_lbound=1, ungridded_ubound=3) 125 | call dshr_fldList_add(fldsExport, 'Faxa_snowl_wiso', ungridded_lbound=1, ungridded_ubound=3) 126 | call dshr_fldList_add(fldsExport, 'Faxa_shum_wiso' , ungridded_lbound=1, ungridded_ubound=3) 127 | end if 128 | 129 | fldlist => fldsExport ! the head of the linked list 130 | do while (associated(fldlist)) 131 | call NUOPC_Advertise(exportState, standardName=fldlist%stdname, rc=rc) 132 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 133 | call ESMF_LogWrite('(datm_comp_advertise): Fr_atm'//trim(fldList%stdname), ESMF_LOGMSG_INFO) 134 | fldList => fldList%next 135 | enddo 136 | 137 | end subroutine datm_datamode_jra55do_advertise 138 | 139 | !=============================================================================== 140 | subroutine datm_datamode_jra55do_init_pointers(exportState, sdat, rc) 141 | 142 | ! input/output variables 143 | type(ESMF_State) , intent(inout) :: exportState 144 | type(shr_strdata_type) , intent(in) :: sdat 145 | integer , intent(out) :: rc 146 | 147 | ! local variables 148 | integer :: n 149 | integer :: lsize 150 | integer :: spatialDim ! number of dimension in mesh 151 | integer :: numOwnedElements ! size of mesh 152 | real(r8), pointer :: ownedElemCoords(:) ! mesh lat and lons 153 | type(ESMF_StateItem_Flag) :: itemFlag 154 | character(len=*), parameter :: subname='(datm_datamode_jra55do_init_pointers): ' 155 | !------------------------------------------------------------------------------- 156 | 157 | rc = ESMF_SUCCESS 158 | 159 | lsize = sdat%model_lsize 160 | 161 | call ESMF_MeshGet(sdat%model_mesh, spatialDim=spatialDim, numOwnedElements=numOwnedElements, rc=rc) 162 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 163 | allocate(ownedElemCoords(spatialDim*numOwnedElements)) 164 | allocate(yc(numOwnedElements)) 165 | call ESMF_MeshGet(sdat%model_mesh, ownedElemCoords=ownedElemCoords) 166 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 167 | do n = 1,numOwnedElements 168 | yc(n) = ownedElemCoords(2*n) 169 | end do 170 | 171 | call shr_strdata_get_stream_pointer( sdat, 'Faxa_prrn' , strm_prrn , rc) 172 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 173 | call shr_strdata_get_stream_pointer( sdat, 'Faxa_prsn' , strm_prsn , rc) 174 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 175 | call shr_strdata_get_stream_pointer( sdat, 'Faxa_swdn' , strm_swdn , rc) 176 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 177 | 178 | call dshr_state_getfldptr(exportState, 'Sa_z' , fldptr1=Sa_z , rc=rc) 179 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 180 | call dshr_state_getfldptr(exportState, 'Sa_tbot' , fldptr1=Sa_tbot , rc=rc) 181 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 182 | call dshr_state_getfldptr(exportState, 'Sa_pbot' , fldptr1=Sa_pbot , rc=rc) 183 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 184 | call dshr_state_getfldptr(exportState, 'Sa_pslv' , fldptr1=Sa_pslv , rc=rc) 185 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 186 | call dshr_state_getfldptr(exportState, 'Sa_ptem' , fldptr1=Sa_ptem , rc=rc) 187 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 188 | call dshr_state_getfldptr(exportState, 'Sa_shum' , fldptr1=Sa_shum , rc=rc) 189 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 190 | call dshr_state_getfldptr(exportState, 'Sa_dens' , fldptr1=Sa_dens , rc=rc) 191 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 192 | call dshr_state_getfldptr(exportState, 'Faxa_rainc' , fldptr1=Faxa_rainc , rc=rc) 193 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 194 | call dshr_state_getfldptr(exportState, 'Faxa_rainl' , fldptr1=Faxa_rainl , rc=rc) 195 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 196 | call dshr_state_getfldptr(exportState, 'Faxa_snowc' , fldptr1=Faxa_snowc , rc=rc) 197 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 198 | call dshr_state_getfldptr(exportState, 'Faxa_snowl' , fldptr1=Faxa_snowl , rc=rc) 199 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 200 | call dshr_state_getfldptr(exportState, 'Faxa_swvdr' , fldptr1=Faxa_swvdr , rc=rc) 201 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 202 | call dshr_state_getfldptr(exportState, 'Faxa_swvdf' , fldptr1=Faxa_swvdf , rc=rc) 203 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 204 | call dshr_state_getfldptr(exportState, 'Faxa_swndr' , fldptr1=Faxa_swndr , rc=rc) 205 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 206 | call dshr_state_getfldptr(exportState, 'Faxa_swndf' , fldptr1=Faxa_swndf , rc=rc) 207 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 208 | call dshr_state_getfldptr(exportState, 'Faxa_swnet' , fldptr1=Faxa_swnet , rc=rc) 209 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 210 | 211 | call ESMF_StateGet(exportState, 'Faxa_ndep', itemFlag, rc=rc) 212 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 213 | if (itemflag /= ESMF_STATEITEM_NOTFOUND) then 214 | call dshr_state_getfldptr(exportState, 'Faxa_ndep', fldptr2=Faxa_ndep, rc=rc) 215 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 216 | end if 217 | 218 | ! erro check 219 | if (.not. associated(strm_prrn) .or. .not. associated(strm_prsn) .or. .not. associated(strm_swdn)) then 220 | call shr_sys_abort(trim(subname)//'ERROR: prrn, prsn and swdn must be in streams for JRA55-do') 221 | endif 222 | 223 | end subroutine datm_datamode_jra55do_init_pointers 224 | 225 | !=============================================================================== 226 | subroutine datm_datamode_jra55do_advance(exportstate, target_ymd, target_tod, model_calendar, rc) 227 | 228 | ! input/output variables 229 | type(ESMF_State) , intent(inout) :: exportState 230 | integer , intent(in) :: target_ymd 231 | integer , intent(in) :: target_tod 232 | character(len=*) , intent(in) :: model_calendar 233 | integer , intent(out) :: rc 234 | 235 | ! local variables 236 | integer :: n 237 | integer :: lsize 238 | real(R8) :: avg_alb ! average albedo 239 | real(R8) :: rday ! elapsed day 240 | real(R8) :: cosFactor ! cosine factor 241 | character(len=*), parameter :: subname='(datm_datamode_jra55do_advance): ' 242 | !------------------------------------------------------------------------------- 243 | 244 | rc = ESMF_SUCCESS 245 | 246 | lsize = size(Sa_z) 247 | 248 | call shr_cal_date2julian(target_ymd, target_tod, rday, model_calendar) 249 | rday = mod((rday - 1.0_R8),365.0_R8) 250 | cosfactor = cos((2.0_R8*SHR_CONST_PI*rday)/365 - phs_c0) 251 | 252 | do n = 1,lsize 253 | Sa_z(n) = 10.0_R8 254 | Sa_pbot(n) = Sa_pslv(n) 255 | Sa_ptem(n) = Sa_tbot(n) 256 | 257 | ! density computation for JRA55-do forcing 258 | Sa_dens(n) = Sa_pbot(n)/(rdair*Sa_tbot(n)*(1 + 0.608*Sa_shum(n))) 259 | 260 | ! precipitation data 261 | Faxa_rainc(n) = 0.0_R8 ! default zero 262 | Faxa_snowc(n) = 0.0_R8 263 | Faxa_snowl(n) = strm_prsn(n) ! Snowfall flux 264 | Faxa_rainl(n) = strm_prrn(n) ! Rainfall flux 265 | 266 | ! radiation data - fabricate required swdn components from net swdn 267 | Faxa_swvdr(n) = strm_swdn(n)*(0.28_R8) 268 | Faxa_swndr(n) = strm_swdn(n)*(0.31_R8) 269 | Faxa_swvdf(n) = strm_swdn(n)*(0.24_R8) 270 | Faxa_swndf(n) = strm_swdn(n)*(0.17_R8) 271 | 272 | ! radiation data - compute net short-wave based on LY08 latitudinally-varying albedo 273 | avg_alb = ( 0.069 - 0.011*cos(2.0_R8*yc(n)*degtorad ) ) 274 | Faxa_swnet(n) = strm_swdn(n)*(1.0_R8 - avg_alb) 275 | enddo ! lsize 276 | 277 | if (associated(Faxa_ndep)) then 278 | ! convert ndep flux to units of kgN/m2/s (input is in gN/m2/s) 279 | Faxa_ndep(:,:) = Faxa_ndep(:,:) / 1000._r8 280 | end if 281 | 282 | end subroutine datm_datamode_jra55do_advance 283 | 284 | end module datm_datamode_jra55do_mod 285 | -------------------------------------------------------------------------------- /CDEPS/patches/atm_comp_nuopc.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/datm/atm_comp_nuopc.F90 b/datm/atm_comp_nuopc.F90 2 | index b74e0d3..bb31c22 100644 3 | --- a/datm/atm_comp_nuopc.F90 4 | +++ b/datm/atm_comp_nuopc.F90 5 | @@ -48,6 +48,10 @@ module cdeps_datm_comp 6 | use datm_datamode_jra_mod , only : datm_datamode_jra_init_pointers 7 | use datm_datamode_jra_mod , only : datm_datamode_jra_advance 8 | 9 | + use datm_datamode_jra55do_mod , only : datm_datamode_jra55do_advertise 10 | + use datm_datamode_jra55do_mod , only : datm_datamode_jra55do_init_pointers 11 | + use datm_datamode_jra55do_mod , only : datm_datamode_jra55do_advance 12 | + 13 | use datm_datamode_clmncep_mod , only : datm_datamode_clmncep_advertise 14 | use datm_datamode_clmncep_mod , only : datm_datamode_clmncep_init_pointers 15 | use datm_datamode_clmncep_mod , only : datm_datamode_clmncep_advance 16 | @@ -357,6 +361,7 @@ contains 17 | if ( trim(datamode) == 'CORE2_NYF' .or. & 18 | trim(datamode) == 'CORE2_IAF' .or. & 19 | trim(datamode) == 'CORE_IAF_JRA' .or. & 20 | + trim(datamode) == 'JRA55do' .or. & 21 | trim(datamode) == 'CLMNCEP' .or. & 22 | trim(datamode) == 'CPLHIST' .or. & 23 | trim(datamode) == 'GEFS' .or. & 24 | @@ -377,6 +382,10 @@ contains 25 | call datm_datamode_jra_advertise(exportState, fldsExport, flds_scalar_name, & 26 | flds_co2, flds_wiso, flds_presaero, flds_presndep, rc) 27 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 28 | + case ('JRA55do') 29 | + call datm_datamode_jra55do_advertise(exportState, fldsExport, flds_scalar_name, & 30 | + flds_co2, flds_wiso, flds_presaero, flds_presndep, rc) 31 | + if (ChkErr(rc,__LINE__,u_FILE_u)) return 32 | case ('CLMNCEP') 33 | call datm_datamode_clmncep_advertise(exportState, fldsExport, flds_scalar_name, & 34 | flds_co2, flds_wiso, flds_presaero, flds_presndep, flds_preso3, rc) 35 | @@ -627,6 +636,9 @@ contains 36 | case('CORE_IAF_JRA') 37 | call datm_datamode_jra_init_pointers(exportState, sdat, rc) 38 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 39 | + case('JRA55do') 40 | + call datm_datamode_jra55do_init_pointers(exportState, sdat, rc) 41 | + if (ChkErr(rc,__LINE__,u_FILE_u)) return 42 | case('CLMNCEP') 43 | call datm_datamode_clmncep_init_pointers(importState, exportState, sdat, rc) 44 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 45 | @@ -652,7 +664,7 @@ contains 46 | call shr_get_rpointer_name(gcomp, 'atm', target_ymd, target_tod, rpfile, 'read', rc) 47 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 48 | select case (trim(datamode)) 49 | - case('CORE2_NYF','CORE2_IAF','CORE_IAF_JRA','CLMNCEP','CPLHIST','ERA5','GEFS','CFSR','SIMPLE') 50 | + case('CORE2_NYF','CORE2_IAF','CORE_IAF_JRA','JRA55do','CLMNCEP','CPLHIST','ERA5','GEFS','CFSR','SIMPLE') 51 | call dshr_restart_read(restfilm, rpfile, logunit, my_task, mpicom, sdat, rc) 52 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 53 | case default 54 | @@ -694,6 +706,9 @@ contains 55 | case('CORE_IAF_JRA') 56 | call datm_datamode_jra_advance(exportstate, target_ymd, target_tod, sdat%model_calendar, rc) 57 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 58 | + case('JRA55do') 59 | + call datm_datamode_jra55do_advance(exportstate, target_ymd, target_tod, sdat%model_calendar, rc) 60 | + if (ChkErr(rc,__LINE__,u_FILE_u)) return 61 | case('CLMNCEP') 62 | call datm_datamode_clmncep_advance(mainproc, logunit, mpicom, rc) 63 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 64 | @@ -722,7 +737,7 @@ contains 65 | call shr_get_rpointer_name(gcomp, 'atm', target_ymd, target_tod, rpfile, 'write', rc) 66 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 67 | select case (trim(datamode)) 68 | - case('CORE2_NYF','CORE2_IAF','CORE_IAF_JRA','CLMNCEP','CPLHIST','ERA5','GEFS','CFSR','SIMPLE') 69 | + case('CORE2_NYF','CORE2_IAF','CORE_IAF_JRA','JRA55do','CLMNCEP','CPLHIST','ERA5','GEFS','CFSR','SIMPLE') 70 | call dshr_restart_write(rpfile, case_name, 'datm', inst_suffix, target_ymd, target_tod, logunit, & 71 | my_task, sdat, rc) 72 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 73 | -------------------------------------------------------------------------------- /CICE/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ### Targets 2 | 3 | ## CICE library 4 | add_fortran_library(OM3_cice mod STATIC) 5 | add_library(AccessOM3::cice ALIAS OM3_cice) 6 | target_compile_definitions(OM3_cice PRIVATE FORTRANUNDERSCORE ncdf) 7 | if(OM3_CICE_IO MATCHES "^(NetCDF|PIO)$") 8 | target_compile_definitions(OM3_cice PRIVATE USE_NETCDF) 9 | endif() 10 | target_link_libraries(OM3_cice 11 | PUBLIC esmf 12 | PRIVATE AccessOM3::cdeps_common AccessOM3::nuopc_cap_share AccessOM3::share AccessOM3::timing 13 | ) 14 | if(OM3_CICE_IO MATCHES "^(NetCDF|PIO)$") 15 | target_link_libraries(OM3_cice PRIVATE NetCDF::NetCDF_Fortran) 16 | if(OM3_CICE_IO MATCHES "PIO") 17 | target_link_libraries(OM3_cice PRIVATE PIO::PIO_Fortran) 18 | endif() 19 | endif() 20 | if(OpenMP_Fortran_FOUND) 21 | target_link_libraries(OM3_cice PRIVATE OpenMP::OpenMP_Fortran) 22 | endif() 23 | 24 | target_sources(OM3_cice PRIVATE 25 | # Shared List: 26 | CICE/cicecore/shared/ice_arrays_column.F90 27 | CICE/cicecore/shared/ice_calendar.F90 28 | CICE/cicecore/shared/ice_constants.F90 29 | CICE/cicecore/shared/ice_distribution.F90 30 | CICE/cicecore/shared/ice_domain_size.F90 31 | CICE/cicecore/shared/ice_fileunits.F90 32 | CICE/cicecore/shared/ice_init_column.F90 33 | CICE/cicecore/shared/ice_kinds_mod.F90 34 | CICE/cicecore/shared/ice_restart_column.F90 35 | CICE/cicecore/shared/ice_restart_shared.F90 36 | CICE/cicecore/shared/ice_spacecurve.F90 37 | 38 | # Analysis 39 | CICE/cicecore/cicedyn/analysis/ice_diagnostics.F90 40 | CICE/cicecore/cicedyn/analysis/ice_diagnostics_bgc.F90 41 | CICE/cicecore/cicedyn/analysis/ice_history.F90 42 | CICE/cicecore/cicedyn/analysis/ice_history_bgc.F90 43 | CICE/cicecore/cicedyn/analysis/ice_history_drag.F90 44 | CICE/cicecore/cicedyn/analysis/ice_history_fsd.F90 45 | CICE/cicecore/cicedyn/analysis/ice_history_mechred.F90 46 | CICE/cicecore/cicedyn/analysis/ice_history_pond.F90 47 | CICE/cicecore/cicedyn/analysis/ice_history_shared.F90 48 | CICE/cicecore/cicedyn/analysis/ice_history_snow.F90 49 | 50 | # Dynamics 51 | CICE/cicecore/cicedyn/dynamics/ice_dyn_core1d.F90 52 | CICE/cicecore/cicedyn/dynamics/ice_dyn_eap.F90 53 | CICE/cicecore/cicedyn/dynamics/ice_dyn_evp.F90 54 | CICE/cicecore/cicedyn/dynamics/ice_dyn_evp1d.F90 55 | CICE/cicecore/cicedyn/dynamics/ice_dyn_shared.F90 56 | CICE/cicecore/cicedyn/dynamics/ice_dyn_vp.F90 57 | CICE/cicecore/cicedyn/dynamics/ice_transport_driver.F90 58 | CICE/cicecore/cicedyn/dynamics/ice_transport_remap.F90 59 | 60 | # General 61 | CICE/cicecore/cicedyn/general/ice_flux.F90 62 | CICE/cicecore/cicedyn/general/ice_flux_bgc.F90 63 | CICE/cicecore/cicedyn/general/ice_forcing.F90 64 | CICE/cicecore/cicedyn/general/ice_forcing_bgc.F90 65 | CICE/cicecore/cicedyn/general/ice_init.F90 66 | CICE/cicecore/cicedyn/general/ice_state.F90 67 | CICE/cicecore/cicedyn/general/ice_step_mod.F90 68 | 69 | # Infrastructure 70 | CICE/cicecore/cicedyn/infrastructure/ice_blocks.F90 71 | CICE/cicecore/cicedyn/infrastructure/ice_domain.F90 72 | CICE/cicecore/cicedyn/infrastructure/ice_grid.F90 73 | CICE/cicecore/cicedyn/infrastructure/ice_memusage.F90 74 | CICE/cicecore/cicedyn/infrastructure/ice_memusage_gptl.c 75 | CICE/cicecore/cicedyn/infrastructure/ice_read_write.F90 76 | CICE/cicecore/cicedyn/infrastructure/ice_restart_driver.F90 77 | CICE/cicecore/cicedyn/infrastructure/ice_restoring.F90 78 | 79 | # Icepack 80 | CICE/icepack/columnphysics/icepack_aerosol.F90 81 | CICE/icepack/columnphysics/icepack_age.F90 82 | CICE/icepack/columnphysics/icepack_algae.F90 83 | CICE/icepack/columnphysics/icepack_atmo.F90 84 | CICE/icepack/columnphysics/icepack_brine.F90 85 | CICE/icepack/columnphysics/icepack_firstyear.F90 86 | CICE/icepack/columnphysics/icepack_flux.F90 87 | CICE/icepack/columnphysics/icepack_fsd.F90 88 | CICE/icepack/columnphysics/icepack_intfc.F90 89 | CICE/icepack/columnphysics/icepack_isotope.F90 90 | CICE/icepack/columnphysics/icepack_itd.F90 91 | CICE/icepack/columnphysics/icepack_kinds.F90 92 | CICE/icepack/columnphysics/icepack_mechred.F90 93 | CICE/icepack/columnphysics/icepack_meltpond_lvl.F90 94 | CICE/icepack/columnphysics/icepack_meltpond_topo.F90 95 | CICE/icepack/columnphysics/icepack_mushy_physics.F90 96 | CICE/icepack/columnphysics/icepack_ocean.F90 97 | CICE/icepack/columnphysics/icepack_orbital.F90 98 | CICE/icepack/columnphysics/icepack_parameters.F90 99 | CICE/icepack/columnphysics/icepack_shortwave_data.F90 100 | CICE/icepack/columnphysics/icepack_shortwave.F90 101 | CICE/icepack/columnphysics/icepack_snow.F90 102 | CICE/icepack/columnphysics/icepack_therm_bl99.F90 103 | CICE/icepack/columnphysics/icepack_therm_itd.F90 104 | CICE/icepack/columnphysics/icepack_therm_mushy.F90 105 | CICE/icepack/columnphysics/icepack_therm_shared.F90 106 | CICE/icepack/columnphysics/icepack_therm_vertical.F90 107 | CICE/icepack/columnphysics/icepack_tracers.F90 108 | CICE/icepack/columnphysics/icepack_warnings.F90 109 | CICE/icepack/columnphysics/icepack_wavefracspec.F90 110 | CICE/icepack/columnphysics/icepack_zbgc.F90 111 | CICE/icepack/columnphysics/icepack_zbgc_shared.F90 112 | 113 | # Shared C 114 | CICE/cicecore/cicedyn/infrastructure/ice_shr_reprosum86.c 115 | 116 | # MPI 117 | CICE/cicecore/cicedyn/infrastructure/comm/mpi/ice_boundary.F90 118 | CICE/cicecore/cicedyn/infrastructure/comm/mpi/ice_broadcast.F90 119 | CICE/cicecore/cicedyn/infrastructure/comm/mpi/ice_communicate.F90 120 | CICE/cicecore/cicedyn/infrastructure/comm/mpi/ice_exit.F90 121 | CICE/cicecore/cicedyn/infrastructure/comm/mpi/ice_gather_scatter.F90 122 | CICE/cicecore/cicedyn/infrastructure/comm/mpi/ice_global_reductions.F90 123 | CICE/cicecore/cicedyn/infrastructure/comm/mpi/ice_reprosum.F90 124 | CICE/cicecore/cicedyn/infrastructure/comm/mpi/ice_timers.F90 125 | 126 | # NUOPC CMEPS driver 127 | CICE/cicecore/drivers/nuopc/cmeps/CICE_FinalMod.F90 128 | CICE/cicecore/drivers/nuopc/cmeps/CICE_InitMod.F90 129 | CICE/cicecore/drivers/nuopc/cmeps/CICE_RunMod.F90 130 | CICE/cicecore/drivers/nuopc/cmeps/cice_wrapper_mod.F90 131 | CICE/cicecore/drivers/nuopc/cmeps/ice_comp_nuopc.F90 132 | CICE/cicecore/drivers/nuopc/cmeps/ice_import_export.F90 133 | CICE/cicecore/drivers/nuopc/cmeps/ice_mesh_mod.F90 134 | CICE/cicecore/drivers/nuopc/cmeps/ice_prescribed_mod.F90 135 | CICE/cicecore/drivers/nuopc/cmeps/ice_scam.F90 136 | CICE/cicecore/drivers/nuopc/cmeps/ice_shr_methods.F90 137 | ) 138 | 139 | # Select IO source files based on CICE_IO 140 | if(OM3_CICE_IO MATCHES "NetCDF") 141 | target_sources(OM3_cice PRIVATE 142 | CICE/cicecore/cicedyn/infrastructure/io/io_netcdf/ice_history_write.F90 143 | CICE/cicecore/cicedyn/infrastructure/io/io_netcdf/ice_restart.F90 144 | ) 145 | elseif(OM3_CICE_IO MATCHES "PIO") 146 | target_sources(OM3_cice PRIVATE 147 | CICE/cicecore/cicedyn/infrastructure/io/io_pio2/ice_history_write.F90 148 | CICE/cicecore/cicedyn/infrastructure/io/io_pio2/ice_pio.F90 149 | CICE/cicecore/cicedyn/infrastructure/io/io_pio2/ice_restart.F90 150 | ) 151 | elseif(OM3_CICE_IO MATCHES "Binary") 152 | target_sources(OM3_cice PRIVATE 153 | CICE/cicecore/cicedyn/infrastructure/io/io_binary/ice_history_write.F90 154 | CICE/cicecore/cicedyn/infrastructure/io/io_binary/ice_restart.F90 155 | ) 156 | endif() 157 | 158 | ### Install and Export 159 | 160 | ## Library 161 | if(OM3_LIB_INSTALL) 162 | set_target_properties(OM3_cice PROPERTIES 163 | OUTPUT_NAME access-cice 164 | EXPORT_NAME cice 165 | ) 166 | install(TARGETS OM3_cice 167 | EXPORT AccessOM3cice_Targets 168 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_RunTime NAMELINK_COMPONENT AccessOM3_Development 169 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_Development 170 | ) 171 | # Fortran module files are a special case, as currently there is no standard 172 | # way of handling them in CMake 173 | target_include_directories(OM3_cice PUBLIC "$") 174 | get_target_property(cice_moddir OM3_cice Fortran_MODULE_DIRECTORY) 175 | install(FILES ${cice_moddir}/ice_comp_nuopc.mod 176 | DESTINATION ${CMAKE_INSTALL_MODULEDIR}/access-cice 177 | COMPONENT AccessOM3_Development 178 | ) 179 | install(EXPORT AccessOM3cice_Targets 180 | FILE AccessOM3ciceTargets.cmake 181 | NAMESPACE AccessOM3:: 182 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AccessOM3 183 | ) 184 | 185 | endif() 186 | -------------------------------------------------------------------------------- /CMEPS/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ### Targets 2 | 3 | ## CMEPS library 4 | add_fortran_library(OM3_cmeps mod/cmeps STATIC) 5 | add_library(AccessOM3::cmeps ALIAS OM3_cmeps) 6 | target_link_libraries(OM3_cmeps 7 | PUBLIC esmf 8 | PRIVATE AccessOM3::nuopc_cap_share AccessOM3::share AccessOM3::timing 9 | ) 10 | if(OpenMP_Fortran_FOUND) 11 | target_link_libraries(OM3_cmeps PRIVATE OpenMP::OpenMP_Fortran) 12 | endif() 13 | target_sources(OM3_cmeps PRIVATE 14 | CMEPS/cesm/flux_atmocn/shr_flux_mod.F90 15 | CMEPS/mediator/med_phases_history_mod.F90 16 | CMEPS/mediator/med_phases_restart_mod.F90 17 | CMEPS/mediator/med_map_mod.F90 18 | CMEPS/mediator/med_methods_mod.F90 19 | CMEPS/mediator/med_phases_prep_ice_mod.F90 20 | CMEPS/mediator/med_phases_prep_glc_mod.F90 21 | CMEPS/mediator/med_internalstate_mod.F90 22 | CMEPS/mediator/med_phases_profile_mod.F90 23 | CMEPS/mediator/esmFldsExchange_hafs_mod.F90 24 | CMEPS/mediator/med_phases_prep_rof_mod.F90 25 | CMEPS/mediator/esmFldsExchange_cesm_mod.F90 26 | CMEPS/mediator/med_merge_mod.F90 27 | CMEPS/mediator/med_constants_mod.F90 28 | CMEPS/mediator/med_kind_mod.F90 29 | CMEPS/mediator/esmFldsExchange_ufs_mod.F90 30 | CMEPS/mediator/med_phases_prep_lnd_mod.F90 31 | CMEPS/mediator/med_phases_prep_atm_mod.F90 32 | CMEPS/mediator/med_phases_prep_ocn_mod.F90 33 | CMEPS/mediator/esmFlds.F90 34 | CMEPS/mediator/med.F90 35 | CMEPS/mediator/med_phases_ocnalb_mod.F90 36 | CMEPS/mediator/med_phases_prep_wav_mod.F90 37 | CMEPS/mediator/med_utils_mod.F90 38 | CMEPS/mediator/med_fraction_mod.F90 39 | CMEPS/mediator/med_phases_aofluxes_mod.F90 40 | CMEPS/mediator/med_io_mod.F90 41 | CMEPS/mediator/med_diag_mod.F90 42 | CMEPS/mediator/med_phases_post_atm_mod.F90 43 | CMEPS/mediator/med_phases_post_ice_mod.F90 44 | CMEPS/mediator/med_phases_post_ocn_mod.F90 45 | CMEPS/mediator/med_phases_post_lnd_mod.F90 46 | CMEPS/mediator/med_phases_post_glc_mod.F90 47 | CMEPS/mediator/med_phases_post_rof_mod.F90 48 | CMEPS/mediator/med_phases_post_wav_mod.F90 49 | ) 50 | 51 | ## NUOPC cap share 52 | add_fortran_library(OM3_nuopc_cap_share mod/nuopc_cap_share STATIC) 53 | add_library(AccessOM3::nuopc_cap_share ALIAS OM3_nuopc_cap_share) 54 | target_link_libraries(OM3_nuopc_cap_share 55 | PUBLIC esmf 56 | PRIVATE AccessOM3::share 57 | ) 58 | target_sources(OM3_nuopc_cap_share PRIVATE 59 | CMEPS/cesm/nuopc_cap_share/driver_pio_mod.F90 60 | CMEPS/cesm/nuopc_cap_share/esm_utils_mod.F90 61 | CMEPS/cesm/nuopc_cap_share/glc_elevclass_mod.F90 62 | ) 63 | 64 | 65 | ### Install and Export 66 | 67 | if(OM3_LIB_INSTALL) 68 | ## CMEPS library 69 | set_target_properties(OM3_cmeps PROPERTIES 70 | OUTPUT_NAME access-cmeps 71 | EXPORT_NAME cmeps 72 | ) 73 | install(TARGETS OM3_cmeps 74 | EXPORT AccessOM3cmeps_Targets 75 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_RunTime NAMELINK_COMPONENT AccessOM3_Development 76 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_Development 77 | ) 78 | # Fortran module files are a special case, as currently there is no standard 79 | # way of handling them in CMake 80 | target_include_directories(OM3_cmeps PUBLIC "$") 81 | get_target_property(cmeps_moddir OM3_cmeps Fortran_MODULE_DIRECTORY) 82 | install(FILES ${cmeps_moddir}/med.mod ${cmeps_moddir}/med_internalstate_mod.mod 83 | DESTINATION ${CMAKE_INSTALL_MODULEDIR}/access-cmeps 84 | COMPONENT AccessOM3_Development 85 | ) 86 | install(EXPORT AccessOM3cmeps_Targets 87 | FILE AccessOM3cmepsTargets.cmake 88 | NAMESPACE AccessOM3:: 89 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AccessOM3 90 | ) 91 | 92 | ## NUOPC cap share 93 | set_target_properties(OM3_nuopc_cap_share PROPERTIES 94 | OUTPUT_NAME access-nuopc_cap_share 95 | EXPORT_NAME nuopc_cap_share 96 | ) 97 | install(TARGETS OM3_nuopc_cap_share 98 | EXPORT AccessOM3nuopc_cap_share_Targets 99 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_RunTime NAMELINK_COMPONENT AccessOM3_Development 100 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_Development 101 | ) 102 | # Fortran module files are a special case, as currently there is no standard 103 | # way of handling them in CMake 104 | target_include_directories(OM3_nuopc_cap_share PUBLIC "$") 105 | get_target_property(nuopc_cap_share_moddir OM3_nuopc_cap_share Fortran_MODULE_DIRECTORY) 106 | install(DIRECTORY ${nuopc_cap_share_moddir}/ 107 | DESTINATION ${CMAKE_INSTALL_MODULEDIR}/access-nuopc_cap_share 108 | COMPONENT AccessOM3_Development 109 | ) 110 | install(EXPORT AccessOM3nuopc_cap_share_Targets 111 | FILE AccessOM3nuopc_cap_shareTargets.cmake 112 | NAMESPACE AccessOM3:: 113 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AccessOM3 114 | ) 115 | endif() 116 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.18) 2 | # CMake version compatibility 3 | 4 | #[==============================================================================[ 5 | # Basic project definition # 6 | #]==============================================================================] 7 | 8 | project(ACCESS-OM3 VERSION "0.2.0" 9 | HOMEPAGE_URL https://github.com/COSIMA/access-om3 10 | DESCRIPTION "Global coupled ocean - sea ice - wave model" 11 | LANGUAGES C Fortran) 12 | 13 | #[==============================================================================[ 14 | # Options # 15 | #]==============================================================================] 16 | 17 | # Configurations to build 18 | list(APPEND KnownConfigurations MOM6 CICE6 WW3 MOM6-CICE6 CICE6-WW3 MOM6-WW3 MOM6-CICE6-WW3) 19 | 20 | option(OM3_ENABLE_MOM6 "Build MOM6 configuration" OFF) 21 | option(OM3_ENABLE_CICE6 "Build CICE6 configuration" OFF) 22 | option(OM3_ENABLE_WW3 "Build WW3 configuration" OFF) 23 | option(OM3_ENABLE_MOM6-WW3 "Build MOM6-WW3 configuration" OFF) 24 | option(OM3_ENABLE_MOM6-CICE6 "Build MOM6-CICE6 configuration" ON) 25 | option(OM3_ENABLE_CICE6-WW3 "Build CICE6-WW3 configuration" ON) 26 | option(OM3_ENABLE_MOM6-CICE6-WW3 "Build MOM6-CICE6-WW3 configuration" ON) 27 | 28 | message(STATUS "Configurations") 29 | message(STATUS " - MOM6 ${OM3_ENABLE_MOM6}") 30 | message(STATUS " - CICE6 ${OM3_ENABLE_CICE6}") 31 | message(STATUS " - WW3 ${OM3_ENABLE_WW3}") 32 | message(STATUS " - MOM6-WW3 ${OM3_ENABLE_MOM6-WW3}") 33 | message(STATUS " - MOM6-CICE6 ${OM3_ENABLE_MOM6-CICE6}") 34 | message(STATUS " - CICE6-WW3 ${OM3_ENABLE_CICE6-WW3}") 35 | message(STATUS " - MOM6-CICE6-WW3 ${OM3_ENABLE_MOM6-CICE6-WW3}") 36 | 37 | # Build options 38 | option(OM3_BIN_INSTALL "Instal ACCESS-OM3 executables" ${PROJECT_IS_TOP_LEVEL}) 39 | option(OM3_LIB_INSTALL "Instal ACCESS-OM3 libraries" OFF) 40 | option(OM3_OPENMP "Enable OpenMP threading" OFF) 41 | option(OM3_MOM_SYMMETRIC "Use symmetric memory" OFF) 42 | set(OM3_CICE_IO "PIO" CACHE STRING "CICE OPTIONS: Choose IO options.") 43 | set_property(CACHE OM3_CICE_IO PROPERTY STRINGS "NetCDF" "PIO" "Binary") 44 | 45 | message(STATUS "Build options") 46 | message(STATUS " - OM3_BIN_INSTALL ${OM3_BIN_INSTALL}") 47 | message(STATUS " - OM3_LIB_INSTALL ${OM3_LIB_INSTALL}") 48 | message(STATUS " - OM3_OPENMP ${OM3_OPENMP}") 49 | message(STATUS " - OM3_MOM_SYMMETRIC ${OM3_MOM_SYMMETRIC}") 50 | message(STATUS " - OM3_CICE_IO ${OM3_CICE_IO}") 51 | 52 | 53 | #[==============================================================================[ 54 | # Project configuration # 55 | #]==============================================================================] 56 | 57 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) 58 | include(GNUInstallDirs) 59 | if(OM3_LIB_INSTALL) 60 | include(CMakePackageConfigHelpers) 61 | endif() 62 | 63 | # Include some custom cmake modules 64 | include(FortranLib) 65 | include(AddPatchedSource) 66 | 67 | ## Configure project variables 68 | 69 | # Do not build components that are not going to be used 70 | if(OM3_ENABLE_MOM6 OR OM3_ENABLE_MOM6-CICE6 OR OM3_ENABLE_MOM6-WW3 OR OM3_ENABLE_MOM6-CICE6-WW3) 71 | set(OM3_BUILD_MOM6 ON) 72 | else() 73 | set(OM3_BUILD_MOM6 OFF) 74 | endif() 75 | if(OM3_ENABLE_CICE6 OR OM3_ENABLE_MOM6-CICE6 OR OM3_ENABLE_CICE6-WW3 OR OM3_ENABLE_MOM6-CICE6-WW3) 76 | set(OM3_BUILD_CICE6 ON) 77 | else() 78 | set(OM3_BUILD_CICE6 OFF) 79 | endif() 80 | if(OM3_ENABLE_WW3 OR OM3_ENABLE_MOM6-WW3 OR OM3_ENABLE_CICE6-WW3 OR OM3_ENABLE_MOM6-CICE6-WW3) 81 | set(OM3_BUILD_WW3 ON) 82 | else() 83 | set(OM3_BUILD_WW3 OFF) 84 | endif() 85 | message(STATUS "Components to build") 86 | message(STATUS " - OM3_BUILD_MOM6 ${OM3_BUILD_MOM6}") 87 | message(STATUS " - OM3_BUILD_CICE6 ${OM3_BUILD_CICE6}") 88 | message(STATUS " - OM3_BUILD_WW3 ${OM3_BUILD_WW3}") 89 | 90 | # Common compiler flags and definitions 91 | if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") 92 | set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fbacktrace -fconvert=big-endian -ffree-line-length-none -ffixed-line-length-none") 93 | if(${CMAKE_Fortran_COMPILER_VERSION} VERSION_GREATER_EQUAL 10) 94 | set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fallow-argument-mismatch") 95 | endif() 96 | set(CMAKE_Fortran_FLAGS_RELEASE "-O") 97 | set(CMAKE_Fortran_FLAGS_DEBUG "-g -Wall -Og -ffpe-trap=zero,overflow -fcheck=bounds") 98 | elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Intel") 99 | set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qno-opt-dynamic-align -convert big_endian -assume byterecl -ftz -traceback -assume realloc_lhs -fp-model source") 100 | set(CMAKE_Fortran_FLAGS_RELEASE "-O2 -debug minimal") 101 | set(CMAKE_Fortran_FLAGS_DEBUG "-O0 -g -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created") 102 | else() 103 | message(WARNING "Fortran compiler with ID ${CMAKE_Fortran_COMPILER_ID} will be used with CMake default options") 104 | endif() 105 | 106 | if(CMAKE_C_COMPILER_ID MATCHES "GNU") 107 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") 108 | set(CMAKE_C_FLAGS_RELEASE "-O") 109 | set(CMAKE_C_FLAGS_DEBUG "-g -Wall -Og -fbacktrace -ffpe-trap=invalid,zero,overflow -fcheck=bounds") 110 | elseif(CMAKE_C_COMPILER_ID MATCHES "Intel") 111 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -traceback -qno-opt-dynamic-align -fp-model precise -std=gnu99") 112 | set(CMAKE_C_FLAGS_RELEASE "-O2 -debug minimal") 113 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g") 114 | else() 115 | message(WARNING "C compiler with ID ${CMAKE_C_COMPILER_ID} will be used with CMake default options") 116 | endif() 117 | 118 | add_compile_definitions( 119 | CESMCOUPLED 120 | ) 121 | 122 | ## Fortran modules path; currently this is simply set to be the include dir 123 | set(CMAKE_INSTALL_MODULEDIR ${CMAKE_INSTALL_INCLUDEDIR} 124 | CACHE STRING 125 | "Fortran module installation path (Not a cmake native variable)" 126 | ) 127 | 128 | #[==============================================================================[ 129 | # External packages # 130 | #]==============================================================================] 131 | 132 | # Find dependencies 133 | find_package(MPI REQUIRED) 134 | if(OM3_OPENMP) 135 | find_package(OpenMP REQUIRED) 136 | endif() 137 | find_package(FoX 4.1.2 REQUIRED) 138 | find_package(NetCDF 4.7.3 REQUIRED Fortran) 139 | find_package(ESMF 8.3.0 MODULE REQUIRED) 140 | find_package(fms COMPONENTS R8 REQUIRED) 141 | find_package(PIO 2.5.3 REQUIRED COMPONENTS C Fortran) 142 | 143 | #[==============================================================================[ 144 | # Main definitions # 145 | #]==============================================================================] 146 | 147 | # Some code shared by several components 148 | add_subdirectory(share) 149 | 150 | ## Components 151 | 152 | # Data component (CDEPS) 153 | add_subdirectory(CDEPS) 154 | 155 | # Ocean component (MOM6) 156 | if(OM3_BUILD_MOM6) 157 | add_subdirectory(MOM6) 158 | endif() 159 | 160 | # Sea-ice component (CICE6) 161 | if(OM3_BUILD_CICE6) 162 | add_subdirectory(CICE) 163 | endif() 164 | 165 | # Wave component (WW3) 166 | if(OM3_BUILD_WW3) 167 | add_subdirectory(WW3) 168 | endif() 169 | 170 | # Mediator component (CMEPS) 171 | add_subdirectory(CMEPS) 172 | 173 | # Add executable for each enabled configuration 174 | foreach(CONF IN LISTS KnownConfigurations) 175 | if(NOT OM3_ENABLE_${CONF}) 176 | continue() 177 | endif() 178 | 179 | set(ComponentsTargets "") 180 | if(OM3_${CONF} MATCHES MOM6) 181 | list(APPEND ComponentsTargets AccessOM3::mom6) 182 | else() 183 | list(APPEND ComponentsTargets AccessOM3::cdeps_docn) 184 | endif() 185 | if(OM3_${CONF} MATCHES CICE6) 186 | list(APPEND ComponentsTargets AccessOM3::cice) 187 | else() 188 | list(APPEND ComponentsTargets AccessOM3::cdeps_dice) 189 | endif() 190 | if(OM3_${CONF} MATCHES WW3) 191 | list(APPEND ComponentsTargets AccessOM3::ww3) 192 | else() 193 | list(APPEND ComponentsTargets AccessOM3::cdeps_dwav) 194 | endif() 195 | 196 | # We use the CESM driver from CMEPS 197 | add_fortran_library(OM3_cesm_driver_${CONF} mod/OM3_cesm_driver_${CONF} STATIC 198 | CMEPS/CMEPS/cesm/driver/esm.F90 199 | CMEPS/CMEPS/cesm/driver/ensemble_driver.F90 200 | CMEPS/CMEPS/cesm/driver/esm_time_mod.F90 201 | ) 202 | target_link_libraries(OM3_cesm_driver_${CONF} 203 | PUBLIC esmf 204 | PRIVATE ${ComponentsTargets} AccessOM3::cdeps_drof AccessOM3::cdeps_datm AccessOM3::cmeps AccessOM3::nuopc_cap_share AccessOM3::share AccessOM3::timing 205 | ) 206 | target_compile_definitions(OM3_cesm_driver_${CONF} PRIVATE MED_PRESENT 207 | ATM_PRESENT 208 | ICE_PRESENT 209 | OCN_PRESENT 210 | WAV_PRESENT 211 | ROF_PRESENT 212 | $<$:DEBUG> 213 | ) 214 | 215 | add_executable(OM3_${CONF} CMEPS/CMEPS/cesm/driver/esmApp.F90) 216 | target_link_libraries(OM3_${CONF} PRIVATE OM3_cesm_driver_${CONF} AccessOM3::share esmf) 217 | 218 | set_target_properties(OM3_${CONF} PROPERTIES 219 | LINKER_LANGUAGE Fortran 220 | OUTPUT_NAME access-om3-${CONF} 221 | ) 222 | endforeach() 223 | 224 | #[==============================================================================[ 225 | # Install or Export # 226 | #]==============================================================================] 227 | 228 | ## Installs 229 | 230 | # Note that the installation of some components is done in the corresponding subdirectory 231 | 232 | # OM3 executables 233 | if(OM3_BIN_INSTALL) 234 | foreach(CONF IN LISTS KnownConfigurations) 235 | if(NOT OM3_ENABLE_${CONF}) 236 | continue() 237 | endif() 238 | 239 | install(TARGETS OM3_${CONF} 240 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 241 | ) 242 | endforeach() 243 | endif() 244 | 245 | # Libraries 246 | if(OM3_LIB_INSTALL) 247 | configure_package_config_file( 248 | cmake/AccessOM3Config.cmake.in 249 | ${CMAKE_CURRENT_BINARY_DIR}/AccessOM3Config.cmake 250 | INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AccessOM3 251 | ) 252 | install(FILES ${CMAKE_SOURCE_DIR}/cmake/FindFoX.cmake ${CMAKE_CURRENT_BINARY_DIR}/AccessOM3Config.cmake 253 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AccessOM3 254 | COMPONENT AccessOM3_Development 255 | ) 256 | endif() 257 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 5, 3 | "cmakeMinimumRequired": { 4 | "major": 3, 5 | "minor": 23, 6 | "patch": 0 7 | }, 8 | "include": [ 9 | "cmake/CMakePresets-defaults.json", 10 | "cmake/CMakePresets-compilers.json", 11 | "cmake/CMakePresets-machines.json" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). 6 | 7 | ## [0.2.0] - 2023-08-29 8 | 9 | ### Changed 10 | 11 | - Components and build system to match CESM [064022e](https://github.com/ESCOMP/CESM/commit/064022ed14bcc48dbb632dabc36a741ae0859822). 12 | 13 | ## [0.1.0] - 2023-08-16 14 | 15 | ### Added 16 | 17 | - All components that make up ACCESS-OM3: MOM6, CICE6, WW3, CDEPS and CMEPS. 18 | - CMake based build-system. 19 | -------------------------------------------------------------------------------- /MOM6/patches/MOM_PointAccel.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/MOM6/src/diagnostics/MOM_PointAccel.F90 b/MOM6/src/diagnostics/MOM_PointAccel.F90.new 2 | index 30f0803..7f91f79 100644 3 | --- a/MOM6/src/diagnostics/MOM_PointAccel.F90 4 | +++ b/MOM6/src/diagnostics/MOM_PointAccel.F90.new 5 | @@ -124,7 +124,7 @@ subroutine write_u_accel(I, j, um, hin, ADp, CDp, dt, G, GV, US, CS, vel_rpt, st 6 | if (CS%u_file == -1) then 7 | if (len_trim(CS%u_trunc_file) < 1) return 8 | call open_ASCII_file(CS%u_file, trim(CS%u_trunc_file), action=APPEND_FILE, & 9 | - threading=MULTIPLE, fileset=SINGLE_FILE) 10 | + threading=MULTIPLE, fileset=MULTIPLE) 11 | if (CS%u_file == -1) then 12 | call MOM_error(NOTE, 'Unable to open file '//trim(CS%u_trunc_file)//'.') 13 | return 14 | @@ -465,7 +465,7 @@ subroutine write_v_accel(i, J, vm, hin, ADp, CDp, dt, G, GV, US, CS, vel_rpt, st 15 | if (CS%v_file == -1) then 16 | if (len_trim(CS%v_trunc_file) < 1) return 17 | call open_ASCII_file(CS%v_file, trim(CS%v_trunc_file), action=APPEND_FILE, & 18 | - threading=MULTIPLE, fileset=SINGLE_FILE) 19 | + threading=MULTIPLE, fileset=MULTIPLE) 20 | if (CS%v_file == -1) then 21 | call MOM_error(NOTE, 'Unable to open file '//trim(CS%v_trunc_file)//'.') 22 | return 23 | -------------------------------------------------------------------------------- /MOM6/patches/MOM_coupler_types.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/MOM6/src/framework/MOM_coupler_types.F90 b/MOM6/src/framework/MOM_coupler_types.F90.new 2 | index b931a2d..cac9309 100644 3 | --- a/MOM6/src/framework/MOM_coupler_types.F90 4 | +++ b/MOM6/src/framework/MOM_coupler_types.F90.new 5 | @@ -9,7 +9,10 @@ use MOM_couplertype_infra, only : CT_set_diags, CT_send_data, CT_write_chksums, 6 | use MOM_couplertype_infra, only : CT_copy_data, CT_increment_data, CT_rescale_data 7 | use MOM_couplertype_infra, only : CT_set_data, CT_extract_data, CT_redistribute_data 8 | use MOM_couplertype_infra, only : coupler_1d_bc_type, coupler_2d_bc_type, coupler_3d_bc_type 9 | -use MOM_couplertype_infra, only : ind_flux, ind_alpha, ind_csurf 10 | +use MOM_couplertype_infra, only : ind_flux, ind_deltap, ind_kw, ind_flux0 11 | +use MOM_couplertype_infra, only : ind_pcair, ind_u10, ind_psurf 12 | +use MOM_couplertype_infra, only : ind_alpha, ind_csurf, ind_sc_no 13 | +use MOM_couplertype_infra, only : ind_runoff, ind_deposition 14 | use MOM_domain_infra, only : domain2D 15 | use MOM_time_manager, only : time_type 16 | 17 | @@ -23,7 +26,10 @@ public :: atmos_ocn_coupler_flux, coupler_type_data_override 18 | public :: coupler_1d_bc_type, coupler_2d_bc_type, coupler_3d_bc_type 19 | ! These are encoding constant parameters that indicate whether a flux, solubility or 20 | ! surface ocean concentration are being set or accessed with an inquiry. 21 | -public :: ind_flux, ind_alpha, ind_csurf 22 | +public :: ind_flux, ind_deltap, ind_kw, ind_flux0 23 | +public :: ind_pcair, ind_u10, ind_psurf 24 | +public :: ind_alpha, ind_csurf, ind_sc_no 25 | +public :: ind_runoff, ind_deposition 26 | 27 | !> This is the interface to spawn one coupler_bc_type into another. 28 | interface coupler_type_spawn 29 | -------------------------------------------------------------------------------- /MOM6/patches/MOM_couplertype_infra.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/MOM6/config_src/infra/FMS2/MOM_couplertype_infra.F90 b/MOM6/config_src/infra/FMS2/MOM_couplertype_infra.F90.new 2 | index 3bcccc1..50fd5b0 100644 3 | --- a/MOM6/config_src/infra/FMS2/MOM_couplertype_infra.F90 4 | +++ b/MOM6/config_src/infra/FMS2/MOM_couplertype_infra.F90.new 5 | @@ -9,7 +9,10 @@ use coupler_types_mod, only : coupler_type_write_chksums, coupler_type_redistrib 6 | use coupler_types_mod, only : coupler_type_increment_data, coupler_type_rescale_data 7 | use coupler_types_mod, only : coupler_type_extract_data, coupler_type_set_data 8 | use coupler_types_mod, only : coupler_type_data_override 9 | -use coupler_types_mod, only : ind_flux, ind_alpha, ind_csurf 10 | +use coupler_types_mod, only : ind_flux, ind_deltap, ind_kw, ind_flux0 11 | +use coupler_types_mod, only : ind_pcair, ind_u10, ind_psurf 12 | +use coupler_types_mod, only : ind_alpha, ind_csurf, ind_sc_no 13 | +use coupler_types_mod, only : ind_runoff, ind_deposition 14 | use coupler_types_mod, only : coupler_1d_bc_type, coupler_2d_bc_type, coupler_3d_bc_type 15 | use atmos_ocean_fluxes_mod, only : aof_set_coupler_flux 16 | use MOM_domain_infra, only : domain2D 17 | @@ -22,7 +25,10 @@ public :: CT_set_diags, CT_send_data, CT_data_override, CT_write_chksums 18 | public :: CT_set_data, CT_increment_data, CT_rescale_data 19 | public :: CT_copy_data, CT_extract_data, CT_redistribute_data 20 | public :: atmos_ocn_coupler_flux 21 | -public :: ind_flux, ind_alpha, ind_csurf 22 | +public :: ind_flux, ind_deltap, ind_kw, ind_flux0 23 | +public :: ind_pcair, ind_u10, ind_psurf 24 | +public :: ind_alpha, ind_csurf, ind_sc_no 25 | +public :: ind_runoff, ind_deposition 26 | public :: coupler_1d_bc_type, coupler_2d_bc_type, coupler_3d_bc_type 27 | 28 | !> This is the interface to spawn one coupler_bc_type into another. 29 | -------------------------------------------------------------------------------- /MOM6/patches/MOM_forcing_type.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/MOM6/src/core/MOM_forcing_type.F90 b/MOM6/src/core/MOM_forcing_type.F90.new 2 | index 998713d..a2efcaa 100644 3 | --- a/MOM6/src/core/MOM_forcing_type.F90 4 | +++ b/MOM6/src/core/MOM_forcing_type.F90.new 5 | @@ -2280,6 +2280,11 @@ subroutine fluxes_accumulate(flux_tmp, fluxes, G, wt2, forces) 6 | 7 | fluxes%salt_flux(i,j) = wt1*fluxes%salt_flux(i,j) + wt2*flux_tmp%salt_flux(i,j) 8 | enddo ; enddo 9 | + if (associated(fluxes%salt_flux_added) .and. associated(flux_tmp%salt_flux_added)) then 10 | + do j=js,je ; do i=is,ie 11 | + fluxes%salt_flux_added(i,j) = wt1*fluxes%salt_flux_added(i,j) + wt2*flux_tmp%salt_flux_added(i,j) 12 | + enddo ; enddo 13 | + endif 14 | if (associated(fluxes%heat_added) .and. associated(flux_tmp%heat_added)) then 15 | do j=js,je ; do i=is,ie 16 | fluxes%heat_added(i,j) = wt1*fluxes%heat_added(i,j) + wt2*flux_tmp%heat_added(i,j) 17 | -------------------------------------------------------------------------------- /MOM6/patches/MOM_generic_tracer.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/MOM6/src/tracer/MOM_generic_tracer.F90 b/MOM6/src/tracer/MOM_generic_tracer.F90.new 2 | index 6b10d15..e092aa7 100644 3 | --- a/MOM6/src/tracer/MOM_generic_tracer.F90 4 | +++ b/MOM6/src/tracer/MOM_generic_tracer.F90.new 5 | @@ -21,7 +21,7 @@ module MOM_generic_tracer 6 | use generic_tracer, only: generic_tracer_coupler_get, generic_tracer_coupler_set 7 | use generic_tracer, only: generic_tracer_end, generic_tracer_get_list, do_generic_tracer 8 | use generic_tracer, only: generic_tracer_update_from_bottom,generic_tracer_vertdiff_G 9 | - use generic_tracer, only: generic_tracer_coupler_accumulate 10 | + use generic_tracer, only: generic_tracer_coupler_accumulate, generic_tracer_update_from_coupler 11 | 12 | use g_tracer_utils, only: g_tracer_get_name,g_tracer_set_values,g_tracer_set_common,g_tracer_get_common 13 | use g_tracer_utils, only: g_tracer_get_next,g_tracer_type,g_tracer_is_prog,g_tracer_flux_init 14 | @@ -527,6 +527,11 @@ contains 15 | ! the fluxes without coming into this subroutine. 16 | ! MOM5 has to modified to conform. 17 | 18 | + ! 19 | + !Call the generic_tracer's update_from_coupler routine (convert salt_flux_added to g/m^2/sec) 20 | + ! 21 | + call generic_tracer_update_from_coupler(G%isd, G%jsd, 1000*(US%RZ_T_to_kg_m2s*fluxes%salt_flux_added)) 22 | + 23 | ! 24 | !Add contribution of river to surface flux 25 | ! 26 | -------------------------------------------------------------------------------- /MOM6/patches/MOM_io_infra.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/MOM6/config_src/infra/FMS2/MOM_io_infra.F90 b/MOM6/config_src/infra/FMS2/MOM_io_infra.F90.new 2 | index a43b4e9..169ed25 100644 3 | --- a/MOM6/config_src/infra/FMS2/MOM_io_infra.F90 4 | +++ b/MOM6/config_src/infra/FMS2/MOM_io_infra.F90.new 5 | @@ -376,8 +376,7 @@ subroutine open_ASCII_file(unit, file, action, threading, fileset) 6 | logical :: exists 7 | logical :: is_open 8 | character(len=6) :: action_arg, position_arg 9 | - character(len=:), allocatable :: filename 10 | - 11 | + character(len=500) :: filename 12 | ! NOTE: This function is written to emulate the original behavior of mpp_open 13 | ! from the FMS1 library, on which the MOM API is still based. Much of this 14 | ! can be removed if we choose to drop this compatibility, but for now we 15 | @@ -433,12 +432,12 @@ subroutine open_ASCII_file(unit, file, action, threading, fileset) 16 | endif 17 | endif 18 | 19 | - inquire(file=filename, exist=exists) 20 | + inquire(file=trim(filename), exist=exists) 21 | if (exists .and. action_flag == WRITEONLY_FILE) & 22 | call MOM_error(WARNING, 'open_ASCII_file: File ' // trim(filename) // & 23 | ' opened WRITEONLY already exists!') 24 | 25 | - open(newunit=unit, file=filename, action=trim(action_arg), & 26 | + open(newunit=unit, file=trim(filename), action=trim(action_arg), & 27 | position=trim(position_arg)) 28 | 29 | ! This checks if open() failed but did not raise a runtime error. 30 | -------------------------------------------------------------------------------- /MOM6/patches/mom_cap.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/MOM6/config_src/drivers/nuopc_cap/mom_cap.F90 b/MOM6/config_src/drivers/nuopc_cap/mom_cap.F90.new 2 | index fab6fe1..541d7f1 100644 3 | --- a/MOM6/config_src/drivers/nuopc_cap/mom_cap.F90 4 | +++ b/MOM6/config_src/drivers/nuopc_cap/mom_cap.F90.new 5 | @@ -2,8 +2,9 @@ 6 | 7 | module MOM_cap_mod 8 | 9 | +use field_manager_mod, only: field_manager_init, field_manager_end 10 | use MOM_domains, only: get_domain_extent 11 | -use MOM_io, only: stdout, io_infra_end 12 | +use MOM_io, only: stdout, io_infra_end, slasher 13 | use mpp_domains_mod, only: mpp_get_compute_domains 14 | use mpp_domains_mod, only: mpp_get_ntile_count, mpp_get_pelist, mpp_get_global_domain 15 | use mpp_domains_mod, only: mpp_get_domain_npes 16 | @@ -30,6 +31,7 @@ use MOM_cap_methods, only: med2mod_areacor, state_diagnose 17 | use MOM_cap_methods, only: ChkErr 18 | use MOM_ensemble_manager, only: ensemble_manager_init 19 | use MOM_coms, only: sum_across_PEs 20 | +use MOM_coupler_types, only: coupler_1d_bc_type, coupler_2d_bc_type 21 | 22 | #ifdef CESMCOUPLED 23 | use shr_log_mod, only: shr_log_setLogUnit 24 | @@ -37,6 +39,15 @@ use nuopc_shr_methods, only: get_component_instance 25 | #endif 26 | use time_utils_mod, only: esmf2fms_time 27 | 28 | +#ifdef _USE_GENERIC_TRACER 29 | +use MOM_coupler_types, only: coupler_type_spawn, coupler_type_destructor 30 | +use MOM_coupler_types, only: coupler_type_set_diags, coupler_type_send_data, coupler_type_data_override 31 | +use MOM_data_override, only: data_override_init, data_override 32 | +use MOM_cap_gtracer_flux, only: gas_exchange_init, gas_fields_restore, gas_fields_restart 33 | +use MOM_cap_gtracer_flux, only: get_coupled_field_name, add_gas_fluxes_param, UNKNOWN_CMEPS_FIELD 34 | +use MOM_cap_gtracer_flux, only: atmos_ocean_fluxes_calc 35 | +#endif 36 | + 37 | use, intrinsic :: iso_fortran_env, only: output_unit 38 | 39 | use ESMF, only: ESMF_ClockAdvance, ESMF_ClockGet, ESMF_ClockPrint, ESMF_VMget 40 | @@ -96,11 +107,14 @@ implicit none; private 41 | public SetServices 42 | public SetVM 43 | 44 | -!> Internal state type with pointers to three types defined by MOM. 45 | +!> Internal state type with pointers to types defined by MOM. 46 | type ocean_internalstate_type 47 | type(ocean_public_type), pointer :: ocean_public_type_ptr 48 | type(ocean_state_type), pointer :: ocean_state_type_ptr 49 | type(ice_ocean_boundary_type), pointer :: ice_ocean_boundary_type_ptr 50 | +#ifdef _USE_GENERIC_TRACER 51 | + type(coupler_2d_bc_type), pointer :: coupler_2d_bc_type_ptr 52 | +#endif 53 | end type 54 | 55 | !> Wrapper-derived type required to associate an internal state instance 56 | @@ -416,6 +430,10 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) 57 | type (ocean_public_type), pointer :: ocean_public => NULL() 58 | type (ocean_state_type), pointer :: ocean_state => NULL() 59 | type(ice_ocean_boundary_type), pointer :: Ice_ocean_boundary => NULL() 60 | + type(coupler_1d_bc_type), pointer :: gas_fields_atm => NULL() 61 | + type(coupler_1d_bc_type), pointer :: gas_fields_ocn => NULL() 62 | + type(coupler_1d_bc_type), pointer :: gas_fluxes => NULL() 63 | + type(coupler_2d_bc_type), pointer :: atm_fields => NULL() 64 | type(ocean_internalstate_wrapper) :: ocean_internalstate 65 | type(ocean_grid_type), pointer :: ocean_grid => NULL() 66 | type(directories) :: dirs 67 | @@ -447,6 +465,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) 68 | character(len=512) :: restartfile ! Path/Name of restart file 69 | character(len=2048) :: restartfiles ! Path/Name of restart files 70 | ! (same as restartfile if single restart file) 71 | + character(240) :: additional_restart_dir 72 | character(len=*), parameter :: subname='(MOM_cap:InitializeAdvertise)' 73 | character(len=32) :: calendar 74 | character(len=:), allocatable :: rpointer_filename 75 | @@ -525,6 +544,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) 76 | if (chkerr(rc,__LINE__,u_FILE_u)) return 77 | call MOM_infra_init(mpi_comm_mom) 78 | 79 | + call field_manager_init 80 | + 81 | ! determine the calendar 82 | if (cesm_coupled) then 83 | call NUOPC_CompAttributeGet(gcomp, name="calendar", value=cvalue, & 84 | @@ -656,13 +677,44 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) 85 | 86 | endif 87 | 88 | + ! Set NUOPC attribute additional_restart_dir to RESTART/ if not defined 89 | + additional_restart_dir = "RESTART/" 90 | + call NUOPC_CompAttributeGet(gcomp, name="additional_restart_dir", value=cvalue, & 91 | + isPresent=isPresent, isSet=isSet, rc=rc) 92 | + if (ChkErr(rc,__LINE__,u_FILE_u)) return 93 | + if (isPresent .and. isSet) then 94 | + additional_restart_dir = slasher(cvalue) 95 | + else 96 | + call ESMF_LogWrite('MOM_cap:additional_restart_dir unset. Defaulting to '//trim(additional_restart_dir), & 97 | + ESMF_LOGMSG_INFO) 98 | + endif 99 | + call NUOPC_CompAttributeSet(gcomp, name="additional_restart_dir", value=additional_restart_dir, rc=rc) 100 | + if (chkerr(rc,__LINE__,u_FILE_u)) return 101 | + 102 | ocean_public%is_ocean_pe = .true. 103 | +#ifdef _USE_GENERIC_TRACER 104 | + ! Initialise structures for extra tracer fluxes 105 | + call gas_exchange_init(gas_fields_atm=gas_fields_atm, gas_fields_ocn=gas_fields_ocn, gas_fluxes=gas_fluxes) 106 | + 107 | + if (cesm_coupled .and. len_trim(inst_suffix)>0) then 108 | + call ocean_model_init(ocean_public, ocean_state, time0, time_start, gas_fields_ocn=gas_fields_ocn, & 109 | + input_restart_file=trim(adjustl(restartfiles)), inst_index=inst_index) 110 | + else 111 | + call ocean_model_init(ocean_public, ocean_state, time0, time_start, gas_fields_ocn=gas_fields_ocn, & 112 | + input_restart_file=trim(adjustl(restartfiles))) 113 | + endif 114 | + 115 | + ! Enable data override via the data_table using the component name 'OCN' 116 | + call get_ocean_grid(ocean_state, ocean_grid) 117 | + call data_override_init(ocean_grid%Domain) 118 | +#else 119 | if (cesm_coupled .and. len_trim(inst_suffix)>0) then 120 | call ocean_model_init(ocean_public, ocean_state, time0, time_start, & 121 | input_restart_file=trim(adjustl(restartfiles)), inst_index=inst_index) 122 | else 123 | call ocean_model_init(ocean_public, ocean_state, time0, time_start, input_restart_file=trim(adjustl(restartfiles))) 124 | endif 125 | +#endif 126 | 127 | ! GMM, this call is not needed in CESM. Check with EMC if it can be deleted. 128 | call ocean_model_flux_init(ocean_state) 129 | @@ -729,6 +781,31 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) 130 | Ice_ocean_boundary%hcond = 0.0 131 | endif 132 | 133 | +#ifdef _USE_GENERIC_TRACER 134 | + ! Allocate fields for extra tracer fluxes in Ice_ocean_boundary 135 | + ! Annoyingly, spawning doesn't copy param array, so add manually 136 | + call coupler_type_spawn(gas_fluxes, Ice_ocean_boundary%fluxes, (/isc,isc,iec,iec/), & 137 | + (/jsc,jsc,jec,jec/), suffix='_ice_ocn') 138 | + call add_gas_fluxes_param(Ice_ocean_boundary%fluxes) 139 | + 140 | + ! Initialise structure for atmos fields related to extra tracer fluxes 141 | + ! This is set in the ESMF Internal State to be accessed elsewhere 142 | + ! TODO: should we deallocate atm_fields in a finalise step? Ice_ocean_boundary is handled 143 | + ! in a similar way and does not appear to be deallocated. 144 | + allocate(atm_fields) 145 | + ocean_internalstate%ptr%coupler_2d_bc_type_ptr => atm_fields 146 | + call coupler_type_spawn(gas_fields_atm, atm_fields, (/isc,isc,iec,iec/), & 147 | + (/jsc,jsc,jec,jec/), suffix='_atm') 148 | + 149 | + ! Register diagnosics for extra tracer flux structures 150 | + call coupler_type_set_diags(Ice_ocean_boundary%fluxes, "ocean_flux", ocean_public%axes(1:2), time_start) 151 | + call coupler_type_set_diags(atm_fields, "atmos_sfc", ocean_public%axes(1:2), time_start) 152 | + 153 | + ! Restore ocean fields related to extra tracer fluxes from restart files 154 | + call get_MOM_input(dirs=dirs) 155 | + call gas_fields_restore(ocean_public%fields, ocean_public%domain, dirs%restart_input_dir) 156 | +#endif 157 | + 158 | call query_ocean_state(ocean_state, use_waves=use_waves, wave_method=wave_method) 159 | if (use_waves) then 160 | if (wave_method == "EFACTOR") then 161 | @@ -797,6 +874,15 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) 162 | endif 163 | endif 164 | 165 | +#ifdef _USE_GENERIC_TRACER 166 | + ! Add import fields required for extra tracer fluxes 167 | + do n = 1, gas_fluxes%num_bcs 168 | + stdname = get_coupled_field_name(gas_fluxes%bc(n)%name) 169 | + if (stdname /= UNKNOWN_CMEPS_FIELD) & 170 | + call fld_list_add(fldsToOcn_num, fldsToOcn, stdname, "will provide") 171 | + enddo 172 | +#endif 173 | + 174 | !--------- export fields ------------- 175 | call fld_list_add(fldsFrOcn_num, fldsFrOcn, "So_omask" , "will provide") 176 | call fld_list_add(fldsFrOcn_num, fldsFrOcn, "So_t" , "will provide") 177 | @@ -808,6 +894,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) 178 | call fld_list_add(fldsFrOcn_num, fldsFrOcn, "Fioo_q" , "will provide") 179 | call fld_list_add(fldsFrOcn_num, fldsFrOcn, "So_bldepth" , "will provide") 180 | 181 | + ! TODO: dts: How to handle export fields from generic tracers? 182 | + 183 | do n = 1,fldsToOcn_num 184 | call NUOPC_Advertise(importState, standardName=fldsToOcn(n)%stdname, name=fldsToOcn(n)%shortname, rc=rc) 185 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 186 | @@ -1619,11 +1707,14 @@ subroutine ModelAdvance(gcomp, rc) 187 | type (ocean_public_type), pointer :: ocean_public => NULL() 188 | type (ocean_state_type), pointer :: ocean_state => NULL() 189 | type(ice_ocean_boundary_type), pointer :: Ice_ocean_boundary => NULL() 190 | + type(coupler_2d_bc_type), pointer :: atm_fields => NULL() 191 | type(ocean_internalstate_wrapper) :: ocean_internalstate 192 | type(ocean_grid_type) , pointer :: ocean_grid 193 | type(time_type) :: Time 194 | + type(time_type) :: Time_import 195 | type(time_type) :: Time_step_coupled 196 | type(time_type) :: Time_restart_current 197 | + integer :: isc,iec,jsc,jec 198 | integer :: dth, dtm, dts 199 | integer :: nc 200 | type(ESMF_Time) :: MyTime 201 | @@ -1635,12 +1726,13 @@ subroutine ModelAdvance(gcomp, rc) 202 | integer :: writeunit 203 | integer :: localPet 204 | type(ESMF_VM) :: vm 205 | - integer :: n, i 206 | + integer :: m, n, i 207 | character(240) :: import_timestr, export_timestr 208 | character(len=128) :: fldname 209 | character(len=*),parameter :: subname='(MOM_cap:ModelAdvance)' 210 | character(len=8) :: suffix 211 | character(len=:), allocatable :: rpointer_filename 212 | + character(240) :: additional_restart_dir 213 | integer :: num_rest_files 214 | real(8) :: MPI_Wtime, timers 215 | logical :: write_restart 216 | @@ -1683,6 +1775,7 @@ subroutine ModelAdvance(gcomp, rc) 217 | 218 | Time_step_coupled = esmf2fms_time(timeStep) 219 | Time = esmf2fms_time(currTime) 220 | + Time_import = Time 221 | 222 | !--------------- 223 | ! Apply ocean lag for startup runs: 224 | @@ -1758,8 +1851,39 @@ subroutine ModelAdvance(gcomp, rc) 225 | ! Import data 226 | !--------------- 227 | 228 | +#ifdef _USE_GENERIC_TRACER 229 | + atm_fields => ocean_internalstate%ptr%coupler_2d_bc_type_ptr 230 | + 231 | + call mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, atm_fields=atm_fields, rc=rc) 232 | + if (ChkErr(rc,__LINE__,u_FILE_u)) return 233 | + 234 | + ! Potentially override atm_fields from data_table. 235 | + call coupler_type_data_override('OCN', atm_fields, Time_import) 236 | + 237 | + ! Potentially override ice_ocean_boundary%fluxes from data_table. 238 | + ! Doing this before atmos_ocean_fluxes_calc call avoids unnecessary calculation of overridden fluxes. 239 | + ! However, we cannot use coupler_type_data_override here since it does not set the override flag on 240 | + ! overridden fields 241 | + do n = 1, ice_ocean_boundary%fluxes%num_bcs 242 | + do m = 1, ice_ocean_boundary%fluxes%bc(n)%num_fields 243 | + call data_override('OCN', ice_ocean_boundary%fluxes%bc(n)%field(m)%name, & 244 | + ice_ocean_boundary%fluxes%bc(n)%field(m)%values, Time_import, & 245 | + override=ice_ocean_boundary%fluxes%bc(n)%field(m)%override) 246 | + enddo 247 | + enddo 248 | + 249 | + ! Calculate the extra tracer fluxes 250 | + call get_domain_extent(ocean_public%domain, isc, iec, jsc, jec) 251 | + call atmos_ocean_fluxes_calc(atm_fields, ocean_public%fields, ice_ocean_boundary%fluxes, & 252 | + ice_ocean_boundary%ice_fraction, isc, iec, jsc, jec) 253 | + 254 | + ! Send diagnostics 255 | + call coupler_type_send_data(atm_fields, Time_import) 256 | + call coupler_type_send_data(ice_ocean_boundary%fluxes, Time_import) 257 | +#else 258 | call mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, rc=rc) 259 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 260 | +#endif 261 | 262 | !--------------- 263 | ! Update MOM6 264 | @@ -1831,7 +1955,7 @@ subroutine ModelAdvance(gcomp, rc) 265 | ! determine restart filename 266 | call ESMF_ClockGetNextTime(clock, MyTime, rc=rc) 267 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 268 | - call ESMF_TimeGet (MyTime, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc ) 269 | + call ESMF_TimeGet (MyTime, yy=year, mm=month, dd=day, s=seconds, rc=rc ) 270 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 271 | 272 | if (cesm_coupled) then 273 | @@ -1889,6 +2013,14 @@ subroutine ModelAdvance(gcomp, rc) 274 | 275 | endif 276 | 277 | +#ifdef _USE_GENERIC_TRACER 278 | + ! Write fields for extra tracer fluxes to their internally defined ocean restart file 279 | + call NUOPC_CompAttributeGet(gcomp, name="additional_restart_dir", value=additional_restart_dir, rc=rc) 280 | + if (ChkErr(rc,__LINE__,u_FILE_u)) return 281 | + 282 | + call gas_fields_restart(ocean_public%fields, ocean_public%domain, additional_restart_dir) 283 | +#endif 284 | + 285 | if (is_root_pe()) then 286 | write(stdout,*) subname//' writing restart file ',trim(restartname) 287 | endif 288 | @@ -2169,6 +2301,7 @@ subroutine ocean_model_finalize(gcomp, rc) 289 | integer :: alarmCount 290 | character(len=64) :: timestamp 291 | logical :: write_restart 292 | + character(240) :: additional_restart_dir 293 | character(len=*),parameter :: subname='(MOM_cap:ocean_model_finalize)' 294 | real(8) :: MPI_Wtime, timefs 295 | 296 | @@ -2202,6 +2335,18 @@ subroutine ocean_model_finalize(gcomp, rc) 297 | 298 | call ocean_model_end(ocean_public, ocean_State, Time, write_restart=write_restart) 299 | 300 | +#ifdef _USE_GENERIC_TRACER 301 | + if (write_restart) then 302 | + ! Write fields for extra tracer fluxes to their internally defined ocean restart file 303 | + call NUOPC_CompAttributeGet(gcomp, name="additional_restart_dir", value=additional_restart_dir, rc=rc) 304 | + if (ChkErr(rc,__LINE__,u_FILE_u)) return 305 | + 306 | + call gas_fields_restart(ocean_public%fields, ocean_public%domain, additional_restart_dir) 307 | + endif 308 | +#endif 309 | + 310 | + call field_manager_end() 311 | + 312 | call io_infra_end() 313 | call MOM_infra_end() 314 | 315 | -------------------------------------------------------------------------------- /MOM6/patches/mom_cap_methods.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/MOM6/config_src/drivers/nuopc_cap/mom_cap_methods.F90 b/MOM6/config_src/drivers/nuopc_cap/mom_cap_methods.F90.new 2 | index 125bae5..3f81f6a 100644 3 | --- a/MOM6/config_src/drivers/nuopc_cap/mom_cap_methods.F90 4 | +++ b/MOM6/config_src/drivers/nuopc_cap/mom_cap_methods.F90.new 5 | @@ -20,8 +20,15 @@ use MOM_ocean_model_nuopc, only: ocean_public_type, ocean_state_type 6 | use MOM_surface_forcing_nuopc, only: ice_ocean_boundary_type 7 | use MOM_grid, only: ocean_grid_type 8 | use MOM_domains, only: pass_var 9 | +use MOM_coupler_types, only: coupler_2d_bc_type 10 | use mpp_domains_mod, only: mpp_get_compute_domain 11 | 12 | +#ifdef _USE_GENERIC_TRACER 13 | +use MOM_coupler_types, only: set_coupler_type_data 14 | +use MOM_coupler_types, only: ind_pcair, ind_u10, ind_psurf, ind_runoff, ind_deposition 15 | +use MOM_cap_gtracer_flux, only: get_coupled_field_name, UNKNOWN_CMEPS_FIELD 16 | +#endif 17 | + 18 | ! By default make data private 19 | implicit none; private 20 | 21 | @@ -72,11 +79,17 @@ end subroutine mom_set_geomtype 22 | !> This function has a few purposes: 23 | !! (1) it imports surface fluxes using data from the mediator; and 24 | !! (2) it can apply restoring in SST and SSS. 25 | -subroutine mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, rc) 26 | +!! (3) optional: if atm_fields is provided, it imports and sets the fields in atm_fields required 27 | +!! for the calculation of coupled generic tracer fluxes 28 | +subroutine mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, atm_fields, rc) 29 | type(ocean_public_type) , intent(in) :: ocean_public !< Ocean surface state 30 | type(ocean_grid_type) , intent(in) :: ocean_grid !< Ocean model grid 31 | type(ESMF_State) , intent(inout) :: importState !< incoming data from mediator 32 | type(ice_ocean_boundary_type) , intent(inout) :: ice_ocean_boundary !< Ocean boundary forcing 33 | + type(coupler_2d_bc_type), optional, intent(inout) :: atm_fields !< If present, this type 34 | + !! describes the atmospheric tracer fields to 35 | + !! be imported for the calculation of generic 36 | + !! tracer fluxes. 37 | integer , intent(inout) :: rc !< Return code 38 | 39 | ! Local Variables 40 | @@ -88,7 +101,10 @@ subroutine mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, 41 | real(ESMF_KIND_R8), allocatable :: tauy(:,:) 42 | real(ESMF_KIND_R8), allocatable :: stkx(:,:,:) 43 | real(ESMF_KIND_R8), allocatable :: stky(:,:,:) 44 | + real(ESMF_KIND_R8), allocatable :: work(:,:) 45 | character(len=*) , parameter :: subname = '(mom_import)' 46 | + character(len=256) :: stdname 47 | + integer :: field_index 48 | 49 | rc = ESMF_SUCCESS 50 | 51 | @@ -364,6 +380,48 @@ subroutine mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, 52 | deallocate(stkx,stky) 53 | endif 54 | 55 | + !--- 56 | + ! Tracer flux fields for generic tracers 57 | + !--- 58 | +#ifdef _USE_GENERIC_TRACER 59 | + if (present(atm_fields)) then 60 | + ! Set fields in atm_fields from coupler 61 | + allocate (work(isc:iec,jsc:jec)) 62 | + do n = 1, atm_fields%num_bcs 63 | + if (atm_fields%bc(n)%flux_type .eq. 'air_sea_deposition') then 64 | + field_index = ind_deposition 65 | + elseif (atm_fields%bc(n)%flux_type .eq. 'land_sea_runoff') then 66 | + field_index = ind_runoff 67 | + else 68 | + ! This is a gas flux - set ind_u10 and ind_psurf 69 | + ! Note, we set these fields even though the pcair field may not be set below. This 70 | + ! is to allow flux calculation with overridden pcair fields 71 | + field_index = ind_pcair 72 | + call set_coupler_type_data(sqrt(ice_ocean_boundary%u10_sqr), n, atm_fields, & 73 | + idim=(/isc,isc,iec,iec/), jdim=(/jsc,jsc,jec,jec/), field_index=ind_u10) 74 | + call set_coupler_type_data(ice_ocean_boundary%p, n, atm_fields, & 75 | + idim=(/isc,isc,iec,iec/), jdim=(/jsc,jsc,jec,jec/), field_index=ind_psurf) 76 | + endif 77 | + 78 | + stdname = get_coupled_field_name(atm_fields%bc(n)%name) 79 | + if (stdname /= UNKNOWN_CMEPS_FIELD) then 80 | + call ESMF_LogWrite(trim(subname)//': generic_tracer flux, '//trim(atm_fields%bc(n)%name)//& 81 | + ': setting field index '//CHAR(48+field_index)//' to '//trim(stdname)//' if provided '//& 82 | + 'by coupler, otherwise defaulting to zero', ESMF_LOGMSG_INFO) 83 | + work(:,:) = 0._ESMF_KIND_R8 84 | + call state_getimport(importState, trim(stdname), isc, iec, jsc, jec, work, rc=rc) 85 | + if (ChkErr(rc,__LINE__,u_FILE_u)) return 86 | + call set_coupler_type_data(work, n, atm_fields, & 87 | + idim=(/isc,isc,iec,iec/), jdim=(/jsc,jsc,jec,jec/), field_index=field_index) 88 | + else 89 | + call ESMF_LogWrite(trim(subname)//': generic_tracer flux, '//trim(atm_fields%bc(n)%name)//& 90 | + ': no fields set from coupler', ESMF_LOGMSG_INFO) 91 | + endif 92 | + enddo 93 | + deallocate(work) 94 | + endif 95 | +#endif 96 | + 97 | end subroutine mom_import 98 | 99 | !> Maps outgoing ocean data to ESMF State 100 | -------------------------------------------------------------------------------- /MOM6/patches/mom_ocean_model_nuopc.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/MOM6/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 b/MOM6/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90.new 2 | index 9ac40da..b6cc4de 100644 3 | --- a/MOM6/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 4 | +++ b/MOM6/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90.new 5 | @@ -20,6 +20,7 @@ use MOM_coms, only : field_chksum 6 | use MOM_constants, only : CELSIUS_KELVIN_OFFSET, hlf 7 | use MOM_diag_mediator, only : diag_ctrl, enable_averages, disable_averaging 8 | use MOM_diag_mediator, only : diag_mediator_close_registration, diag_mediator_end 9 | +use MOM_domains, only : MOM_domain_type, domain2d, clone_MOM_domain, get_domain_extent 10 | use MOM_domains, only : pass_var, pass_vector, AGRID, BGRID_NE, CGRID_NE 11 | use MOM_domains, only : TO_ALL, Omit_Corners 12 | use MOM_error_handler, only : MOM_error, FATAL, WARNING, is_root_pe 13 | @@ -51,8 +52,6 @@ use MOM_coupler_types, only : coupler_1d_bc_type, coupler_2d_bc_type 14 | use MOM_coupler_types, only : coupler_type_spawn, coupler_type_write_chksums 15 | use MOM_coupler_types, only : coupler_type_initialized, coupler_type_copy_data 16 | use MOM_coupler_types, only : coupler_type_set_diags, coupler_type_send_data 17 | -use mpp_domains_mod, only : domain2d, mpp_get_layout, mpp_get_global_domain 18 | -use mpp_domains_mod, only : mpp_define_domains, mpp_get_compute_domain, mpp_get_data_domain 19 | use MOM_io, only : stdout 20 | use MOM_EOS, only : gsw_sp_from_sr, gsw_pt_from_ct 21 | use MOM_wave_interface, only : wave_parameters_CS, MOM_wave_interface_init 22 | @@ -102,7 +101,7 @@ type, public :: ocean_public_type 23 | !! points of the two velocity components. Valid entries 24 | !! include AGRID, BGRID_NE, CGRID_NE, BGRID_SW, and CGRID_SW, 25 | !! corresponding to the community-standard Arakawa notation. 26 | - !! (These are named integers taken from mpp_parameter_mod.) 27 | + !! (These are named integers taken from the MOM_domains module.) 28 | !! Following MOM5, stagger is BGRID_NE by default when the 29 | !! ocean is initialized, but here it is set to -999 so that 30 | !! a global max across ocean and non-ocean processors can be 31 | @@ -407,14 +406,7 @@ subroutine ocean_model_init(Ocean_sfc, OS, Time_init, Time_in, gas_fields_ocn, i 32 | ! it also initializes statistical waves. 33 | call MOM_wave_interface_init(OS%Time, OS%grid, OS%GV, OS%US, param_file, OS%Waves, OS%diag) 34 | 35 | - if (associated(OS%grid%Domain%maskmap)) then 36 | - call initialize_ocean_public_type(OS%grid%Domain%mpp_domain, Ocean_sfc, & 37 | - OS%diag, maskmap=OS%grid%Domain%maskmap, & 38 | - gas_fields_ocn=gas_fields_ocn) 39 | - else 40 | - call initialize_ocean_public_type(OS%grid%Domain%mpp_domain, Ocean_sfc, & 41 | - OS%diag, gas_fields_ocn=gas_fields_ocn) 42 | - endif 43 | + call initialize_ocean_public_type(OS%grid%Domain, Ocean_sfc, OS%diag, gas_fields_ocn=gas_fields_ocn) 44 | 45 | ! This call can only occur here if the coupler_bc_type variables have been 46 | ! initialized already using the information from gas_fields_ocn. 47 | @@ -529,8 +521,7 @@ subroutine update_ocean_model(Ice_ocean_boundary, OS, Ocean_sfc, & 48 | (/is,is,ie,ie/), (/js,js,je,je/), as_needed=.true.) 49 | 50 | ! Translate Ice_ocean_boundary into fluxes. 51 | - call mpp_get_compute_domain(Ocean_sfc%Domain, index_bnds(1), index_bnds(2), & 52 | - index_bnds(3), index_bnds(4)) 53 | + call get_domain_extent(Ocean_sfc%Domain, index_bnds(1), index_bnds(2), index_bnds(3), index_bnds(4)) 54 | 55 | weight = 1.0 56 | 57 | @@ -792,7 +783,7 @@ end subroutine ocean_model_end 58 | subroutine ocean_model_save_restart(OS, Time, directory, filename_suffix) 59 | type(ocean_state_type), pointer :: OS !< A pointer to the structure containing the 60 | !! internal ocean state (in). 61 | - type(time_type), intent(in) :: Time !< The model time at this call, needed for mpp_write calls. 62 | + type(time_type), intent(in) :: Time !< The model time at this call, needed for writing files. 63 | character(len=*), optional, intent(in) :: directory !< An optional directory into which to 64 | !! write these restart files. 65 | character(len=*), optional, intent(in) :: filename_suffix !< An optional suffix (e.g., a time-stamp) 66 | @@ -823,16 +814,12 @@ subroutine ocean_model_save_restart(OS, Time, directory, filename_suffix) 67 | end subroutine ocean_model_save_restart 68 | 69 | !> Initialize the public ocean type 70 | -subroutine initialize_ocean_public_type(input_domain, Ocean_sfc, diag, maskmap, & 71 | - gas_fields_ocn) 72 | - type(domain2D), intent(in) :: input_domain !< The ocean model domain description 73 | +subroutine initialize_ocean_public_type(input_domain, Ocean_sfc, diag, gas_fields_ocn) 74 | + type(MOM_domain_type), intent(in) :: input_domain !< The ocean model domain description 75 | type(ocean_public_type), intent(inout) :: Ocean_sfc !< A structure containing various publicly 76 | - !! visible ocean surface properties after initialization, whose 77 | - !! elements are allocated here. 78 | - type(diag_ctrl), intent(in) :: diag !< A structure that regulates diagnsotic output 79 | - logical, dimension(:,:), & 80 | - optional, intent(in) :: maskmap !< A mask indicating which virtual processors 81 | - !! are actually in use. If missing, all are used. 82 | + !! visible ocean surface properties after 83 | + !! initialization, whose elements are allocated here. 84 | + type(diag_ctrl), intent(in) :: diag !< A structure that regulates diagnostic output 85 | type(coupler_1d_bc_type), & 86 | optional, intent(in) :: gas_fields_ocn !< If present, this type describes the 87 | !! ocean and surface-ice fields that will participate 88 | @@ -844,14 +831,9 @@ subroutine initialize_ocean_public_type(input_domain, Ocean_sfc, diag, maskmap, 89 | ! and have no halos. 90 | integer :: isc, iec, jsc, jec 91 | 92 | - call mpp_get_layout(input_domain,layout) 93 | - call mpp_get_global_domain(input_domain, xsize=xsz, ysize=ysz) 94 | - if (PRESENT(maskmap)) then 95 | - call mpp_define_domains((/1,xsz,1,ysz/),layout,Ocean_sfc%Domain, maskmap=maskmap) 96 | - else 97 | - call mpp_define_domains((/1,xsz,1,ysz/),layout,Ocean_sfc%Domain) 98 | - endif 99 | - call mpp_get_compute_domain(Ocean_sfc%Domain, isc, iec, jsc, jec) 100 | + call clone_MOM_domain(input_domain, Ocean_sfc%Domain, halo_size=0, symmetric=.false.) 101 | + 102 | + call get_domain_extent(Ocean_sfc%Domain, isc, iec, jsc, jec) 103 | 104 | allocate ( Ocean_sfc%t_surf (isc:iec,jsc:jec), & 105 | Ocean_sfc%s_surf (isc:iec,jsc:jec), & 106 | @@ -907,8 +889,7 @@ subroutine convert_state_to_ocean_type(sfc_state, Ocean_sfc, G, US, patm, press_ 107 | is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec 108 | call pass_vector(sfc_state%u, sfc_state%v, G%Domain) 109 | 110 | - call mpp_get_compute_domain(Ocean_sfc%Domain, isc_bnd, iec_bnd, & 111 | - jsc_bnd, jec_bnd) 112 | + call get_domain_extent(Ocean_sfc%Domain, isc_bnd, iec_bnd, jsc_bnd, jec_bnd) 113 | if (present(patm)) then 114 | ! Check that the inidicies in patm are (isc_bnd:iec_bnd,jsc_bnd:jec_bnd). 115 | if (.not.present(press_to_z)) call MOM_error(FATAL, & 116 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |                 2 |

3 | [![Compilation Status](https://github.com/COSIMA/access-om3/actions/workflows/compilation.yml/badge.svg)](https://github.com/COSIMA/access-om3/actions/workflows/compilation.yml) 4 | 5 | # ACCESS-OM3 6 | 7 | ACCESS-OM3 is a global coupled ocean - sea ice - wave model being developed by [COSIMA](http://www.cosima.org.au) and [ACCESS-NRI](https://www.access-nri.org.au/). It consists of MOM6, CICE6 and (optionally) WaveWatch3, coupled with NUOPC and driven by prescribed surface forcing - see [here](https://access-om3-configs.access-hive.org.au/pages/Architecture/). 8 | 9 | # Downloading 10 | 11 | This repository only stores the model source code. Model configurations are available from branches in [github.com/ACCESS-NRI/access-om3-configs](https://github.com/ACCESS-NRI/access-om3-configs), which use pre-built executables available on [NCI](https://nci.org.au/), so NCI-based users of ACCESS-OM3 typically won't need to download this repository unless they need to make model component code changes. 12 | 13 | This respository contains submodules, so you will need to clone it with the `--recursive` flag: 14 | ``` 15 | git clone --recursive https://github.com/COSIMA/access-om3.git 16 | ``` 17 | 18 | To update a previous clone of this repository to the latest version, you will need to do 19 | ``` 20 | git pull 21 | git submodule update --init --recursive 22 | ``` 23 | to update all the submodules. 24 | 25 | # Documentation (including building and running the model) 26 | 27 | See [access-om3-configs.access-hive.org.au](https://access-om3-configs.access-hive.org.au/), particularly the [quick start](https://access-om3-configs.access-hive.org.au/pages/Quick-start/). 28 | -------------------------------------------------------------------------------- /WW3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ### Global definitions, flags, etc 2 | 3 | ## List of switches 4 | list(APPEND switches "CESMCOUPLED" "DIST" "MPI" "PR1" "FLX4" "ST6" "STAB0" "LN1" "NL1" "BT1" "DB1" "MLIM" "TR0" "BS0" "RWND" "WNX1" "WNT0" "CRX1" "CRT0" "O0" "O1" "O2" "O3" "O4" "O5" "O6" "O7" "O14" "O15" "IS2" "REF0" "NOGRB" "IC3") 5 | 6 | ## Global compile definitions 7 | foreach(switch ${switches}) 8 | add_compile_definitions(W3_${switch}) 9 | endforeach() 10 | 11 | ### Targets 12 | 13 | ## WW3 library 14 | add_fortran_library(OM3_ww3 mod STATIC) 15 | add_library(AccessOM3::ww3 ALIAS OM3_ww3) 16 | target_include_directories(OM3_ww3 PRIVATE $) 17 | target_compile_definitions(OM3_ww3 PRIVATE ENDIANNESS="big_endian") 18 | set_property(SOURCE WW3/model/src/w3initmd.F90 19 | APPEND 20 | PROPERTY COMPILE_DEFINITIONS 21 | "__WW3_SWITCHES__=\'\'" 22 | ) 23 | target_link_libraries(OM3_ww3 24 | PUBLIC esmf 25 | ) 26 | # Process switches and get list of extra source files 27 | include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_switches.cmake) 28 | check_switches("${switches}" switch_files) 29 | message(VERBOSE "WW3 switch files: ${switch_files}") 30 | target_sources(OM3_ww3 PRIVATE 31 | WW3/model/src/constants.F90 32 | WW3/model/src/w3adatmd.F90 33 | WW3/model/src/w3arrymd.F90 34 | WW3/model/src/w3bullmd.F90 35 | WW3/model/src/w3cspcmd.F90 36 | WW3/model/src/w3dispmd.F90 37 | WW3/model/src/w3fldsmd.F90 38 | WW3/model/src/w3gdatmd.F90 39 | WW3/model/src/w3gridmd.F90 40 | WW3/model/src/w3gsrumd.F90 41 | WW3/model/src/w3idatmd.F90 42 | WW3/model/src/w3initmd.F90 43 | WW3/model/src/w3iobcmd.F90 44 | WW3/model/src/w3iogomd.F90 45 | WW3/model/src/w3iogrmd.F90 46 | WW3/model/src/w3iopomd.F90 47 | WW3/model/src/w3iorsmd.F90 48 | WW3/model/src/w3iosfmd.F90 49 | WW3/model/src/w3iotrmd.F90 50 | WW3/model/src/w3macros.h 51 | WW3/model/src/w3metamd.F90 52 | WW3/model/src/w3nmlbouncmd.F90 53 | WW3/model/src/w3nmlboundmd.F90 54 | WW3/model/src/w3nmlgridmd.F90 55 | WW3/model/src/w3nmlmultimd.F90 56 | WW3/model/src/w3nmlounfmd.F90 57 | WW3/model/src/w3nmlounpmd.F90 58 | WW3/model/src/w3nmlprncmd.F90 59 | WW3/model/src/w3nmlshelmd.F90 60 | WW3/model/src/w3nmltrncmd.F90 61 | WW3/model/src/w3nmluprstrmd.F90 62 | WW3/model/src/w3odatmd.F90 63 | WW3/model/src/w3parall.F90 64 | WW3/model/src/w3partmd.F90 65 | WW3/model/src/w3servmd.F90 66 | WW3/model/src/w3strkmd.F90 67 | WW3/model/src/w3timemd.F90 68 | WW3/model/src/w3triamd.F90 69 | WW3/model/src/w3updtmd.F90 70 | WW3/model/src/w3wavemd.F90 71 | WW3/model/src/w3wdasmd.F90 72 | WW3/model/src/w3wdatmd.F90 73 | WW3/model/src/wmfinlmd.F90 74 | WW3/model/src/wmgridmd.F90 75 | WW3/model/src/wminiomd.F90 76 | WW3/model/src/wminitmd.F90 77 | WW3/model/src/wmiopomd.F90 78 | WW3/model/src/wmmdatmd.F90 79 | WW3/model/src/w3wavemd.F90 80 | WW3/model/src/wmunitmd.F90 81 | WW3/model/src/wmupdtmd.F90 82 | WW3/model/src/w3tidemd.F90 83 | WW3/model/src/wav_grdout.F90 84 | WW3/model/src/w3iogoncdmd.F90 85 | WW3/model/src/wav_shr_flags.F90 86 | 87 | WW3/model/src/wav_kind_mod.F90 88 | WW3/model/src/wav_shr_mod.F90 89 | WW3/model/src/wav_shel_inp.F90 90 | WW3/model/src/wav_comp_nuopc.F90 91 | WW3/model/src/wav_import_export.F90 92 | WW3/model/src/wav_wrapper_mod.F90 93 | 94 | ${switch_files} 95 | ) 96 | 97 | add_patched_source(OM3_ww3 WW3/model/src/w3srcemd.F90) 98 | 99 | ## Utilities 100 | 101 | # ww3_grid 102 | add_executable(OM3_ww3_grid WW3/model/src/ww3_grid.F90) 103 | set_target_properties(OM3_ww3_grid PROPERTIES 104 | LINKER_LANGUAGE Fortran 105 | OUTPUT_NAME ww3_grid 106 | ) 107 | target_link_libraries(OM3_ww3_grid PRIVATE AccessOM3::ww3) 108 | 109 | # ww3_strt 110 | add_executable(OM3_ww3_strt WW3/model/src/ww3_strt.F90) 111 | set_target_properties(OM3_ww3_strt PROPERTIES 112 | LINKER_LANGUAGE Fortran 113 | OUTPUT_NAME ww3_strt 114 | ) 115 | target_link_libraries(OM3_ww3_strt PRIVATE AccessOM3::ww3) 116 | 117 | # ww3_outf 118 | add_executable(OM3_ww3_outf WW3/model/src/ww3_outf.F90) 119 | set_target_properties(OM3_ww3_outf PROPERTIES 120 | LINKER_LANGUAGE Fortran 121 | OUTPUT_NAME ww3_outf 122 | ) 123 | target_link_libraries(OM3_ww3_outf PRIVATE AccessOM3::ww3) 124 | 125 | # ww3_ounf 126 | add_executable(OM3_ww3_ounf) 127 | target_sources(OM3_ww3_ounf PRIVATE 128 | WW3/model/src/ww3_ounf.F90 129 | WW3/model/src/w3ounfmetamd.F90 130 | ) 131 | set_target_properties(OM3_ww3_ounf PROPERTIES 132 | LINKER_LANGUAGE Fortran 133 | OUTPUT_NAME ww3_ounf 134 | ) 135 | target_link_libraries(OM3_ww3_ounf PRIVATE AccessOM3::ww3) 136 | 137 | # ww3_ounp 138 | add_executable(OM3_ww3_ounp WW3/model/src/ww3_ounp.F90) 139 | set_target_properties(OM3_ww3_ounp PROPERTIES 140 | LINKER_LANGUAGE Fortran 141 | OUTPUT_NAME ww3_ounp 142 | ) 143 | target_link_libraries(OM3_ww3_ounp PRIVATE AccessOM3::ww3) 144 | 145 | ### Install and Export 146 | 147 | ## Library 148 | if(OM3_LIB_INSTALL) 149 | set_target_properties(OM3_ww3 PROPERTIES 150 | OUTPUT_NAME access-ww3 151 | EXPORT_NAME ww3 152 | ) 153 | install(TARGETS OM3_ww3 154 | EXPORT AccessOM3ww3_Targets 155 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_RunTime NAMELINK_COMPONENT AccessOM3_Development 156 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_Development 157 | ) 158 | # Fortran module files are a special case, as currently there is no standard 159 | # way of handling them in CMake 160 | target_include_directories(OM3_ww3 PUBLIC "$") 161 | get_target_property(ww3_moddir OM3_ww3 Fortran_MODULE_DIRECTORY) 162 | install(FILES ${ww3_moddir}/wav_comp_nuopc.mod 163 | DESTINATION ${CMAKE_INSTALL_MODULEDIR}/access-ww3 164 | COMPONENT AccessOM3_Development 165 | ) 166 | install(EXPORT AccessOM3ww3_Targets 167 | FILE AccessOM3ww3Targets.cmake 168 | NAMESPACE AccessOM3:: 169 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AccessOM3 170 | ) 171 | endif() 172 | 173 | ## Utilities 174 | if(OM3_BIN_INSTALL) 175 | install(TARGETS OM3_ww3_grid OM3_ww3_strt OM3_ww3_outf OM3_ww3_ounf OM3_ww3_ounp 176 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 177 | endif() 178 | -------------------------------------------------------------------------------- /WW3/cmake/check_switches.cmake: -------------------------------------------------------------------------------- 1 | function(check_switches switches switch_files) 2 | # Read JSON file 3 | file(READ ${CMAKE_CURRENT_SOURCE_DIR}/WW3/model/src/cmake/switches.json json_str) 4 | # Get length of top-level array of all switch categories 5 | string(JSON len LENGTH ${json_str}) 6 | # CMake's foreach RANGE is inclusive, so subtract 1 when looping 7 | math(EXPR len "${len} - 1") 8 | 9 | # Loop over switch categories 10 | set(files "") 11 | foreach(i_category RANGE ${len}) 12 | string(JSON category GET ${json_str} ${i_category}) 13 | string(JSON num_options LENGTH ${category} valid-options) 14 | 15 | # Loop over valid options 16 | math(EXPR num_options "${num_options} - 1") 17 | set(n_switches_in_category 0) 18 | foreach(j_options RANGE ${num_options}) 19 | string(JSON valid_opt GET ${category} valid-options ${j_options} name) 20 | 21 | # This option is in current switch file 22 | if(valid_opt IN_LIST switches) 23 | math(EXPR n_switches_in_category "${n_switches_in_category} + 1") 24 | string(JSON n_files ERROR_VARIABLE err LENGTH ${category} valid-options ${j_options} build_files) 25 | 26 | # Check for conflicting switches 27 | string(JSON n_conflicts ERROR_VARIABLE err LENGTH ${category} valid-options ${j_options} conflicts) 28 | if(n_conflicts) 29 | math(EXPR n_conflicts "${n_conflicts} -1") 30 | # Loop over conflcits 31 | foreach(i_conflict RANGE ${n_conflicts}) 32 | string(JSON conflict GET ${category} valid-options ${j_options} conflicts ${i_conflict}) 33 | if(conflict IN_LIST switches) 34 | message(FATAL_ERROR "Switch '${valid_opt}' and '${conflict}' conflict") 35 | endif() 36 | endforeach() 37 | endif() 38 | 39 | # Check for required dependent switches 40 | string(JSON n_requires ERROR_VARIABLE err LENGTH ${category} valid-options ${j_options} requires) 41 | if(n_requires) 42 | math(EXPR n_requires "${n_requires} - 1") 43 | # Loop over required switches 44 | foreach(i_requires RANGE ${n_requires}) 45 | 46 | string(JSON json_type TYPE ${category} valid-options ${j_options} requires ${i_requires}) 47 | 48 | # Can be a string or an array. String values or directly required, while if an array one of the values is required. 49 | if(json_type STREQUAL "STRING") 50 | string(JSON required_switch GET ${category} valid-options ${j_options} requires ${i_requires}) 51 | if(NOT required_switch IN_LIST switches) 52 | message(FATAL_ERROR "Switch '${valid_opt}' requires '${required_switch}' to be set") 53 | endif() 54 | elseif(json_type STREQUAL "ARRAY") 55 | string(JSON n_requires_any LENGTH ${vategory} valid-options ${j_options} requries ${i_requires}) 56 | math(EXPR n_requires_any "${n_requires_any} - 1") 57 | 58 | # Loop over array and check that one of the switches is present 59 | set(found false) 60 | set(possible_values "") 61 | foreach(i_requires_any RANGE ${n_requires_any}) 62 | string(JSON required_switch GET ${category} valid-options ${j_options} requires ${i_requires} ${i_requires_any}) 63 | list(APPEND possible_values "${required_switch}") 64 | 65 | if(required_switch IN_LIST switches) 66 | set(found true) 67 | endif() 68 | endforeach() 69 | 70 | if(NOT found) 71 | message(FATAL_ERROR "Switch ${valid_opt} requires one of ${possible_values} to be set") 72 | endif() 73 | 74 | endif() 75 | endforeach() 76 | endif() 77 | 78 | if(n_files) 79 | # Loop over files associated with switch and add them to build 80 | math(EXPR n_files "${n_files} - 1") 81 | foreach(i_files RANGE ${n_files}) 82 | string(JSON file GET ${category} valid-options ${j_options} build_files ${i_files}) 83 | list(APPEND files "WW3/model/src/${file}") 84 | endforeach() 85 | endif() 86 | endif() 87 | 88 | endforeach() 89 | 90 | # Check for the correct number of switches per category 91 | string(JSON num_switches GET ${category} num_switches) 92 | string(JSON category_name GET ${category} name) 93 | 94 | if(num_switches STREQUAL "one" AND NOT n_switches_in_category EQUAL 1) 95 | message(FATAL_ERROR "No valid ${category_name} switches found, but one is required") 96 | elseif(num_switches STREQUAL "upto1" AND n_switches_in_category GREATER 1) 97 | message(FATAL_ERROR "Too many ${category_name} switches found (max 1)") 98 | elseif(num_switches STREQUAL "upto2" AND n_switches_in_category GREATER 2) 99 | message(FATAL_ERROR "Too many ${category_name} switches found (max 2)") 100 | endif() 101 | 102 | endforeach() 103 | 104 | set(${switch_files} ${files} PARENT_SCOPE) 105 | endfunction() 106 | -------------------------------------------------------------------------------- /WW3/patches/w3iorsmd.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/w3iorsmd.F90 b/w3iorsmd.F90.new 2 | index ffb34d47..0e32748b 100644 3 | --- a/w3iorsmd.F90 4 | +++ b/w3iorsmd.F90.new 5 | @@ -893,7 +893,7 @@ CONTAINS 6 | WRITEBUFF(:) = 0. 7 | WRITE (NDSR,POS=RPOS,ERR=803,IOSTAT=IERR) WRITEBUFF 8 | WRITE (NDSR,POS=RPOS,ERR=803,IOSTAT=IERR) & 9 | - TLEV, TICE, TRHO 10 | + TLEV, TICE, TRHO, TIC1, TIC5 11 | DO IPART=1,NPART 12 | NREC = NREC + 1 13 | RPOS = 1_8 + LRECL*(NREC-1_8) 14 | @@ -1078,7 +1078,7 @@ CONTAINS 15 | IF (TYPE.EQ.'FULL') THEN 16 | RPOS = 1_8 + LRECL*(NREC-1_8) 17 | READ (NDSR,POS=RPOS,ERR=802,IOSTAT=IERR) & 18 | - TLEV, TICE, TRHO 19 | + TLEV, TICE, TRHO, TIC1, TIC5 20 | DO IPART=1,NPART 21 | NREC = NREC + 1 22 | RPOS = 1_8 + LRECL*(NREC-1_8) 23 | -------------------------------------------------------------------------------- /WW3/patches/w3srcemd.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/model/src/w3srcemd.F90 b/model/src/w3srcemd.F90 2 | index 9bd97c6f..c51a8609 100644 3 | --- a/model/src/w3srcemd.F90 4 | +++ b/model/src/w3srcemd.F90 5 | @@ -2088,7 +2088,7 @@ CONTAINS 6 | #ifdef W3_IC3 7 | CALL W3SIC3 ( SPEC,DEPTH, CG1, WN1, IX, IY, VSIC, VDIC ) 8 | #endif 9 | -#ifndef W3_IC4_NUMERICS 10 | +#if defined(W3_IC4) && !defined(W3_IC4_NUMERICS) 11 | CALL W3SIC4 ( SPEC,DEPTH, CG1, IX, IY, VSIC, VDIC ) 12 | #endif 13 | #ifdef W3_IC5 14 | @@ -2119,7 +2119,7 @@ CONTAINS 15 | #ifdef W3_IC3 16 | ATT=EXP(ICE*VDIC(IS)*DTG) 17 | #endif 18 | -#ifndef W3_IC4_NUMERICS 19 | +#if defined(W3_IC4) && !defined(W3_IC4_NUMERICS) 20 | ATT=EXP(ICE*VDIC(IS)*DTG) 21 | #endif 22 | #ifdef W3_IC5 23 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # Compiles ACCESS-OM3 on gadi.nci.org.au 4 | # 5 | # This is just a prototype to get things working - eventually we'd want to do all of this with spack 6 | # 7 | # NB: Requires membership of the "ik11" project - apply at https://my.nci.org.au/mancini/project/ik11 if needed 8 | 9 | set -e 10 | 11 | SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" # dir of this script 12 | 13 | BUILD_TYPES=('Debug' 'Release') 14 | 15 | # CMakeLists.txt requires ESMF v8.3.0 or higher, FMS, and ParallelIO, but NCI doesn't supply them, so we use our own installation via spack. 16 | # This is in /g/data/ik11/spack/ which uses https://github.com/COSIMA/spack-config 17 | 18 | module purge 19 | module load cmake/3.24.2 20 | module use /g/data/ik11/spack/0.21.2/modules/access-om3/0.x.0/linux-rocky8-cascadelake # requires membership of "ik11" group 21 | module load esmf/8.5.0 fms/2023.02 parallelio/2.6.2 fortranxml/4.1.2 22 | module load intel-compiler/2021.10.0 openmpi/4.1.5 23 | 24 | cd ${SCRIPT_DIR} 25 | for BUILD_TYPE in "${BUILD_TYPES[@]}"; do 26 | echo "BUILD_TYPE = "${BUILD_TYPE} 27 | rm -r build || true 28 | INSTALL_DIR=${SCRIPT_DIR}/${BUILD_TYPE} 29 | 30 | cmake -S . -B build --preset=gadi -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_VERBOSE_MAKEFILE=ON 31 | cmake --build build -j 4 32 | cmake --install build --prefix=${INSTALL_DIR} 33 | 34 | echo "Successfully built ${INSTALL_DIR}" 35 | done 36 | -------------------------------------------------------------------------------- /cmake/AccessOM3Config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | if(NOT AccessOM3_FIND_QUIETLY) 4 | message(STATUS "Found AccessOM3: ${PACKAGE_PREFIX_DIR}") 5 | endif() 6 | 7 | # Available components 8 | 9 | # The following components are always available (order is important!) 10 | set(_supported_components timing share nuopc_cap_share cmeps cdeps mom6 cice ww3) 11 | 12 | # Check validity of requested components 13 | foreach(_comp ${AccessOM3_FIND_COMPONENTS}) 14 | if (NOT _comp IN_LIST _supported_components) 15 | set(AccessOM3_FOUND False) 16 | set(AccessOM3_NOT_FOUND_MESSAGE "Unsupported component: ${_comp}") 17 | endif() 18 | endforeach() 19 | 20 | # Some components are only available if they were built 21 | if ((mom6 IN_LIST ${AccessOM3_FIND_COMPONENTS}) AND (NOT @OM3_BUILD_MOM6@)) 22 | set(AccessOM3_FOUND False) 23 | set(AccessOM3_NOT_FOUND_MESSAGE "The following component is not available: mom6") 24 | endif() 25 | if ((cice IN_LIST ${AccessOM3_FIND_COMPONENTS}) AND (NOT @OM3_BUILD_CICE6@)) 26 | set(AccessOM3_FOUND False) 27 | set(AccessOM3_NOT_FOUND_MESSAGE "The following component is not available: cice") 28 | endif() 29 | if ((ww3 IN_LIST ${AccessOM3_FIND_COMPONENTS}) AND (NOT @OM3_BUILD_WW3@)) 30 | set(AccessOM3_FOUND False) 31 | set(AccessOM3_NOT_FOUND_MESSAGE "The following component is not available: ww3") 32 | endif() 33 | 34 | # Build a list of all the required components, taking into account their dependencies 35 | set(_required_components ${AccessOM3_FIND_COMPONENTS}) 36 | if(cice IN_LIST _required_components) 37 | list(APPEND _required_components cdeps nuopc_cap_share share timing) 38 | endif() 39 | if(mom6 IN_LIST _required_components) 40 | list(APPEND _required_components nuopc_cap_share share) 41 | endif() 42 | if(cdeps IN_LIST _required_components) 43 | list(APPEND _required_components cmeps share nuopc_cap_share) 44 | endif() 45 | if(cmeps IN_LIST _required_components) 46 | list(APPEND _required_components nuopc_cap_share share timing) 47 | endif() 48 | if(nuopc_cap_share IN_LIST _required_components) 49 | list(APPEND _required_components share timing) 50 | endif() 51 | if(share IN_LIST _required_components) 52 | list(APPEND _required_components timing) 53 | endif() 54 | list(REMOVE_DUPLICATES _required_components) 55 | 56 | if(NOT AccessOM3_FIND_QUIETLY) 57 | message(STATUS " - AccessOM3 Components: ${_required_components}") 58 | endif() 59 | 60 | # Include required targets. We do this by looping over the _supported_components 61 | # list because the order in which targets are loaded matters. 62 | foreach(_comp ${_supported_components}) 63 | if (_comp IN_LIST _required_components) 64 | include("${CMAKE_CURRENT_LIST_DIR}/AccessOM3${_comp}Targets.cmake") 65 | endif() 66 | endforeach() 67 | 68 | # Find dependencies of required components 69 | include(CMakeFindDependencyMacro) 70 | 71 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) 72 | 73 | if (cdeps IN_LIST _required_components) 74 | find_dependency(FoX) 75 | endif() 76 | if (mom6 IN_LIST _required_components) 77 | find_dependency(fms COMPONENTS R8 REQUIRED) 78 | endif() 79 | 80 | list(REMOVE_ITEM CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) 81 | 82 | check_required_components(_supported_components) 83 | -------------------------------------------------------------------------------- /cmake/AddPatchedSource.cmake: -------------------------------------------------------------------------------- 1 | # Apply a patch to a source file and add the resulting file to the sources of a 2 | # given target. 3 | function(add_patched_source TARGET FILE) 4 | # This function makes the following assumptions: 5 | # - patches are stored in ${CMAKE_CURRENT_SOURCE_DIR}/patches 6 | # - all patches to a given file are kept in the same patch file 7 | # - patch files are named ${FILE}.patch 8 | 9 | get_filename_component(filename ${FILE} NAME) 10 | 11 | add_custom_command( 12 | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${filename} 13 | COMMAND ${CMAKE_COMMAND} 14 | -Din_file:FILEPATH=${CMAKE_CURRENT_SOURCE_DIR}/${FILE} 15 | -Dpatch_file:FILEPATH=${CMAKE_CURRENT_SOURCE_DIR}/patches/${filename}.patch 16 | -Dout_file:FILEPATH=${CMAKE_CURRENT_BINARY_DIR}/${filename} 17 | -P ${CMAKE_SOURCE_DIR}/cmake/PatchFile.cmake 18 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} 19 | ) 20 | 21 | target_sources(${TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/${filename}) 22 | endfunction(add_patched_source) 23 | -------------------------------------------------------------------------------- /cmake/CMakePresets-compilers.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 5, 3 | "include": [ 4 | "CMakePresets-defaults.json" 5 | ], 6 | "configurePresets": [ 7 | { 8 | "name": "openmpi", 9 | "displayName": "Configure preset for OpenMPI based toolchains", 10 | "inherits": [ 11 | "default" 12 | ], 13 | "cacheVariables": { 14 | "CMAKE_Fortran_COMPILER": { 15 | "value": "mpif90" 16 | }, 17 | "CMAKE_C_COMPILER": { 18 | "value": "mpicc" 19 | } 20 | } 21 | }, 22 | { 23 | "name": "intel-mpi", 24 | "displayName": "Configure preset for Intel-MPI based toolchain", 25 | "inherits": [ 26 | "default" 27 | ], 28 | "cacheVariables": { 29 | "CMAKE_Fortran_COMPILER": { 30 | "type": "FILEPATH", 31 | "value": "mpiifort" 32 | }, 33 | "CMAKE_C_COMPILER": { 34 | "type": "FILEPATH", 35 | "value": "mpiicc" 36 | } 37 | } 38 | } 39 | ], 40 | "buildPresets": [ 41 | { 42 | "name": "toolchain-base", 43 | "hidden": true, 44 | "inherits": [ 45 | "default" 46 | ], 47 | "cleanFirst": true 48 | }, 49 | { 50 | "name": "openmpi", 51 | "displayName": "Build preset for OpenMPI based toolchains", 52 | "inherits": [ 53 | "toolchain-base" 54 | ], 55 | "configurePreset": "openmpi" 56 | }, 57 | { 58 | "name": "intel", 59 | "displayName": "Build preset for Intel-MPI based toolchains", 60 | "inherits": [ 61 | "toolchain-base" 62 | ], 63 | "configurePreset": "intel-mpi" 64 | } 65 | ] 66 | } 67 | -------------------------------------------------------------------------------- /cmake/CMakePresets-defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 5, 3 | "configurePresets": [ 4 | { 5 | "name": "default", 6 | "displayName": "Default configuration preset", 7 | "binaryDir": "cmake-build-release", 8 | "cacheVariables": { 9 | "CMAKE_BUILD_TYPE": { 10 | "type": "STRING", 11 | "value": "Release" 12 | } 13 | } 14 | } 15 | ], 16 | "buildPresets": [ 17 | { 18 | "name": "default", 19 | "displayName": "Default build preset", 20 | "configurePreset": "default" 21 | } 22 | ], 23 | "testPresets": [ 24 | { 25 | "name": "default", 26 | "displayName": "Default test preset", 27 | "configurePreset": "default" 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /cmake/CMakePresets-machines.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 5, 3 | "include": [ 4 | "CMakePresets-defaults.json", 5 | "CMakePresets-compilers.json" 6 | ], 7 | "configurePresets": [ 8 | { 9 | "name": "gadi", 10 | "displayName": "Configure preset for Gadi", 11 | "inherits": [ 12 | "openmpi" 13 | ], 14 | "cacheVariables": { 15 | "NetCDF_C_LIBRARY": { 16 | "type": "FILEPATH", 17 | "value": "$env{SPACK_NETCDF_C_ROOT}/lib/libnetcdf.so" 18 | }, 19 | "NetCDF_Fortran_LIBRARY": { 20 | "type": "FILEPATH", 21 | "value": "$env{SPACK_NETCDF_FORTRAN_ROOT}/lib/libnetcdff.so" 22 | }, 23 | "NetCDF_Fortran_INCLUDE_DIRS": { 24 | "type": "FILEPATH", 25 | "value": "$env{SPACK_NETCDF_FORTRAN_ROOT}/include" 26 | } 27 | } 28 | } 29 | ], 30 | "buildPresets": [ 31 | { 32 | "name": "gadi", 33 | "displayName": "Build preset for Gadi", 34 | "inherits": [ 35 | "openmpi" 36 | ], 37 | "cleanFirst": true, 38 | "configurePreset": "gadi" 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /cmake/FindESMF.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find ESMF 2 | # 3 | # Requires setting ESMFMKFILE to the filepath of esmf.mk. If this is NOT set, 4 | # then ESMF_FOUND will always be FALSE. If ESMFMKFILE exists, then ESMF_FOUND=TRUE 5 | # and all ESMF makefile variables will be set in the global scope. Optionally, 6 | # set ESMF_MKGLOBALS to a string list to filter makefile variables. For example, 7 | # to globally scope only ESMF_LIBSDIR and ESMF_APPSDIR variables, use this CMake 8 | # command in CMakeLists.txt: 9 | # 10 | # set(ESMF_MKGLOBALS "LIBSDIR" "APPSDIR") 11 | 12 | 13 | # Add the ESMFMKFILE path to the cache if defined as system env variable 14 | if(DEFINED ENV{ESMFMKFILE} AND NOT DEFINED ESMFMKFILE) 15 | set(ESMFMKFILE $ENV{ESMFMKFILE} CACHE FILEPATH "Path to ESMF mk file") 16 | endif() 17 | 18 | # If it's not explicitly set try to find esmf.mk file in default locations (ESMF_ROOT, CMAKE_PREFIX_PATH, etc) 19 | if(NOT DEFINED ESMFMKFILE) 20 | find_path(ESMFMKFILE_PATH esmf.mk PATH_SUFFIXES lib lib64) 21 | if(ESMFMKFILE_PATH) 22 | set(ESMFMKFILE ${ESMFMKFILE_PATH}/esmf.mk) 23 | message(STATUS "Found esmf.mk file ${ESMFMKFILE}") 24 | else() 25 | message(STATUS "ESMFMKFILE not defined. This is the path to esmf.mk file. \ 26 | Without this filepath, ESMF_FOUND will always be FALSE.") 27 | endif() 28 | endif() 29 | 30 | # Only parse the mk file if it is found 31 | if(EXISTS ${ESMFMKFILE}) 32 | # Read the mk file 33 | file(STRINGS "${ESMFMKFILE}" esmfmkfile_contents) 34 | # Parse each line in the mk file 35 | foreach(str ${esmfmkfile_contents}) 36 | # Only consider uncommented lines 37 | string(REGEX MATCH "^[^#]" def ${str}) 38 | # Line is not commented 39 | if(def) 40 | # Extract the variable name 41 | string(REGEX MATCH "^[^=]+" esmf_varname ${str}) 42 | # Extract the variable's value 43 | string(REGEX MATCH "=.+$" esmf_vardef ${str}) 44 | # Only for variables with a defined value 45 | if(esmf_vardef) 46 | # Get rid of the assignment string 47 | string(SUBSTRING ${esmf_vardef} 1 -1 esmf_vardef) 48 | # Remove whitespace 49 | string(STRIP ${esmf_vardef} esmf_vardef) 50 | # A string or single-valued list 51 | if(NOT DEFINED ESMF_MKGLOBALS) 52 | # Set in global scope 53 | set(${esmf_varname} ${esmf_vardef}) 54 | # Don't display by default in GUI 55 | mark_as_advanced(esmf_varname) 56 | else() # Need to filter global promotion 57 | foreach(m ${ESMF_MKGLOBALS}) 58 | string(FIND ${esmf_varname} ${m} match) 59 | # Found the string 60 | if(NOT ${match} EQUAL -1) 61 | # Promote to global scope 62 | set(${esmf_varname} ${esmf_vardef}) 63 | # Don't display by default in the GUI 64 | mark_as_advanced(esmf_varname) 65 | # No need to search for the current string filter 66 | break() 67 | endif() 68 | endforeach() 69 | endif() 70 | endif() 71 | endif() 72 | endforeach() 73 | 74 | # Construct ESMF_VERSION from ESMF_VERSION_STRING_GIT 75 | # ESMF_VERSION_MAJOR and ESMF_VERSION_MINOR are defined in ESMFMKFILE 76 | set(ESMF_VERSION 0) 77 | set(ESMF_VERSION_PATCH ${ESMF_VERSION_REVISION}) 78 | set(ESMF_BETA_RELEASE FALSE) 79 | if(ESMF_VERSION_BETASNAPSHOT MATCHES "^('T')$") 80 | set(ESMF_BETA_RELEASE TRUE) 81 | string(REGEX REPLACE ".*beta_snapshot_*\([0-9]*\).*" "\\1" ESMF_BETA_SNAPSHOT "${ESMF_VERSION_STRING_GIT}") 82 | message(STATUS "Detected ESMF Beta snapshot ${ESMF_BETA_SNAPSHOT}") 83 | endif() 84 | set(ESMF_VERSION "${ESMF_VERSION_MAJOR}.${ESMF_VERSION_MINOR}.${ESMF_VERSION_PATCH}") 85 | 86 | separate_arguments(ESMF_F90COMPILEPATHS NATIVE_COMMAND ${ESMF_F90COMPILEPATHS}) 87 | foreach(ITEM ${ESMF_F90COMPILEPATHS}) 88 | string(REGEX REPLACE "^-I" "" ITEM "${ITEM}") 89 | list(APPEND tmp ${ITEM}) 90 | endforeach() 91 | set(ESMF_F90COMPILEPATHS ${tmp}) 92 | 93 | # Look for static library, if not found try dynamic library 94 | find_library(esmf_lib NAMES libesmf.a PATHS ${ESMF_LIBSDIR}) 95 | if(esmf_lib MATCHES "esmf_lib-NOTFOUND") 96 | unset(esmf_lib) 97 | message(STATUS "Static ESMF library not found, searching for dynamic library instead") 98 | find_library(esmf_lib NAMES esmf_fullylinked libesmf.so PATHS ${ESMF_LIBSDIR}) 99 | if(esmf_lib MATCHES "esmf_lib-NOTFOUND") 100 | unset(esmf_lib) 101 | message(STATUS "Neither the dynamic nor the static ESMF library was found") 102 | else() 103 | set(_library_type SHARED) 104 | endif() 105 | else() 106 | set(_library_type STATIC) 107 | endif() 108 | 109 | string(STRIP "${ESMF_F90ESMFLINKRPATHS} ${ESMF_F90ESMFLINKPATHS} ${ESMF_F90LINKPATHS} ${ESMF_F90LINKLIBS} ${ESMF_F90LINKOPTS}" ESMF_INTERFACE_LINK_LIBRARIES) 110 | set(ESMF_LIBRARY_LOCATION ${esmf_lib}) 111 | 112 | else() 113 | 114 | message(WARNING "ESMFMKFILE ${ESMFMKFILE} does not exist") 115 | 116 | endif() 117 | 118 | ## Finalize find_package 119 | include(FindPackageHandleStandardArgs) 120 | 121 | find_package_handle_standard_args( 122 | ${CMAKE_FIND_PACKAGE_NAME} 123 | REQUIRED_VARS ESMF_LIBRARY_LOCATION 124 | ESMF_INTERFACE_LINK_LIBRARIES 125 | ESMF_F90COMPILEPATHS 126 | VERSION_VAR ESMF_VERSION) 127 | 128 | ## If ESMF is found create imported library target 129 | if(ESMF_FOUND) 130 | add_library(esmf ${_library_type} IMPORTED) 131 | set_target_properties(esmf PROPERTIES 132 | IMPORTED_LOCATION "${ESMF_LIBRARY_LOCATION}" 133 | INTERFACE_INCLUDE_DIRECTORIES "${ESMF_F90COMPILEPATHS}" 134 | INTERFACE_LINK_LIBRARIES "${ESMF_INTERFACE_LINK_LIBRARIES}") 135 | endif() 136 | -------------------------------------------------------------------------------- /cmake/FindFoX.cmake: -------------------------------------------------------------------------------- 1 | # We will use pkgconfig to find the library 2 | find_package(PkgConfig REQUIRED) 3 | 4 | ## Prepare arguments to pass to pkg_search_module 5 | 6 | # QUIET 7 | set(_quiet_arg) 8 | if (FoX_FIND_QUIETLY) 9 | list(APPEND _quiet_arg QUIET) 10 | endif () 11 | 12 | # REQUIRED 13 | set(_required_arg) 14 | if (FoX_FIND_REQUIRED) 15 | list(APPEND _required_arg REQUIRED) 16 | endif () 17 | 18 | # Construct the moduleSpec to search for 19 | if (DEFINED FoX_FIND_VERSION_RANGE) 20 | # Can only parse the minimum requirement 21 | list(APPEND PKG_MODULE_SPECS "fox>=${FoX_FIND_VERSION_MIN}") 22 | elseif ({FoX_FIND_VERSION_EXACT) 23 | # Requesting exact version 24 | list(APPEND PKG_MODULE_SPECS "fox=${FoX_FIND_VERSION}") 25 | elseif (DEFINED FoX_FIND_VERSION) 26 | # Otherwise treat the request as minimum requirement 27 | list(APPEND PKG_MODULE_SPECS "fox>=${FoX_FIND_VERSION}") 28 | else () 29 | # Fallthrough if no version is required 30 | list(APPEND PKG_MODULE_SPECS "fox") 31 | endif () 32 | 33 | ## Call pkg-config 34 | if (CMAKE_VERSION VERSION_LESS 3.28) 35 | # https://gitlab.kitware.com/cmake/cmake/-/issues/25228 36 | set(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS} 1) 37 | endif () 38 | if (CMAKE_VERSION VERSION_LESS 3.22) 39 | # Back-porting 40 | # https://gitlab.kitware.com/cmake/cmake/-/merge_requests/6345 41 | set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} 1) 42 | endif () 43 | pkg_search_module(FoX 44 | ${_required_arg} ${_quiet_arg} 45 | IMPORTED_TARGET 46 | ${PKG_MODULE_SPECS}) 47 | 48 | ## Create alias if package was found by pkg-config 49 | if (FoX_FOUND) 50 | add_library(FoX::FoX ALIAS PkgConfig::FoX) 51 | endif () 52 | 53 | # Sanitize local variables 54 | set(PKG_MODULE_SPECS) 55 | set(_quiet_arg) 56 | set(_required_arg) 57 | -------------------------------------------------------------------------------- /cmake/FindNetCDF.cmake: -------------------------------------------------------------------------------- 1 | # (C) Copyright 2011- ECMWF. 2 | # 3 | # This software is licensed under the terms of the Apache Licence Version 2.0 4 | # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. 5 | # In applying this licence, ECMWF does not waive the privileges and immunities 6 | # granted to it by virtue of its status as an intergovernmental organisation nor 7 | # does it submit to any jurisdiction. 8 | 9 | # Try to find NetCDF includes and library. 10 | # Supports static and shared libaries and allows each component to be found in sepearte prefixes. 11 | # 12 | # This module defines 13 | # 14 | # - NetCDF_FOUND - System has NetCDF 15 | # - NetCDF_INCLUDE_DIRS - the NetCDF include directories 16 | # - NetCDF_VERSION - the version of NetCDF 17 | # - NetCDF_CONFIG_EXECUTABLE - the netcdf-config executable if found 18 | # - NetCDF_PARALLEL - Boolean True if NetCDF4 has parallel IO support via hdf5 and/or pnetcdf 19 | # - NetCDF_HAS_PNETCDF - Boolean True if NetCDF4 has pnetcdf support 20 | # 21 | # Deprecated Defines 22 | # - NetCDF_LIBRARIES - [Deprecated] Use NetCDF::NetCDF_ targets instead. 23 | # 24 | # 25 | # Following components are available: 26 | # 27 | # - C - C interface to NetCDF (netcdf) 28 | # - CXX - CXX4 interface to NetCDF (netcdf_c++4) 29 | # - Fortran - Fortran interface to NetCDF (netcdff) 30 | # 31 | # For each component the following are defined: 32 | # 33 | # - NetCDF__FOUND - whether the component is found 34 | # - NetCDF__LIBRARIES - the libraries for the component 35 | # - NetCDF__LIBRARY_SHARED - Boolean is true if libraries for component are shared 36 | # - NetCDF__INCLUDE_DIRS - the include directories for specified component 37 | # - NetCDF::NetCDF_ - target of component to be used with target_link_libraries() 38 | # 39 | # The following paths will be searched in order if set in CMake (first priority) or environment (second priority) 40 | # 41 | # - NetCDF_ROOT - root of NetCDF installation 42 | # - NetCDF_PATH - root of NetCDF installation 43 | # 44 | # The search process begins with locating NetCDF Include headers. If these are in a non-standard location, 45 | # set one of the following CMake or environment variables to point to the location: 46 | # 47 | # - NetCDF_INCLUDE_DIR or NetCDF_${comp}_INCLUDE_DIR 48 | # - NetCDF_INCLUDE_DIRS or NetCDF_${comp}_INCLUDE_DIR 49 | # 50 | # Notes: 51 | # 52 | # - Use "NetCDF::NetCDF_" targets only. NetCDF_LIBRARIES exists for backwards compatibility and should not be used. 53 | # - These targets have all the knowledge of include directories and library search directories, and a single 54 | # call to target_link_libraries will provide all these transitive properties to your target. Normally all that is 55 | # needed to build and link against NetCDF is, e.g.: 56 | # target_link_libraries(my_c_tgt PUBLIC NetCDF::NetCDF_C) 57 | # - "NetCDF" is always the preferred naming for this package, its targets, variables, and environment variables 58 | # - For compatibility, some variables are also set/checked using alternate names NetCDF4, NETCDF, or NETCDF4 59 | # - Environments relying on these older environment variable names should move to using a "NetCDF_ROOT" environment variable 60 | # - Preferred component capitalization follows the CMake LANGUAGES variables: i.e., C, Fortran, CXX 61 | # - For compatibility, alternate capitalizations are supported but should not be used. 62 | # - If no components are defined, all components will be searched 63 | # 64 | 65 | list( APPEND _possible_components C CXX Fortran ) 66 | 67 | ## Include names for each component 68 | set( NetCDF_C_INCLUDE_NAME netcdf.h ) 69 | set( NetCDF_CXX_INCLUDE_NAME netcdf ) 70 | set( NetCDF_Fortran_INCLUDE_NAME netcdf.mod ) 71 | 72 | ## Library names for each component 73 | set( NetCDF_C_LIBRARY_NAME netcdf ) 74 | set( NetCDF_CXX_LIBRARY_NAME netcdf_c++4 ) 75 | set( NetCDF_Fortran_LIBRARY_NAME netcdff ) 76 | 77 | ## Enumerate search components 78 | foreach( _comp ${_possible_components} ) 79 | string( TOUPPER "${_comp}" _COMP ) 80 | set( _arg_${_COMP} ${_comp} ) 81 | set( _name_${_COMP} ${_comp} ) 82 | endforeach() 83 | 84 | set( _search_components C) 85 | foreach( _comp ${${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS} ) 86 | string( TOUPPER "${_comp}" _COMP ) 87 | set( _arg_${_COMP} ${_comp} ) 88 | list( APPEND _search_components ${_name_${_COMP}} ) 89 | if( NOT _name_${_COMP} ) 90 | message(SEND_ERROR "Find${CMAKE_FIND_PACKAGE_NAME}: COMPONENT ${_comp} is not a valid component. Valid components: ${_possible_components}" ) 91 | endif() 92 | endforeach() 93 | list( REMOVE_DUPLICATES _search_components ) 94 | 95 | ## Search hints for finding include directories and libraries 96 | foreach( _comp IN ITEMS "_" "_C_" "_Fortran_" "_CXX_" ) 97 | foreach( _name IN ITEMS NetCDF4 NetCDF NETCDF4 NETCDF ) 98 | foreach( _var IN ITEMS ROOT PATH ) 99 | list(APPEND _search_hints ${${_name}${_comp}${_var}} $ENV{${_name}${_comp}${_var}} ) 100 | list(APPEND _include_search_hints 101 | ${${_name}${_comp}INCLUDE_DIR} $ENV{${_name}${_comp}INCLUDE_DIR} 102 | ${${_name}${_comp}INCLUDE_DIRS} $ENV{${_name}${_comp}INCLUDE_DIRS} ) 103 | endforeach() 104 | endforeach() 105 | endforeach() 106 | #Old-school HPC module env variable names 107 | foreach( _name IN ITEMS NetCDF4 NetCDF NETCDF4 NETCDF ) 108 | foreach( _comp IN ITEMS "_C" "_Fortran" "_CXX" ) 109 | list(APPEND _search_hints ${${_name}} $ENV{${_name}}) 110 | list(APPEND _search_hints ${${_name}${_comp}} $ENV{${_name}${_comp}}) 111 | endforeach() 112 | endforeach() 113 | 114 | ## Find headers for each component 115 | set(NetCDF_INCLUDE_DIRS) 116 | set(_new_search_components) 117 | foreach( _comp IN LISTS _search_components ) 118 | if(NOT ${PROJECT_NAME}_NetCDF_${_comp}_FOUND) 119 | list(APPEND _new_search_components ${_comp}) 120 | endif() 121 | find_file(NetCDF_${_comp}_INCLUDE_FILE 122 | NAMES ${NetCDF_${_comp}_INCLUDE_NAME} 123 | DOC "NetCDF ${_comp} include directory" 124 | HINTS ${_include_search_hints} ${_search_hints} 125 | PATH_SUFFIXES include include/netcdf 126 | ) 127 | mark_as_advanced(NetCDF_${_comp}_INCLUDE_FILE) 128 | message(DEBUG "NetCDF_${_comp}_INCLUDE_FILE: ${NetCDF_${_comp}_INCLUDE_FILE}") 129 | if( NetCDF_${_comp}_INCLUDE_FILE ) 130 | get_filename_component(NetCDF_${_comp}_INCLUDE_FILE ${NetCDF_${_comp}_INCLUDE_FILE} ABSOLUTE) 131 | get_filename_component(NetCDF_${_comp}_INCLUDE_DIR ${NetCDF_${_comp}_INCLUDE_FILE} DIRECTORY) 132 | list(APPEND NetCDF_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIR}) 133 | endif() 134 | endforeach() 135 | if(NetCDF_INCLUDE_DIRS) 136 | list(REMOVE_DUPLICATES NetCDF_INCLUDE_DIRS) 137 | endif() 138 | set(NetCDF_INCLUDE_DIRS "${NetCDF_INCLUDE_DIRS}" CACHE STRING "NetCDF Include directory paths" FORCE) 139 | 140 | ## Find n*-config executables for search components 141 | foreach( _comp IN LISTS _search_components ) 142 | if( _comp MATCHES "^(C)$" ) 143 | set(_conf "c") 144 | elseif( _comp MATCHES "^(Fortran)$" ) 145 | set(_conf "f") 146 | elseif( _comp MATCHES "^(CXX)$" ) 147 | set(_conf "cxx4") 148 | endif() 149 | find_program( NetCDF_${_comp}_CONFIG_EXECUTABLE 150 | NAMES n${_conf}-config 151 | HINTS ${NetCDF_INCLUDE_DIRS} ${_include_search_hints} ${_search_hints} 152 | PATH_SUFFIXES bin Bin ../bin ../../bin 153 | DOC "NetCDF n${_conf}-config helper" ) 154 | message(DEBUG "NetCDF_${_comp}_CONFIG_EXECUTABLE: ${NetCDF_${_comp}_CONFIG_EXECUTABLE}") 155 | endforeach() 156 | 157 | set(_C_libs_flag --libs) 158 | set(_Fortran_libs_flag --flibs) 159 | set(_CXX_libs_flag --libs) 160 | set(_C_includes_flag --includedir) 161 | set(_Fortran_includes_flag --includedir) 162 | set(_CXX_includes_flag --includedir) 163 | function(netcdf_config exec flag output_var) 164 | set(${output_var} False PARENT_SCOPE) 165 | if( exec ) 166 | execute_process( COMMAND ${exec} ${flag} RESULT_VARIABLE _ret OUTPUT_VARIABLE _val) 167 | if( _ret EQUAL 0 ) 168 | string( STRIP ${_val} _val ) 169 | set( ${output_var} ${_val} PARENT_SCOPE ) 170 | endif() 171 | endif() 172 | endfunction() 173 | 174 | ## Find libraries for each component 175 | set( NetCDF_LIBRARIES ) 176 | foreach( _comp IN LISTS _search_components ) 177 | string( TOUPPER "${_comp}" _COMP ) 178 | 179 | find_library( NetCDF_${_comp}_LIBRARY 180 | NAMES ${NetCDF_${_comp}_LIBRARY_NAME} 181 | DOC "NetCDF ${_comp} library" 182 | HINTS ${NetCDF_${_comp}_INCLUDE_DIRS} ${_search_hints} 183 | PATH_SUFFIXES lib64 lib ../lib64 ../lib ../../lib64 ../../lib ) 184 | mark_as_advanced( NetCDF_${_comp}_LIBRARY ) 185 | get_filename_component(NetCDF_${_comp}_LIBRARY ${NetCDF_${_comp}_LIBRARY} ABSOLUTE) 186 | set(NetCDF_${_comp}_LIBRARY ${NetCDF_${_comp}_LIBRARY} CACHE STRING "NetCDF ${_comp} library" FORCE) 187 | message(DEBUG "NetCDF_${_comp}_LIBRARY: ${NetCDF_${_comp}_LIBRARY}") 188 | 189 | if( NetCDF_${_comp}_LIBRARY ) 190 | if( NetCDF_${_comp}_LIBRARY MATCHES ".a$" ) 191 | set( NetCDF_${_comp}_LIBRARY_SHARED FALSE ) 192 | set( _library_type STATIC) 193 | else() 194 | list( APPEND NetCDF_LIBRARIES ${NetCDF_${_comp}_LIBRARY} ) 195 | set( NetCDF_${_comp}_LIBRARY_SHARED TRUE ) 196 | set( _library_type SHARED) 197 | endif() 198 | endif() 199 | 200 | #Use nc-config to set per-component LIBRARIES variable if possible 201 | netcdf_config( ${NetCDF_${_comp}_CONFIG_EXECUTABLE} ${_${_comp}_libs_flag} _val ) 202 | if( _val ) 203 | set( NetCDF_${_comp}_LIBRARIES ${_val} ) 204 | 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. 205 | list( APPEND NetCDF_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) 206 | endif() 207 | else() 208 | set( NetCDF_${_comp}_LIBRARIES ${NetCDF_${_comp}_LIBRARY} ) 209 | if(NOT NetCDF_${_comp}_LIBRARY_SHARED) 210 | message(SEND_ERROR "Unable to properly find NetCDF. Found static libraries at: ${NetCDF_${_comp}_LIBRARY} but could not run nc-config: ${NetCDF_CONFIG_EXECUTABLE}") 211 | endif() 212 | endif() 213 | 214 | #Use nc-config to set per-component INCLUDE_DIRS variable if possible 215 | netcdf_config( ${NetCDF_${_comp}_CONFIG_EXECUTABLE} ${_${_comp}_includes_flag} _val ) 216 | if( _val ) 217 | string( REPLACE " " ";" _val ${_val} ) 218 | set( NetCDF_${_comp}_INCLUDE_DIRS ${_val} ) 219 | else() 220 | set( NetCDF_${_comp}_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIR} ) 221 | endif() 222 | 223 | if( NetCDF_${_comp}_LIBRARIES AND NetCDF_${_comp}_INCLUDE_DIRS ) 224 | set( ${CMAKE_FIND_PACKAGE_NAME}_${_arg_${_COMP}}_FOUND TRUE ) 225 | if (NOT TARGET NetCDF::NetCDF_${_comp}) 226 | add_library(NetCDF::NetCDF_${_comp} ${_library_type} IMPORTED) 227 | set_target_properties(NetCDF::NetCDF_${_comp} PROPERTIES 228 | IMPORTED_LOCATION ${NetCDF_${_comp}_LIBRARY} 229 | INTERFACE_INCLUDE_DIRECTORIES "${NetCDF_${_comp}_INCLUDE_DIRS}" 230 | INTERFACE_LINK_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) 231 | endif() 232 | endif() 233 | endforeach() 234 | if(NetCDF_LIBRARIES AND NetCDF_${_comp}_LIBRARY_SHARED) 235 | list(REMOVE_DUPLICATES NetCDF_LIBRARIES) 236 | endif() 237 | set(NetCDF_LIBRARIES "${NetCDF_LIBRARIES}" CACHE STRING "NetCDF library targets" FORCE) 238 | 239 | ## Find version via netcdf-config if possible 240 | if (NetCDF_INCLUDE_DIRS) 241 | if( NetCDF_C_CONFIG_EXECUTABLE ) 242 | netcdf_config( ${NetCDF_C_CONFIG_EXECUTABLE} --version _vers ) 243 | if( _vers ) 244 | string(REGEX REPLACE ".* ((([0-9]+)\\.)+([0-9]+)).*" "\\1" NetCDF_VERSION "${_vers}" ) 245 | endif() 246 | else() 247 | foreach( _dir IN LISTS NetCDF_INCLUDE_DIRS) 248 | if( EXISTS "${_dir}/netcdf_meta.h" ) 249 | file(STRINGS "${_dir}/netcdf_meta.h" _netcdf_version_lines 250 | REGEX "#define[ \t]+NC_VERSION_(MAJOR|MINOR|PATCH|NOTE)") 251 | string(REGEX REPLACE ".*NC_VERSION_MAJOR *\([0-9]*\).*" "\\1" _netcdf_version_major "${_netcdf_version_lines}") 252 | string(REGEX REPLACE ".*NC_VERSION_MINOR *\([0-9]*\).*" "\\1" _netcdf_version_minor "${_netcdf_version_lines}") 253 | string(REGEX REPLACE ".*NC_VERSION_PATCH *\([0-9]*\).*" "\\1" _netcdf_version_patch "${_netcdf_version_lines}") 254 | string(REGEX REPLACE ".*NC_VERSION_NOTE *\"\([^\"]*\)\".*" "\\1" _netcdf_version_note "${_netcdf_version_lines}") 255 | set(NetCDF_VERSION "${_netcdf_version_major}.${_netcdf_version_minor}.${_netcdf_version_patch}${_netcdf_version_note}") 256 | unset(_netcdf_version_major) 257 | unset(_netcdf_version_minor) 258 | unset(_netcdf_version_patch) 259 | unset(_netcdf_version_note) 260 | unset(_netcdf_version_lines) 261 | endif() 262 | endforeach() 263 | endif() 264 | endif () 265 | 266 | ## Detect additional package properties 267 | netcdf_config(${NetCDF_C_CONFIG_EXECUTABLE} --has-parallel4 _val) 268 | if( NOT _val MATCHES "^(yes|no)$" ) 269 | netcdf_config(${NetCDF_C_CONFIG_EXECUTABLE} --has-parallel _val) 270 | endif() 271 | if( _val MATCHES "^(yes)$" ) 272 | set(NetCDF_PARALLEL TRUE CACHE STRING "NetCDF has parallel IO capability via pnetcdf or hdf5." FORCE) 273 | else() 274 | set(NetCDF_PARALLEL FALSE CACHE STRING "NetCDF has no parallel IO capability." FORCE) 275 | endif() 276 | 277 | ## Finalize find_package 278 | include(FindPackageHandleStandardArgs) 279 | 280 | if(NOT NetCDF_FOUND OR _new_search_components) 281 | find_package_handle_standard_args( ${CMAKE_FIND_PACKAGE_NAME} 282 | REQUIRED_VARS NetCDF_INCLUDE_DIRS NetCDF_LIBRARIES 283 | VERSION_VAR NetCDF_VERSION 284 | HANDLE_COMPONENTS ) 285 | endif() 286 | 287 | foreach( _comp IN LISTS _search_components ) 288 | if( NetCDF_${_comp}_FOUND ) 289 | #Record found components to avoid duplication in NetCDF_LIBRARIES for static libraries 290 | set(NetCDF_${_comp}_FOUND ${NetCDF_${_comp}_FOUND} CACHE BOOL "NetCDF ${_comp} Found" FORCE) 291 | #Set a per-package, per-component found variable to communicate between multiple calls to find_package() 292 | set(${PROJECT_NAME}_NetCDF_${_comp}_FOUND True) 293 | endif() 294 | endforeach() 295 | 296 | if( ${CMAKE_FIND_PACKAGE_NAME}_FOUND AND NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY AND _new_search_components) 297 | message( STATUS "Find${CMAKE_FIND_PACKAGE_NAME} defines targets:" ) 298 | message( STATUS " - NetCDF_VERSION [${NetCDF_VERSION}]") 299 | message( STATUS " - NetCDF_PARALLEL [${NetCDF_PARALLEL}]") 300 | foreach( _comp IN LISTS _new_search_components ) 301 | string( TOUPPER "${_comp}" _COMP ) 302 | message( STATUS " - NetCDF_${_comp}_CONFIG_EXECUTABLE [${NetCDF_${_comp}_CONFIG_EXECUTABLE}]") 303 | if( ${CMAKE_FIND_PACKAGE_NAME}_${_arg_${_COMP}}_FOUND ) 304 | get_filename_component(_root ${NetCDF_${_comp}_INCLUDE_DIR}/.. ABSOLUTE) 305 | if( NetCDF_${_comp}_LIBRARY_SHARED ) 306 | message( STATUS " - NetCDF::NetCDF_${_comp} [SHARED] [Root: ${_root}] Lib: ${NetCDF_${_comp}_LIBRARY} ") 307 | else() 308 | message( STATUS " - NetCDF::NetCDF_${_comp} [STATIC] [Root: ${_root}] Lib: ${NetCDF_${_comp}_LIBRARY} ") 309 | endif() 310 | endif() 311 | endforeach() 312 | endif() 313 | 314 | foreach( _prefix NetCDF NetCDF4 NETCDF NETCDF4 ${CMAKE_FIND_PACKAGE_NAME} ) 315 | set( ${_prefix}_INCLUDE_DIRS ${NetCDF_INCLUDE_DIRS} ) 316 | set( ${_prefix}_LIBRARIES ${NetCDF_LIBRARIES}) 317 | set( ${_prefix}_VERSION ${NetCDF_VERSION} ) 318 | set( ${_prefix}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_FOUND} ) 319 | set( ${_prefix}_CONFIG_EXECUTABLE ${NetCDF_CONFIG_EXECUTABLE} ) 320 | set( ${_prefix}_PARALLEL ${NetCDF_PARALLEL} ) 321 | 322 | foreach( _comp ${_search_components} ) 323 | string( TOUPPER "${_comp}" _COMP ) 324 | set( _arg_comp ${_arg_${_COMP}} ) 325 | set( ${_prefix}_${_comp}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_${_arg_comp}_FOUND} ) 326 | set( ${_prefix}_${_COMP}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_${_arg_comp}_FOUND} ) 327 | set( ${_prefix}_${_arg_comp}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_${_arg_comp}_FOUND} ) 328 | 329 | set( ${_prefix}_${_comp}_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) 330 | set( ${_prefix}_${_COMP}_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) 331 | set( ${_prefix}_${_arg_comp}_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) 332 | 333 | set( ${_prefix}_${_comp}_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIRS} ) 334 | set( ${_prefix}_${_COMP}_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIRS} ) 335 | set( ${_prefix}_${_arg_comp}_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIRS} ) 336 | endforeach() 337 | endforeach() 338 | -------------------------------------------------------------------------------- /cmake/FindPIO.cmake: -------------------------------------------------------------------------------- 1 | # FindPIO.cmake 2 | # 3 | # Copyright UCAR 2020 4 | # Copyright NOAA/NWS/NCEP/EMC 2020 5 | # 6 | # Find PIO: A high-level Parallel I/O Library for structured grid applications 7 | # https://github.com/NCAR/ParallelIO 8 | # 9 | # Components available for query: 10 | # C - Has C support 11 | # Fortran - Has Fortran support 12 | # SHARED - Has shared targets 13 | # STATIC - Has static targets 14 | # 15 | # Variables provided: 16 | # PIO_FOUND - True if PIO was found 17 | # PIO_C_FOUND - True if PIO C support was found 18 | # PIO_Fortran_FOUND - True if PIO Fortran support was found 19 | # PIO_VERSION - Version of installed PIO 20 | # 21 | # Targets provided: 22 | # PIO::PIO_C - C interface target aliased to SHARED|STATIC as requested or to shared libraries if available else static libraries 23 | # PIO::PIO_Fortran - Fortran interface target aliases to SHARED|STATIC as requested or to shared libraries if available else static libraries 24 | # 25 | # To control finding of this package, set PIO_ROOT environment variable to the full path to the prefix 26 | # under which PIO was installed (e.g., /usr/local) 27 | 28 | set( _search_components ) 29 | set( _search_library_type ) 30 | foreach( _comp ${${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS} ) 31 | if( _comp MATCHES "^(STATIC|SHARED)$" ) 32 | list( APPEND _search_library_type ${_comp} ) 33 | else() 34 | list( APPEND _search_components ${_comp} ) 35 | endif() 36 | endforeach() 37 | set( ${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS ${_search_components} ) 38 | 39 | # If no COMPONENTS are requested, seach both C and Fortran 40 | if( NOT _search_components ) 41 | list( APPEND _search_components C Fortran ) 42 | endif() 43 | 44 | # Ensure there is only one type of library being requested 45 | if( _search_library_type ) 46 | list( LENGTH _search_library_type _len) 47 | if( _len GREATER 1 ) 48 | message(FATAL_ERROR "User requesting both STATIC and SHARED is not permissible") 49 | endif() 50 | unset(_len) 51 | endif() 52 | 53 | ## Find libraries and paths, and determine found components 54 | find_path(PIO_INCLUDE_DIR NAMES pio.h HINTS "${PIO_PREFIX}" PATH_SUFFIXES include include/pio) 55 | if(PIO_INCLUDE_DIR) 56 | string(REGEX REPLACE "/include(/.+)?" "" PIO_PREFIX ${PIO_INCLUDE_DIR}) 57 | set(PIO_PREFIX ${PIO_PREFIX} CACHE STRING "") 58 | find_path(PIO_MODULE_DIR NAMES pio.mod PATHS "${PIO_PREFIX}" 59 | PATH_SUFFIXES include include/pio lib/pio/module module module/pio NO_DEFAULT_PATH) 60 | if(APPLE) 61 | set(_SHARED_LIB_EXT dylib) 62 | else() 63 | set(_SHARED_LIB_EXT so) 64 | endif() 65 | find_library(PIO_C_STATIC_LIB libpioc.a PATHS "${PIO_PREFIX}" PATH_SUFFIXES lib lib64 NO_DEFAULT_PATH) 66 | find_library(PIO_C_SHARED_LIB libpioc.${_SHARED_LIB_EXT} PATHS "${PIO_PREFIX}" PATH_SUFFIXES lib lib64 NO_DEFAULT_PATH) 67 | find_library(PIO_Fortran_STATIC_LIB libpiof.a PATHS "${PIO_PREFIX}" PATH_SUFFIXES lib lib64 NO_DEFAULT_PATH) 68 | find_library(PIO_Fortran_SHARED_LIB libpiof.${_SHARED_LIB_EXT} PATHS "${PIO_PREFIX}" PATH_SUFFIXES lib lib64 NO_DEFAULT_PATH) 69 | unset(_SHARED_LIB_EXT) 70 | #Check for Fortran components 71 | if(PIO_MODULE_DIR) 72 | if(PIO_Fortran_STATIC_LIB) 73 | set(PIO_Fortran_STATIC_FOUND 1) 74 | endif() 75 | if(PIO_Fortran_SHARED_LIB) 76 | set(PIO_Fortran_SHARED_FOUND 1) 77 | endif() 78 | endif() 79 | #Check for C components 80 | if(PIO_C_STATIC_LIB) 81 | set(PIO_C_STATIC_FOUND 1) 82 | endif() 83 | if(PIO_C_SHARED_LIB) 84 | set(PIO_C_SHARED_FOUND 1) 85 | endif() 86 | endif() 87 | ## Debugging output 88 | message(DEBUG "[FindPIO] PIO_INCLUDE_DIR: ${PIO_INCLUDE_DIR}") 89 | message(DEBUG "[FindPIO] PIO_PREFIX: ${PIO_PREFIX}") 90 | message(DEBUG "[FindPIO] PIO_MODULE_DIR: ${PIO_MODULE_DIR}") 91 | message(DEBUG "[FindPIO] PIO_C_STATIC_LIB: ${PIO_C_STATIC_LIB}") 92 | message(DEBUG "[FindPIO] PIO_C_SHARED_LIB: ${PIO_C_SHARED_LIB}") 93 | message(DEBUG "[FindPIO] PIO_C_SHARED_FOUND: ${PIO_C_SHARED_FOUND}") 94 | message(DEBUG "[FindPIO] PIO_C_STATIC_FOUND: ${PIO_C_STATIC_FOUND}") 95 | message(DEBUG "[FindPIO] PIO_Fortran_STATIC_LIB: ${PIO_Fortran_STATIC_LIB}") 96 | message(DEBUG "[FindPIO] PIO_Fortran_SHARED_LIB: ${PIO_Fortran_SHARED_LIB}") 97 | message(DEBUG "[FindPIO] PIO_Fortran_SHARED_FOUND: ${PIO_Fortran_SHARED_FOUND}") 98 | message(DEBUG "[FindPIO] PIO_Fortran_STATIC_FOUND: ${PIO_Fortran_STATIC_FOUND}") 99 | 100 | ## Create targets 101 | set(_new_components) 102 | # PIO_C_STATIC imported interface target 103 | if(PIO_C_STATIC_FOUND AND NOT TARGET PIO_C_STATIC) 104 | add_library(PIO_C_STATIC INTERFACE IMPORTED) 105 | set_target_properties(PIO_C_STATIC PROPERTIES 106 | INTERFACE_INCLUDE_DIRECTORIES ${PIO_INCLUDE_DIR} 107 | INTERFACE_LINK_LIBRARIES ${PIO_C_STATIC_LIB} 108 | IMPORTED_GLOBAL True ) 109 | set(_new_components 1) 110 | endif() 111 | # PIO_C_SHARED imported interface target 112 | if(PIO_C_SHARED_FOUND AND NOT TARGET PIO_C_SHARED) 113 | add_library(PIO_C_SHARED INTERFACE IMPORTED) 114 | set_target_properties(PIO_C_SHARED PROPERTIES 115 | INTERFACE_INCLUDE_DIRECTORIES ${PIO_INCLUDE_DIR} 116 | INTERFACE_LINK_LIBRARIES ${PIO_C_SHARED_LIB} 117 | IMPORTED_GLOBAL True ) 118 | set(_new_components 1) 119 | endif() 120 | # PIO_Fortran_STATIC imported interface target 121 | if(PIO_Fortran_STATIC_FOUND AND NOT TARGET PIO_Fortran_STATIC) 122 | add_library(PIO_Fortran_STATIC INTERFACE IMPORTED) 123 | set_target_properties(PIO_Fortran_STATIC PROPERTIES 124 | INTERFACE_INCLUDE_DIRECTORIES ${PIO_INCLUDE_DIR} 125 | INTERFACE_LINK_LIBRARIES ${PIO_Fortran_STATIC_LIB} 126 | IMPORTED_GLOBAL True ) 127 | if(PIO_MODULE_DIR AND NOT PIO_MODULE_DIR STREQUAL PIO_INCLUDE_DIR ) 128 | set_property(TARGET PIO_Fortran_STATIC APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${PIO_MODULE_DIR}) 129 | endif() 130 | set(_new_components 1) 131 | target_link_libraries(PIO_Fortran_STATIC INTERFACE PIO_C_STATIC) 132 | endif() 133 | # PIO_Fortran_SHARED imported interface target 134 | if(PIO_Fortran_SHARED_FOUND AND NOT TARGET PIO_Fortran_SHARED) 135 | add_library(PIO_Fortran_SHARED INTERFACE IMPORTED) 136 | set_target_properties(PIO_Fortran_SHARED PROPERTIES 137 | INTERFACE_INCLUDE_DIRECTORIES ${PIO_INCLUDE_DIR} 138 | INTERFACE_LINK_LIBRARIES ${PIO_Fortran_SHARED_LIB} 139 | IMPORTED_GLOBAL True ) 140 | if(PIO_MODULE_DIR AND NOT PIO_MODULE_DIR STREQUAL PIO_INCLUDE_DIR ) 141 | set_property(TARGET PIO_Fortran_SHARED APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${PIO_MODULE_DIR}) 142 | endif() 143 | target_link_libraries(PIO_Fortran_SHARED INTERFACE PIO_C_SHARED) 144 | set(_new_components 1) 145 | endif() 146 | 147 | if( _search_library_type MATCHES "^(SHARED)$" ) 148 | if( TARGET PIO_C_SHARED ) 149 | add_library(PIO::PIO_C ALIAS PIO_C_SHARED) 150 | set(PIO_C_FOUND 1) 151 | endif() 152 | if( TARGET PIO_Fortran_SHARED ) 153 | add_library(PIO::PIO_Fortran ALIAS PIO_Fortran_SHARED) 154 | set(PIO_Fortran_FOUND 1) 155 | endif() 156 | elseif( _search_library_type MATCHES "^(STATIC)$" ) 157 | if( TARGET PIO_C_STATIC ) 158 | add_library(PIO::PIO_C ALIAS PIO_C_STATIC) 159 | set(PIO_C_FOUND 1) 160 | endif() 161 | if( TARGET PIO_Fortran_STATIC ) 162 | add_library(PIO::PIO_Fortran ALIAS PIO_Fortran_STATIC) 163 | set(PIO_Fortran_FOUND 1) 164 | endif() 165 | else() 166 | if( TARGET PIO_C_SHARED ) 167 | add_library(PIO::PIO_C ALIAS PIO_C_SHARED) 168 | set(PIO_C_FOUND 1) 169 | elseif( TARGET PIO_C_STATIC ) 170 | add_library(PIO::PIO_C ALIAS PIO_C_STATIC) 171 | set(PIO_C_FOUND 1) 172 | endif() 173 | if( TARGET PIO_Fortran_SHARED ) 174 | add_library(PIO::PIO_Fortran ALIAS PIO_Fortran_SHARED) 175 | set(PIO_Fortran_FOUND 1) 176 | elseif( TARGET PIO_Fortran_STATIC ) 177 | add_library(PIO::PIO_Fortran ALIAS PIO_Fortran_STATIC) 178 | set(PIO_Fortran_FOUND 1) 179 | endif() 180 | endif() 181 | 182 | ## Check package has been found correctly 183 | include(FindPackageHandleStandardArgs) 184 | find_package_handle_standard_args( 185 | PIO 186 | REQUIRED_VARS 187 | PIO_PREFIX 188 | PIO_INCLUDE_DIR 189 | HANDLE_COMPONENTS 190 | ) 191 | message(DEBUG "[FindPIO] PIO_FOUND: ${PIO_FOUND}") 192 | 193 | ## Print status 194 | if(${CMAKE_FIND_PACKAGE_NAME}_FOUND AND NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY AND _new_components) 195 | message( STATUS "Find${CMAKE_FIND_PACKAGE_NAME}:" ) 196 | message( STATUS " - ${CMAKE_FIND_PACKAGE_NAME}_PREFIX [${${CMAKE_FIND_PACKAGE_NAME}_PREFIX}]") 197 | set(_found_comps) 198 | foreach( _comp ${_search_components} ) 199 | if( ${CMAKE_FIND_PACKAGE_NAME}_${_comp}_FOUND ) 200 | list(APPEND _found_comps ${_comp}) 201 | endif() 202 | endforeach() 203 | message( STATUS " - ${CMAKE_FIND_PACKAGE_NAME} Components Found: ${_found_comps}") 204 | unset(_found_comps) 205 | endif() 206 | unset(_new_components) 207 | unset(_search_components) 208 | unset(_search_library_type) 209 | unset(_library_type) 210 | -------------------------------------------------------------------------------- /cmake/FortranLib.cmake: -------------------------------------------------------------------------------- 1 | function(add_fortran_library LIB MOD_DIR) 2 | add_library(${LIB} ${ARGN}) 3 | 4 | get_target_property(LIB_DIR ${LIB} BINARY_DIR) 5 | set_target_properties(${LIB} PROPERTIES Fortran_MODULE_DIRECTORY ${LIB_DIR}/${MOD_DIR}) 6 | 7 | target_include_directories(${LIB} INTERFACE "$") 8 | endfunction(add_fortran_library) 9 | -------------------------------------------------------------------------------- /cmake/PatchFile.cmake: -------------------------------------------------------------------------------- 1 | # use GNU Patch from any platform 2 | 3 | if(WIN32) 4 | # prioritize Git Patch on Windows as other Patches may be very old and incompatible. 5 | find_package(Git) 6 | if(Git_FOUND) 7 | get_filename_component(GIT_DIR ${GIT_EXECUTABLE} DIRECTORY) 8 | get_filename_component(GIT_DIR ${GIT_DIR} DIRECTORY) 9 | endif() 10 | endif() 11 | 12 | find_program(PATCH 13 | NAMES patch 14 | HINTS ${GIT_DIR} 15 | PATH_SUFFIXES usr/bin 16 | ) 17 | 18 | if(NOT PATCH) 19 | message(FATAL_ERROR "Did not find GNU Patch") 20 | endif() 21 | 22 | execute_process(COMMAND ${PATCH} ${in_file} --input=${patch_file} --output=${out_file} --ignore-whitespace 23 | TIMEOUT 15 24 | COMMAND_ECHO STDOUT 25 | RESULT_VARIABLE ret 26 | ) 27 | 28 | if(NOT ret EQUAL 0) 29 | message(FATAL_ERROR "Failed to apply patch ${patch_file} to ${in_file} with ${PATCH}") 30 | endif() 31 | -------------------------------------------------------------------------------- /share/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | ## share library 3 | add_fortran_library(OM3_share mod/share STATIC) 4 | add_library(AccessOM3::share ALIAS OM3_share) 5 | target_include_directories(OM3_share PUBLIC "$") 6 | if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") 7 | target_compile_definitions(OM3_share PRIVATE CPRGNU NAMING=_ADD_UNDERSCORE FORTRANUNDERSCORE) 8 | elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Intel") 9 | target_compile_definitions(OM3_share PRIVATE CPRINTEL NAMING=_ADD_UNDERSCORE FORTRANUNDERSCORE) 10 | endif() 11 | target_link_libraries(OM3_share 12 | PUBLIC esmf PIO::PIO_Fortran 13 | PRIVATE AccessOM3::timing 14 | ) 15 | target_sources(OM3_share PRIVATE 16 | # The following files are generated with a script acting on templates 17 | # We include pre-generated files that are committed to the repository 18 | src/shr_assert_mod.F90 19 | src/shr_frz_mod.F90 20 | src/shr_infnan_mod.F90 21 | src/dtypes.h 22 | 23 | # Modules shared among several components 24 | CESM_share/include/shr_assert.h 25 | CESM_share/src/shr_abort_mod.F90 26 | CESM_share/src/shr_cal_mod.F90 27 | CESM_share/src/shr_file_mod.F90 28 | CESM_share/src/shr_kind_mod.F90 29 | CESM_share/src/shr_log_mod.F90 30 | CESM_share/src/shr_mem_mod.F90 31 | CESM_share/src/shr_mpi_mod.F90 32 | CESM_share/src/shr_nl_mod.F90 33 | CESM_share/src/shr_orb_mod.F90 34 | CESM_share/src/shr_pio_mod.F90 35 | CESM_share/src/shr_precip_mod.F90 36 | CESM_share/src/shr_reprosum_mod.F90 37 | CESM_share/src/shr_reprosumx86.c 38 | CESM_share/src/shr_strconvert_mod.F90 39 | CESM_share/src/shr_string_mod.F90 40 | CESM_share/src/shr_sys_mod.F90 41 | CESM_share/src/shr_timer_mod.F90 42 | CESM_share/src/shr_wv_sat_mod.F90 43 | CESM_share/src/water_isotopes/water_isotopes.F90 44 | 45 | # The following file is a stub. 46 | stubs/mct_mod.F90 47 | ) 48 | add_patched_source(OM3_share CESM_share/src/nuopc_shr_methods.F90) 49 | add_patched_source(OM3_share CESM_share/src/shr_const_mod.F90) 50 | 51 | if(CMAKE_Fortran_COMPILER_ID MATCHES "Intel") 52 | # CESM reduces the precision and increases speed for the following file 53 | set_source_files_properties(CESM_share/src/shr_wv_sat_mod.F90 PROPERTIES COMPILE_FLAGS "-fimf-precision=low -fp-model fast") 54 | endif() 55 | 56 | ## GPTL timing library 57 | add_fortran_library(OM3_timing mod/timing STATIC) 58 | add_library(AccessOM3::timing ALIAS OM3_timing) 59 | target_compile_definitions(OM3_timing PRIVATE NUOPC_INTERFACE HAVE_MPI) 60 | if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") 61 | target_compile_definitions(OM3_timing PRIVATE CPRGNU NAMING=_ADD_UNDERSCORE FORTRANUNDERSCORE) 62 | elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Intel") 63 | target_compile_definitions(OM3_timing PRIVATE CPRINTEL NAMING=_ADD_UNDERSCORE FORTRANUNDERSCORE) 64 | endif() 65 | target_link_libraries(OM3_timing PRIVATE esmf) 66 | target_sources(OM3_timing PRIVATE 67 | timing/f_wrappers.c 68 | timing/gptl.c 69 | timing/GPTLget_memusage.c 70 | timing/gptl.h 71 | timing/gptl.inc 72 | timing/gptl_papi.c 73 | timing/GPTLprint_memusage.c 74 | timing/GPTLutil.c 75 | timing/perf_mod.F90 76 | timing/perf_utils.F90 77 | ) 78 | 79 | ### Install and Export 80 | 81 | if(OM3_LIB_INSTALL) 82 | ## share library 83 | set_target_properties(OM3_share PROPERTIES 84 | OUTPUT_NAME access-share 85 | EXPORT_NAME share 86 | ) 87 | install(TARGETS OM3_share 88 | EXPORT AccessOM3share_Targets 89 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_RunTime NAMELINK_COMPONENT AccessOM3_Development 90 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_Development 91 | ) 92 | # Fortran module files are a special case, as currently there is no standard 93 | # way of handling them in CMake 94 | target_include_directories(OM3_share PUBLIC "$") 95 | get_target_property(share_moddir OM3_share Fortran_MODULE_DIRECTORY) 96 | install(DIRECTORY ${share_moddir}/ 97 | DESTINATION ${CMAKE_INSTALL_MODULEDIR}/access-share 98 | COMPONENT AccessOM3_Development 99 | ) 100 | install(EXPORT AccessOM3share_Targets 101 | FILE AccessOM3shareTargets.cmake 102 | NAMESPACE AccessOM3:: 103 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AccessOM3 104 | ) 105 | 106 | ## timing library 107 | set_target_properties(OM3_timing PROPERTIES 108 | OUTPUT_NAME access-timing 109 | EXPORT_NAME timing 110 | ) 111 | install(TARGETS OM3_timing 112 | EXPORT AccessOM3timing_Targets 113 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_RunTime NAMELINK_COMPONENT AccessOM3_Development 114 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT AccessOM3_Development 115 | ) 116 | # Fortran module files are a special case, as currently there is no standard 117 | # way of handling them in CMake 118 | target_include_directories(OM3_timing PUBLIC "$") 119 | get_target_property(timing_moddir OM3_timing Fortran_MODULE_DIRECTORY) 120 | install(DIRECTORY ${timing_moddir}/ 121 | DESTINATION ${CMAKE_INSTALL_MODULEDIR}/access-timing 122 | COMPONENT AccessOM3_Development 123 | ) 124 | install(EXPORT AccessOM3timing_Targets 125 | FILE AccessOM3timingTargets.cmake 126 | NAMESPACE AccessOM3:: 127 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AccessOM3 128 | ) 129 | endif() 130 | -------------------------------------------------------------------------------- /share/patches/nuopc_shr_methods.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/nuopc_shr_methods.F90 b/src/nuopc_shr_methods.F90 2 | index 07cf7e5..8bdf11f 100644 3 | --- a/src/nuopc_shr_methods.F90 4 | +++ b/src/nuopc_shr_methods.F90 5 | @@ -820,9 +820,9 @@ contains 6 | 7 | ! local vars 8 | integer :: yr, mon, day 9 | - character(len=16) timestr 10 | - logical :: isPresent 11 | - character(len=ESMF_MAXSTR) :: inst_suffix 12 | + character(len=17) timestr 13 | + logical :: isPresent , isSet 14 | + character(len=ESMF_MAXSTR) :: inst_suffix , pointer_date 15 | character(len=*), parameter :: subname='shr_get_rpointer_name' 16 | 17 | rc = ESMF_SUCCESS 18 | @@ -832,19 +832,31 @@ contains 19 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 20 | if(ispresent) call NUOPC_CompAttributeGet(gcomp, name='inst_suffix', value=inst_suffix, rc=rc) 21 | 22 | - yr = ymd/10000 23 | - mon = (ymd - yr*10000)/100 24 | - day = (ymd - yr*10000 - mon*100) 25 | - write(timestr,'(i4.4,a,i2.2,a,i2.2,a,i5.5)') yr,'-',mon,'-',day,'-',time 26 | - write(rpfile,*) "rpointer."//compname//trim(inst_suffix)//'.'//trim(timestr) 27 | + ! if restart_pointer_append_date is false then don't append timestamp 28 | + timestr = "" 29 | + pointer_date = ".true." 30 | + call NUOPC_CompAttributeGet(gcomp, name="restart_pointer_append_date", isPresent=isPresent, isSet=isSet, rc=rc) 31 | + if (ChkErr(rc,__LINE__,u_FILE_u)) return 32 | + if (isPresent .and. isSet) then 33 | + call NUOPC_CompAttributeGet(gcomp, name='restart_pointer_append_date', value=pointer_date, rc=rc) 34 | + endif 35 | + if (trim(pointer_date) .eq. '.true.') then 36 | + yr = ymd/10000 37 | + mon = (ymd - yr*10000)/100 38 | + day = (ymd - yr*10000 - mon*100) 39 | + write(timestr,'(a,i4.4,a,i2.2,a,i2.2,a,i5.5)') '.',yr,'-',mon,'-',day,'-',time 40 | + endif 41 | + 42 | + write(rpfile,*) "rpointer."//compname//trim(inst_suffix)//trim(timestr) 43 | rpfile = adjustl(rpfile) 44 | + 45 | if (mode.eq.'read') then 46 | inquire(file=trim(rpfile), exist=isPresent) 47 | if(.not. isPresent) then 48 | rpfile = "rpointer."//compname//trim(inst_suffix) 49 | inquire(file=trim(rpfile), exist=isPresent) 50 | if(.not. isPresent) then 51 | - call shr_sys_abort( subname//'ERROR no rpointer file found in '//rpfile//' or in '//rpfile//'.'//timestr ) 52 | + call shr_sys_abort( subname//'ERROR no rpointer file found in '//rpfile//' or in '//rpfile//trim(inst_suffix)//trim(timestr) ) 53 | endif 54 | endif 55 | endif 56 | -------------------------------------------------------------------------------- /share/patches/shr_const_mod.F90.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/shr_const_mod.F90 b/src/shr_const_mod.F90 2 | index 8437190..9696c81 100644 3 | --- shr_const_mod.F90.old 4 | +++ shr_const_mod.F90.new 5 | @@ -87,9 +87,8 @@ contains 6 | !----------------------------------------------------------------------------- 7 | 8 | elemental logical function shr_const_isspval(rval) 9 | -!$omp declare simd(shr_const_isspval) 10 | 11 | real(r8), intent(in) :: rval 12 | 13 | if (rval > SHR_CONST_SPVAL_TOLMIN .and. & 14 | rval < SHR_CONST_SPVAL_TOLMAX) then 15 | -------------------------------------------------------------------------------- /share/src/dtypes.h: -------------------------------------------------------------------------------- 1 | #define TYPETEXT 100 2 | #define TYPEREAL 101 3 | #define TYPEDOUBLE 102 4 | #define TYPEINT 103 5 | #define TYPELONG 104 6 | #define TYPELOGICAL 105 7 | -------------------------------------------------------------------------------- /share/src/shr_frz_mod.F90: -------------------------------------------------------------------------------- 1 | !=================================================== 2 | ! DO NOT EDIT THIS FILE, it was generated using genf90.pl 3 | ! Any changes you make to this file may be lost 4 | !=================================================== 5 | module shr_frz_mod 6 | 7 | !=============================================================================== 8 | ! This is a module used for the freezing point of salt water 9 | !=============================================================================== 10 | 11 | use shr_kind_mod, only: R8=>SHR_KIND_R8, CS=>SHR_KIND_CS 12 | use shr_log_mod, only: s_logunit => shr_log_Unit, shr_log_level 13 | use shr_sys_mod, only: shr_sys_abort 14 | 15 | implicit none 16 | 17 | !---------------------------------------------------------------------------- 18 | ! PUBLIC: Interfaces and global data 19 | !---------------------------------------------------------------------------- 20 | public :: shr_frz_freezetemp, shr_frz_freezetemp_init 21 | 22 | # 18 "CESM_share/src/shr_frz_mod.F90.in" 23 | interface shr_frz_freezetemp 24 | module procedure shr_frz_freezetemp_0d 25 | module procedure shr_frz_freezetemp_1d 26 | module procedure shr_frz_freezetemp_2d 27 | end interface shr_frz_freezetemp 28 | 29 | integer, public, parameter :: TFREEZE_OPTION_MINUS1P8 = 1 30 | integer, public, parameter :: TFREEZE_OPTION_LINEAR_SALT = 2 31 | integer, public, parameter :: TFREEZE_OPTION_MUSHY = 3 32 | integer, public, parameter :: TFREEZE_OPTION_UNINITIALIZED = -999 33 | 34 | private 35 | 36 | integer :: tfrz_option = TFREEZE_OPTION_UNINITIALIZED 37 | 38 | !=============================================================================== 39 | # 34 "CESM_share/src/shr_frz_mod.F90.in" 40 | contains 41 | !=============================================================================== 42 | 43 | # 37 "CESM_share/src/shr_frz_mod.F90.in" 44 | subroutine shr_frz_freezetemp_init(tfreeze_option, mastertask) 45 | 46 | implicit none 47 | 48 | character(len=*),parameter :: subname = "(shr_frz_freezetemp_init) " 49 | character(CS),intent(in) :: tfreeze_option ! option for computing freezing point 50 | logical, intent(in) :: mastertask ! for io 51 | ! minus1p8 is constant -1.8C 52 | ! linear_salt is linear equation 53 | ! mushy for CICE mushy-layer nonlinear equation 54 | 55 | !--------------------------------------------------------------- 56 | ! Check tfreeze_option 57 | !--------------------------------------------------------------- 58 | if (trim(tfreeze_option) == 'minus1p8') then 59 | if (mastertask .and. shr_log_level>0) write(s_logunit,*) ' tfreeze_option is minus1p8' 60 | tfrz_option = TFREEZE_OPTION_MINUS1P8 61 | elseif (trim(tfreeze_option) == 'linear_salt') then 62 | if (mastertask .and. shr_log_level>0) write(s_logunit,*) ' tfreeze_option is linear_salt' 63 | tfrz_option = TFREEZE_OPTION_LINEAR_SALT 64 | elseif (trim(tfreeze_option) == 'mushy') then 65 | if (mastertask .and. shr_log_level>0) write(s_logunit,*) ' tfreeze_option is mushy' 66 | tfrz_option = TFREEZE_OPTION_MUSHY 67 | else 68 | call shr_sys_abort(subname//' ERROR: not a valid tfreeze_option '//trim(tfreeze_option)) 69 | endif 70 | 71 | # 64 "CESM_share/src/shr_frz_mod.F90.in" 72 | end subroutine shr_frz_freezetemp_init 73 | 74 | ! DIMS 0,1,2 75 | # 67 "CESM_share/src/shr_frz_mod.F90.in" 76 | function shr_frz_freezetemp_0d(s) result(shr_frz_freezetemp) 77 | 78 | !---------------------------------------------------------------------------- 79 | ! 80 | ! FUNCTION to return the freezing point of salt water in degrees Celsus 81 | ! 82 | !--------------- Code History ----------------------------------------------- 83 | ! 84 | ! Original Author: David Bailey 85 | ! Date: Feb, 2016 86 | !---------------------------------------------------------------------------- 87 | 88 | implicit none 89 | 90 | character(len=*),parameter :: subname = "(shr_frz_freezetemp_0d) " 91 | 92 | real (R8),intent(in) :: s ! Salinity in psu 93 | #if (0==0) 94 | real (R8) :: shr_frz_freezetemp 95 | #elif (0==1) 96 | real (R8) :: shr_frz_freezetemp(size(s)) 97 | #elif (0==2) 98 | real (R8) :: shr_frz_freezetemp(size(s,1),size(s,2)) 99 | #endif 100 | 101 | !---------------------------------------------------------------------------- 102 | shr_frz_freezetemp = -274.0_R8 103 | if (tfrz_option == TFREEZE_OPTION_MINUS1P8) then 104 | shr_frz_freezetemp = -1.8_R8 105 | elseif (tfrz_option == TFREEZE_OPTION_LINEAR_SALT) then 106 | shr_frz_freezetemp = -0.0544_R8*max(s,0.0_R8) 107 | elseif (tfrz_option == TFREEZE_OPTION_MUSHY) then 108 | ! This form is the high temperature part of the liquidus relation (Assur 1958) 109 | shr_frz_freezetemp = max(s,0.0_R8) & 110 | / (-18.48_R8 + (0.01848_R8*max(s,0.0_R8))) 111 | else 112 | call shr_sys_abort(subname//' ERROR: not intialized correctly with a valid tfreeze_option - & 113 | &call shr_frz_freezetemp_init first with a valid tfreeze_option') 114 | endif 115 | 116 | shr_frz_freezetemp = max(shr_frz_freezetemp,-2.0_R8) 117 | 118 | # 109 "CESM_share/src/shr_frz_mod.F90.in" 119 | end function shr_frz_freezetemp_0d 120 | ! DIMS 0,1,2 121 | # 67 "CESM_share/src/shr_frz_mod.F90.in" 122 | function shr_frz_freezetemp_1d(s) result(shr_frz_freezetemp) 123 | 124 | !---------------------------------------------------------------------------- 125 | ! 126 | ! FUNCTION to return the freezing point of salt water in degrees Celsus 127 | ! 128 | !--------------- Code History ----------------------------------------------- 129 | ! 130 | ! Original Author: David Bailey 131 | ! Date: Feb, 2016 132 | !---------------------------------------------------------------------------- 133 | 134 | implicit none 135 | 136 | character(len=*),parameter :: subname = "(shr_frz_freezetemp_1d) " 137 | 138 | real (R8),intent(in) :: s(:) ! Salinity in psu 139 | #if (1==0) 140 | real (R8) :: shr_frz_freezetemp 141 | #elif (1==1) 142 | real (R8) :: shr_frz_freezetemp(size(s)) 143 | #elif (1==2) 144 | real (R8) :: shr_frz_freezetemp(size(s,1),size(s,2)) 145 | #endif 146 | 147 | !---------------------------------------------------------------------------- 148 | shr_frz_freezetemp = -274.0_R8 149 | if (tfrz_option == TFREEZE_OPTION_MINUS1P8) then 150 | shr_frz_freezetemp = -1.8_R8 151 | elseif (tfrz_option == TFREEZE_OPTION_LINEAR_SALT) then 152 | shr_frz_freezetemp = -0.0544_R8*max(s,0.0_R8) 153 | elseif (tfrz_option == TFREEZE_OPTION_MUSHY) then 154 | ! This form is the high temperature part of the liquidus relation (Assur 1958) 155 | shr_frz_freezetemp = max(s,0.0_R8) & 156 | / (-18.48_R8 + (0.01848_R8*max(s,0.0_R8))) 157 | else 158 | call shr_sys_abort(subname//' ERROR: not intialized correctly with a valid tfreeze_option - & 159 | &call shr_frz_freezetemp_init first with a valid tfreeze_option') 160 | endif 161 | 162 | shr_frz_freezetemp = max(shr_frz_freezetemp,-2.0_R8) 163 | 164 | # 109 "CESM_share/src/shr_frz_mod.F90.in" 165 | end function shr_frz_freezetemp_1d 166 | ! DIMS 0,1,2 167 | # 67 "CESM_share/src/shr_frz_mod.F90.in" 168 | function shr_frz_freezetemp_2d(s) result(shr_frz_freezetemp) 169 | 170 | !---------------------------------------------------------------------------- 171 | ! 172 | ! FUNCTION to return the freezing point of salt water in degrees Celsus 173 | ! 174 | !--------------- Code History ----------------------------------------------- 175 | ! 176 | ! Original Author: David Bailey 177 | ! Date: Feb, 2016 178 | !---------------------------------------------------------------------------- 179 | 180 | implicit none 181 | 182 | character(len=*),parameter :: subname = "(shr_frz_freezetemp_2d) " 183 | 184 | real (R8),intent(in) :: s(:,:) ! Salinity in psu 185 | #if (2==0) 186 | real (R8) :: shr_frz_freezetemp 187 | #elif (2==1) 188 | real (R8) :: shr_frz_freezetemp(size(s)) 189 | #elif (2==2) 190 | real (R8) :: shr_frz_freezetemp(size(s,1),size(s,2)) 191 | #endif 192 | 193 | !---------------------------------------------------------------------------- 194 | shr_frz_freezetemp = -274.0_R8 195 | if (tfrz_option == TFREEZE_OPTION_MINUS1P8) then 196 | shr_frz_freezetemp = -1.8_R8 197 | elseif (tfrz_option == TFREEZE_OPTION_LINEAR_SALT) then 198 | shr_frz_freezetemp = -0.0544_R8*max(s,0.0_R8) 199 | elseif (tfrz_option == TFREEZE_OPTION_MUSHY) then 200 | ! This form is the high temperature part of the liquidus relation (Assur 1958) 201 | shr_frz_freezetemp = max(s,0.0_R8) & 202 | / (-18.48_R8 + (0.01848_R8*max(s,0.0_R8))) 203 | else 204 | call shr_sys_abort(subname//' ERROR: not intialized correctly with a valid tfreeze_option - & 205 | &call shr_frz_freezetemp_init first with a valid tfreeze_option') 206 | endif 207 | 208 | shr_frz_freezetemp = max(shr_frz_freezetemp,-2.0_R8) 209 | 210 | # 109 "CESM_share/src/shr_frz_mod.F90.in" 211 | end function shr_frz_freezetemp_2d 212 | 213 | !=============================================================================== 214 | 215 | end module shr_frz_mod 216 | -------------------------------------------------------------------------------- /share/stubs/mct_mod.F90: -------------------------------------------------------------------------------- 1 | module m_MCTWorld 2 | implicit none 3 | 4 | contains 5 | 6 | subroutine init(ncomps, globalcomm, mycomms, myids) 7 | integer, intent(in) :: ncomps 8 | integer, intent(in) :: globalcomm 9 | integer, dimension(:), pointer :: mycomms 10 | integer, dimension(:), pointer :: myids 11 | end subroutine init 12 | 13 | end module m_MCTWorld 14 | -------------------------------------------------------------------------------- /share/timing/COPYING: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any person obtaining a copy 2 | of this software and associated documentation files (the “Software”), to deal 3 | in the Software for any noncommercial purposes without restriction, including 4 | without limitation the rights to use, copy, modify, merge, publish, 5 | distribute, sublicense, and/or sell copies of the Software, and to permit 6 | persons to whom the Software is furnished to do so, subject to the following 7 | conditions: The above copyright notice and this permission notice shall be 8 | included in all copies or substantial portions of the Software. Any 9 | commercial use (including sale) of the software, and derivative development 10 | towards commercial use, requires written permission of the copyright 11 | holder. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 12 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 13 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 14 | EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 15 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 16 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | DEALINGS IN THE SOFTWARE. 18 | -------------------------------------------------------------------------------- /share/timing/ChangeLog: -------------------------------------------------------------------------------- 1 | timing_180912: Moved prefix support from perf_mod.F90 to gptl.c 2 | and also added support for setting prefixes in 3 | threaded regions. 4 | [Patrick Worley] 5 | timing_180911: Moved detail to end of timer name when specify 6 | profile_add_detail (so that will not interfere with 7 | planned move of the prefix logic into gptl.c) 8 | [Patrick Worley] 9 | timing_180910: Removed addition of double quotes to timer names in 10 | perf_mod.F90 and added this as an output option in 11 | gptl.c (so internally the names do not have the quotes) 12 | [Patrick Worley] 13 | timing_180822: Fixed perf_mod.F90 bug that prevents PAPI derived events 14 | from being recognized. 15 | [Patrick Worley] 16 | timing_180731: Refactored implementation of append/write modes; 17 | collected and output "on" events for global statistics 18 | [Patrick Worley] 19 | timing_180730: Added support for setting GPTLmaxthreads. Cleaned up white space. 20 | Added SEQUENTIAL to fortran open, to avoid problems on some systems. 21 | Added timing overhead measurement to perf_mod. Fixed errors in 22 | f_wrappers.c in definition of gptlpr_query_append and 23 | gptlpr_XXX_write. 24 | [Patrick Worley (some from Jim Rosinksi)] 25 | timing_180403: Added GPTLstartstop_val(f) to gptl.h, to provide explicit 26 | typing and eliminate compile-time warning for some compilers. 27 | Also do not define the CPP tokens HAVE_COMM_F2C and 28 | HAVE_GETTIMEOFDAY in private.h if they have already been 29 | defined, also eliminating compile-time warnings. 30 | [Patrick Worley] 31 | timing_171028: Backported GPTLstartstop_val from a more recent version 32 | of GPTL, added a callcount parameter, and renamed it 33 | GPTLstartstop_vals. Also added a version for non-null 34 | terminated timing event names (GPTLstartstop_valsf). 35 | Added t_startstop_valsf to perf_mod. Also replaced 36 | all strncpy calls in f_wrapper.c, just to be safe. 37 | [Patrick Worley (but primarily Jim Rosinksi)] 38 | timing_171027: Mitigated against nonmonotonic timing calls by 39 | setting negative deltas to zero in gptl.c . 40 | [Patrick Worley] 41 | timing_160816: Added quotes to timing event names in t_startf and t_stopf 42 | before calling GPTL routines. 43 | [Patrick Worley and Sean Patrick Santos] 44 | timing_161207: Replaced strncpy and snprintf where applied to 45 | non-null-terminated strings, to avoid memory issues 46 | when strncpy and snprintf implementations use strnlen 47 | to check validity of passed in string length parameter. 48 | (Why this causes problems is still a mystery.) 49 | [Patrick Worley and Gautam Bisht] 50 | timing_160320: Added routines t_set_prefixf and t_unset_prefixf. 51 | Setting the prefix adds this to the beginning of all subsequent 52 | timer event names (defined in t_startf/t_stopf). 53 | Also doubling default hash index tablesize to 2048. 54 | [Patrick Worley] 55 | timing_160124: Added option to prefix timer names with detail level. This is 56 | controlled by a new namelist variable (profile_add_detail). 57 | The default is to not enable this option. It is meant to be 58 | used for inspecting the profile detail definitions and 59 | associated logic. 60 | [Patrick Worley] 61 | timing_150903: Changed API to be compatible with NCAR CIME version of timing 62 | library: (a) changed handle argument from integer8 to integer 63 | in t_startf and t_stopf, and disabled use of handles in these 64 | routines until gptl.c can be updated; (b) added MaxThreads 65 | optional argument to t_initf, though it does not do anything 66 | yet. 67 | [Patrick Worley] 68 | timing_150518: Disabled abort when calling GPTL routines before GPTLinitialize 69 | (so can use with Chombo library, for example); changed top 70 | level default from nanotimer to MPI_WTIME. 71 | [Patrick Worley] 72 | timing_150327: Added option to more accurately measure measurement overhead 73 | (incurring additional overhead, so not on by default). 74 | [Patrick Worley] 75 | timing_150217: Added support for enabling/disabling start/stop timers from 76 | perf_mod even when calling GPTL routines directly from C/C++ 77 | libraries; increased maximum timer name length. 78 | [Patrick Worley] 79 | timing_141119: Enabled cmake build of timing library. 80 | [Jayesh Krishna] 81 | timing_140805: Disabled GPTL autoinstrumentation, as this conflicts with the 82 | VampirTrace tool. (We do not use the autoinstrumentation 83 | capability.) [Patrick Worley, from B. Jamroz] 84 | timing_140416: Changed Makefile so that .mods and the static library are copied to 85 | LIBROOT 86 | timing_140317: Modified Makefile to deal with shared mpi-serial builds 87 | timing_131108: Added memory retrieval commands for BG/Q [S Mickelson] 88 | timing_131023: Added explicit include path for gptl.h [J Edwards] 89 | timing_130827: added routines supporting non-null terminated timer labels, for use with 90 | with C++ std:string (and more efficient usage with Fortran); also CMake 91 | logic fixes 92 | [Patrick Worley] 93 | timing_130506: Copy all modules to the include directory on install 94 | timing_130417: Made nano time the default timer if available. 95 | timing_130316: Changed declarations of functions used in qsort in gptl.c, to eliminate 96 | error with Cray compiler (and warnings from other compilers) 97 | [Patrick Worley] 98 | timing_130214: NAG port: Put mpif.h include before "save", and don't use 99 | "abort" and "flush" extensions for NAG. [Sean Patrick Santos] 100 | timing_120921: Add code for cmake build, should not have any affect otherwise 101 | timing_120731: Correction in Makefile for serial build [Jim Edwards] 102 | timing_120728: Replace process subset optional parameter in t_prf with 103 | outpe_thispe optional parameter. Change def_perf_outpe_num to 0. 104 | [Patrick Worley] 105 | timing_120717: Retain timestamp on cp in Makefile [Jim Edwards] 106 | timing_120710: Correct issue in Makefile [Jim Edwards] 107 | timing_120709: Change for BGP to measure on compute nodes rather than IO nodes only, 108 | minor Change in Makefile so that gptl can build seperate from csm_share 109 | in cesm [Jim Edwards] 110 | timing_120512: Bug fix in global statistics logic for when a thread has no events 111 | to contribute to the merge (mods to gptl.c) 112 | [Patrick Worley] 113 | timing_120419: Minor changes for mpi-serial compile (jedwards) 114 | timing_120408: Make HAVE_COMM_F2C default to true. (jedwards) 115 | timing_120110: Update to GPTL 4.1 source (mods to gptl.c and GPTLprint_memusage) 116 | [Jim Rosinski (GPTL 4.1), Patrick Worley] 117 | timing_120109: Bug fix (adding shr_kind_i8 to shr_kind_mod list) 118 | timing_111205: Update to gptl 4.0 (introducing CESM customizations); 119 | support for handles in t_startf/t_stopf; 120 | support for restricting output to explicitly named process subsets 121 | [Jim Rosinski (gptl 4.0), Patrick Worley] 122 | timing_111101: Workaround for mpi_rsend issue on cray/gemini 123 | timing_110928: Add a Makefile and build as a library usable by mct and pio 124 | timing_101215: No changes from previous tag other than updating Changelog 125 | timing_101210: Fix interface to cesm build system, add workaround for xlf bug 126 | timing_101202: updated get_memusage and print_memusage from GPTL version 3.7; adds 127 | improved support for MacOS and SLASHPROC 128 | [Jim Rosinski, Chuck Bardeen (integrated by P. Worley)] 129 | timing_091021: update to GPTL version 3.5; rewrite of GPTLpr_summary: much faster, merging 130 | events from all processes and all threads (not just process 0/thread 0); 131 | miscellaneous fixes 132 | [Jim Rosinski (gptl 3.5), Joseph Singh, Patrick Worley] 133 | timing_090929: added explicit support for the GPTL-native token HAVE_MPI (indicating 134 | presence of MPI library) 135 | [Patrick Worley] 136 | timing_081221: restore default assumption that gettimeofday available 137 | timing_081028: bug fix in include order in gptl_papi.c 138 | timing_081026: change in output format to make postprocessing simpler 139 | timing_081024: support for up to one million processes and writing timing files to 140 | subdirectories 141 | timing_081017: updated to gptl version 3_4_2. Changed some defaults. 142 | [Jim Rosinski, Patrick Worley] 143 | timing_080629: added optional parameters perf_outpe_num and perf_outpe_stride to t_prf. 144 | These are used to override the user specified values for timing data 145 | written out before the end of a simulation. 146 | [Patrick Worley] 147 | timing_071213: changed default to disable inline keyword; changed global statistics 148 | logic to avoid problems at scale; moved shr and CAM routine equivalencies 149 | to a new module (in perf_utils.F90); added t_getLogUnit/t_setLogUnit 150 | routines to control Log output in same way as shr_file_get/setLogUnit; 151 | modified GPTLpr logic to support output of timing data during a run 152 | [Patrick Worley] 153 | timing_071023: updated to gptl version 2.16, added support for output of global 154 | statistics; removed dependencies on shr and CAM routines; renamed 155 | gptlutil.c to GPTLutil.c 156 | [Patrick Worley, Jim Rosinski] 157 | timing_071019: modified namelist logic to abort if try to set unknown namelist parameters; 158 | changed default number of reporting processes to 1; 159 | reversed meaning and changed names of CPP tokens to NO_C99_INLINE and NO_VPRINTF 160 | [Patrick Worley] 161 | timing_071010: modified gptl.c to remove the 'inline' specification unless the 162 | CPP token C99 is defined. 163 | [Patrick Worley] 164 | timing_070810: added ChangeLog 165 | updated to latest version of GPTL (from Jim Rosinski) 166 | modified perf_mod.F90: 167 | - added perf_outpe_num and perf_outpe_stride to perf_inparm 168 | namelist to control which processes output timing data 169 | - added perf_papi_enable to perf_inparm namelist to enable 170 | PAPI counters 171 | - added papi_inparm namelist and papi_ctr1,2,3,4 namelist 172 | parameters to specify PAPI counters 173 | [Patrick Worley, Jim Rosinski] 174 | timing_070525: bug fix in gptl.c 175 | - unitialized pointer, testing for null pter 176 | before traversing 177 | [Patrick Worley] 178 | timing_070328: modified perf_mod.F90 179 | - deleted HIDE_MPI cpp token 180 | [Erik Kluzek] 181 | timing_070327: bug fixes in gptl.c 182 | - testing for null pters before traversing 183 | links; added missing type declaration to GPTLallocate for sum 184 | bug fixes in perf_mod.F90 185 | - fixed OMP-related logic, modified settings reporting, 186 | modified to work when namelist input is 187 | missing; moved timer depth logic back into gptl.c 188 | [Patrick Worley] 189 | timing_070308: added perf_mod.F90 190 | - defines all t_xxx entry points - calling gptlxxx directly 191 | and removing all external gptlxxx dependencies, 192 | added detail option as an alternative way to disable 193 | event timing, added runtime selection of timing_disable, 194 | perf_timer, timer_depth_limit, timing_detail_limit, 195 | timing_barrier, perf_single_file via namelist parameters 196 | modified f_wrappers.c 197 | - replaced all t_xxx entry points with gptlxxx entry points, 198 | added new gptlxxx entry points, deleted _fcd support 199 | modified gptl.c 200 | - deleted DISABLE_TIMERS cpp token, modified GPTLpr call 201 | and logic to move some of support for concatenating timing 202 | output into a single file to perf_mod.F90 203 | modified gptl.h 204 | - exposed gptlxxx entry points and to add support for choice 205 | of GPTL timer 206 | modified gptl.inc 207 | - removed t_xxx entry points and expose gptlxxx entry points 208 | [Patrick Worley] 209 | timing_061207: modified gptl.c 210 | - improved event output ordering 211 | [Jim Edwards] 212 | timing_061124: modified gptl.c 213 | - modified GPTLpr to add option to concatenate 214 | all timing data in a single output file, added GPTL_enable 215 | and GPTL_disable as runtime control of event timing, 216 | process 0-only reporting of timing options - unless DEBUG 217 | cpp token defined 218 | modified gptl.h 219 | - redefined GPTLpr parameters 220 | modified f_wrappers.c 221 | - added t_enablef and t_disablef to call GPTL_enable and 222 | GPTL_disable, added t_pr_onef, added string.h include 223 | bug fix in f_wrappers.c 224 | - changed character string size declaration from int to size_t 225 | bug fix in gptl_papi.c 226 | - modified error message - from Jim Edwards 227 | modified private.h 228 | - increased maximum event name length 229 | [Patrick Worley] 230 | timing_061028: modified f_wrappers.c 231 | - deleted dependency on cfort.h 232 | [Patrick Worley] 233 | timing_060524: modified f_wrappers.c 234 | - added support for CRAY cpp token and fixed routine 235 | type declarations 236 | [Patrick Worley] 237 | timing_051212: original subversion version 238 | - see CAM ChangeLog for earlier history 239 | -------------------------------------------------------------------------------- /share/timing/GPTLget_memusage.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: get_memusage.c,v 1.10 2010-11-09 19:08:53 rosinski Exp $ 3 | ** 4 | ** Author: Jim Rosinski 5 | ** Credit to Chuck Bardeen for MACOS section (__APPLE__ ifdef) 6 | ** 7 | ** get_memusage: 8 | ** 9 | ** Designed to be called from Fortran, returns information about memory 10 | ** usage in each of 5 input int* args. On Linux read from the /proc 11 | ** filesystem because getrusage() returns placebos (zeros). Return -1 for 12 | ** values which are unavailable or ambiguous on a particular architecture. 13 | ** Reported numbers are in kilobytes. 14 | ** 15 | ** Return value: 0 = success 16 | ** -1 = failure 17 | */ 18 | 19 | #include 20 | #include "gptl.h" /* additional cpp defs and function prototypes */ 21 | #include 22 | 23 | /* _AIX is automatically defined when using the AIX C compilers */ 24 | #ifdef _AIX 25 | #include 26 | #endif 27 | 28 | #ifdef IRIX64 29 | #include 30 | #endif 31 | 32 | #ifdef HAVE_SLASHPROC 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #elif (defined __APPLE__) 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #endif 45 | 46 | #ifdef BGP 47 | 48 | #include 49 | #include 50 | #include 51 | #include 52 | #define Personality _BGP_Personality_t 53 | 54 | #endif 55 | 56 | #ifdef __bgq__ 57 | 58 | #include 59 | #include 60 | 61 | #endif 62 | 63 | #define PRINT_MEMUSAGE 0 64 | 65 | int GPTLget_memusage (int *size, int *rss, int *share, int *text, int *datastack) 66 | { 67 | #if defined (BGP) 68 | long long alloc, total; 69 | int node_config; 70 | struct mallinfo m; 71 | Personality pers; 72 | 73 | /* memory available */ 74 | Kernel_GetPersonality(&pers, sizeof(pers)); 75 | total = BGP_Personality_DDRSizeMB(&pers); 76 | 77 | node_config = BGP_Personality_processConfig(&pers); 78 | if (node_config == _BGP_PERS_PROCESSCONFIG_VNM) total /= 4; 79 | else if (node_config == _BGP_PERS_PROCESSCONFIG_2x2) total /= 2; 80 | total *= 1024; // in KB 81 | 82 | /* total memory used - heap only (not static memory)*/ 83 | *size = total; 84 | 85 | m = mallinfo(); 86 | alloc = m.hblkhd + m.uordblks; 87 | 88 | *rss = alloc; 89 | *share = -1; 90 | *text = -1; 91 | *datastack = -1; 92 | return 0; 93 | 94 | #elif (defined __bgq__) 95 | uint64_t heap, shared, stack; 96 | 97 | Kernel_GetMemorySize(KERNEL_MEMSIZE_HEAP, &heap); 98 | Kernel_GetMemorySize(KERNEL_MEMSIZE_SHARED, &shared); 99 | Kernel_GetMemorySize(KERNEL_MEMSIZE_STACK, &stack); 100 | 101 | *size = heap/1024; 102 | *rss = heap/1024; 103 | *share = shared/1024; 104 | *text = -1; 105 | *datastack = stack/1024; 106 | return 0; 107 | 108 | #elif (defined HAVE_SLASHPROC) 109 | FILE *fd; /* file descriptor for fopen */ 110 | int pid; /* process id */ 111 | char file[19]; /* full path to file in /proc */ 112 | int dum; /* placeholder for unused return arguments */ 113 | int ret; /* function return value */ 114 | static int pg_sz = -1; /* page size */ 115 | 116 | /* 117 | ** The file we want to open is /proc//statm 118 | */ 119 | 120 | pid = (int) getpid (); 121 | if (pid <= 0) { 122 | fprintf (stderr, "get_memusage: pid %d is non-positive\n", pid); 123 | return -1; 124 | } 125 | 126 | sprintf (file, "/proc/%d/statm", pid); 127 | if ((fd = fopen (file, "r")) < 0) { 128 | fprintf (stderr, "get_memusage: bad attempt to open %s\n", file); 129 | return -1; 130 | } 131 | 132 | /* 133 | ** Read the desired data from the /proc filesystem directly into the output 134 | ** arguments, close the file and return. 135 | */ 136 | 137 | ret = fscanf (fd, "%d %d %d %d %d %d %d", 138 | size, rss, share, text, datastack, &dum, &dum); 139 | ret = fclose (fd); 140 | 141 | // read page size once 142 | if (pg_sz == -1) { 143 | pg_sz = sysconf(_SC_PAGESIZE) / 1024; 144 | } 145 | 146 | // convert from pages to KBs 147 | *size = *size * pg_sz; 148 | *rss = *rss * pg_sz; 149 | *share = *share * pg_sz; 150 | *text = *text * pg_sz; 151 | *datastack = *datastack * pg_sz; 152 | #if PRINT_MEMUSAGE 153 | fprintf (stderr, "get_memusage: size=%d KB, rss=%d KB, share=%d KB, text=%d KB, datastack=%d KB, page_size=%d KB\n", 154 | *size, *rss, *share, *text, *datastack, pg_sz); 155 | #endif 156 | 157 | return 0; 158 | 159 | #elif (defined __APPLE__) 160 | 161 | FILE *fd; 162 | char cmd[60]; 163 | int pid = (int) getpid (); 164 | 165 | // returned values are in KBs 166 | sprintf (cmd, "ps -o vsz -o rss -o tsiz -p %d | grep -v RSS", pid); 167 | fd = popen (cmd, "r"); 168 | 169 | if (fd) { 170 | fscanf (fd, "%d %d %d", size, rss, text); 171 | *share = -1; 172 | *datastack = -1; 173 | (void) pclose (fd); 174 | } 175 | 176 | return 0; 177 | 178 | #else 179 | 180 | struct rusage usage; /* structure filled in by getrusage */ 181 | 182 | if (getrusage (RUSAGE_SELF, &usage) < 0) 183 | return -1; 184 | 185 | *size = -1; 186 | *rss = usage.ru_maxrss; // in KBs 187 | *share = -1; 188 | *text = -1; 189 | *datastack = -1; 190 | #ifdef IRIX64 191 | *datastack = usage.ru_idrss + usage.ru_isrss; 192 | #endif 193 | return 0; 194 | 195 | #endif 196 | } 197 | -------------------------------------------------------------------------------- /share/timing/GPTLprint_memusage.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: print_memusage.c,v 1.13 2010-11-09 19:08:54 rosinski Exp $ 3 | ** 4 | ** Author: Jim Rosinski 5 | ** 6 | ** print_memusage: 7 | ** 8 | ** Prints info about memory usage of this process by calling get_memusage. 9 | ** 10 | ** Return value: 0 = success 11 | ** -1 = failure 12 | */ 13 | 14 | #include "gptl.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #ifdef __bgq__ 20 | #include 21 | #endif 22 | 23 | static int nearest_powerof2 (const int); 24 | static int convert_to_mb = 1; /* true */ 25 | 26 | int GPTLprint_memusage (const char *str) 27 | { 28 | #ifdef __bgq__ 29 | uint64_t shared, persist, heapavail, stackavail, stack, heap, guard, mmap; 30 | 31 | Kernel_GetMemorySize(KERNEL_MEMSIZE_HEAP, &heap); 32 | Kernel_GetMemorySize(KERNEL_MEMSIZE_SHARED, &shared); 33 | Kernel_GetMemorySize(KERNEL_MEMSIZE_STACK, &stack); 34 | Kernel_GetMemorySize(KERNEL_MEMSIZE_PERSIST, &persist); 35 | Kernel_GetMemorySize(KERNEL_MEMSIZE_HEAPAVAIL, &heapavail); 36 | Kernel_GetMemorySize(KERNEL_MEMSIZE_STACKAVAIL, &stackavail); 37 | Kernel_GetMemorySize(KERNEL_MEMSIZE_GUARD, &guard); 38 | Kernel_GetMemorySize(KERNEL_MEMSIZE_MMAP, &mmap); 39 | 40 | printf("%s Memory(MB): heap-alloc: %.2f, heap-avail: %.2f," 41 | "stack-alloc: %.2f, stack-avail: %.2f," 42 | "shared: %.2f, persist: %.2f, guard: %.2f, mmap: %.2f\n", str, 43 | (double)heap/(1024*1024), (double)heapavail/(1024*1024), 44 | (double)stack/(1024*1024), (double)stackavail/(1024*1024), 45 | (double)shared/(1024*1024), (double)persist/(1024*1024), 46 | (double)guard/(1024*1024), (double)mmap/(1024*1024)); 47 | return 0; 48 | 49 | #else 50 | int size, size2; /* process size (returned from OS) */ 51 | int rss, rss2; /* resident set size (returned from OS) */ 52 | int share, share2; /* shared data segment size (returned from OS) */ 53 | int text, text2; /* text segment size (returned from OS) */ 54 | int datastack, datastack2; /* data/stack size (returned from OS) */ 55 | static int kbytesperblock = -1; /* convert to Kbytes (init to invalid) */ 56 | static const int nbytes =1024*1024*1024;/* allocate 1 GB */ 57 | void *space; /* allocated space */ 58 | 59 | setbuf(stdout, NULL); // don't buffer stdout, flush 60 | if (GPTLget_memusage (&size, &rss, &share, &text, &datastack) < 0) { 61 | printf ("GPTLprint_memusage: GPTLget_memusage failed.\n"); 62 | return -1; 63 | } 64 | 65 | #if (defined HAVE_SLASHPROC || defined __APPLE__) 66 | if (kbytesperblock == -1) { 67 | kbytesperblock = sysconf(_SC_PAGESIZE) / 1024; 68 | printf ("GPTLprint_memusage: Using Kbytesperpage=%d\n", kbytesperblock); 69 | } 70 | 71 | /* 72 | ** Determine size in bytes of memory usage info presented by the OS. Method: allocate a 73 | ** known amount of memory and see how much bigger the process becomes. 74 | */ 75 | 76 | if (convert_to_mb && kbytesperblock == -1 && (space = malloc (nbytes))) { 77 | memset (space, 0, nbytes); /* ensure the space is really allocated */ 78 | if (GPTLget_memusage (&size2, &rss2, &share2, &text2, &datastack2) == 0) { 79 | if (size2 > size) { 80 | /* 81 | ** Estimate bytes per block, then refine to nearest power of 2. 82 | ** The assumption is that the OS presents memory usage info in 83 | ** units that are a power of 2. 84 | */ 85 | kbytesperblock = (int) ((nbytes / (double) (size2 - size)) + 0.5); 86 | kbytesperblock = nearest_powerof2 (kbytesperblock); 87 | printf ("GPTLprint_memusage: Using Kbytesperblock=%d\n", kbytesperblock); 88 | } else { 89 | printf ("GPTLprint_memusage: highwater did not increase.\n"); 90 | } 91 | } else { 92 | printf ("GPTLprint_memusage: call GPTLget_memusage failed.\n"); 93 | } 94 | free (space); 95 | } 96 | 97 | if (kbytesperblock > 0) { 98 | printf ("%s sysmem size=%.1f MB rss=%.1f MB share=%.1f MB text=%.1f MB datastack=%.1f MB\n", 99 | str, size/1024., rss/1024., share/1024., text/1024., datastack/1024.); 100 | } else { 101 | printf ("%s sysmem size=%d rss=%d share=%d text=%d datastack=%d\n", 102 | str, size, rss, share, text, datastack); 103 | } 104 | 105 | #else 106 | 107 | /* 108 | ** Use max rss as returned by getrusage. If someone knows how to 109 | ** get the process size under AIX please tell me. 110 | */ 111 | 112 | if (convert_to_mb) 113 | printf ("%s max rss=%.1f MB\n", str, rss*1024.); 114 | else 115 | printf ("%s max rss=%d\n", str, rss); 116 | #endif 117 | 118 | return 0; 119 | #endif 120 | } 121 | 122 | /* 123 | ** nearest_powerof2: 124 | ** Determine nearest integer which is a power of 2. 125 | ** Note: algorithm can't use anything that requires -lm because this is a library, 126 | ** and we don't want to burden the user with having to add extra libraries to the 127 | ** link line. 128 | ** 129 | ** Input arguments: 130 | ** val: input integer 131 | ** 132 | ** Return value: nearest integer to val which is a power of 2 133 | */ 134 | 135 | static int nearest_powerof2 (const int val) 136 | { 137 | int lower; /* power of 2 which is just less than val */ 138 | int higher; /* power of 2 which is just more than val */ 139 | int delta1; /* difference between val and lower */ 140 | int delta2; /* difference between val and higher */ 141 | 142 | if (val < 2) 143 | return 0; 144 | 145 | for (higher = 1; higher < val; higher *= 2) 146 | lower = higher; 147 | 148 | delta1 = val - lower; 149 | delta2 = higher - val; 150 | 151 | if (delta1 < delta2) 152 | return lower; 153 | else 154 | return higher; 155 | } 156 | -------------------------------------------------------------------------------- /share/timing/GPTLutil.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: util.c,v 1.13 2010-01-01 01:34:07 rosinski Exp $ 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "private.h" 10 | 11 | static bool abort_on_error = false; /* flag says to abort on any error */ 12 | static int max_error = 500; /* max number of error print msgs */ 13 | 14 | /* 15 | ** GPTLerror: error return routine to print a message and return a failure 16 | ** value. 17 | ** 18 | ** Input arguments: 19 | ** fmt: format string 20 | ** variable list of additional arguments for vfprintf 21 | ** 22 | ** Return value: -1 (failure) 23 | */ 24 | 25 | int GPTLerror (const char *fmt, ...) 26 | { 27 | va_list args; 28 | 29 | va_start (args, fmt); 30 | static int num_error = 0; 31 | 32 | if (fmt != NULL && num_error < max_error) { 33 | #ifndef NO_VPRINTF 34 | (void) vfprintf (stderr, fmt, args); 35 | #else 36 | (void) fprintf (stderr, "GPTLerror: no vfprintf: fmt is %s\n", fmt); 37 | #endif 38 | if (num_error == max_error) 39 | (void) fprintf (stderr, "Truncating further error print now after %d msgs", 40 | num_error); 41 | ++num_error; 42 | } 43 | 44 | va_end (args); 45 | 46 | if (abort_on_error) 47 | exit (-1); 48 | 49 | return (-1); 50 | } 51 | 52 | /* 53 | ** GPTLset_abort_on_error: User-visible routine to set abort_on_error flag 54 | ** 55 | ** Input arguments: 56 | ** val: true (abort on error) or false (don't) 57 | */ 58 | 59 | void GPTLset_abort_on_error (bool val) 60 | { 61 | abort_on_error = val; 62 | } 63 | 64 | /* 65 | ** GPTLallocate: wrapper utility for malloc 66 | ** 67 | ** Input arguments: 68 | ** nbytes: size to allocate 69 | ** 70 | ** Return value: pointer to the new space (or NULL) 71 | */ 72 | 73 | void *GPTLallocate (const int nbytes) 74 | { 75 | void *ptr; 76 | 77 | if ( nbytes <= 0 || ! (ptr = malloc (nbytes))) 78 | (void) GPTLerror ("GPTLallocate: malloc failed for %d bytes\n", nbytes); 79 | 80 | return ptr; 81 | } 82 | -------------------------------------------------------------------------------- /share/timing/README: -------------------------------------------------------------------------------- 1 | This file contains information about using GPTL. For information on building 2 | and installing GPTL, see the file INSTALL. 3 | 4 | GPTL is the "General Purpose Timing Library". It can be used to manually 5 | instrument application codes with an arbitrary set of "regions" (or "timers") 6 | over which statistics such as wallclock time and CPU time are gathered and 7 | subsequently printed. If the target application is built with the GNU 8 | compilers (gcc or gfortran) or Pathscale (pathcc or pathf95), GPTL can also be 9 | used to automatically instrument regions which are defined by function entry 10 | and exit points. This is an easy way to generate a dynamic call tree. See 11 | Auto-Instrumentation below for a description of how to use this feature. 12 | 13 | If the PAPI library is installed (http://icl.cs.utk.edu/papi), GPTL 14 | also provides a convenient mechanism to access all available PAPI events. In 15 | addtion to PAPI preset and native events, GPTL defines derived events which 16 | are based on PAPI counters. See gptl.h for a list of available derived events. 17 | Of course these events can only be enabled if the PAPI counters they require 18 | are available on the target architecture. 19 | 20 | 21 | Using GPTL 22 | ---------- 23 | 24 | C codes making GPTL library calls should #include . Fortran codes 25 | should #include or Fortran include 'gptl.inc'. The C and Fortran interfaces 26 | are identical, except that the C interface uses mixed case. All 27 | user-accessible functions return either 0 (success) or -1 (failure). Example 28 | codes that use the library can be found in subdirectories ctests/ and ftests/. 29 | 30 | Code instrumentation to utilize GPTL involves zero or more calls to 31 | GPTLsetoption(), then a single call to GPTLinitialize(), then an arbitrary 32 | sequence of calls to GPTLstart() and GPTLstop(), and finally a call to 33 | GPTLpr() or GPTLpr_file(). See "Example" below for a sample calling 34 | sequence. Calls to GPTLstart() and GPTLstop() are thread-safe, with per-thread 35 | statistics printed by GPTLpr() or GPTLpr_file(). 36 | 37 | The purpose of GPTLsetoption() is to enable or disable various library 38 | options. For example, to enable the PAPI counter for total cycles, do this: 39 | 40 | ret = GPTLsetoption (PAPI_TOT_CYC, 1); 41 | 42 | The "1" says "enable". Use "0" for "disable". See the man pages for complete 43 | documentation on function usage and arguments. The list of available GPTL 44 | options is contained in gptl.h, and a complete list of available PAPI-based 45 | events can be found by running "ctests/avail". 46 | 47 | GPTLinitialize() initializes the GPTL library. 48 | 49 | There can be an arbitrary number of start/stop pairs before GPTLpr() or 50 | GPTLpr_file() is called to print the results. And an arbitrary amount of 51 | nesting of regions is also allowed. The printed results will be indented to 52 | indicate the level of nesting for each region. 53 | 54 | GPTLpr() prints the results to a file named timing., where the single 55 | argument is an integer. For MPI jobs, it is most convenient to use 56 | the MPI rank of the invoking task for . Equivalently, function 57 | GPTLpr_file() can be called. Its input argument is a character string 58 | indicating the output file name to be written. It is up to the user to ensure 59 | that these print functions write to uniquely-named files, in order to avoid 60 | name-space collisions. 61 | 62 | GPTLfinalize() can be called to clean up the GPTL environment. All space 63 | malloc'ed by the GPTL library will be freed by this call. 64 | 65 | 66 | Example 67 | ------- 68 | 69 | From "man GPTLstart", a simple example calling sequence to time a couple of 70 | code regions and print the results is: 71 | 72 | (void) GPTLsetoption (GPTLcpu, 1); /* enable cpu timings */ 73 | (void) GPTLsetoption (GPTLwall, 0); /* disable wallclock timings */ 74 | (void) GPTLsetoption (PAPI_TOT_CYC, 1); /* enable counting of total cycles */ 75 | ... 76 | (void) GPTLinitialize(); /* initialize the GPTL library */ 77 | (void) GPTLstart ("total"); /* start a timer */ 78 | ... 79 | (void) GPTLstart ("do_work"); /* start another timer */ 80 | 81 | do_work(); /* do some work */ 82 | 83 | (void) GPTLstop ("do_work"); /* stop a timer */ 84 | (void) GPTLstop ("total"); /* stop a timer */ 85 | ... 86 | (void) GPTLpr (mympitaskid); /* print the results to timing. */ 87 | 88 | 89 | Auto-instrumentation 90 | -------------------- 91 | 92 | If the regions to be timed are defined by function entry and exit points, and 93 | the application to be profiled is built with either the GNU or Pathscale 94 | compilers, you might find it convenient to use the auto-instrumentation 95 | feature of GPTL. Here's how: 96 | 97 | 1) Add the flag -finstrument-functions when compiling the routines you'd like 98 | to profile. 99 | 100 | 2) Add calls to GPTLsetoption() (if desired), and GPTLinitialize() to the main 101 | program before any other routines are invoked. 102 | 103 | 3) Add a call to GPTLpr() or GPTLpr_file() wherever appropriate prior to where 104 | the code terminates. 105 | 106 | 4) Link with -lgptl (and -lpapi if PAPI is enabled). 107 | 108 | 5) Run the code. 109 | 110 | 6) Run "hex2name.pl | less", where 111 | is the name of the executable, and is the name of the 112 | timing file to be converted. 113 | 114 | The result should be a dynamic call tree with timings and (if enabled) PAPI 115 | counts and derived event statistics for each region, where regions are defined 116 | by function entry and exit points. 117 | 118 | Here's what's happening under the covers: 119 | 120 | The -finstrument-functions flag tells the compiler to insert calls to 121 | __cyg_profile_func_enter (void *this_fn, void *call_site) at function start, 122 | and __cyg_profile_func_exit (void *this_fn, void *call_site) at function 123 | exit. GPTL defines these functions as calls to (effectively) GPTLstart() and 124 | GPTLstop(), where the address of the function is used as the input sentinel to 125 | these routines. 126 | 127 | Running hex2name.pl converts the function addresses back to human-readable 128 | function names. It uses the UNIX "nm" utility to do this. 129 | 130 | 131 | Multi-processor instrumented codes 132 | ---------------------------------- 133 | 134 | For instrumented codes which make use of threading and/or MPI, a 135 | post-processing script is provided to analyze GPTL output files and gather 136 | max/min/average stats on a per-region basis. The script is parsegptlout.pl. It 137 | might be invoked as, for example: 138 | 139 | parsegptlout.pl sub1 140 | 141 | The script will look through all files in the current directory named timing.* 142 | for regions named "sub1", then gather and print various statistics. Numerous 143 | options are available. See "man parsegptlout" for more in-depth information. 144 | -------------------------------------------------------------------------------- /share/timing/gptl.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: gptl.h,v 1.59 2011-03-28 20:55:19 rosinski Exp $ 3 | ** 4 | ** Author: Jim Rosinski 5 | ** 6 | ** GPTL header file to be included in user code 7 | */ 8 | 9 | #ifndef GPTL_H 10 | #define GPTL_H 11 | 12 | #ifdef INCLUDE_CMAKE_FCI 13 | #include "cmake_fortran_c_interface.h" 14 | #endif 15 | 16 | /* following block for camtimers only */ 17 | #ifndef NO_GETTIMEOFDAY 18 | #ifndef HAVE_GETTIMEOFDAY 19 | #define HAVE_GETTIMEOFDAY 20 | #endif 21 | #endif 22 | 23 | #ifdef SPMD 24 | #undef HAVE_MPI 25 | #define HAVE_MPI 26 | #endif 27 | 28 | #ifdef _OPENMP 29 | #ifndef THREADED_PTHREADS 30 | #define THREADED_OMP 31 | #endif 32 | #endif 33 | /* above block for camtimers only */ 34 | 35 | #ifdef HAVE_MPI 36 | #include 37 | #endif 38 | 39 | /* 40 | ** Options settable by a call to GPTLsetoption() (default in parens) 41 | ** These numbers need to be small integers because GPTLsetoption can 42 | ** be passed PAPI counters, and we need to avoid collisions in that 43 | ** integer space. PAPI presets are big negative integers, and PAPI 44 | ** native events are big positive integers. 45 | */ 46 | 47 | typedef enum { 48 | GPTLsync_mpi = 0, /* Synchronize before certain MPI calls (PMPI-mode only) */ 49 | GPTLwall = 1, /* Collect wallclock stats (true) */ 50 | GPTLcpu = 2, /* Collect CPU stats (false)*/ 51 | GPTLabort_on_error = 3, /* Abort on failure (false) */ 52 | GPTLoverhead = 4, /* Estimate overhead of underlying timing routine (true) */ 53 | GPTLdepthlimit = 5, /* Only print timers this depth or less in the tree (inf) */ 54 | GPTLverbose = 6, /* Verbose output (false) */ 55 | GPTLnarrowprint = 7, /* Print PAPI and derived stats in 8 columns not 16 (true) */ 56 | GPTLpercent = 9, /* Add a column for percent of first timer (false) */ 57 | GPTLpersec = 10, /* Add a PAPI column that prints "per second" stats (true) */ 58 | GPTLmultiplex = 11, /* Allow PAPI multiplexing (false) */ 59 | GPTLdopr_preamble = 12, /* Print preamble info (true) */ 60 | GPTLdopr_threadsort = 13, /* Print sorted thread stats (true) */ 61 | GPTLdopr_multparent = 14, /* Print multiple parent info (true) */ 62 | GPTLdopr_collision = 15, /* Print hastable collision info (true) */ 63 | GPTLprint_method = 16, /* Tree print method: first parent, last parent 64 | most frequent, or full tree (most frequent) */ 65 | GPTLprint_mode = 50, /* Write mode for output file (overwrite, append) */ 66 | GPTLtablesize = 51, /* per-thread size of hash table (1024) */ 67 | GPTLmaxthreads = 52, /* maximum number of threads */ 68 | /* 69 | ** These are derived counters based on PAPI counters. All default to false 70 | */ 71 | GPTL_IPC = 17, /* Instructions per cycle */ 72 | GPTL_CI = 18, /* Computational intensity */ 73 | GPTL_FPC = 19, /* FP ops per cycle */ 74 | GPTL_FPI = 20, /* FP ops per instruction */ 75 | GPTL_LSTPI = 21, /* Load-store instruction fraction */ 76 | GPTL_DCMRT = 22, /* L1 miss rate (fraction) */ 77 | GPTL_LSTPDCM = 23, /* Load-stores per L1 miss */ 78 | GPTL_L2MRT = 24, /* L2 miss rate (fraction) */ 79 | GPTL_LSTPL2M = 25, /* Load-stores per L2 miss */ 80 | GPTL_L3MRT = 26, /* L3 read miss rate (fraction) */ 81 | /* 82 | ** New ESMF options for GPTL 83 | */ 84 | GPTLprofile_ovhd = 27, /* Direct measurement of profiling overhead (false) */ 85 | GPTLdopr_quotes = 28 /* Add double quotes to timer names on output (false) */ 86 | } Option; 87 | 88 | /* 89 | ** Underlying wallclock timer: optimize for best granularity with least overhead. 90 | ** These numbers need not be distinct from the above because these are passed 91 | ** to GPTLsetutr() and the above are passed to GPTLsetoption() 92 | */ 93 | 94 | typedef enum { 95 | GPTLgettimeofday = 1, /* the default */ 96 | GPTLnanotime = 2, /* only available on x86 */ 97 | GPTLmpiwtime = 4, /* MPI_Wtime */ 98 | GPTLclockgettime = 5, /* clock_gettime */ 99 | GPTLpapitime = 6, /* only if PAPI is available */ 100 | GPTLread_real_time = 3 /* AIX only */ 101 | } Funcoption; 102 | 103 | /* 104 | ** How to report parent/child relationships at print time (for children with multiple parents) 105 | */ 106 | 107 | typedef enum { 108 | GPTLfirst_parent = 1, /* first parent found */ 109 | GPTLlast_parent = 2, /* last parent found */ 110 | GPTLmost_frequent = 3, /* most frequent parent (default) */ 111 | GPTLfull_tree = 4 /* complete call tree */ 112 | } Method; 113 | 114 | /* 115 | ** Whether to overwrite or append to output file 116 | */ 117 | 118 | typedef enum { 119 | GPTLprint_write = 1, /* overwrite */ 120 | GPTLprint_append = 2, /* append */ 121 | } PRMode; 122 | 123 | /* 124 | ** Function prototypes 125 | */ 126 | 127 | #ifdef __cplusplus 128 | extern "C" { 129 | #endif 130 | 131 | extern int GPTLsetoption (const int, const int); 132 | extern int GPTLinitialize (void); 133 | extern int GPTLprefix_set (const char *); 134 | extern int GPTLprefix_setf (const char *, const int); 135 | extern int GPTLprefix_unset (void); 136 | extern int GPTLstart (const char *); 137 | extern int GPTLstart_handle (const char *, void **); 138 | extern int GPTLstartf (const char *, const int); 139 | extern int GPTLstartf_handle (const char *, const int, void **); 140 | extern int GPTLstop (const char *); 141 | extern int GPTLstopf (const char *, const int); 142 | extern int GPTLstop_handle (const char *, void **); 143 | extern int GPTLstopf_handle (const char *, const int, void **); 144 | extern int GPTLstartstop_vals (const char *, double, int); 145 | extern int GPTLstartstop_valsf (const char *, const int, double, int); 146 | extern int GPTLstamp (double *, double *, double *); 147 | extern int GPTLprint_mode_query (void); 148 | extern int GPTLprint_mode_set (const int); 149 | extern int GPTLpr (const int); 150 | extern int GPTLpr_file (const char *); 151 | 152 | #ifdef HAVE_MPI 153 | extern int GPTLpr_summary (MPI_Comm comm); 154 | extern int GPTLpr_summary_file (MPI_Comm, const char *); 155 | extern int GPTLbarrier (MPI_Comm comm, const char *); 156 | #else 157 | extern int GPTLpr_summary (int); 158 | extern int GPTLpr_summary_file (int, const char *); 159 | extern int GPTLbarrier (int, const char *); 160 | #endif 161 | 162 | extern int GPTLreset (void); 163 | extern int GPTLfinalize (void); 164 | extern int GPTLget_memusage (int *, int *, int *, int *, int *); 165 | extern int GPTLprint_memusage (const char *); 166 | extern int GPTLenable (void); 167 | extern int GPTLdisable (void); 168 | extern int GPTLsetutr (const int); 169 | extern int GPTLquery (const char *, int, int *, int *, double *, double *, double *, 170 | long long *, const int); 171 | extern int GPTLquerycounters (const char *, int, long long *); 172 | extern int GPTLget_wallclock (const char *, int, double *); 173 | extern int GPTLget_eventvalue (const char *, const char *, int, double *); 174 | extern int GPTLget_nregions (int, int *); 175 | extern int GPTLget_regionname (int, int, char *, int); 176 | extern int GPTL_PAPIlibraryinit (void); 177 | extern int GPTLevent_name_to_code (const char *, int *); 178 | extern int GPTLevent_code_to_name (const int, char *); 179 | 180 | #ifdef __cplusplus 181 | } 182 | #endif 183 | 184 | #endif 185 | -------------------------------------------------------------------------------- /share/timing/gptl.inc: -------------------------------------------------------------------------------- 1 | ! 2 | ! $Id: gptl.inc,v 1.44 2011-03-28 20:55:19 rosinski Exp $ 3 | ! 4 | ! Author: Jim Rosinski 5 | ! 6 | ! GPTL header file to be included in user code. Values match 7 | ! their counterparts in gptl.h. See that file or man pages 8 | ! or web-based documenation for descriptions of each value 9 | ! 10 | integer GPTLsync_mpi 11 | integer GPTLwall 12 | integer GPTLcpu 13 | integer GPTLabort_on_error 14 | integer GPTLoverhead 15 | integer GPTLdepthlimit 16 | integer GPTLverbose 17 | integer GPTLnarrowprint 18 | integer GPTLpercent 19 | integer GPTLpersec 20 | integer GPTLmultiplex 21 | integer GPTLdopr_preamble 22 | integer GPTLdopr_threadsort 23 | integer GPTLdopr_multparent 24 | integer GPTLdopr_collision 25 | integer GPTLprint_method 26 | integer GPTLprint_mode 27 | integer GPTLtablesize 28 | integer GPTLmaxthreads 29 | 30 | integer GPTL_IPC 31 | integer GPTL_CI 32 | integer GPTL_FPC 33 | integer GPTL_FPI 34 | integer GPTL_LSTPI 35 | integer GPTL_DCMRT 36 | integer GPTL_LSTPDCM 37 | integer GPTL_L2MRT 38 | integer GPTL_LSTPL2M 39 | integer GPTL_L3MRT 40 | 41 | integer GPTLprofile_ovhd 42 | integer GPTLdopr_quotes 43 | 44 | integer GPTLnanotime 45 | integer GPTLmpiwtime 46 | integer GPTLclockgettime 47 | integer GPTLgettimeofday 48 | integer GPTLpapitime 49 | integer GPTLread_real_time 50 | 51 | integer GPTLfirst_parent 52 | integer GPTLlast_parent 53 | integer GPTLmost_frequent 54 | integer GPTLfull_tree 55 | 56 | integer GPTLprint_write 57 | integer GPTLprint_append 58 | 59 | parameter (GPTLsync_mpi = 0) 60 | parameter (GPTLwall = 1) 61 | parameter (GPTLcpu = 2) 62 | parameter (GPTLabort_on_error = 3) 63 | parameter (GPTLoverhead = 4) 64 | parameter (GPTLdepthlimit = 5) 65 | parameter (GPTLverbose = 6) 66 | parameter (GPTLnarrowprint = 7) 67 | parameter (GPTLpercent = 9) 68 | parameter (GPTLpersec = 10) 69 | parameter (GPTLmultiplex = 11) 70 | parameter (GPTLdopr_preamble = 12) 71 | parameter (GPTLdopr_threadsort= 13) 72 | parameter (GPTLdopr_multparent= 14) 73 | parameter (GPTLdopr_collision = 15) 74 | parameter (GPTLprint_method = 16) 75 | parameter (GPTLprint_mode = 50) 76 | parameter (GPTLtablesize = 51) 77 | parameter (GPTLmaxthreads = 52) 78 | 79 | parameter (GPTL_IPC = 17) 80 | parameter (GPTL_CI = 18) 81 | parameter (GPTL_FPC = 19) 82 | parameter (GPTL_FPI = 20) 83 | parameter (GPTL_LSTPI = 21) 84 | parameter (GPTL_DCMRT = 22) 85 | parameter (GPTL_LSTPDCM = 23) 86 | parameter (GPTL_L2MRT = 24) 87 | parameter (GPTL_LSTPL2M = 25) 88 | parameter (GPTL_L3MRT = 26) 89 | 90 | parameter (GPTLprofile_ovhd = 27) 91 | parameter (GPTLdopr_quotes = 28) 92 | 93 | parameter (GPTLgettimeofday = 1) 94 | parameter (GPTLnanotime = 2) 95 | parameter (GPTLmpiwtime = 4) 96 | parameter (GPTLclockgettime = 5) 97 | parameter (GPTLpapitime = 6) 98 | parameter (GPTLread_real_time = 3) 99 | 100 | parameter (GPTLfirst_parent = 1) 101 | parameter (GPTLlast_parent = 2) 102 | parameter (GPTLmost_frequent = 3) 103 | parameter (GPTLfull_tree = 4) 104 | 105 | parameter (GPTLprint_write = 1) 106 | parameter (GPTLprint_append = 2) 107 | 108 | ! Externals 109 | 110 | integer gptlsetoption 111 | integer gptlinitialize 112 | integer gptlprefix_set 113 | integer gptlprefix_setf 114 | integer gptlprefix_unset 115 | integer gptlstart 116 | integer gptlstart_handle 117 | integer gptlstartf 118 | integer gptlstartf_handle 119 | integer gptlstop 120 | integer gptlstop_handle 121 | integer gptlstopf 122 | integer gptlstopf_handle 123 | integer gptlstartstop_vals 124 | integer gptlstartstop_valsf 125 | integer gptlstamp 126 | integer gptlprint_mode_query 127 | integer gptlprint_mode_set 128 | integer gptlpr 129 | integer gptlpr_file 130 | integer gptlpr_summary 131 | integer gptlpr_summary_file 132 | integer gptlbarrier 133 | integer gptlreset 134 | integer gptlfinalize 135 | integer gptlget_memusage 136 | integer gptlprint_memusage 137 | integer gptlenable 138 | integer gptldisable 139 | integer gptlsetutr 140 | integer gptlquery 141 | integer gptlquerycounters 142 | integer gptlget_wallclock 143 | integer gptlget_eventvalue 144 | integer gptlget_nregions 145 | integer gptlget_regionname 146 | integer gptl_papilibraryinit 147 | integer gptlevent_name_to_code 148 | integer gptlevent_code_to_name 149 | 150 | external gptlsetoption 151 | external gptlinitialize 152 | external gptlprefix_set 153 | external gptlprefix_setf 154 | external gptlprefix_unset 155 | external gptlstart 156 | external gptlstart_handle 157 | external gptlstartf 158 | external gptlstartf_handle 159 | external gptlstop 160 | external gptlstop_handle 161 | external gptlstopf 162 | external gptlstopf_handle 163 | external gptlstartstop_vals 164 | external gptlstartstop_valsf 165 | external gptlstamp 166 | external gptlprint_mode_query 167 | external gptlprint_mode_set 168 | external gptlpr 169 | external gptlpr_file 170 | external gptlpr_summary 171 | external gptlpr_summary_file 172 | external gptlbarrier 173 | external gptlreset 174 | external gptlfinalize 175 | external gptlget_memusage 176 | external gptlprint_memusage 177 | external gptlenable 178 | external gptldisable 179 | external gptlsetutr 180 | external gptlquery 181 | external gptlquerycounters 182 | external gptlget_wallclock 183 | external gptlget_eventvalue 184 | external gptlget_nregions 185 | external gptlget_regionname 186 | external gptl_papilibraryinit 187 | external gptlevent_name_to_code 188 | external gptlevent_code_to_name 189 | -------------------------------------------------------------------------------- /share/timing/private.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: private.h,v 1.74 2011-03-28 20:55:19 rosinski Exp $ 3 | ** 4 | ** Author: Jim Rosinski 5 | ** 6 | ** Contains definitions private to GPTL and inaccessible to invoking user environment 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #ifndef NO_COMM_F2C 13 | #ifndef HAVE_COMM_F2C 14 | #define HAVE_COMM_F2C 15 | #endif 16 | #endif 17 | 18 | #ifndef MIN 19 | #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) 20 | #endif 21 | 22 | #ifndef MAX 23 | #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) 24 | #endif 25 | 26 | #define STRMATCH(X,Y) (strcmp((X),(Y)) == 0) 27 | 28 | #define STRNMATCH(X,Y,N) (strncmp((X),(Y),(N)) == 0) 29 | 30 | /* Output counts less than PRTHRESH will be printed as integers */ 31 | #define PRTHRESH 1000000L 32 | 33 | /* Maximum allowed callstack depth */ 34 | #define MAX_STACK 128 35 | 36 | /* longest timer name allowed (probably safe to just change) */ 37 | #define MAX_CHARS 127 38 | 39 | /* 40 | ** max allowable number of PAPI counters, or derived events. For convenience, 41 | ** set to max (# derived events, # papi counters required) so "avail" lists 42 | ** all available options. 43 | */ 44 | #define MAX_AUX 9 45 | 46 | #ifndef __cplusplus 47 | typedef enum {false = 0, true = 1} bool; /* mimic C++ */ 48 | #endif 49 | 50 | typedef struct { 51 | long last_utime; /* saved usr time from "start" */ 52 | long last_stime; /* saved sys time from "start" */ 53 | long accum_utime; /* accumulator for usr time */ 54 | long accum_stime; /* accumulator for sys time */ 55 | } Cpustats; 56 | 57 | typedef struct { 58 | double last; /* timestamp from last call */ 59 | double latest; /* most recent delta */ 60 | double accum; /* accumulated time */ 61 | float max; /* longest time for start/stop pair */ 62 | float min; /* shortest time for start/stop pair */ 63 | float prev_min; /* previous shortest time for start/stop pair */ 64 | int latest_is_min; /* whether min is current latest (1) or not (0) */ 65 | } Wallstats; 66 | 67 | typedef struct { 68 | long long last[MAX_AUX]; /* array of saved counters from "start" */ 69 | long long accum[MAX_AUX]; /* accumulator for counters */ 70 | } Papistats; 71 | 72 | typedef struct { 73 | int counter; /* PAPI or Derived counter */ 74 | char *namestr; /* PAPI or Derived counter as string */ 75 | char *str8; /* print string for output timers (8 chars) */ 76 | char *str16; /* print string for output timers (16 chars) */ 77 | char *longstr; /* long descriptive print string */ 78 | } Entry; 79 | 80 | typedef struct { 81 | Entry event; 82 | int numidx; /* derived event: PAPI counter array index for numerator */ 83 | int denomidx; /* derived event: PAPI counter array index for denominator */ 84 | } Pr_event; 85 | 86 | typedef struct TIMER { 87 | char name[MAX_CHARS+1]; /* timer name (user input) */ 88 | bool onflg; /* timer currently on or off */ 89 | #ifdef ENABLE_PMPI 90 | double nbytes; /* number of bytes for MPI call */ 91 | #endif 92 | #ifdef HAVE_PAPI 93 | Papistats aux; /* PAPI stats */ 94 | #endif 95 | Wallstats wall; /* wallclock stats */ 96 | Cpustats cpu; /* cpu stats */ 97 | unsigned long count; /* number of start/stop calls */ 98 | unsigned long nrecurse; /* number of recursive start/stop calls */ 99 | void *address; /* address of timer: used only by _instr routines */ 100 | struct TIMER *next; /* next timer in linked list */ 101 | struct TIMER **parent; /* array of parents */ 102 | struct TIMER **children; /* array of children */ 103 | int *parent_count; /* array of call counts, one for each parent */ 104 | unsigned int recurselvl; /* recursion level */ 105 | unsigned int nchildren; /* number of children */ 106 | unsigned int nparent; /* number of parents */ 107 | unsigned int norphan; /* number of times this timer was an orphan */ 108 | int num_desc; /* number of descendants */ 109 | } Timer; 110 | 111 | typedef struct { 112 | Timer **entries; /* array of timers hashed to the same value */ 113 | unsigned int nument; /* number of entries hashed to the same value */ 114 | } Hashentry; 115 | 116 | /* Function prototypes */ 117 | 118 | extern int GPTLerror (const char *, ...); /* print error msg and return */ 119 | extern void GPTLset_abort_on_error (bool val); /* set flag to abort on error */ 120 | extern void *GPTLallocate (const int); /* malloc wrapper */ 121 | 122 | extern int GPTLstart_instr (void *); /* auto-instrumented start */ 123 | extern int GPTLstop_instr (void *); /* auto-instrumented stop */ 124 | extern int GPTLis_initialized (void); /* needed by MPI_Init wrapper */ 125 | 126 | #ifdef __cplusplus 127 | extern "C" { 128 | #endif 129 | 130 | #ifdef AUTO_INST 131 | extern void __cyg_profile_func_enter (void *, void *); 132 | extern void __cyg_profile_func_exit (void *, void *); 133 | #endif 134 | 135 | #ifdef __cplusplus 136 | }; 137 | #endif 138 | 139 | /* 140 | ** These are needed for communication between gptl.c and gptl_papi.c 141 | */ 142 | 143 | #ifdef HAVE_PAPI 144 | extern int GPTL_PAPIsetoption (const int, const int); 145 | extern int GPTL_PAPIinitialize (const int, const bool, int *, Entry *); 146 | extern int GPTL_PAPIstart (const int, Papistats *); 147 | extern int GPTL_PAPIstop (const int, Papistats *); 148 | extern void GPTL_PAPIprstr (FILE *); 149 | extern void GPTL_PAPIpr (FILE *, const Papistats *, const int, const int, const double); 150 | extern void GPTL_PAPIadd (Papistats *, const Papistats *); 151 | extern void GPTL_PAPIfinalize (int); 152 | extern void GPTL_PAPIquery (const Papistats *, long long *, int); 153 | extern int GPTL_PAPIget_eventvalue (const char *, const Papistats *, double *); 154 | extern bool GPTL_PAPIis_multiplexed (void); 155 | extern void GPTL_PAPIprintenabled (FILE *); 156 | extern void read_counters100 (void); 157 | extern int GPTLget_npapievents (void); 158 | extern int GPTLcreate_and_start_events (const int); 159 | #endif 160 | 161 | #ifdef ENABLE_PMPI 162 | extern Timer *GPTLgetentry (const char *); 163 | extern int GPTLpmpi_setoption (const int, const int); 164 | extern int GPTLpr_has_been_called (void); /* needed by MPI_Finalize wrapper*/ 165 | #endif 166 | --------------------------------------------------------------------------------