From c918615337a8ee05e76f1e7f3810508fe3670c3e Mon Sep 17 00:00:00 2001 From: Dan Rosen Date: Fri, 9 Oct 2026 11:00:32 -0600 Subject: [PATCH] Finalize ESMF objects for components * adds helper function for ESMF cleanup to dshr_strdata_mod * adds helper functions for ESMF cleanup to dshr_mod * finalize strdata: destroy ESMF objs in each pstrm for each cmp * finalize mesh: destroy ESMF mesh(es) for each cmp * finalize alarms: destroy alarms associated with each cmp clock * destroy temporary ESMF objects in datm_get_adjustment_factors * destroy temporary ESMF objects in dglc_datamode_noevolve_advance * destroy temporary ESMF objects in dshr_set_modelmask * destroy temporary ESMF objects in shr_strdata_readstrm * destroy temporary ESMF objects in shr_stream_init_from_esmfconfig --- datm/atm_comp_nuopc.F90 | 17 ++++ datm/datm_datamode_core2_mod.F90 | 52 +++++++--- dglc/dglc_datamode_noevolve_mod.F90 | 20 +++- dglc/glc_comp_nuopc.F90 | 27 +++++ dice/ice_comp_nuopc.F90 | 17 ++++ dlnd/lnd_comp_nuopc.F90 | 15 +++ docn/ocn_comp_nuopc.F90 | 17 ++++ drof/rof_comp_nuopc.F90 | 17 ++++ dshr/dshr_mod.F90 | 96 +++++++++++++++++- dwav/wav_comp_nuopc.F90 | 17 ++++ streams/dshr_strdata_mod.F90 | 152 ++++++++++++++++++++++++++++ streams/dshr_stream_mod.F90 | 4 + 12 files changed, 429 insertions(+), 22 deletions(-) diff --git a/datm/atm_comp_nuopc.F90 b/datm/atm_comp_nuopc.F90 index f49db0ca6..bc9c79b32 100644 --- a/datm/atm_comp_nuopc.F90 +++ b/datm/atm_comp_nuopc.F90 @@ -33,9 +33,11 @@ module cdeps_datm_comp use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_init_from_config, shr_strdata_advance use dshr_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_setOrbs + use dshr_strdata_mod , only : shr_strdata_finalize use dshr_mod , only : dshr_model_initphase, dshr_init, dshr_restart_write use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_log_clock_advance use dshr_mod , only : dshr_mesh_init, dshr_check_restart_alarm, dshr_restart_read + use dshr_mod , only : dshr_mesh_finalize, dshr_destroy_clock_alarms use dshr_mod , only : dshr_orbital_init, dshr_orbital_update use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add, dshr_fldlist_realize @@ -858,9 +860,24 @@ end function getNextRadCDay subroutine ModelFinalize(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc + + ! local variables !------------------------------------------------------------------------------- rc = ESMF_SUCCESS + + ! finalize sdat + call shr_strdata_finalize(sdat, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! destroy model mesh using dshr_mesh_finalize routine + call dshr_mesh_finalize(gcomp, logunit, 'ATM', model_mesh, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! destroy alarms associated with model's clock + call dshr_destroy_clock_alarms(gcomp, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (my_task == main_task) then write(logunit,*) write(logunit,*) 'datm : end of main integration loop' diff --git a/datm/datm_datamode_core2_mod.F90 b/datm/datm_datamode_core2_mod.F90 index 8e22fb7db..f5d1c53c6 100644 --- a/datm/datm_datamode_core2_mod.F90 +++ b/datm/datm_datamode_core2_mod.F90 @@ -3,6 +3,7 @@ module datm_datamode_core2_mod use ESMF , only : ESMF_State, ESMF_StateGet, ESMF_Field, ESMF_FieldBundle use ESMF , only : ESMF_DistGrid, ESMF_RouteHandle, ESMF_MeshCreate use ESMF , only : ESMF_Mesh, ESMF_MeshGet, ESMF_MeshCreate + use ESMF , only : ESMF_FieldDestroy, ESMF_FieldBundleDestroy, ESMF_MeshDestroy use ESMF , only : ESMF_SUCCESS, ESMF_LogWrite, ESMF_FILEFORMAT_ESMFMESH use ESMF , only : ESMF_StateItem_Flag, ESMF_STATEITEM_NOTFOUND, operator(/=) use ESMF , only : ESMF_FieldBundleCreate, ESMF_FieldCreate, ESMF_MESHLOC_ELEMENT @@ -10,6 +11,7 @@ module datm_datamode_core2_mod use ESMF , only : ESMF_RouteHandleDestroy, ESMF_EXTRAPMETHOD_NEAREST_STOD use ESMF , only : ESMF_POLEMETHOD_ALLAVG, ESMF_REGRIDMETHOD_BILINEAR use ESMF , only : ESMF_DistGridGet, ESMF_FieldRegridStore, ESMF_FieldRedistStore + use ESMF , only : ESMF_FieldRegridRelease, ESMF_FieldRedistRelease use pio , only : Var_Desc_t, file_desc_t, io_desc_t, pio_read_darray, pio_freedecomp use pio , only : pio_openfile, PIO_NOWRITE, pio_seterrorhandling, PIO_BCAST_ERROR use pio , only : pio_initdecomp, pio_inq_dimlen, pio_inq_varid @@ -422,8 +424,8 @@ subroutine datm_get_adjustment_factors(sdat, fileName_mesh, fileName_data, windF type(ESMF_FieldBundle) :: fldbun_src type(ESMF_FieldBundle) :: fldbun_dst type(ESMF_RouteHandle) :: route_handle - type(ESMF_Field) :: field_src - type(ESMF_Field) :: field_dst + type(ESMF_Field) :: field_src_1, field_src_2, field_src_3 + type(ESMF_Field) :: field_dst_1, field_dst_2, field_dst_3 integer :: lsize integer, pointer :: gindex(:) ! domain decomposition of data integer :: ndims ! number of dims @@ -446,37 +448,37 @@ subroutine datm_get_adjustment_factors(sdat, fileName_mesh, fileName_data, windF ! Create input and output field bundles fldbun_src = ESMF_FieldBundleCreate(rc=rc) ! input field bundle - field_src = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, name='windFactor', & + field_src_1 = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, name='windFactor', & meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleAdd(fldbun_src, (/field_src/), rc=rc) + call ESMF_FieldBundleAdd(fldbun_src, (/field_src_1/), rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - field_src = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, name='winddFactor', & + field_src_2 = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, name='winddFactor', & meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleAdd(fldbun_src, (/field_src/), rc=rc) + call ESMF_FieldBundleAdd(fldbun_src, (/field_src_2/), rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - field_src = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, name='qsatFactor', & + field_src_3 = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, name='qsatFactor', & meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleAdd(fldbun_src, (/field_src/), rc=rc) + call ESMF_FieldBundleAdd(fldbun_src, (/field_src_3/), rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return fldbun_dst = ESMF_FieldBundleCreate(rc=rc) ! output field bundle - field_dst = ESMF_FieldCreate(sdat%model_mesh, ESMF_TYPEKIND_R8, name='windFactor', & + field_dst_1 = ESMF_FieldCreate(sdat%model_mesh, ESMF_TYPEKIND_R8, name='windFactor', & meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleAdd(fldbun_dst, (/field_dst/), rc=rc) + call ESMF_FieldBundleAdd(fldbun_dst, (/field_dst_1/), rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - field_dst = ESMF_FieldCreate(sdat%model_mesh, ESMF_TYPEKIND_R8, name='winddFactor', & + field_dst_2 = ESMF_FieldCreate(sdat%model_mesh, ESMF_TYPEKIND_R8, name='winddFactor', & meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleAdd(fldbun_dst, (/field_dst/), rc=rc) + call ESMF_FieldBundleAdd(fldbun_dst, (/field_dst_2/), rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - field_dst = ESMF_FieldCreate(sdat%model_mesh, ESMF_TYPEKIND_R8, name='qsatFactor', & + field_dst_3 = ESMF_FieldCreate(sdat%model_mesh, ESMF_TYPEKIND_R8, name='qsatFactor', & meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleAdd(fldbun_dst, (/field_dst/), rc=rc) + call ESMF_FieldBundleAdd(fldbun_dst, (/field_dst_3/), rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return ! Get mesh info @@ -520,7 +522,7 @@ subroutine datm_get_adjustment_factors(sdat, fileName_mesh, fileName_data, windF if (nxg*nyg /= sdat%model_gsize) then ! TODO: this needs a mask that needs to be read in to have the mapping be accurate ! create bilinear route handle - - call ESMF_FieldRegridStore(field_src, field_dst, routehandle=route_handle, & + call ESMF_FieldRegridStore(field_src_3, field_dst_3, routehandle=route_handle, & regridmethod=ESMF_REGRIDMETHOD_BILINEAR, & polemethod=ESMF_POLEMETHOD_ALLAVG, & extrapMethod=ESMF_EXTRAPMETHOD_NEAREST_STOD, & @@ -528,7 +530,7 @@ subroutine datm_get_adjustment_factors(sdat, fileName_mesh, fileName_data, windF ignoreDegenerate=.true., rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return else - call ESMF_FieldRedistStore(field_src, field_dst, routehandle=route_handle, & + call ESMF_FieldRedistStore(field_src_3, field_dst_3, routehandle=route_handle, & ignoreUnmatchedIndices=.true., rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return end if @@ -549,6 +551,24 @@ subroutine datm_get_adjustment_factors(sdat, fileName_mesh, fileName_data, windF call pio_freedecomp(sdat%pio_subsystem, pio_iodesc) call ESMF_RouteHandleDestroy(route_handle, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldBundleDestroy(fldbun_dst, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldBundleDestroy(fldbun_src, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldDestroy(field_dst_1, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldDestroy(field_dst_2, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldDestroy(field_dst_3, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldDestroy(field_src_1, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldDestroy(field_src_2, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldDestroy(field_src_3, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_MeshDestroy(mesh, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return end subroutine datm_get_adjustment_factors diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 index 1c6809486..e82fda486 100644 --- a/dglc/dglc_datamode_noevolve_mod.F90 +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -4,6 +4,7 @@ module dglc_datamode_noevolve_mod use ESMF , only : ESMF_Mesh, ESMF_DistGrid, ESMF_FieldBundle, ESMF_Field use ESMF , only : ESMF_FieldBundleCreate, ESMF_FieldCreate, ESMF_MeshLoc_Element use ESMF , only : ESMF_FieldBundleAdd, ESMF_MeshGet, ESMF_DistGridGet, ESMF_Typekind_R8 + use ESMF , only : ESMF_FieldBundleDestroy, ESMF_FieldDestroy use ESMF , only : ESMF_GridComp use ESMF , only : ESMF_VM, ESMF_VMGetCurrent, ESMF_VMBroadCast use NUOPC , only : NUOPC_Advertise, NUOPC_IsConnected @@ -238,7 +239,8 @@ subroutine dglc_datamode_noevolve_advance(gcomp, pio_subsystem, io_type, io_form ! local variables type(ESMF_FieldBundle) :: fldbun_noevolve type(ESMF_DistGrid) :: distgrid - type(ESMF_Field) :: field_noevolve + type(ESMF_Field) :: field_thk + type(ESMF_Field) :: field_topg type(file_desc_t) :: pioid type(io_desc_t) :: pio_iodesc integer :: ns ! ice sheet index @@ -296,17 +298,17 @@ subroutine dglc_datamode_noevolve_advance(gcomp, pio_subsystem, io_type, io_form fldbun_noevolve = ESMF_FieldBundleCreate(rc=rc) ! input field bundle ! "ice thickness" ; - field_noevolve = ESMF_FieldCreate(model_meshes(ns), ESMF_TYPEKIND_R8, & + field_thk = ESMF_FieldCreate(model_meshes(ns), ESMF_TYPEKIND_R8, & name='thk', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleAdd(fldbun_noevolve, (/field_noevolve/), rc=rc) + call ESMF_FieldBundleAdd(fldbun_noevolve, (/field_thk/), rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return ! "bed topography" ; - field_noevolve = ESMF_FieldCreate(model_meshes(ns), ESMF_TYPEKIND_R8, & + field_topg = ESMF_FieldCreate(model_meshes(ns), ESMF_TYPEKIND_R8, & name='topg', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleAdd(fldbun_noevolve, (/field_noevolve/), rc=rc) + call ESMF_FieldBundleAdd(fldbun_noevolve, (/field_topg/), rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return ! Create pioid and pio_iodesc at the module level @@ -386,6 +388,14 @@ subroutine dglc_datamode_noevolve_advance(gcomp, pio_subsystem, io_type, io_form call pio_closefile(pioid) call pio_freedecomp(pio_subsystem, pio_iodesc) + nullify(topog, thck) + call ESMF_FieldBundleDestroy(fldbun_noevolve, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldDestroy(field_thk, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldDestroy(field_topg, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end do ! end loop over ice sheets end if diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 index d5d81879d..64955e09c 100644 --- a/dglc/glc_comp_nuopc.F90 +++ b/dglc/glc_comp_nuopc.F90 @@ -37,7 +37,9 @@ module cdeps_dglc_comp #endif use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_init_from_config + use dshr_strdata_mod , only : shr_strdata_finalize use dshr_mod , only : dshr_model_initphase, dshr_init, dshr_mesh_init + use dshr_mod , only : dshr_mesh_finalize, dshr_destroy_clock_alarms use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_check_restart_alarm use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_realize use nuopc_shr_methods, only : shr_get_rpointer_name, alarmInit @@ -764,8 +766,33 @@ end subroutine ModelSetRunClock subroutine ModelFinalize(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc + + ! local variables + integer :: i !------------------------------------------------------------------------------- + rc = ESMF_SUCCESS + + ! finalize sdat + if (allocated(sdat)) then + do i=1, size(sdat) + call shr_strdata_finalize(sdat(i), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end do + end if + + ! destroy model meshes using dshr_mesh_finalize routine + if (allocated(model_meshes)) then + do i=1, size(model_meshes) + call dshr_mesh_finalize(gcomp, logunit, 'GLC', model_meshes(i), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end do + end if + + ! destroy alarms associated with model's clock + call dshr_destroy_clock_alarms(gcomp, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (my_task == main_task) then write(logunit,*) write(logunit,*) 'dglc : end of main integration loop' diff --git a/dice/ice_comp_nuopc.F90 b/dice/ice_comp_nuopc.F90 index 6a328923e..769ce0c58 100644 --- a/dice/ice_comp_nuopc.F90 +++ b/dice/ice_comp_nuopc.F90 @@ -30,9 +30,11 @@ module cdeps_dice_comp use shr_log_mod , only : shr_log_setLogUnit, shr_log_error use shr_cal_mod , only : shr_cal_ymd2date, shr_cal_ymd2julian use dshr_mod , only : dshr_model_initphase, dshr_init, dshr_mesh_init, dshr_check_restart_alarm + use dshr_mod , only : dshr_mesh_finalize, dshr_destroy_clock_alarms use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_log_clock_advance use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_init_from_config, shr_strdata_advance + use dshr_strdata_mod , only : shr_strdata_finalize use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add, dshr_fldlist_realize use dice_datamode_ssmi_mod , only : dice_datamode_ssmi_advertise @@ -581,9 +583,24 @@ end subroutine dice_comp_run subroutine ModelFinalize(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc + + ! local variables !------------------------------------------------------------------------------- rc = ESMF_SUCCESS + + ! finalize sdat + call shr_strdata_finalize(sdat, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! destroy model mesh using dshr_mesh_finalize routine + call dshr_mesh_finalize(gcomp, logunit, 'ICE', model_mesh, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! destroy alarms associated with model's clock + call dshr_destroy_clock_alarms(gcomp, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (mainproc) then write(logunit,*) write(logunit,*) 'dice : end of main integration loop' diff --git a/dlnd/lnd_comp_nuopc.F90 b/dlnd/lnd_comp_nuopc.F90 index 045aaeb5c..e5d2b8bca 100644 --- a/dlnd/lnd_comp_nuopc.F90 +++ b/dlnd/lnd_comp_nuopc.F90 @@ -29,9 +29,11 @@ module cdeps_dlnd_comp use shr_log_mod , only : shr_log_setLogUnit, shr_log_error use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_init_from_config + use dshr_strdata_mod , only : shr_strdata_finalize use dshr_mod , only : dshr_model_initphase, dshr_init, dshr_check_restart_alarm use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_log_clock_advance use dshr_mod , only : dshr_restart_read, dshr_restart_write, dshr_mesh_init + use dshr_mod , only : dshr_mesh_finalize, dshr_destroy_clock_alarms use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add, dshr_fldlist_realize ! Datamode specialized modules @@ -419,6 +421,19 @@ subroutine ModelFinalize(gcomp, rc) !------------------------------------------------------------------------------- rc = ESMF_SUCCESS + + ! finalize sdat + call shr_strdata_finalize(sdat, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! destroy model mesh using dshr_mesh_finalize routine + call dshr_mesh_finalize(gcomp, logunit, 'LND', model_mesh, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! destroy alarms associated with model's clock + call dshr_destroy_clock_alarms(gcomp, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_LogWrite(subname//' called', ESMF_LOGMSG_INFO) if (my_task == main_task) then write(logunit,F91) diff --git a/docn/ocn_comp_nuopc.F90 b/docn/ocn_comp_nuopc.F90 index 013aae46f..b62b23d22 100644 --- a/docn/ocn_comp_nuopc.F90 +++ b/docn/ocn_comp_nuopc.F90 @@ -28,7 +28,9 @@ module cdeps_docn_comp use shr_log_mod , only : shr_log_setLogUnit, shr_log_error use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_init_from_config + use dshr_strdata_mod , only : shr_strdata_finalize use dshr_mod , only : dshr_model_initphase, dshr_init, dshr_mesh_init, dshr_restart_read + use dshr_mod , only : dshr_mesh_finalize, dshr_destroy_clock_alarms use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_check_restart_alarm use dshr_mod , only : dshr_restart_write use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_realize @@ -673,8 +675,23 @@ end subroutine docn_comp_run subroutine ModelFinalize(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc + + ! local variables !------------------------------------------------------------------------------- rc = ESMF_SUCCESS + + ! finalize sdat + call shr_strdata_finalize(sdat, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! destroy model mesh using dshr_mesh_finalize routine + call dshr_mesh_finalize(gcomp, logunit, 'OCN', model_mesh, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! destroy alarms associated with model's clock + call dshr_destroy_clock_alarms(gcomp, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (mainproc) then write(logunit,*) write(logunit,*) 'docn : end of main integration loop' diff --git a/drof/rof_comp_nuopc.F90 b/drof/rof_comp_nuopc.F90 index 9693778a2..6e68e4cf2 100644 --- a/drof/rof_comp_nuopc.F90 +++ b/drof/rof_comp_nuopc.F90 @@ -28,9 +28,11 @@ module cdeps_drof_comp use shr_log_mod , only : shr_log_setLogUnit, shr_log_error use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_init_from_config + use dshr_strdata_mod , only : shr_strdata_finalize use dshr_mod , only : dshr_model_initphase, dshr_init use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_check_restart_alarm use dshr_mod , only : dshr_restart_read, dshr_restart_write, dshr_mesh_init + use dshr_mod , only : dshr_mesh_finalize, dshr_destroy_clock_alarms use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_realize use nuopc_shr_methods, only : shr_get_rpointer_name @@ -478,9 +480,24 @@ subroutine ModelFinalize(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc + + ! local variables !-------------------------------- rc = ESMF_SUCCESS + + ! finalize sdat + call shr_strdata_finalize(sdat, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! destroy model mesh using dshr_mesh_finalize routine + call dshr_mesh_finalize(gcomp, logunit, 'ROF', model_mesh, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! destroy alarms associated with model's clock + call dshr_destroy_clock_alarms(gcomp, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (mainproc) then write(logunit,*) write(logunit,*) 'drof : end of main integration loop' diff --git a/dshr/dshr_mod.F90 b/dshr/dshr_mod.F90 index a88561502..476c6debf 100644 --- a/dshr/dshr_mod.F90 +++ b/dshr/dshr_mod.F90 @@ -15,12 +15,13 @@ module dshr_mod use ESMF , only : ESMF_GridComp, ESMF_GridCompGet, ESMF_GridCompSet use ESMF , only : ESMF_GeomType_Flag, ESMF_FieldStatus_Flag use ESMF , only : ESMF_Mesh, ESMF_MeshGet, ESMF_MeshSet, ESMF_MeshCreate, ESMF_MeshDestroy + use ESMF , only : ESMF_MeshIsCreated use ESMF , only : ESMF_STAGGERLOC_CENTER, ESMF_STAGGERLOC_CORNER, ESMF_GRIDCREATENOPERIDIMUFRM use ESMF , only : ESMF_FILEFORMAT_ESMFMESH, ESMF_Grid use ESMF , only : ESMF_GEOMTYPE_MESH, ESMF_GEOMTYPE_GRID, ESMF_FIELDSTATUS_COMPLETE use ESMF , only : ESMF_Clock, ESMF_ClockCreate, ESMF_ClockGet, ESMF_ClockSet use ESMF , only : ESMF_ClockPrint, ESMF_ClockAdvance, ESMF_ClockGetAlarmList - use ESMF , only : ESMF_Alarm, ESMF_AlarmCreate, ESMF_AlarmGet, ESMF_AlarmSet + use ESMF , only : ESMF_Alarm, ESMF_AlarmCreate, ESMF_AlarmGet, ESMF_AlarmSet, ESMF_AlarmDestroy use ESMF , only : ESMF_ALARMLIST_ALL use ESMF , only : ESMF_Calendar use ESMF , only : ESMF_CALKIND_NOLEAP, ESMF_CALKIND_GREGORIAN, ESMF_CALKIND_FLAG @@ -29,6 +30,7 @@ module dshr_mod use ESMF , only : ESMF_VM, ESMF_VMGet, ESMF_VMBroadcast, ESMF_VMGetCurrent use ESMF , only : ESMF_RouteHandle, ESMF_FieldRegrid use ESMF , only : ESMF_TERMORDER_SRCSEQ, ESMF_FieldRegridStore, ESMF_SparseMatrixWrite + use ESMF , only : ESMF_FieldRegridRelease use ESMF , only : ESMF_Region_Flag, ESMF_REGION_TOTAL, ESMF_MAXSTR, ESMF_RC_NOT_VALID use ESMF , only : ESMF_UtilStringUpperCase use shr_kind_mod , only : r8=>shr_kind_r8, cs=>shr_kind_cs, cl=>shr_kind_cl, cx=>shr_kind_cx, cxx=>shr_kind_cxx, i8=>shr_kind_i8 @@ -52,10 +54,12 @@ module dshr_mod public :: dshr_model_initphase public :: dshr_init public :: dshr_mesh_init + public :: dshr_mesh_finalize public :: dshr_set_runclock public :: dshr_restart_read public :: dshr_restart_write public :: dshr_log_clock_advance + public :: dshr_destroy_clock_alarms public :: dshr_state_getscalar public :: dshr_state_setscalar public :: dshr_orbital_update @@ -390,6 +394,51 @@ subroutine dshr_mesh_init(gcomp, sdat, nullstr, logunit, compname, & end subroutine dshr_mesh_init + !=============================================================================== + subroutine dshr_mesh_finalize(gcomp, logunit, compname, & + model_mesh, rc) + + ! ---------------------------------------------- + ! Initialize model mesh + ! ---------------------------------------------- + + ! input/output variables + type(ESMF_GridComp) , intent(inout) :: gcomp + integer , intent(in) :: logunit + character(len=*) , intent(in) :: compname !e.g. ATM, OCN, ... + type(ESMF_Mesh) , intent(inout) :: model_mesh + integer , intent(out) :: rc + + ! local variables + type(ESMF_VM) :: vm + logical :: mainproc + integer :: my_task + logical :: isCreated + character(len=*), parameter :: F00 ="('(dshr_mesh_finalize) ',a)" + character(len=*), parameter :: subname='(dshr_mod:dshr_mesh_finalize)' + ! ---------------------------------------------- + + rc = ESMF_SUCCESS + + ! generate local mpi comm + call ESMF_GridCompGet(gcomp, vm=vm, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMGet(vm, localPet=my_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + mainproc = (my_task == main_task) + + isCreated = ESMF_MeshIsCreated(model_mesh, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (isCreated) then + call ESMF_MeshDestroy(model_mesh, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (mainproc) then + write(logunit,F00) subname// " destroyed "//trim(compname)//" mesh" + end if + end if + + end subroutine dshr_mesh_finalize + !=============================================================================== subroutine dshr_mesh_create_scol(gcomp, compname, scol_lon, scol_lat, & model_mesh, model_mask, model_frac, rc) @@ -747,6 +796,47 @@ subroutine dshr_log_clock_advance(clock, component, logunit, rc) end subroutine dshr_log_clock_advance + !=============================================================================== + subroutine dshr_destroy_clock_alarms(gcomp, rc) + type(ESMF_GridComp) :: gcomp + integer, intent(out) :: rc + + ! local variables + type(ESMF_Clock) :: clock + integer :: alarmCount + type(ESMF_Alarm), allocatable :: alarmlist(:) + integer :: i + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + ! query the Component for its clock + call NUOPC_ModelGet(gcomp, modelClock=clock, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! get the list of alarms associated with the clock + call ESMF_ClockGetAlarmList(clock, & + alarmlistflag=ESMF_ALARMLIST_ALL, & + alarmCount=alarmCount, & + rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (alarmCount > 0) then + allocate(alarmlist(alarmCount)) + call ESMF_ClockGetAlarmList(clock, & + alarmlistflag=ESMF_ALARMLIST_ALL, & + alarmlist=alarmlist, & + rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + ! destroy each alarm in the list + do i = 1, alarmCount + call ESMF_AlarmDestroy(alarmlist(i), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end do + deallocate(alarmlist) + end if + + end subroutine dshr_destroy_clock_alarms + !=============================================================================== subroutine dshr_state_getscalar(state, scalar_id, scalar_value, flds_scalar_name, flds_scalar_num, rc) @@ -1069,6 +1159,8 @@ subroutine dshr_set_modelmask(mesh_dst, meshfile_mask, compname, mask_dst, frac_ ! The following call fills in the values of field_mask call ESMF_FieldGet(field_mask, farrayptr=dataptr1d, rc=rc) dataptr1d(:) = mask_src(:) + call ESMF_ArrayDestroy(elemMaskArray, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return ! map source mask to destination mesh - to obtain destination mask and frac call ESMF_FieldRegrid(field_mask, field_dst, routehandle=rhandle, & @@ -1117,6 +1209,8 @@ subroutine dshr_set_modelmask(mesh_dst, meshfile_mask, compname, mask_dst, frac_ call ESMF_FieldDestroy(field_dst, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return deallocate(mask_src) + call ESMF_MeshDestroy(mesh_mask, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return end subroutine dshr_set_modelmask diff --git a/dwav/wav_comp_nuopc.F90 b/dwav/wav_comp_nuopc.F90 index 39f367a2e..6aacc1d9a 100644 --- a/dwav/wav_comp_nuopc.F90 +++ b/dwav/wav_comp_nuopc.F90 @@ -28,9 +28,11 @@ module cdeps_dwav_comp use shr_log_mod , only : shr_log_setLogUnit, shr_log_error use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_init_from_config + use dshr_strdata_mod , only : shr_strdata_finalize use dshr_mod , only : dshr_model_initphase, dshr_init use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_check_restart_alarm use dshr_mod , only : dshr_restart_read, dshr_restart_write, dshr_mesh_init + use dshr_mod , only : dshr_mesh_finalize, dshr_destroy_clock_alarms use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add, dshr_fldlist_realize use nuopc_shr_methods, only : shr_get_rpointer_name @@ -463,9 +465,24 @@ subroutine ModelFinalize(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc + + ! local variables !------------------------------------------------------------------------------- rc = ESMF_SUCCESS + + ! finalize sdat + call shr_strdata_finalize(sdat, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! destroy model mesh using dshr_mesh_finalize routine + call dshr_mesh_finalize(gcomp, logunit, 'DWAV', model_mesh, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! destroy alarms associated with model's clock + call dshr_destroy_clock_alarms(gcomp, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (my_task == main_task) then write(logunit,*) write(logunit,*) ' dwav : end of main integration loop' diff --git a/streams/dshr_strdata_mod.F90 b/streams/dshr_strdata_mod.F90 index 64ccdbbfa..4b6a09d57 100644 --- a/streams/dshr_strdata_mod.F90 +++ b/streams/dshr_strdata_mod.F90 @@ -4,6 +4,11 @@ module dshr_strdata_mod ! Obtain the model domain and the stream domain for each stream use ESMF , only : ESMF_Mesh, ESMF_RouteHandle, ESMF_Field, ESMF_FieldBundle + use ESMF , only : ESMF_FieldBundleGet + use ESMF , only : ESMF_MeshIsCreated, ESMF_RouteHandleIsCreated + use ESMF , only : ESMF_FieldIsCreated, ESMF_FieldBundleIsCreated + use ESMF , only : ESMF_MeshDestroy, ESMF_RouteHandleDestroy + use ESMF , only : ESMF_FieldDestroy, ESMF_FieldBundleDestroy use ESMF , only : ESMF_Clock, ESMF_VM, ESMF_VMGet, ESMF_VMGetCurrent use ESMF , only : ESMF_DistGrid, ESMF_SUCCESS, ESMF_MeshGet, ESMF_DistGridGet use ESMF , only : ESMF_VMBroadCast, ESMF_MeshIsCreated, ESMF_MeshCreate @@ -65,6 +70,7 @@ module dshr_strdata_mod ! Public routines public :: shr_strdata_init_from_config public :: shr_strdata_init_from_inline + public :: shr_strdata_finalize public :: shr_strdata_setOrbs public :: shr_strdata_advance public :: shr_strdata_get_stream_domain ! public since needed by dshr_mod @@ -362,6 +368,148 @@ subroutine shr_strdata_init_from_inline(sdat, my_task, logunit, compname, & end subroutine shr_strdata_init_from_inline + !=============================================================================== + subroutine shr_strdata_finalize(sdat, rc) + ! input/output variables + type(shr_strdata_type) , intent(inout) :: sdat + integer , intent(out) :: rc + + ! local variables + integer :: str_i + integer :: fbd_i + integer :: fld_i + integer :: fieldCount + logical :: fbd_allocated + logical :: msh_created + logical :: rhl_created + logical :: fbd_created + logical :: fld_created + type(ESMF_Field), allocatable :: fldlist(:) + integer :: istat + character(len=*), parameter :: subname='(shr_strdata_finalize)' + !---------------------------------------------- + + rc = ESMF_SUCCESS + + ! destroy ESMF objects created in each sdat%pstrm + do str_i = 1, shr_strdata_get_stream_count(sdat) + + ! destroy sdat%pstrm(str_i)%stream_mesh + msh_created = ESMF_MeshIsCreated(sdat%pstrm(str_i)%stream_mesh, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (msh_created) then + call ESMF_MeshDestroy(sdat%pstrm(str_i)%stream_mesh, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + + ! destroy sdat%pstrm(str_i)%routehandle + rhl_created = ESMF_RouteHandleIsCreated(sdat%pstrm(str_i)%routehandle, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (rhl_created) then + call ESMF_RouteHandleDestroy(sdat%pstrm(str_i)%routehandle, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + + ! destroy sdat%pstrm(str_i)%field_stream + fld_created = ESMF_FieldIsCreated(sdat%pstrm(str_i)%field_stream, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (fld_created) then + call ESMF_FieldDestroy(sdat%pstrm(str_i)%field_stream, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + + ! destroy sdat%pstrm(str_i)%field_stream_vector + fld_created = ESMF_FieldIsCreated(sdat%pstrm(str_i)%field_stream_vector, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (fld_created) then + call ESMF_FieldDestroy(sdat%pstrm(str_i)%field_stream_vector, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + + ! destroy all sdat%pstrm(ns)%fldbun_data field bundles and their fields + if (allocated(sdat%pstrm(str_i)%fldbun_data)) then + fbd_allocated = .true. + else + fbd_allocated = .false. + end if + if (fbd_allocated) then + do fbd_i=1,size(sdat%pstrm(str_i)%fldbun_data) + fbd_created = ESMF_FieldBundleIsCreated(sdat%pstrm(str_i)%fldbun_data(fbd_i), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (.not. fbd_created) cycle + call ESMF_FieldBundleGet(sdat%pstrm(str_i)%fldbun_data(fbd_i), fieldCount=fieldCount, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (fieldCount > 0) then + allocate(fldlist(fieldCount), stat=istat) + if (istat /= 0) then + call shr_log_error(subname//': allocation error for fldlist', rc=rc) + return + end if + call ESMF_FieldBundleGet(sdat%pstrm(str_i)%fldbun_data(fbd_i), fieldList=fldlist, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + call ESMF_FieldBundleDestroy(sdat%pstrm(str_i)%fldbun_data(fbd_i), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (allocated(fldlist)) then + do fld_i = 1, fieldCount + fld_created = ESMF_FieldIsCreated(fldlist(fld_i), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (.not. fld_created) cycle + call ESMF_FieldDestroy(fldlist(fld_i), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end do + deallocate(fldlist) + end if + end do + end if + + ! destroy sdat%pstrm(str_i)%fldbun_model and its fields + fbd_created = ESMF_FieldBundleIsCreated(sdat%pstrm(str_i)%fldbun_model, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (fbd_created) then + call ESMF_FieldBundleGet(sdat%pstrm(str_i)%fldbun_model, fieldCount=fieldCount, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (fieldCount > 0) then + allocate(fldlist(fieldCount), stat=istat) + if (istat /= 0) then + call shr_log_error(subname//': allocation error for fldlist', rc=rc) + return + end if + call ESMF_FieldBundleGet(sdat%pstrm(str_i)%fldbun_model, fieldList=fldlist, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + call ESMF_FieldBundleDestroy(sdat%pstrm(str_i)%fldbun_model, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (allocated(fldlist)) then + do fld_i = 1, fieldCount + fld_created = ESMF_FieldIsCreated(fldlist(fld_i), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (.not. fld_created) cycle + call ESMF_FieldDestroy(fldlist(fld_i), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end do + deallocate(fldlist) + end if + end if + + ! destroy sdat%pstrm(str_i)%field_coszen + fld_created = ESMF_FieldIsCreated(sdat%pstrm(str_i)%field_coszen, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (fld_created) then + call ESMF_FieldDestroy(sdat%pstrm(str_i)%field_coszen, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + + end do + + ! destroy ESMF objects associated with the sdat + + ! sdat%model_mesh is an alias and should not be destroyed here + + ! sdat%model_clock is an alias and should not be destroyed here + + end subroutine shr_strdata_finalize + !=============================================================================== subroutine shr_strdata_init_model_domain( sdat, rc) @@ -2245,6 +2393,10 @@ subroutine shr_strdata_readstrm(sdat, per_stream, stream, fldbun_data, & data_v_dst(i) = -sinlon * dataptr2d_dst(1,i) + coslon * dataptr2d_dst(2,i) enddo deallocate(dataptr) + if (ESMF_FieldIsCreated(field_vector_dst)) then + call ESMF_FieldDestroy(field_vector_dst, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if endif if (pio_iovartype == PIO_REAL) then diff --git a/streams/dshr_stream_mod.F90 b/streams/dshr_stream_mod.F90 index 0a860dc4f..ecc33e0e7 100644 --- a/streams/dshr_stream_mod.F90 +++ b/streams/dshr_stream_mod.F90 @@ -612,6 +612,7 @@ subroutine shr_stream_init_from_esmfconfig(streamfilename, streamdat, logunit, use esmf , only : ESMF_SUCCESS, ESMF_ConfigCreate, ESMF_ConfigLoadFile use esmf , only : ESMF_ConfigGetLen, ESMF_ConfigGetAttribute use esmf , only : ESMF_Config, ESMF_MAXSTR + use esmf , only : ESMF_ConfigDestroy !!--------------------------------------------------------------------- !! The configuration file is a text file that can have following entries @@ -834,6 +835,9 @@ subroutine shr_stream_init_from_esmfconfig(streamfilename, streamdat, logunit, enddo ! end loop nstrm + call ESMF_ConfigDestroy(cf, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + ! initialize flag that stream has been set streamdat(:)%init = .true.