├── CHANGELOG.md ├── README.md ├── aio_comp_esmf.c ├── .github └── workflows │ └── bumpversion.yml ├── cime_config └── config_component.xml └── aio_comp_nuopc.F90 /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # APIO 2 | Adds an asyncronous interface to the PIO library to a CIME compset. -------------------------------------------------------------------------------- /aio_comp_esmf.c: -------------------------------------------------------------------------------- 1 | /* just added this file to test github actions */ 2 | #include 3 | -------------------------------------------------------------------------------- /.github/workflows/bumpversion.yml: -------------------------------------------------------------------------------- 1 | name: Bump version 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Bump version and push tag 12 | id: tag_version 13 | uses: mathieudutour/github-tag-action@v6.0 14 | with: 15 | github_token: ${{ secrets.GITHUB_TOKEN }} 16 | create_annotated_tag: true 17 | default_bump: patch 18 | dry_run: false 19 | tag_prefix: apio 20 | -------------------------------------------------------------------------------- /cime_config/config_component.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | Asyncronous interface to PIO library (APIO) 14 | 15 | 16 | 17 | char 18 | apio 19 | apio 20 | case_comp 21 | env_case.xml 22 | Name of async IO component 23 | 24 | 25 | 26 | ========================================= 27 | APIO naming conventions in compset name 28 | ========================================= 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /aio_comp_nuopc.F90: -------------------------------------------------------------------------------- 1 | module aio_comp_nuopc 2 | 3 | !---------------------------------------------------------------------------- 4 | ! This is the NUOPC cap for APIO (asyncronous PIO interface) 5 | !---------------------------------------------------------------------------- 6 | 7 | use ESMF , only : ESMF_Mesh, ESMF_GridComp, ESMF_Time, ESMF_TimeInterval 8 | use ESMF , only : ESMF_State, ESMF_Clock, ESMF_SUCCESS, ESMF_LOGMSG_INFO 9 | use ESMF , only : ESMF_TraceRegionEnter, ESMF_TraceRegionExit 10 | use ESMF , only : ESMF_Alarm, ESMF_METHOD_INITIALIZE, ESMF_MethodAdd, ESMF_MethodRemove 11 | use ESMF , only : ESMF_TimeGet, ESMF_ClockGet, ESMF_GridCompSetEntryPoint 12 | use ESMF , only : ESMF_ClockGetAlarm, ESMF_AlarmIsRinging, ESMF_AlarmRingerOff 13 | use ESMF , only : operator(+), ESMF_LogWrite 14 | use NUOPC , only : NUOPC_CompDerive, NUOPC_CompSetEntryPoint, NUOPC_CompSpecialize 15 | use NUOPC , only : NUOPC_CompAttributeGet, NUOPC_Advertise 16 | use NUOPC_Model , only : model_routine_SS => SetServices 17 | use NUOPC_Model , only : model_label_Advance => label_Advance 18 | use NUOPC_Model , only : model_label_SetRunClock => label_SetRunClock 19 | use NUOPC_Model , only : model_label_Finalize => label_Finalize 20 | use NUOPC_Model , only : NUOPC_ModelGet, SetVM 21 | use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs 22 | use shr_const_mod , only : SHR_CONST_SPVAL 23 | use shr_sys_mod , only : shr_sys_abort 24 | use shr_cal_mod , only : shr_cal_ymd2date 25 | use shr_mpi_mod , only : shr_mpi_bcast 26 | use dshr_methods_mod , only : dshr_state_getfldptr, dshr_state_diagnose, chkerr, memcheck 27 | use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_get_stream_domain 28 | use dshr_strdata_mod , only : shr_strdata_init_from_config 29 | use dshr_mod , only : dshr_model_initphase, dshr_init 30 | use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_check_restart_alarm 31 | use dshr_mod , only : dshr_restart_read, dshr_restart_write, dshr_mesh_init 32 | use dshr_dfield_mod , only : dfield_type, dshr_dfield_add, dshr_dfield_copy 33 | use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add, dshr_fldlist_realize 34 | 35 | implicit none 36 | private ! except 37 | 38 | public :: SetServices 39 | public :: SetVM 40 | private :: InitializeAdvertise 41 | private :: InitializeRealize 42 | private :: ModelAdvance 43 | private :: drof_comp_run 44 | private :: ModelFinalize 45 | 46 | !-------------------------------------------------------------------------- 47 | ! Private module data 48 | !-------------------------------------------------------------------------- 49 | 50 | type(shr_strdata_type) :: sdat 51 | type(ESMF_Mesh) :: model_mesh ! model mesh 52 | character(len=CS) :: flds_scalar_name = '' 53 | integer :: flds_scalar_num = 0 54 | integer :: flds_scalar_index_nx = 0 55 | integer :: flds_scalar_index_ny = 0 56 | integer :: mpicom ! mpi communicator 57 | integer :: my_task ! my task in mpi communicator mpicom 58 | logical :: masterproc ! true of my_task == master_task 59 | character(len=16) :: inst_suffix = "" ! char string associated with instance (ie. "_0001" or "") 60 | integer :: logunit ! logging unit number 61 | logical :: restart_read 62 | character(CL) :: case_name ! case name 63 | character(*) , parameter :: nullstr = 'null' 64 | ! drof_in namelist input 65 | character(CL) :: streamfilename = nullstr ! filename to obtain stream info from 66 | character(CL) :: nlfilename = nullstr ! filename to obtain namelist info from 67 | character(CL) :: dataMode = nullstr ! flags physics options wrt input data 68 | character(CL) :: model_meshfile = nullstr ! full pathname to model meshfile 69 | character(CL) :: model_maskfile = nullstr ! full pathname to obtain mask from 70 | character(CL) :: restfilm = nullstr ! model restart file namelist 71 | integer :: nx_global 72 | integer :: ny_global 73 | 74 | logical :: diagnose_data = .true. 75 | integer , parameter :: master_task=0 ! task number of master task 76 | character(*) , parameter :: rpfile = 'rpointer.rof' 77 | #ifdef CESMCOUPLED 78 | character(*) , parameter :: modName = "(aio_comp_nuopc)" 79 | #else 80 | character(*) , parameter :: modName = "(cdeps_drof_comp)" 81 | #endif 82 | 83 | ! linked lists 84 | type(fldList_type) , pointer :: fldsExport => null() 85 | type(dfield_type) , pointer :: dfields => null() 86 | 87 | ! model mask and model fraction 88 | real(r8), pointer :: model_frac(:) => null() 89 | integer , pointer :: model_mask(:) => null() 90 | 91 | ! module pointer arrays 92 | real(r8), pointer :: Forr_rofl(:) => null() 93 | real(r8), pointer :: Forr_rofi(:) => null() 94 | 95 | character(*) , parameter :: u_FILE_u = & 96 | __FILE__ 97 | 98 | !=============================================================================== 99 | contains 100 | !=============================================================================== 101 | 102 | subroutine SetServices(gcomp, rc) 103 | type(ESMF_GridComp) :: gcomp 104 | integer, intent(out) :: rc 105 | 106 | ! Local varaibles 107 | character(len=*),parameter :: subname=trim(modName)//':(SetServices) ' 108 | !-------------------------------- 109 | 110 | rc = ESMF_SUCCESS 111 | call ESMF_LogWrite(subname//' called', ESMF_LOGMSG_INFO) 112 | 113 | ! the NUOPC gcomp component will register the generic methods 114 | call NUOPC_CompDerive(gcomp, model_routine_SS, rc=rc) 115 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 116 | 117 | ! switching to IPD versions 118 | call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & 119 | userRoutine=dshr_model_initphase, phase=0, rc=rc) 120 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 121 | 122 | ! attach specializing method(s) 123 | call NUOPC_CompSpecialize(gcomp, specLabel=model_label_Advance, specRoutine=ModelAdvance, rc=rc) 124 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 125 | 126 | call ESMF_MethodRemove(gcomp, label=model_label_SetRunClock, rc=rc) 127 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 128 | call NUOPC_CompSpecialize(gcomp, specLabel=model_label_SetRunClock, specRoutine=dshr_set_runclock, rc=rc) 129 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 130 | 131 | call NUOPC_CompSpecialize(gcomp, specLabel=model_label_Finalize, specRoutine=ModelFinalize, rc=rc) 132 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 133 | 134 | call ESMF_LogWrite(subname//' done', ESMF_LOGMSG_INFO) 135 | 136 | end subroutine SetServices 137 | 138 | !=============================================================================== 139 | 140 | subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) 141 | 142 | ! input/output variables 143 | type(ESMF_GridComp) :: gcomp 144 | type(ESMF_State) :: importState, exportState 145 | type(ESMF_Clock) :: clock 146 | integer, intent(out) :: rc 147 | 148 | ! local variables 149 | integer :: inst_index ! number of current instance (ie. 1) 150 | integer :: nu ! unit number 151 | integer :: ierr ! error code 152 | logical :: exists ! check for file existence 153 | type(fldlist_type), pointer :: fldList 154 | character(len=*),parameter :: subname=trim(modName)//':(InitializeAdvertise) ' 155 | character(*) ,parameter :: F00 = "('(" // trim(modName) // ") ',8a)" 156 | character(*) ,parameter :: F01 = "('(" // trim(modName) // ") ',a,2x,i8)" 157 | character(*) ,parameter :: F02 = "('(" // trim(modName) // ") ',a,l6)" 158 | !------------------------------------------------------------------------------- 159 | 160 | namelist / drof_nml / datamode, model_meshfile, model_maskfile, & 161 | restfilm, nx_global, ny_global 162 | 163 | rc = ESMF_SUCCESS 164 | 165 | call NUOPC_CompAttributeGet(gcomp, name='case_name', value=case_name, rc=rc) 166 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 167 | 168 | ! Obtain flds_scalar values, mpi values, multi-instance values and 169 | ! set logunit and set shr logging to my log file 170 | call dshr_init(gcomp, 'ROF', sdat, mpicom, my_task, inst_index, inst_suffix, & 171 | flds_scalar_name, flds_scalar_num, flds_scalar_index_nx, flds_scalar_index_ny, & 172 | logunit, rc=rc) 173 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 174 | 175 | ! determine logical masterproc 176 | masterproc = (my_task == master_task) 177 | 178 | ! Read drof_nml from nlfilename 179 | if (masterproc) then 180 | nlfilename = "drof_in"//trim(inst_suffix) 181 | open (newunit=nu,file=trim(nlfilename),status="old",action="read") 182 | read (nu,nml=drof_nml,iostat=ierr) 183 | close(nu) 184 | if (ierr > 0) then 185 | write(logunit,*) 'ERROR: reading input namelist, '//trim(nlfilename)//' iostat=',ierr 186 | call shr_sys_abort(subName//': namelist read error '//trim(nlfilename)) 187 | end if 188 | 189 | ! write namelist input to standard out 190 | write(logunit,F00)' datamode = ',trim(datamode) 191 | write(logunit,F00)' model_meshfile = ',trim(model_meshfile) 192 | write(logunit,F00)' model_maskfile = ',trim(model_maskfile) 193 | write(logunit,F01)' nx_global = ',nx_global 194 | write(logunit,F01)' ny_global = ',ny_global 195 | write(logunit,F00)' restfilm = ',trim(restfilm) 196 | end if 197 | 198 | ! broadcast namelist input 199 | call shr_mpi_bcast(datamode , mpicom, 'datamode') 200 | call shr_mpi_bcast(model_meshfile , mpicom, 'model_meshfile') 201 | call shr_mpi_bcast(model_maskfile , mpicom, 'model_maskfile') 202 | call shr_mpi_bcast(nx_global , mpicom, 'nx_global') 203 | call shr_mpi_bcast(ny_global , mpicom, 'ny_global') 204 | call shr_mpi_bcast(restfilm , mpicom, 'restfilm') 205 | 206 | ! Validate datamode 207 | if (trim(datamode) == 'copyall') then 208 | if (masterproc) write(logunit,*) 'drof datamode = ',trim(datamode) 209 | else 210 | call shr_sys_abort(' ERROR illegal drof datamode = '//trim(datamode)) 211 | end if 212 | 213 | call dshr_fldList_add(fldsExport, trim(flds_scalar_name)) 214 | call dshr_fldlist_add(fldsExport, "Forr_rofl") 215 | call dshr_fldlist_add(fldsExport, "Forr_rofi") 216 | 217 | fldlist => fldsExport ! the head of the linked list 218 | do while (associated(fldlist)) 219 | call NUOPC_Advertise(exportState, standardName=fldlist%stdname, rc=rc) 220 | if (ChkErr(rc,__LINE__,u_FILE_u)) return 221 | call ESMF_LogWrite('(drof_comp_advertise): Fr_rof '//trim(fldList%stdname), ESMF_LOGMSG_INFO) 222 | fldList => fldList%next 223 | enddo 224 | 225 | end subroutine InitializeAdvertise 226 | 227 | !=============================================================================== 228 | subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) 229 | 230 | ! input/output variables 231 | type(ESMF_GridComp) :: gcomp 232 | type(ESMF_State) :: importState, exportState 233 | type(ESMF_Clock) :: clock 234 | integer, intent(out) :: rc 235 | 236 | ! local variables 237 | type(ESMF_TIME) :: currTime 238 | integer :: current_ymd ! model date 239 | integer :: current_year ! model year 240 | integer :: current_mon ! model month 241 | integer :: current_day ! model day 242 | integer :: current_tod ! model sec into model date 243 | character(len=*), parameter :: F00 = "('" // trim(modName) // ": ')',8a)" 244 | character(len=*), parameter :: subname=trim(modName)//':(InitializeRealize) ' 245 | !------------------------------------------------------------------------------- 246 | 247 | rc = ESMF_SUCCESS 248 | 249 | end subroutine InitializeRealize 250 | 251 | subroutine ModelFinalize(gcomp, rc) 252 | type(ESMF_GridComp) :: gcomp 253 | integer, intent(out) :: rc 254 | rc = ESMF_SUCCESS 255 | if (masterproc) then 256 | write(logunit,*) 257 | write(logunit,*) 'drof : end of main integration loop' 258 | write(logunit,*) 259 | end if 260 | end subroutine ModelFinalize 261 | 262 | end module aio_comp_nuopc 263 | --------------------------------------------------------------------------------