From 0b7d4809351d7a66bdffb435e15e39c25876df01 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 27 Sep 2023 07:54:39 -0600 Subject: [PATCH 01/41] Swath grid step 1: allow for destroy grid, regridder and metadata. Modifications made to GriddedIO.F90, MAPL_AbstractRegridder.F90, and MAPL_EsmfRegridder.F90. --- CHANGELOG.md | 2 + base/MAPL_AbstractRegridder.F90 | 21 +++++ base/MAPL_EsmfRegridder.F90 | 151 +++++++++++++++++++++----------- griddedio/GriddedIO.F90 | 39 +++++++-- 4 files changed, 156 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db7f3b27251a..dbf06f84488e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Swath grid step 1: allow for destroy grid, regridder and metadata. + Modifications made to GriddedIO.F90, MAPL_AbstractRegridder.F90, and MAPL_EsmfRegridder.F90. - Modified fpp macro `_UNUSED_DUMMY(x) to use ASSOCIATE instead of PRINT. With this change it can be used in PURE procedures. ### Fixed diff --git a/base/MAPL_AbstractRegridder.F90 b/base/MAPL_AbstractRegridder.F90 index 52aa6364a388..86086af152d3 100644 --- a/base/MAPL_AbstractRegridder.F90 +++ b/base/MAPL_AbstractRegridder.F90 @@ -8,6 +8,7 @@ module MAPL_AbstractRegridderMod use ESMF use MAPL_MemUtilsMod use MAPL_ExceptionHandling + use MAPL_RegridderSpecRouteHandleMap use, intrinsic :: iso_fortran_env, only: REAL32, REAL64 implicit none private @@ -92,6 +93,9 @@ module MAPL_AbstractRegridderMod procedure :: has_undef_value procedure :: get_regrid_method + procedure :: destroy + procedure :: destroy_route_handle + end type AbstractRegridder @@ -1006,4 +1010,21 @@ integer function get_regrid_method(this) result(method) method = this%spec%regrid_method end function get_regrid_method + + subroutine destroy(this, rc) + class(AbstractRegridder), intent(inout) :: this + integer, optional, intent(out) :: rc + integer :: status + + _RETURN(_SUCCESS) + end subroutine destroy + + subroutine destroy_route_handle(this, kind, rc) + class(AbstractRegridder), intent(inout) :: this + type(ESMF_TypeKind_Flag), intent(in) :: kind + integer, optional, intent(out) :: rc + + _RETURN(_SUCCESS) + end subroutine destroy_route_handle + end module MAPL_AbstractRegridderMod diff --git a/base/MAPL_EsmfRegridder.F90 b/base/MAPL_EsmfRegridder.F90 index 382ec9cc2c4f..cea42e1fbf2c 100644 --- a/base/MAPL_EsmfRegridder.F90 +++ b/base/MAPL_EsmfRegridder.F90 @@ -23,27 +23,27 @@ module MAPL_EsmfRegridderMod ! ESMF Route handles type (RegridderSpecRouteHandleMap), save, target :: route_handles_r4 type (RegridderSpecRouteHandleMap), save, target :: route_handles_r8 - + type (RegridderSpecRouteHandleMap), save, target :: transpose_route_handles_r4 type (RegridderSpecRouteHandleMap), save, target :: transpose_route_handles_r8 - + type, extends(AbstractRegridder) :: EsmfRegridder integer :: regrid_method type (ESMF_DynamicMask) :: dynamic_mask contains procedure :: initialize_subclass procedure, nopass :: supports - + procedure :: regrid_scalar_2d_real32 procedure :: regrid_scalar_2d_real64 procedure :: regrid_scalar_3d_real32 procedure :: regrid_scalar_3d_real64 - + procedure :: regrid_vector_2d_real32 procedure :: regrid_vector_2d_real64 procedure :: regrid_vector_3d_real32 procedure :: regrid_vector_3d_real64 - + procedure :: transpose_regrid_scalar_2d_real32 procedure :: transpose_regrid_scalar_3d_real32 procedure :: transpose_regrid_vector_2d_real32 @@ -53,7 +53,9 @@ module MAPL_EsmfRegridderMod procedure :: do_regrid procedure :: create_route_handle procedure :: select_route_handle - + procedure :: destroy + procedure :: destroy_route_handle + end type EsmfRegridder interface EsmfRegridder @@ -96,7 +98,7 @@ logical function supports(spec, unusable, rc) _RETURN(_SUCCESS) end function supports - + subroutine regrid_scalar_2d_real32(this, q_in, q_out, rc) class (EsmfRegridder), intent(in) :: this @@ -114,7 +116,7 @@ subroutine regrid_scalar_2d_real32(this, q_in, q_out, rc) logical :: HasDE spec = this%get_spec() - + ! TODO support other staggerings src_field = ESMF_FieldCreate(spec%grid_in, typekind=ESMF_TYPEKIND_R4, & gridToFieldMap=[1,2],& @@ -148,7 +150,7 @@ subroutine regrid_scalar_2d_real32(this, q_in, q_out, rc) _VERIFY(status) call ESMF_FieldDestroy(dst_field, noGarbage=.true., rc=status) _VERIFY(status) - + _RETURN(ESMF_SUCCESS) end subroutine regrid_scalar_2d_real32 @@ -169,7 +171,7 @@ subroutine regrid_scalar_2d_real64(this, q_in, q_out, rc) logical :: HasDE spec = this%get_spec() - + ! TODO support other staggerings src_field = ESMF_FieldCreate(spec%grid_in, typekind=ESMF_TYPEKIND_R8, & gridToFieldMap=[1,2],& @@ -203,11 +205,11 @@ subroutine regrid_scalar_2d_real64(this, q_in, q_out, rc) _VERIFY(status) call ESMF_FieldDestroy(dst_field, noGarbage=.true., rc=status) _VERIFY(status) - + _RETURN(ESMF_SUCCESS) end subroutine regrid_scalar_2d_real64 - + subroutine transpose_regrid_scalar_2d_real32(this, q_in, q_out, rc) class (EsmfRegridder), intent(in) :: this real(kind=REAL32), intent(in) :: q_in(:,:) @@ -234,7 +236,7 @@ subroutine transpose_regrid_scalar_2d_real32(this, q_in, q_out, rc) _VERIFY(status) p_src = q_in end if - + dst_field = ESMF_FieldCreate(spec%grid_in, typekind=ESMF_TYPEKIND_R4, & gridToFieldMap=[1,2],& rc=status) @@ -292,7 +294,7 @@ subroutine regrid_scalar_3d_real32(this, q_in, q_out, rc) end if call ESMF_VMAllReduce(vm,sendData=km,recvData=kin,reduceflag=ESMF_REDUCE_MAX,rc=status) _VERIFY(status) - + if (hasDE) then _ASSERT(kin == size(q_in,3),'inconsistent array shape') end if @@ -306,7 +308,7 @@ subroutine regrid_scalar_3d_real32(this, q_in, q_out, rc) p_src = reshape(q_in,shape(p_src), order=[2,3,1]) end if - + HasDE = MAPL_GridHasDE(spec%grid_out,rc=status) _VERIFY(status) if (hasDE) then @@ -375,7 +377,7 @@ subroutine regrid_scalar_3d_real64(this, q_in, q_out, rc) end if call ESMF_VMAllReduce(vm,sendData=km,recvData=kin,reduceflag=ESMF_REDUCE_MAX,rc=status) _VERIFY(status) - + if (hasDE) then _ASSERT(kin == size(q_in,3),'inconsistent array shape') end if @@ -389,7 +391,7 @@ subroutine regrid_scalar_3d_real64(this, q_in, q_out, rc) p_src = reshape(q_in,shape(p_src), order=[2,3,1]) end if - + HasDE = MAPL_GridHasDE(spec%grid_out,rc=status) _VERIFY(status) if (hasDE) then @@ -425,7 +427,7 @@ subroutine regrid_scalar_3d_real64(this, q_in, q_out, rc) _RETURN(ESMF_SUCCESS) end subroutine regrid_scalar_3d_real64 - + subroutine transpose_regrid_scalar_3d_real32(this, q_in, q_out, rc) class (EsmfRegridder), intent(in) :: this real, intent(in) :: q_in(:,:,:) @@ -471,9 +473,9 @@ subroutine transpose_regrid_scalar_3d_real32(this, q_in, q_out, rc) _VERIFY(status) p_src = reshape(q_in,shape(p_src), order=[2,3,1]) end if - + HasDE = MAPL_GridHasDE(spec%grid_in,rc=status) - _VERIFY(status) + _VERIFY(status) if (hasDE) then km = size(q_out,3) else @@ -495,7 +497,7 @@ subroutine transpose_regrid_scalar_3d_real32(this, q_in, q_out, rc) call this%do_regrid(src_field, dst_field, doTranspose=.true., rc=status) _VERIFY(status) - + if (HasDE) q_out = reshape(p_dst, shape(q_out), order=[3,1,2]) call ESMF_FieldDestroy(src_field, noGarbage=.true., rc=status) @@ -554,7 +556,7 @@ subroutine regrid_vector_2d_real32(this, u_in, v_in, u_out, v_out, rotate, rc) factory => grid_manager%get_factory(spec%grid_in,rc=status) _VERIFY(status) - + ! TODO support other staggerings src_field = ESMF_FieldCreate(spec%grid_in, typekind=ESMF_TYPEKIND_R4, & & gridToFieldMap=[3,4], UngriddedLBound=[1,1], ungriddedUBound=[3,1], & @@ -568,7 +570,7 @@ subroutine regrid_vector_2d_real32(this, u_in, v_in, u_out, v_out, rotate, rc) call factory%spherical_to_cartesian(u_in, v_in, p_src, grid_axis_in, rc=status) _VERIFY(status) end if - + dst_field = ESMF_FieldCreate(spec%grid_out, typekind=ESMF_TYPEKIND_R4, & & gridToFieldMap=[3,4], UngriddedLBound=[1,1], ungriddedUBound=[3,1], & @@ -695,7 +697,7 @@ subroutine regrid_vector_2d_real64(this, u_in, v_in, u_out, v_out, rotate, rc) end subroutine regrid_vector_2d_real64 - + subroutine transpose_regrid_vector_2d_real32(this, u_in, v_in, u_out, v_out, rotate, rc) class (EsmfRegridder), intent(in) :: this real, intent(in) :: u_in(:,:) @@ -753,10 +755,10 @@ subroutine transpose_regrid_vector_2d_real32(this, u_in, v_in, u_out, v_out, rot call factory%spherical_to_cartesian(u_in, v_in, p_src, grid_axis_in, rc=status) _VERIFY(status) end if - + hasDE = MAPL_GridHasDE(spec%grid_in,rc=status) - _VERIFY(status) + _VERIFY(status) dst_field = ESMF_FieldCreate(spec%grid_in, typekind = ESMF_TYPEKIND_R4, & & gridToFieldMap=[3,4],ungriddedLBound=[1,1],ungriddedUBound=[3,1],rc=status) _VERIFY(status) @@ -837,7 +839,7 @@ subroutine regrid_vector_3d_real32(this, u_in, v_in, u_out, v_out, rotate, rc) if (present(rotate)) then if (rotate) then grid_axis_in = 'xyz' - grid_axis_out = 'grid' + grid_axis_out = 'grid' end if end if @@ -861,9 +863,9 @@ subroutine regrid_vector_3d_real32(this, u_in, v_in, u_out, v_out, rotate, rc) call factory%spherical_to_cartesian(u_in, v_in, p_src, grid_axis_in, rc=status) _VERIFY(status) end if - + hasDE = MAPL_GridHasDE(spec%grid_out,rc=status) - _VERIFY(status) + _VERIFY(status) hasDE = MAPL_GridHasDE(spec%grid_out,rc=status) _VERIFY(status) if (hasDE) then @@ -972,7 +974,7 @@ subroutine regrid_vector_3d_real64(this, u_in, v_in, u_out, v_out, rc) end if hasDE = MAPL_GridHasDE(spec%grid_out,rc=status) - _VERIFY(status) + _VERIFY(status) hasDE = MAPL_GridHasDE(spec%grid_out,rc=status) _VERIFY(status) if (hasDE) then @@ -1009,8 +1011,8 @@ subroutine regrid_vector_3d_real64(this, u_in, v_in, u_out, v_out, rc) _RETURN(ESMF_SUCCESS) end subroutine regrid_vector_3d_real64 - - + + subroutine transpose_regrid_vector_3d_real32(this, u_in, v_in, u_out, v_out, rotate, rc) class (EsmfRegridder), intent(in) :: this real, intent(in) :: u_in(:,:,:) @@ -1065,7 +1067,7 @@ subroutine transpose_regrid_vector_3d_real32(this, u_in, v_in, u_out, v_out, rot if (present(rotate)) then if (rotate) then grid_axis_in = 'grid' - grid_axis_out = 'xyz' + grid_axis_out = 'xyz' end if end if @@ -1089,9 +1091,9 @@ subroutine transpose_regrid_vector_3d_real32(this, u_in, v_in, u_out, v_out, rot call factory%spherical_to_cartesian(u_in, v_in, p_src, grid_axis_in, rc=status) _VERIFY(status) end if - + hasDE = MAPL_GridHasDE(spec%grid_in,rc=status) - _VERIFY(status) + _VERIFY(status) if (hasDE) then km = size(u_out,3) else @@ -1125,7 +1127,7 @@ subroutine transpose_regrid_vector_3d_real32(this, u_in, v_in, u_out, v_out, rot deallocate(p_src) deallocate(p_dst) - + _RETURN(ESMF_SUCCESS) end subroutine transpose_regrid_vector_3d_real32 @@ -1154,7 +1156,7 @@ subroutine simpleDynMaskProcV(dynamicMaskList, dynamicSrcMaskValue, & do k = 1, size(dynamicMaskList(i)%srcElement(j)%ptr) if (.not. & match(dynamicSrcMaskValue,dynamicMaskList(i)%srcElement(j)%ptr(k))) then - dynamicMaskList(i)%dstElement(k) = dynamicMaskList(i)%dstElement(k) & + dynamicMaskList(i)%dstElement(k) = dynamicMaskList(i)%dstElement(k) & + dynamicMaskList(i)%factor(j) & * dynamicMaskList(i)%srcElement(j)%ptr(k) renorm(k) = renorm(k) + dynamicMaskList(i)%factor(j) @@ -1226,7 +1228,7 @@ end subroutine monotonicDynMaskProcV logical function match(missing,b) real(kind=REAL32), intent(in) :: missing, b - match = (missing==b) + match = (missing==b) end function match @@ -1333,10 +1335,10 @@ subroutine do_regrid(this, src_field, dst_field, unusable, doTranspose, rc) _ASSERT(src_kind == dst_kind,'inconsistent kinds') route_handle = this%select_route_handle(src_kind, do_transpose = doTranspose, rc = status) - _VERIFY(status) + _VERIFY(status) spec = this%get_spec() - + if (spec%regrid_method /= REGRID_METHOD_NEAREST_STOD) then call ESMF_FieldRegrid(src_field, dst_field, & & routeHandle=route_handle, & @@ -1364,17 +1366,17 @@ subroutine initialize_subclass(this, unusable, rc) integer, optional, intent(out) :: rc - integer :: status + integer :: status character(len=*), parameter :: Iam = 'initialize_subclass' type (RegridderSpec) :: spec - + _UNUSED_DUMMY(unusable) spec = this%get_spec() this%regrid_method = spec%regrid_method - call this%create_route_handle(ESMF_TYPEKIND_R4, rc = status) + call this%create_route_handle(ESMF_TYPEKIND_R4, rc = status) _VERIFY(status) ! TODO: should get missing value from source file @@ -1411,14 +1413,14 @@ subroutine initialize_subclass(this, unusable, rc) _RETURN(_SUCCESS) end subroutine initialize_subclass - + subroutine create_route_handle(this, kind, rc) class (EsmfRegridder), intent(in) :: this type(ESMF_TypeKind_Flag), intent(in) :: kind integer, optional, intent(out) :: rc - integer :: status + integer :: status character(len=*), parameter :: Iam = 'create_route_handle' type (RegridderSpec) :: spec @@ -1434,7 +1436,7 @@ subroutine create_route_handle(this, kind, rc) logical :: global, isPresent type(RegridderSpecRouteHandleMap), pointer :: route_handles, transpose_route_handles type(ESMF_RouteHandle) :: route_handle, transpose_route_handle - + if (kind == ESMF_TYPEKIND_R4) then route_handles => route_handles_r4 transpose_route_handles => transpose_route_handles_r4 @@ -1468,7 +1470,7 @@ subroutine create_route_handle(this, kind, rc) dst_field = ESMF_FieldCreate(spec%grid_out, typekind=kind, & & indexflag=ESMF_INDEX_DELOCAL, staggerloc=ESMF_STAGGERLOC_CENTER, rc=status) - _VERIFY(status) + _VERIFY(status) if (MAPL_GridHasDE(spec%grid_out)) then if (kind == ESMF_TYPEKIND_R4) then call ESMF_FieldGet(dst_field, localDe=0, farrayPtr=dst_dummy_r4, rc=status) @@ -1552,7 +1554,7 @@ subroutine create_route_handle(this, kind, rc) _RETURN(_SUCCESS) end subroutine create_route_handle - + function select_route_handle(this, kind, do_transpose, rc) result(route_handle) type(ESMF_RouteHandle) :: route_handle class (EsmfRegridder), intent(in) :: this @@ -1580,7 +1582,7 @@ function select_route_handle(this, kind, do_transpose, rc) result(route_handle) ! Create route-handle if none exist if (route_handles%count(spec) == 0) then - call this%create_route_handle(kind, rc = status) + call this%create_route_handle(kind, rc = status) _VERIFY(status) end if @@ -1589,7 +1591,7 @@ function select_route_handle(this, kind, do_transpose, rc) result(route_handle) if (present(do_transpose)) then transpose = do_transpose end if - + if (.not. transpose) then route_handle = route_handles%at(spec) else @@ -1600,4 +1602,53 @@ function select_route_handle(this, kind, do_transpose, rc) result(route_handle) end function select_route_handle + subroutine destroy(this, rc) + class(EsmfRegridder), intent(inout) :: this + integer, optional, intent(out) :: rc + integer :: status + + call this%destroy_route_handle(ESMF_TYPEKIND_R4, _RC) + + _RETURN(_SUCCESS) + end subroutine destroy + + subroutine destroy_route_handle(this, kind, rc) + class(EsmfRegridder), intent(inout) :: this + type(ESMF_TypeKind_Flag), intent(in) :: kind + integer, optional, intent(out) :: rc + + type (RegridderSpec) :: spec + type(ESMF_RouteHandle) :: dummy_rh + type(RegridderSpecRouteHandleMap), pointer :: route_handles, transpose_route_handles + type(ESMF_RouteHandle) :: route_handle + type(RegridderSpecRouteHandleMapIterator) :: iter + integer :: status + + if (kind == ESMF_TYPEKIND_R4) then + route_handles => route_handles_r4 + transpose_route_handles => transpose_route_handles_r4 + else if(kind == ESMF_TYPEKIND_R8) then + route_handles => route_handles_r8 + transpose_route_handles => transpose_route_handles_r8 + else + _FAIL('unsupported type kind (must be R4 or R8)') + end if + + spec = this%get_spec() + + _ASSERT(route_handles%count(spec) == 1, 'Did not find this spec in route handle table.') + route_handle = route_handles%at(spec) + call ESMF_RouteHandleDestroy(route_handle, noGarbage=.true.,_RC) + iter = route_handles%find(spec) + call route_handles%erase(iter) + + _ASSERT(transpose_route_handles%count(spec) == 1, 'Did not find this spec in route handle table.') + route_handle = transpose_route_handles%at(spec) + call ESMF_RouteHandleDestroy(route_handle, noGarbage=.true., _RC) + iter = transpose_route_handles%find(spec) + call transpose_route_handles%erase(iter) + + _RETURN(_SUCCESS) + end subroutine destroy_route_handle + end module MAPL_EsmfRegridderMod diff --git a/griddedio/GriddedIO.F90 b/griddedio/GriddedIO.F90 index 7b62d2e0dacf..602ea72f74fc 100644 --- a/griddedio/GriddedIO.F90 +++ b/griddedio/GriddedIO.F90 @@ -31,7 +31,7 @@ module MAPL_GriddedIOMod private type, public :: MAPL_GriddedIO - type(FileMetaData) :: metadata + type(FileMetaData), allocatable :: metadata type(fileMetadataUtils), pointer :: current_file_metadata integer :: write_collection_id integer :: read_collection_id @@ -73,6 +73,7 @@ module MAPL_GriddedIOMod procedure :: request_data_from_file procedure :: process_data_from_file procedure :: swap_undef_value + procedure :: destroy end type MAPL_GriddedIO interface MAPL_GriddedIO @@ -114,7 +115,7 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr type(TimeData), intent(inout) :: timeInfo type(VerticalData), intent(inout), optional :: vdata type (ESMF_Grid), intent(inout), pointer, optional :: ogrid - type(StringStringMap), intent(in), optional :: global_attributes + type(StringStringMap), target, intent(in), optional :: global_attributes integer, intent(out), optional :: rc type(ESMF_Grid) :: input_grid @@ -128,6 +129,11 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr character(len=:), pointer :: attr_name, attr_val integer :: status + if ( allocated (this%metadata) ) deallocate(this%metadata) + allocate(this%metadata) + + call MAPL_FieldBundleDestroy(this%output_bundle, _RC) + this%items = items this%input_bundle = bundle this%output_bundle = ESMF_FieldBundleCreate(rc=status) @@ -141,9 +147,11 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr call ESMF_FieldBundleGet(this%input_bundle,grid=this%output_grid,rc=status) _VERIFY(status) end if + this%regrid_handle => new_regridder_manager%make_regridder(input_grid,this%output_grid,this%regrid_method,rc=status) _VERIFY(status) + ! We get the regrid_method here because in the case of Identity, we set it to ! REGRID_METHOD_IDENTITY in the regridder constructor if identity. Now we need ! to change the regrid_method in the GriddedIO object to be the same as the @@ -156,6 +164,7 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr _VERIFY(status) call factory%append_metadata(this%metadata) + if (present(vdata)) then this%vdata=vdata else @@ -179,6 +188,7 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr call this%check_chunking(this%vdata%lm,_RC) end if + order = this%metadata%get_order(rc=status) _VERIFY(status) metadataVarsSize = order%size() @@ -213,7 +223,16 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr end if _RETURN(_SUCCESS) - end subroutine CreateFileMetaData + end subroutine CreateFileMetaData + + + subroutine destroy(this, rc) + class (MAPL_GriddedIO), intent(inout) :: this + integer, intent(out), optional :: rc + if(allocated(this%chunking)) deallocate(this%chunking) + _RETURN(_SUCCESS) + end subroutine destroy + subroutine set_param(this,deflation,quantize_algorithm,quantize_level,chunking,nbits_to_keep,regrid_method,itemOrder,write_collection_id,rc) class (MAPL_GriddedIO), intent(inout) :: this @@ -483,6 +502,7 @@ subroutine bundlepost(this,filename,oClients,rc) end if else tindex = -1 + call this%stage2DLatLon(filename,oClients=oClients,_RC) end if if (this%vdata%regrid_type==VERTICAL_METHOD_ETA2LEV) then @@ -841,8 +861,9 @@ subroutine stage2DLatLon(this, fileName, oClients, rc) _VERIFY(STATUS) this%lons=ptr2d*MAPL_RADIANS_TO_DEGREES ref = ArrayReference(this%lons) - call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lons', & - ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) + call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lons', & + ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) + call ESMF_GridGetCoord(this%output_grid, localDE=0, coordDim=2, & staggerloc=ESMF_STAGGERLOC_CENTER, & farrayPtr=ptr2d, rc=status) @@ -883,6 +904,7 @@ subroutine stage2DLatLon(this, fileName, oClients, rc) call oClients%collective_stage_data(this%write_collection_id,trim(filename),'corner_lats', & ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) end if + _RETURN(_SUCCESS) end subroutine stage2DLatLon @@ -936,11 +958,12 @@ subroutine stageData(this, field, fileName, tIndex, oClients, rc) allocate(ptr2d(0,0)) end if ref = factory%generate_file_reference2D(Ptr2D) - allocate(localStart,source=[gridLocalStart,1]) if (tindex > -1) then + allocate(localStart,source=[gridLocalStart,1]) allocate(globalStart,source=[gridGlobalStart,tindex]) allocate(globalCount,source=[gridGlobalCount,1]) else + allocate(localStart,source=[gridLocalStart]) allocate(globalStart,source=gridGlobalStart) allocate(globalCount,source=gridGlobalCount) end if @@ -957,17 +980,19 @@ subroutine stageData(this, field, fileName, tIndex, oClients, rc) allocate(ptr3d(0,0,0)) end if ref = factory%generate_file_reference3D(Ptr3D) - allocate(localStart,source=[gridLocalStart,1,1]) if (tindex > -1) then + allocate(localStart,source=[gridLocalStart,1,1]) allocate(globalStart,source=[gridGlobalStart,1,tindex]) allocate(globalCount,source=[gridGlobalCount,lm,1]) else + allocate(localStart,source=[gridLocalStart,1]) allocate(globalStart,source=[gridGlobalStart,1]) allocate(globalCount,source=[gridGlobalCount,lm]) end if else _FAIL( "Rank not supported") end if + call oClients%collective_stage_data(this%write_collection_id,trim(filename),trim(fieldName), & ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) _RETURN(_SUCCESS) From 50a8caab2ce21b890cb73dd58d3aa8b08b296094 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 27 Sep 2023 08:23:49 -0600 Subject: [PATCH 02/41] small update to CHANGELOG.md --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a15e5e12cfb..27c03e80cbbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Swath grid step 1: allow for destroy grid, regridder and metadata. - Modifications made to GriddedIO.F90, MAPL_AbstractRegridder.F90, and MAPL_EsmfRegridder.F90. - Modified fpp macro `_UNUSED_DUMMY(x) to use ASSOCIATE instead of PRINT. With this change it can be used in PURE procedures. - Make error handling in Plain_netCDF_Time consistent with MAPL standard error handling +- Swath grid step 1: allow for destroy grid, regridder and metadata. + Modifications made to GriddedIO.F90, MAPL_AbstractRegridder.F90, and MAPL_EsmfRegridder.F90. ### Fixed From faf24237062ac44b65ef9e9a6cd4708894d3da99 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 27 Sep 2023 10:56:13 -0600 Subject: [PATCH 03/41] swath grid factory with Epoch update --- base/CMakeLists.txt | 2 +- base/MAPL_AbstractGridFactory.F90 | 54 + base/MAPL_GridManager.F90 | 45 +- base/MAPL_SwathGridFactory.F90 | 1333 +++++++++++++++++ base/Plain_netCDF_Time.F90 | 1 - gridcomps/History/CMakeLists.txt | 1 + gridcomps/History/MAPL_EpochSwathMod.F90 | 1377 ++++++++++++++++++ gridcomps/History/MAPL_HistoryCollection.F90 | 2 + gridcomps/History/MAPL_HistoryGridComp.F90 | 151 +- 9 files changed, 2925 insertions(+), 41 deletions(-) create mode 100644 base/MAPL_SwathGridFactory.F90 create mode 100644 gridcomps/History/MAPL_EpochSwathMod.F90 diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 95edd9be0d81..5b6d6dd2683f 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -32,7 +32,7 @@ set (srcs MAPL_IO.F90 MAPL_LatLonGridFactory.F90 MAPL_TransposeRegridder.F90 MAPL_Comms.F90 MAPL_LatLonToLatLonRegridder.F90 MAPL_TripolarGridFactory.F90 - MAPL_LlcGridFactory.F90 + MAPL_LlcGridFactory.F90 MAPL_SwathGridFactory.F90 MAPL_Config.F90 MAPL_LocStreamMod.F90 MAPL_ConservativeRegridder.F90 MAPL_MaxMinMod.F90 MAPL_VerticalInterpMod.F90 MAPL_CubedSphereGridFactory.F90 MAPL_MemUtils.F90 MAPL_VerticalMethods.F90 diff --git a/base/MAPL_AbstractGridFactory.F90 b/base/MAPL_AbstractGridFactory.F90 index 2a422d617991..b9b912a3a0ad 100644 --- a/base/MAPL_AbstractGridFactory.F90 +++ b/base/MAPL_AbstractGridFactory.F90 @@ -82,6 +82,11 @@ module MAPL_AbstractGridFactoryMod procedure(get_file_format_vars), deferred :: get_file_format_vars procedure(decomps_are_equal), deferred :: decomps_are_equal procedure(physical_params_are_equal), deferred :: physical_params_are_equal + + procedure :: get_xy_subset + procedure :: get_xy_mask + procedure :: destroy + procedure :: get_obs_time end type AbstractGridFactory abstract interface @@ -238,6 +243,7 @@ function generate_file_reference3D(this,fpointer,metadata) result(ref) type(FileMetadata), intent(in), optional :: metaData end function generate_file_reference3D + end interface character(len=*), parameter :: MOD_NAME = 'MAPL_AbstractGridFactory::' @@ -1030,5 +1036,53 @@ function get_grid(this, unusable, rc) result(grid) end if end function get_grid + + + ! This procedure should only be called for time dependent grids. + ! A default implementation is to fail for other grid types, so we do not + ! have to explicitly add methods to all of the existing subclasses. + subroutine get_xy_subset(this, interval, xy_subset, rc) + class(AbstractGridFactory), intent(in) :: this + type(ESMF_Time), intent(in) :: interval(2) + integer, intent(out) :: xy_subset(2,2) + integer, optional, intent(out) :: rc + + integer :: status + + _RETURN(_FAILURE) + end subroutine get_xy_subset + + subroutine get_xy_mask(this, interval, xy_mask, rc) + class(AbstractGridFactory), intent(inout) :: this + type(ESMF_Time), intent(in) :: interval(2) + integer, allocatable, intent(out) :: xy_mask(:,:) + integer, optional, intent(out) :: rc + + integer :: status + _RETURN(_FAILURE) + end subroutine get_xy_mask + + ! Probably don't need to do anything more for subclasses unless they have + ! other objects that don't finalize well. (NetCDF, ESMF, MPI, ...) + subroutine destroy(this, rc) + class(AbstractGridFactory), intent(inout) :: this + integer, optional, intent(out) :: rc + + integer :: status + + call ESMF_GridDestroy(this%grid, noGarbage=.true., _RC) + + _RETURN(_SUCCESS) + end subroutine destroy + + subroutine get_obs_time(this, grid, obs_time, rc) + class(AbstractGridFactory), intent(inout) :: this + type (ESMF_Grid), intent(in) :: grid + real(ESMF_KIND_R4), intent(out) :: obs_time(:,:) + integer, optional, intent(out) :: rc + + _RETURN(_SUCCESS) + end subroutine get_obs_time + end module MAPL_AbstractGridFactoryMod diff --git a/base/MAPL_GridManager.F90 b/base/MAPL_GridManager.F90 index eb2bd07b782b..72ea1abe2758 100644 --- a/base/MAPL_GridManager.F90 +++ b/base/MAPL_GridManager.F90 @@ -21,7 +21,7 @@ module MAPL_GridManager_private private public :: GridManager - public :: factory_id_attribute + public :: FACTORY_ID_ATTRIBUTE ! singleton type :: GridManager @@ -32,6 +32,9 @@ module MAPL_GridManager_private type (Integer64GridFactoryMap) :: factories contains procedure :: add_prototype + procedure :: destroy_grid + generic :: destroy => destroy_grid + procedure :: delete !!$ procedure :: make_field !!$ procedure :: delete_field @@ -63,7 +66,7 @@ module MAPL_GridManager_private end type GridManager character(len=*), parameter :: MOD_NAME = 'MAPL_GridManager_private::' - character(len=*), parameter :: factory_id_attribute = 'MAPL_grid_factory_id' + character(len=*), parameter :: FACTORY_ID_ATTRIBUTE = 'MAPL_grid_factory_id' contains @@ -120,6 +123,7 @@ subroutine initialize_prototypes(this, unusable, rc) use MAPL_LlcGridFactoryMod, only: LlcGridFactory use MAPL_ExternalGridFactoryMod, only: ExternalGridFactory use MAPL_XYGridFactoryMod, only: XYGridFactory + use MAPL_SwathGridFactoryMod, only : SwathGridFactory class (GridManager), intent(inout) :: this class (KeywordEnforcer), optional, intent(in) :: unusable @@ -131,7 +135,8 @@ subroutine initialize_prototypes(this, unusable, rc) type (LlcGridFactory) :: llc_factory type (ExternalGridFactory) :: external_factory type (XYGridFactory) :: xy_factory - + type (SwathGridFactory) :: swath_factory + ! This is a local variable to prevent the subroutine from running ! initialiazation twice. Calling functions have their own local variables ! to prevent calling this subroutine twice, but the initialization status @@ -147,6 +152,7 @@ subroutine initialize_prototypes(this, unusable, rc) call this%prototypes%insert('llc', llc_factory) call this%prototypes%insert('External', external_factory) call this%prototypes%insert('XY', xy_factory) + call this%prototypes%insert('Swath', swath_factory) initialized = .true. end if @@ -258,7 +264,7 @@ function make_grid_from_factory(this, factory, unusable, rc) result(grid) ! TODO: this should only be done if the grid is new, rather than cached, in which case ! the attribute is already set. - call ESMF_AttributeSet(grid, factory_id_attribute, factory_id, rc=status) + call ESMF_AttributeSet(grid, FACTORY_ID_ATTRIBUTE, factory_id, rc=status) _VERIFY(status) _RETURN(_SUCCESS) @@ -397,6 +403,27 @@ function make_factory_from_distGrid(this, grid_type, dist_grid, lon_array, lat_a end function make_factory_from_distGrid + subroutine destroy_grid(this, grid, unusable, rc) + use ESMF + class (GridManager), target, intent(inout) :: this + type (ESMF_Grid), intent(inout) :: grid + class (KeywordEnforcer), optional, intent(in) :: unusable + integer, optional, intent(out) :: rc + + integer :: status + integer (kind=ESMF_KIND_I8) :: id + class(AbstractGridFactory), pointer :: factory + type(Integer64GridFactoryMapIterator) :: iter + + call ESMF_AttributeGet(grid, FACTORY_ID_ATTRIBUTE, id, _RC) + factory => this%factories%at(id) + call factory%destroy(_RC) + iter = this%factories%find(id) + call this%factories%erase(iter) + + _RETURN(_SUCCESS) + _UNUSED_DUMMY(unusable) + end subroutine destroy_grid ! Clients should use this procedure to release ESMF resources when a grid ! is no longer being used. @@ -413,15 +440,13 @@ subroutine delete(this, grid, unusable, rc) integer :: status character(len=*), parameter :: Iam= MOD_NAME // 'destroy_grid' - _UNUSED_DUMMY(unusable) - if (.not. this%keep_grids) then - call ESMF_GridDestroy(grid, rc=status) + call ESMF_GridDestroy(grid, noGarbage=.true., rc=status) _ASSERT(status==0,'failed to destroy grid') end if _RETURN(_SUCCESS) - + _UNUSED_DUMMY(unusable) end subroutine delete @@ -438,7 +463,7 @@ function get_factory(this, grid, unusable, rc) result(factory) _UNUSED_DUMMY(unusable) - call ESMF_AttributeGet(grid, factory_id_attribute, id, rc=status) + call ESMF_AttributeGet(grid, FACTORY_ID_ATTRIBUTE, id, rc=status) _VERIFY(status) factory => this%factories%at(id) @@ -608,7 +633,7 @@ function get_factory_id(grid, unusable, rc) result(id) _UNUSED_DUMMY(unusable) - call ESMF_AttributeGet(grid, factory_id_attribute, id, rc=status) + call ESMF_AttributeGet(grid, FACTORY_ID_ATTRIBUTE, id, rc=status) _VERIFY(status) _RETURN(_SUCCESS) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 new file mode 100644 index 000000000000..5c3cd5e19db5 --- /dev/null +++ b/base/MAPL_SwathGridFactory.F90 @@ -0,0 +1,1333 @@ +#include "MAPL_Exceptions.h" +#include "MAPL_ErrLog.h" +#include "unused_dummy.H" + +module MAPL_SwathGridFactoryMod + use MAPL_AbstractGridFactoryMod + use MAPL_MinMaxMod + use MAPL_KeywordEnforcerMod + use MAPL_ExceptionHandling + use MAPL_ShmemMod + use mapl_ErrorHandlingMod + use MAPL_Constants + use Plain_netCDF_Time + use MAPL_Base, only : MAPL_GridGetInterior + use ESMF + use pFIO + use MAPL_CommsMod + use netcdf + use, intrinsic :: iso_fortran_env, only: REAL32 + use, intrinsic :: iso_fortran_env, only: REAL64 + implicit none + integer, parameter :: gridLabel_max = 20 + private + + public :: SwathGridFactory + + type, extends(AbstractGridFactory) :: SwathGridFactory + private + character(len=:), allocatable :: grid_name + character(len=:), allocatable :: grid_file_name + + integer :: cell_across_swath + integer :: cell_along_swath + integer :: im_world = MAPL_UNDEFINED_INTEGER + integer :: jm_world = MAPL_UNDEFINED_INTEGER + integer :: lm = MAPL_UNDEFINED_INTEGER + logical :: force_decomposition = .false. + + integer :: epoch ! unit: second + integer(ESMF_KIND_I8) :: epoch_index(4) ! is,ie,js,je + character(len=ESMF_MAXSTR) :: tunit + real(ESMF_KIND_R8), allocatable :: t_alongtrack(:) + character(len=ESMF_MAXSTR) :: nc_index + character(len=ESMF_MAXSTR) :: nc_time + character(len=ESMF_MAXSTR) :: nc_latitude + character(len=ESMF_MAXSTR) :: nc_longitude + character(len=ESMF_MAXSTR) :: var_name_time + character(len=ESMF_MAXSTR) :: var_name_lat + character(len=ESMF_MAXSTR) :: var_name_lon + logical :: found_group + + ! Domain decomposition: + integer :: nx = MAPL_UNDEFINED_INTEGER + integer :: ny = MAPL_UNDEFINED_INTEGER + integer, allocatable :: ims(:) + integer, allocatable :: jms(:) + ! Used for halo + type (ESMF_DELayout) :: layout + logical :: initialized_from_metadata = .false. + contains + procedure :: make_new_grid + procedure :: create_basic_grid + procedure :: add_horz_coordinates_from_file + procedure :: init_halo + procedure :: halo + + procedure :: initialize_from_file_metadata + procedure :: initialize_from_config_with_prefix + procedure :: initialize_from_esmf_distGrid + + procedure :: equals + procedure :: check_and_fill_consistency + procedure :: generate_grid_name + procedure :: to_string + + procedure :: append_metadata + procedure :: get_grid_vars + procedure :: get_file_format_vars + procedure :: append_variable_metadata + procedure :: check_decomposition + procedure :: generate_newnxy + procedure :: generate_file_bounds + procedure :: generate_file_corner_bounds + procedure :: generate_file_reference2D + procedure :: generate_file_reference3D + procedure :: decomps_are_equal + procedure :: physical_params_are_equal + + procedure :: get_xy_subset + procedure :: destroy + procedure :: get_obs_time + end type SwathGridFactory + + character(len=*), parameter :: MOD_NAME = 'MAPL_SwathGridFactory::' + + interface SwathGridFactory + module procedure SwathGridFactory_from_parameters + end interface SwathGridFactory + + interface set_with_default + module procedure set_with_default_integer + module procedure set_with_default_real + module procedure set_with_default_real64 + module procedure set_with_default_character + module procedure set_with_default_bounds + end interface set_with_default + +contains + + function SwathGridFactory_from_parameters(unusable, grid_name, & + & im_world, jm_world, lm, nx, ny, ims, jms, rc) result(factory) + type (SwathGridFactory) :: factory + class (KeywordEnforcer), optional, intent(in) :: unusable + character(len=*), optional, intent(in) :: grid_name + + ! grid details: + integer, optional, intent(in) :: im_world + integer, optional, intent(in) :: jm_world + integer, optional, intent(in) :: lm + + ! decomposition: + integer, optional, intent(in) :: nx + integer, optional, intent(in) :: ny + integer, optional, intent(in) :: ims(:) + integer, optional, intent(in) :: jms(:) + + integer, optional, intent(out) :: rc + + integer :: status + + _UNUSED_DUMMY(unusable) + + call set_with_default(factory%grid_name, grid_name, MAPL_GRID_NAME_DEFAULT) + call set_with_default(factory%nx, nx, MAPL_UNDEFINED_INTEGER) + call set_with_default(factory%ny, ny, MAPL_UNDEFINED_INTEGER) + call set_with_default(factory%im_world, im_world, MAPL_UNDEFINED_INTEGER) + call set_with_default(factory%jm_world, jm_world, MAPL_UNDEFINED_INTEGER) + call set_with_default(factory%lm, lm, MAPL_UNDEFINED_INTEGER) + + ! default is unallocated + if (present(ims)) factory%ims = ims + if (present(jms)) factory%jms = jms + + call factory%check_and_fill_consistency(_RC) + + _RETURN(_SUCCESS) + end function SwathGridFactory_from_parameters + + + function make_new_grid(this, unusable, rc) result(grid) + type (ESMF_Grid) :: grid + class (SwathGridFactory), intent(in) :: this + class (KeywordEnforcer), optional, intent(in) :: unusable + integer, optional, intent(out) :: rc + integer :: status + + _UNUSED_DUMMY(unusable) + grid = this%create_basic_grid(_RC) + call this%add_horz_coordinates_from_file(grid,_RC) + _RETURN(_SUCCESS) + end function make_new_grid + + + function create_basic_grid(this, unusable, rc) result(grid) + type (ESMF_Grid) :: grid + class (SwathGridFactory), intent(in) :: this + class (KeywordEnforcer), optional, intent(in) :: unusable + integer, optional, intent(out) :: rc + integer :: status + + _UNUSED_DUMMY(unusable) + + grid = ESMF_GridCreateNoPeriDim( & + & name = this%grid_name, & + & countsPerDEDim1=this%ims, & + & countsPerDEDim2=this%jms, & + & indexFlag=ESMF_INDEX_DELOCAL, & + & coordDep1=[1,2], & + & coordDep2=[1,2], & + & coordSys=ESMF_COORDSYS_SPH_RAD, & + & _RC) + + ! Allocate coords at default stagger location + call ESMF_GridAddCoord(grid, _RC) + + if (this%lm /= MAPL_UNDEFINED_INTEGER) then + call ESMF_AttributeSet(grid, name='GRID_LM', value=this%lm, _RC) + end if + call ESMF_AttributeSet(grid, 'GridType', 'LatLon', _RC) + call ESMF_AttributeSet(grid, 'Global', .false., _RC) + + _RETURN(_SUCCESS) + end function create_basic_grid + + + subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) + use MAPL_BaseMod, only: MAPL_grid_interior + use pflogger, only : Logger, logging + implicit none + class (SwathGridFactory), intent(in) :: this + type (ESMF_Grid), intent(inout) :: grid + class (KeywordEnforcer), optional, intent(in) :: unusable + integer, optional, intent(out) :: rc + integer :: status + + real(kind=ESMF_KIND_R8), pointer :: fptr(:,:) + real, pointer :: centers(:,:) + real, allocatable :: centers_full(:,:) + + integer :: i, j, k + integer :: Xdim, Ydim + integer :: Xdim_full, Ydim_full + + integer :: IM, JM + integer :: IM_WORLD, JM_WORLD + integer :: COUNTS(3), DIMS(3) + integer :: i_1, i_n, j_1, j_n ! regional array bounds + ! character(len=:), allocatable :: lon_center_name, lat_center_name, time_name + character(len=ESMF_MAXSTR) :: lon_center_name, lat_center_name, time_name + type(Logger), pointer :: lgr + + _UNUSED_DUMMY(unusable) + + ! keywords in netCDF + lon_center_name = "clon" + lat_center_name = "clat" + time_name = "scanTime" + Xdim=this%im_world + Ydim=this%jm_world + Xdim_full=this%cell_across_swath + Ydim_full=this%cell_along_swath + + call MAPL_grid_interior(grid, i_1, i_n, j_1, j_n) + call MAPL_AllocateShared(centers,[Xdim,Ydim],transroot=.true.,_RC) + call MAPL_SyncSharedMemory(_RC) + + ! read longitudes + if (MAPL_AmNodeRoot .or. (.not. MAPL_ShmInitialized)) then + allocate( centers_full(Xdim_full, Ydim_full)) + call get_v2d_netcdf(this%grid_file_name, lon_center_name, centers_full, Xdim_full, Ydim_full) + k=0 + do j=this%epoch_index(3), this%epoch_index(4) + k=k+1 + centers(1:Xdim, k) = centers_full(1:Xdim, j) + enddo + centers=centers*MAPL_DEGREES_TO_RADIANS_R8 + deallocate (centers_full) + end if + call MAPL_SyncSharedMemory(_RC) + call ESMF_GridGetCoord(grid, coordDim=1, localDE=0, & + staggerloc=ESMF_STAGGERLOC_CENTER, farrayPtr=fptr, _RC) + fptr=real(centers(i_1:i_n,j_1:j_n), kind=ESMF_KIND_R8) + + ! read latitudes + if (MAPL_AmNodeRoot .or. (.not. MAPL_ShmInitialized)) then + allocate( centers_full(Xdim_full, Ydim_full)) + call get_v2d_netcdf(this%grid_file_name, lat_center_name, centers_full, Xdim_full, Ydim_full) + k=0 + do j=this%epoch_index(3), this%epoch_index(4) + k=k+1 + centers(1:Xdim, k) = centers_full(1:Xdim, j) + enddo + centers=centers*MAPL_DEGREES_TO_RADIANS_R8 + deallocate (centers_full) + end if + call MAPL_SyncSharedMemory(_RC) + call ESMF_GridGetCoord(grid, coordDim=2, localDE=0, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + farrayPtr=fptr, rc=status) + fptr=real(centers(i_1:i_n,j_1:j_n), kind=ESMF_KIND_R8) + + if(MAPL_ShmInitialized) then + call MAPL_DeAllocNodeArray(centers,_RC) + else + deallocate(centers) + end if + + lgr => logging%get_logger('HISTORY.sampler') + call lgr%debug('%a', 'test') + call lgr%debug('%a %i8 %i8', 'Xdim, Ydim', Xdim, Ydim) + call lgr%debug('%a %i8 %i8', 'Xdim_full, Ydim_full', Xdim_full, Ydim_full) + call lgr%debug('%a %i8 %i8 %i8 %i8', 'epoch_index(1:4)', & + this%epoch_index(1), this%epoch_index(2), & + this%epoch_index(3), this%epoch_index(4)) + + _RETURN(_SUCCESS) + end subroutine add_horz_coordinates_from_file + + + subroutine initialize_from_file_metadata(this, file_metadata, unusable, force_file_coordinates, rc) + use MAPL_KeywordEnforcerMod + use MAPL_BaseMod, only: MAPL_DecomposeDim + + class (SwathGridFactory), intent(inout) :: this + type (FileMetadata), target, intent(in) :: file_metadata + class (KeywordEnforcer), optional, intent(in) :: unusable + logical, optional, intent(in) :: force_file_coordinates + integer, optional, intent(out) :: rc + + integer :: status + + class (CoordinateVariable), pointer :: v + class (*), pointer :: ptr(:) + + character(:), allocatable :: lon_name + character(:), allocatable :: lat_name + character(:), allocatable :: lev_name + integer :: i + logical :: hasLon, hasLat, hasLongitude, hasLatitude, hasLev,hasLevel,regLat,regLon + real(kind=REAL64) :: del12,delij + + integer :: i_min, i_max + real(kind=REAL64) :: d_lat, d_lat_temp, extrap_lat + logical :: is_valid, use_file_coords, compute_lons, compute_lats + + _UNUSED_DUMMY(unusable) + + if (present(force_file_coordinates)) then + use_file_coords = force_file_Coordinates + else + use_file_coords = .false. + end if + + ! Cannot assume that lats and lons are evenly spaced + + associate (im => this%im_world, jm => this%jm_world, lm => this%lm) + lon_name = 'lon' + hasLon = file_metadata%has_dimension(lon_name) + if (hasLon) then + im = file_metadata%get_dimension(lon_name, _RC) + else + lon_name = 'longitude' + hasLongitude = file_metadata%has_dimension(lon_name) + if (hasLongitude) then + im = file_metadata%get_dimension(lon_name, _RC) + else + _FAIL('no longitude coordinate') + end if + end if + lat_name = 'lat' + hasLat = file_metadata%has_dimension(lat_name) + if (hasLat) then + jm = file_metadata%get_dimension(lat_name, _RC) + else + lat_name = 'latitude' + hasLatitude = file_metadata%has_dimension(lat_name) + if (hasLatitude) then + jm = file_metadata%get_dimension(lat_name, _RC) + else + _FAIL('no latitude coordinate') + end if + end if + hasLev=.false. + hasLevel=.false. + lev_name = 'lev' + hasLev = file_metadata%has_dimension(lev_name) + if (hasLev) then + lm = file_metadata%get_dimension(lev_name,_RC) + else + lev_name = 'levels' + hasLevel = file_metadata%has_dimension(lev_name) + if (hasLevel) then + lm = file_metadata%get_dimension(lev_name,_RC) + end if + end if + end associate + + call this%make_arbitrary_decomposition(this%nx, this%ny, _RC) + + ! Determine IMS and JMS with constraint for ESMF that each DE has at least an extent + ! of 2. Required for ESMF_FieldRegrid(). + allocate(this%ims(0:this%nx-1)) + allocate(this%jms(0:this%ny-1)) + call MAPL_DecomposeDim(this%im_world, this%ims, this%nx, min_DE_extent=2) + call MAPL_DecomposeDim(this%jm_world, this%jms, this%ny, min_DE_extent=2) + + call this%check_and_fill_consistency(_RC) + + _RETURN(_SUCCESS) + + end subroutine initialize_from_file_metadata + + + subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc) + use esmf + use pflogger, only : Logger, logging + implicit none + class (SwathGridFactory), intent(inout) :: this + type (ESMF_Config), intent(inout) :: config + character(len=*), intent(in) :: prefix + class (KeywordEnforcer), optional, intent(in) :: unusable + integer, optional, intent(out) :: rc + integer :: status + + type(ESMF_VM) :: VM + integer :: nlon, nlat, tdim + integer :: Xdim, Ydim, ntime + character(len=ESMF_MAXSTR) :: key_lon, key_lat, key_time + character(len=ESMF_MAXSTR) :: filename, tunit, tmp, grp_name + real, allocatable :: scanTime(:,:) + integer :: yy, mm, dd, h, m, s, sec + integer :: i, j + + type(ESMF_Time) :: time0 + integer (ESMF_KIND_I8) :: j0, j1, jt, jt1, jt2 + real(ESMF_KIND_R8) :: jx0, jx1 + real(ESMF_KIND_R8) :: x0, x1 + integer :: khi, klo, k, nstart, max_iter + type(Logger), pointer :: lgr + logical :: ispresent + + _UNUSED_DUMMY(unusable) + + call ESMF_VmGetCurrent(VM, _RC) + + + call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'GRIDNAME:', default=MAPL_GRID_NAME_DEFAULT) + this%grid_name = trim(tmp) + call ESMF_ConfigGetAttribute(config, this%nx, label=prefix//'NX:', default=MAPL_UNDEFINED_INTEGER) + call ESMF_ConfigGetAttribute(config, this%ny, label=prefix//'NY:', default=MAPL_UNDEFINED_INTEGER) + call ESMF_ConfigGetAttribute(config, this%lm, label=prefix//'LM:', default=MAPL_UNDEFINED_INTEGER) + call ESMF_ConfigGetAttribute(config, filename, label=prefix//'GRIDSPEC:', default='unknown.txt', _RC) + call ESMF_ConfigGetAttribute(config, this%epoch, label=prefix//'Epoch:', default=300, _RC) + call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'Epoch_init:', default='2006', _RC) + + !!write(6,'(2x,a,/,4i8,/,5(2x,a))') 'nx,ny,lm,epoch -- filename,tmp', & + !! this%nx,this%ny,this%lm,this%epoch,& + !! trim(filename),trim(tmp) + !!print*, 'ck: Epoch_init:', trim(tmp) + + if ( index(tmp, 'T') /= 0 .OR. index(tmp, '-') /= 0 ) then + call ESMF_TimeSet(time0, timeString=tmp, _RC) + else + read(tmp,'(i4,5i2)') yy,mm,dd,h,m,s + call ESMF_Timeset(time0, yy=yy, mm=mm, dd=dd, h=h, m=m, s=s, _RC) + endif + this%grid_file_name = trim(filename) + + call ESMF_ConfigGetAttribute(config, value=this%nc_index, default="", & + label=prefix // 'nc_Index:', _RC) + call ESMF_ConfigGetAttribute(config, value=this%nc_time, default="", & + label=prefix//'nc_Time:', _RC) + call ESMF_ConfigGetAttribute(config, this%nc_longitude, & + label=prefix // 'nc_Longitude:', default="", _RC) + call ESMF_ConfigGetAttribute(config, this%nc_latitude, & + label=prefix // 'nc_Latitude:', default="", _RC) + + write(6,'((2x,a),10(2x,a15))') 'nc_time =', trim(this%nc_time) + write(6,'((2x,a),10(2x,a15))') 'nc_lon =', trim(this%nc_longitude) + write(6,'((2x,a),10(2x,a15))') 'nc_lat =', trim(this%nc_latitude) + + + i=index(this%nc_longitude, '/') + if (i>0) then + this%found_group = .true. + grp_name = this%nc_longitude(1:i-1) + else + this%found_group = .false. + grp_name = '' + endif + this%var_name_lat = this%nc_latitude(i+1:) + this%var_name_lon = this%nc_longitude(i+1:) + this%var_name_time= this%nc_time(i+1:) + + write(6,'(10(2x,a))') 'name lat, lon, time', & + trim(this%var_name_lat), trim(this%var_name_lon), trim(this%var_name_time) + + ! read global dim from nc file + ! ---------------------------- + key_lon=this%var_name_lon + key_lat=this%var_name_lat + key_time=this%var_name_time + ! CALL get_ncfile_dimension(filename, nlon, nlat, tdim, key_lon, key_lat, key_time, _RC) + CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, tdim=tdim, & + key_lon=key_lon, key_lat=key_lat, key_time=key_time, _RC) + allocate(scanTime(nlon, nlat)) + allocate(this%t_alongtrack(nlat)) + + lgr => logging%get_logger('HISTORY.sampler') + call lgr%debug('%a %a', & + 'swath Epoch init time:', trim(tmp) ) + call lgr%debug('%a %a', & + 'swath obs filename: ', trim(filename) ) + call lgr%debug('%a %i8 %i8 %i8', & + 'swath obs nlon,nlat,tdim:', nlon,nlat,tdim ) + + call get_v2d_netcdf(filename, 'scanTime', scanTime, nlon, nlat) + do j=1, nlat + this%t_alongtrack(j)= scanTime(1,j) + enddo + ! + ! skip un-defined time value + ! + ! + nstart = 1 + x0 = this%t_alongtrack(1) + x1 = 1.d16 + + if (x0 > x1) then + ! + ! bisect backward finding the first index arr[n] < x1 + klo=1 + khi=nlat + max_iter = int( log( real(nlat) ) / log(2.d0) ) + 2 + do i=1, max_iter + k = (klo+khi)/2 + if ( this%t_alongtrack(k) < x1 ) then + khi=k + else + nstart = khi + exit + endif + enddo + call lgr%debug('%a %i4', 'nstart', nstart) + call lgr%debug('%a %i4', 'this%t_alongtrack(nstart)', this%t_alongtrack(nstart)) + endif + + deallocate(scanTime) + + this%cell_across_swath = nlon + this%cell_along_swath = nlat + + +!! stop -11 + + ! determine im_world from Epoch + ! ----------------------------- + ! t_axis = t_alongtrack = t_a + ! convert time0 to j0 + ! use Epoch to find j1 + ! search j0, j1 in t_a + + + ! this is a bug + ! + tunit='seconds since 1993-01-01 00:00:00' + this%tunit = tunit + call time_esmf_2_nc_int (time0, tunit, j0, _RC) + call hms_2_s (this%Epoch, sec, _RC) + j1= j0 + sec + jx0= j0 + jx1= j1 + !!call lgr%debug ('%a %f8 %f8', 'jx0, jx1', jx0, jx1) + call lgr%debug ('%a %i16 %i16', 'j0, j1 ', j0, j1) + + + this%epoch_index(1)= 1 + this%epoch_index(2)= this%cell_across_swath + call bisect( this%t_alongtrack, jx0, jt1, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) + call bisect( this%t_alongtrack, jx1, jt2, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) + + + if (jt1==jt2) then + _FAIL('Epoch Time is too small, empty swath grid is generated, increase Epoch') + endif + jt1 = jt1 + 1 ! (x1,x2] design + this%epoch_index(3)= jt1 + this%epoch_index(4)= jt2 + Xdim = this%cell_across_swath + Ydim = this%epoch_index(4) - this%epoch_index(3) + 1 + + + call lgr%debug ('%a %i4 %i4', 'bisect for j0: rc, jt', rc, jt1) + call lgr%debug ('%a %i4 %i4', 'bisect for j1: rc, jt', rc, jt2) + call lgr%debug ('%a %i4 %i4', 'Xdim, Ydim', Xdim, Ydim) + call lgr%debug ('%a %i4 %i4 %i4 %i4', 'this%epoch_index(4)', & + this%epoch_index(1), this%epoch_index(2), & + this%epoch_index(3), this%epoch_index(4)) + + + this%im_world = Xdim + this%jm_world = Ydim + + + call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'IMS_FILE:', rc=status) + if ( status == _SUCCESS ) then + call get_ims_from_file(this%ims, trim(tmp),this%nx, _RC) + else + call get_multi_integer(this%ims, 'IMS:', _RC) + endif + call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'JMS_FILE:', rc=status) + if ( status == _SUCCESS ) then + call get_ims_from_file(this%jms, trim(tmp),this%ny, _RC) + else + call get_multi_integer(this%jms, 'JMS:', _RC) + endif + ! ims is set at here + call this%check_and_fill_consistency(_RC) + + + _RETURN(_SUCCESS) + + + contains + + subroutine get_multi_integer(values, label, rc) + integer, allocatable, intent(out) :: values(:) + character(len=*) :: label + integer, optional, intent(out) :: rc + + integer :: i + integer :: n + integer :: tmp + integer :: status + logical :: isPresent + + call ESMF_ConfigFindLabel(config, label=prefix//label, isPresent=isPresent, _RC) + + if (.not. isPresent) then + _RETURN(_SUCCESS) + end if + + ! First pass: count values + n = 0 + do + call ESMF_ConfigGetAttribute(config, tmp, rc=status) + if (status /= _SUCCESS) then + exit + else + n = n + 1 + end if + end do + + + ! Second pass: allocate and fill + allocate(values(n), stat=status) ! no point in checking status + _VERIFY(status) + call ESMF_ConfigFindLabel(config, label=prefix//label,_RC) + do i = 1, n + call ESMF_ConfigGetAttribute(config, values(i), _RC) + write(6,*) 'values(i)=', values(i) + end do + + _RETURN(_SUCCESS) + + end subroutine get_multi_integer + + subroutine get_ims_from_file(values, file_name, n, rc) + integer, allocatable, intent(out) :: values(:) + character(len=*), intent(in) :: file_name + integer, intent(in) :: n + integer, optional, intent(out) :: rc + + logical :: FileExists + integer :: i, total, unit + integer :: status + + inquire(FILE = trim(file_name), EXIST=FileExists) + allocate(values(n), stat=status) ! no point in checking status + _VERIFY(status) + + _ASSERT(FileExists, "File <"//trim(file_name)//"> not found") + if (MAPL_AM_I_Root(VM)) then + open(newunit=UNIT, file=trim(file_name), form="formatted", iostat=status ) + _VERIFY(STATUS) + read(UNIT,*) total + _ASSERT(total == n, trim(file_name) // " n is different from total") + do i = 1,total + read(UNIT,*) values(i) + enddo + close(UNIT) + endif + + call MAPL_CommsBcast(VM, values, n=N, ROOT=MAPL_Root, _RC) + _RETURN(_SUCCESS) + + end subroutine get_ims_from_file + + subroutine get_range(range, label, rc) + type(RealMinMax), intent(out) :: range + character(len=*) :: label + integer, optional, intent(out) :: rc + + integer :: i + integer :: n + integer :: status + logical :: isPresent + + call ESMF_ConfigFindLabel(config, label=prefix//label,isPresent=isPresent,_RC) + if (.not. isPresent) then + _RETURN(_SUCCESS) + end if + + ! Must be 2 values: min and max + call ESMF_ConfigGetAttribute(config, range%min, _RC) + call ESMF_ConfigGetAttribute(config, range%max, _RC) + + _RETURN(_SUCCESS) + + end subroutine get_range + + + end subroutine initialize_from_config_with_prefix + + + + function to_string(this) result(string) + character(len=:), allocatable :: string + class (SwathGridFactory), intent(in) :: this + + _UNUSED_DUMMY(this) + string = 'SwathGridFactory' + + end function to_string + + + subroutine check_and_fill_consistency(this, unusable, rc) + use MAPL_BaseMod, only: MAPL_DecomposeDim + class (SwathGridFactory), intent(inout) :: this + class (KeywordEnforcer), optional, intent(in) :: unusable + integer, optional, intent(out) :: rc + + integer :: status + logical :: verify_decomp + + _UNUSED_DUMMY(unusable) + + if (.not. allocated(this%grid_name)) then + this%grid_name = MAPL_GRID_NAME_DEFAULT + end if + + ! Check decomposition/bounds + ! WY notes: should not have this assert + !_ASSERT(allocated(this%ims) .eqv. allocated(this%jms), 'inconsistent options') + call verify(this%nx, this%im_world, this%ims, rc=status) + call verify(this%ny, this%jm_world, this%jms, rc=status) + + if (.not.this%force_decomposition) then + verify_decomp = this%check_decomposition(_RC) + if ( (.not.verify_decomp) ) then + call this%generate_newnxy(_RC) + end if + end if + + _RETURN(_SUCCESS) + + contains + + subroutine verify(n, m_world, ms, rc) + integer, intent(inout) :: n + integer, intent(inout) :: m_world + integer, allocatable, intent(inout) :: ms(:) + integer, optional, intent(out) :: rc + + integer :: status + + if (allocated(ms)) then + _ASSERT(size(ms) > 0, 'degenerate topology') + + if (n == MAPL_UNDEFINED_INTEGER) then + n = size(ms) + else + _ASSERT(n == size(ms), 'inconsistent topology') + end if + + if (m_world == MAPL_UNDEFINED_INTEGER) then + m_world = sum(ms) + else + _ASSERT(m_world == sum(ms), 'inconsistent decomponsition') + end if + + else + + _ASSERT(n /= MAPL_UNDEFINED_INTEGER, 'uninitialized topology') + _ASSERT(m_world /= MAPL_UNDEFINED_INTEGER,'uninitialized dimension') + allocate(ms(n), stat=status) + _VERIFY(status) + !call MAPL_DecomposeDim(m_world, ms, n, min_DE_extent=2) + call MAPL_DecomposeDim(m_world, ms, n) + + end if + + _RETURN(_SUCCESS) + + end subroutine verify + + end subroutine check_and_fill_consistency + + + elemental subroutine set_with_default_integer(to, from, default) + integer, intent(out) :: to + integer, optional, intent(in) :: from + integer, intent(in) :: default + + if (present(from)) then + to = from + else + to = default + end if + + end subroutine set_with_default_integer + + elemental subroutine set_with_default_real64(to, from, default) + real(REAL64), intent(out) :: to + real(REAL64), optional, intent(in) :: from + real(REAL64), intent(in) :: default + + if (present(from)) then + to = from + else + to = default + end if + + end subroutine set_with_default_real64 + + elemental subroutine set_with_default_real(to, from, default) + real, intent(out) :: to + real, optional, intent(in) :: from + real, intent(in) :: default + + if (present(from)) then + to = from + else + to = default + end if + + end subroutine set_with_default_real + + subroutine set_with_default_character(to, from, default) + character(len=:), allocatable, intent(out) :: to + character(len=*), optional, intent(in) :: from + character(len=*), intent(in) :: default + + if (present(from)) then + to = from + else + to = default + end if + + end subroutine set_with_default_character + + + elemental subroutine set_with_default_bounds(to, from, default) + type (RealMinMax), intent(out) :: to + type (RealMinMax), optional, intent(in) :: from + type (RealMinMax), intent(in) :: default + + if (present(from)) then + to = from + else + to = default + end if + + end subroutine set_with_default_bounds + + + ! MAPL uses values in lon_array and lat_array only to determine the + ! general positioning. Actual coordinates are then recomputed. + ! This helps to avoid roundoff differences from slightly different + ! input files. + subroutine initialize_from_esmf_distGrid(this, dist_grid, lon_array, lat_array, unusable, rc) + use MAPL_ConfigMod + use MAPL_Constants, only: PI => MAPL_PI_R8 + class (SwathGridFactory), intent(inout) :: this + type (ESMF_DistGrid), intent(in) :: dist_grid + type (ESMF_LocalArray), intent(in) :: lon_array + type (ESMF_LocalArray), intent(in) :: lat_array + class (KeywordEnforcer), optional, intent(in) :: unusable + integer, optional, intent(out) :: rc + + integer :: dim_count, tile_count + integer, allocatable :: max_index(:,:) + integer :: status + character(len=2) :: pole ,dateline + + type (ESMF_Config) :: config + type (ESMF_VM) :: vm + integer :: nPet + real(kind=REAL32), pointer :: lon(:) + real(kind=REAL32), pointer :: lat(:) + integer :: nx_guess,nx,ny + integer :: i + + real, parameter :: tiny = 1.e-4 + + _FAIL ('stop: not implemented: subroutine initialize_from_esmf_distGrid') + + _UNUSED_DUMMY(unusable) + + call ESMF_DistGridGet(dist_grid, dimCount=dim_count, tileCount=tile_count) + allocate(max_index(dim_count, tile_count)) + call ESMF_DistGridGet(dist_grid, maxindexPTile=max_index) + + config = MAPL_ConfigCreate(_RC) + call MAPL_ConfigSetAttribute(config, max_index(1,1), 'IM_WORLD:', _RC) + call MAPL_ConfigSetAttribute(config, max_index(2,1), 'JM_WORLD:', _RC) + call MAPL_ConfigSetAttribute(config, max_index(3,1), 'LM:', _RC) + + lon => null() + lat => null() + call ESMF_LocalArrayGet(lon_array, farrayPtr=lon, _RC) + call ESMF_LocalArrayGet(lat_array, farrayPtr=lat, _RC) + + call ESMF_VMGetCurrent(vm, _RC) + call ESMF_VMGet(vm, PETcount=nPet, _RC) + + nx_guess = nint(sqrt(real(nPet))) + do nx = nx_guess,1,-1 + ny=nPet/nx + if (nx*ny==nPet) then + call MAPL_ConfigSetAttribute(config, nx, 'NX:') + call MAPL_ConfigSetAttribute(config, ny, 'NY:') + exit + end if + enddo + + call this%initialize(config, _RC) + + end subroutine initialize_from_esmf_distGrid + + + function decomps_are_equal(this,a) result(equal) + class (SwathGridFactory), intent(in) :: this + class (AbstractGridFactory), intent(in) :: a + logical :: equal + + select type (a) + class default + equal = .false. + return + class is (SwathGridFactory) + equal = .true. + + + equal = size(a%ims)==size(this%ims) .and. size(a%jms)==size(this%jms) + if (.not. equal) return + + ! same decomposition + equal = all(a%ims == this%ims) .and. all(a%jms == this%jms) + if (.not. equal) return + + end select + + end function decomps_are_equal + + + function physical_params_are_equal(this, a) result(equal) + class (SwathGridFactory), intent(in) :: this + class (AbstractGridFactory), intent(in) :: a + logical :: equal + + select type (a) + class default + equal = .false. + return + class is (SwathGridFactory) + equal = .true. + + equal = (a%im_world == this%im_world) .and. (a%jm_world == this%jm_world) + if (.not. equal) return + end select + + end function physical_params_are_equal + + logical function equals(a, b) + class (SwathGridFactory), intent(in) :: a + class (AbstractGridFactory), intent(in) :: b + + select type (b) + class default + equals = .false. + return + class is (SwathGridFactory) + equals = .true. + + equals = (a%lm == b%lm) + if (.not. equals) return + + equals = a%decomps_are_equal(b) + if (.not. equals) return + + equals = a%physical_params_are_equal(b) + if (.not. equals) return + + end select + + end function equals + + + function generate_grid_name(this) result(name) + character(len=:), allocatable :: name + class (SwathGridFactory), intent(in) :: this +! from tclune: This needs thought. I suspect we want something that indicates this is a swath grid. + character(len=4) :: im_string, jm_string + name = im_string // 'x' // jm_string + end function generate_grid_name + + + function check_decomposition(this,unusable,rc) result(can_decomp) + class (SwathGridFactory), target, intent(inout) :: this + class (KeywordEnforcer), optional, intent(in) :: unusable + integer, optional, intent(out) :: rc + logical :: can_decomp + integer :: n + _UNUSED_DUMMY(unusable) + + can_decomp = .true. + if (this%im_world==1 .and. this%jm_world==1) then + _RETURN(_SUCCESS) + end if + n = this%im_world/this%nx + if (n < 2) can_decomp = .false. + n = this%jm_world/this%ny + if (n < 2) can_decomp = .false. + _RETURN(_SUCCESS) + end function check_decomposition + + + subroutine generate_newnxy(this,unusable,rc) + use MAPL_BaseMod, only: MAPL_DecomposeDim + class (SwathGridFactory), target, intent(inout) :: this + class (KeywordEnforcer), optional, intent(in) :: unusable + integer, optional, intent(out) :: rc + integer :: n + + _UNUSED_DUMMY(unusable) + + n = this%im_world/this%nx + if (n < 2) then + this%nx = generate_new_decomp(this%im_world,this%nx) + deallocate(this%ims) + allocate(this%ims(0:this%nx-1)) + call MAPL_DecomposeDim(this%im_world, this%ims, this%nx) + end if + n = this%jm_world/this%ny + if (n < 2) then + this%ny = generate_new_decomp(this%jm_world,this%ny) + deallocate(this%jms) + allocate(this%jms(0:this%ny-1)) + call MAPL_DecomposeDim(this%jm_world, this%jms, this%ny) + end if + + _RETURN(_SUCCESS) + + end subroutine generate_newnxy + + function generate_new_decomp(im,nd) result(n) + integer, intent(in) :: im, nd + integer :: n + logical :: canNotDecomp + + canNotDecomp = .true. + n = nd + do while(canNotDecomp) + if ( (im/n) < 2) then + n = n/2 + else + canNotDecomp = .false. + end if + enddo + end function generate_new_decomp + + subroutine init_halo(this, unusable, rc) + class (SwathGridFactory), target, intent(inout) :: this + class (KeywordEnforcer), optional, intent(in) :: unusable + integer, optional, intent(out) :: rc + _FAIL('Stop: subroutine init_halo is not needed for SwathGridFactory') + end subroutine init_halo + + subroutine halo(this, array, unusable, halo_width, rc) + use MAPL_CommsMod + class (SwathGridFactory), intent(inout) :: this + real(kind=REAL32), intent(inout) :: array(:,:) + class (KeywordEnforcer), optional, intent(in) :: unusable + integer, optional, intent(in) :: halo_width + integer, optional, intent(out) :: rc + _FAIL( 'Stop: subroutine halo is not needed for SwathGridFactory') + end subroutine halo + + + subroutine append_metadata(this, metadata) + use MAPL_Constants + class (SwathGridFactory), intent(inout) :: this + type (FileMetadata), intent(inout) :: metadata + + type (Variable) :: v + real(kind=REAL64), allocatable :: temp_coords(:) + + character(len=ESMF_MAXSTR) :: key_lon + character(len=ESMF_MAXSTR) :: key_lat + + ! Horizontal grid dimensions + call metadata%add_dimension('lon', this%im_world) + call metadata%add_dimension('lat', this%jm_world) + + ! Coordinate variables + v = Variable(type=PFIO_REAL64, dimensions='lon,lat') + call v%add_attribute('long_name', 'longitude') + call v%add_attribute('units', 'degrees_east') + call metadata%add_variable('lons', v) + + v = Variable(type=PFIO_REAL64, dimensions='lon,lat') + call v%add_attribute('long_name', 'latitude') + call v%add_attribute('units', 'degrees_north') + call metadata%add_variable('lats', v) + + end subroutine append_metadata + + + function get_grid_vars(this) result(vars) + class (SwathGridFactory), intent(inout) :: this + + character(len=:), allocatable :: vars + character(len=ESMF_MAXSTR) :: key_lon + character(len=ESMF_MAXSTR) :: key_lat + _UNUSED_DUMMY(this) + + key_lon=trim(this%var_name_lon) + key_lat=trim(this%var_name_lat) + vars = 'lon,lat' + + end function get_grid_vars + + + function get_file_format_vars(this) result(vars) + class (SwathGridFactory), intent(inout) :: this + + character(len=:), allocatable :: vars + _UNUSED_DUMMY(this) + + vars = 'lon,lat' + end function get_file_format_vars + + + subroutine append_variable_metadata(this,var) + class (SwathGridFactory), intent(inout) :: this + type(Variable), intent(inout) :: var + _UNUSED_DUMMY(this) + _UNUSED_DUMMY(var) + end subroutine append_variable_metadata + + + subroutine generate_file_bounds(this,grid,local_start,global_start,global_count,metadata,rc) + use MAPL_BaseMod + class(SwathGridFactory), intent(inout) :: this + type(ESMF_Grid), intent(inout) :: grid + integer, allocatable, intent(out) :: local_start(:) + integer, allocatable, intent(out) :: global_start(:) + integer, allocatable, intent(out) :: global_count(:) + type(FileMetaData), intent(in), optional :: metaData + integer, optional, intent(out) :: rc + + integer :: status + integer :: global_dim(3), i1,j1,in,jn + + _UNUSED_DUMMY(this) + + call MAPL_GridGet(grid,globalCellCountPerDim=global_dim,_RC) + call MAPL_GridGetInterior(grid,i1,in,j1,jn) + allocate(local_start,source=[i1,j1]) + allocate(global_start,source=[1,1]) + allocate(global_count,source=[global_dim(1),global_dim(2)]) + + _RETURN(_SUCCESS) + + end subroutine generate_file_bounds + + + subroutine generate_file_corner_bounds(this,grid,local_start,global_start,global_count,rc) + use esmf + class (SwathGridFactory), intent(inout) :: this + type(ESMF_Grid), intent(inout) :: grid + integer, allocatable, intent(out) :: local_start(:) + integer, allocatable, intent(out) :: global_start(:) + integer, allocatable, intent(out) :: global_count(:) + integer, optional, intent(out) :: rc + + _UNUSED_DUMMY(this) + _UNUSED_DUMMY(grid) + _UNUSED_DUMMY(local_start) + _UNUSED_DUMMY(global_start) + _UNUSED_DUMMY(global_count) + + _FAIL('unimplemented') + _RETURN(_SUCCESS) + end subroutine generate_file_corner_bounds + + function generate_file_reference2D(this,fpointer) result(ref) + use pFIO + type(ArrayReference) :: ref + class(SwathGridFactory), intent(inout) :: this + real, pointer, intent(in) :: fpointer(:,:) + _UNUSED_DUMMY(this) + ref = ArrayReference(fpointer) + end function generate_file_reference2D + + function generate_file_reference3D(this,fpointer,metaData) result(ref) + use pFIO + type(ArrayReference) :: ref + class(SwathGridFactory), intent(inout) :: this + real, pointer, intent(in) :: fpointer(:,:,:) + type(FileMetaData), intent(in), optional :: metaData + _UNUSED_DUMMY(this) + ref = ArrayReference(fpointer) + end function generate_file_reference3D + + + subroutine get_xy_subset(this, interval, xy_subset, rc) + class(SwathGridFactory), intent(in) :: this + type(ESMF_Time), intent(in) :: interval(2) + integer, intent(out) :: xy_subset(2,2) + integer, optional, intent(out) :: rc + + integer :: status + type(ESMF_Time) :: T1, T2 + integer(ESMF_KIND_I8) :: i1, i2 + real(ESMF_KIND_R8) :: iT1, iT2 + integer(ESMF_KIND_I8) :: index1, index2 + integer :: jlo, jhi, je + + ! xtrack + xy_subset(1:2,1)=this%epoch_index(1:2) + + ! atrack + T1= interval(1) + T2= interval(2) + + ! this%t_alongtrack + ! + call time_esmf_2_nc_int (T1, this%tunit, i1, _RC) + call time_esmf_2_nc_int (T2, this%tunit, i2, _RC) + iT1 = i1 ! int to real*8 + iT2 = i2 + jlo = this%epoch_index(3) - 2 + jhi = this%epoch_index(4) + 1 + call bisect( this%t_alongtrack, iT1, index1, n_LB=int(jlo, ESMF_KIND_I8), n_UB=int(jhi, ESMF_KIND_I8), rc=rc) + call bisect( this%t_alongtrack, iT2, index2, n_LB=int(jlo, ESMF_KIND_I8), n_UB=int(jhi, ESMF_KIND_I8), rc=rc) + +!! complex version +!! ! (x1, x2] design in bisect +!! if (index1==jlo-1) then +!! je = index1 + 1 +!! else +!! je = index1 +!! end if +!! xy_subset(1, 2) = je +!! if (index2==jlo-1) then +!! je = index2 + 1 +!! else +!! je = index2 +!! end if +!! xy_subset(2, 2) = je + + ! simple version + xy_subset(1, 2)=index1+1 ! atrack + xy_subset(2, 2)=index2 + + ! + !- relative + ! + xy_subset(1,2)= xy_subset(1,2) - this%epoch_index(3) + 1 + xy_subset(2,2)= xy_subset(2,2) - this%epoch_index(3) + 1 + + _RETURN(_SUCCESS) + end subroutine get_xy_subset + + + subroutine destroy(this, rc) + class(SwathGridFactory), intent(inout) :: this + integer, optional, intent(out) :: rc + integer :: i + return + end subroutine destroy + + + ! here grid == external_grid + ! because this%grid is protected in AbstractGridFactory + subroutine get_obs_time(this, grid, obs_time, rc) + use MAPL_BaseMod, only: MAPL_grid_interior + class(SwathGridFactory), intent(inout) :: this + type (ESMF_Grid), intent(in) :: grid + real(ESMF_KIND_R4), intent(out) :: obs_time(:,:) + integer, optional, intent(out) :: rc + integer :: status + + integer :: i_1, i_n, j_1, j_n ! regional array bounds + + !! shared mem + real(kind=ESMF_KIND_R8), pointer :: fptr(:,:) + real, pointer :: centers(:,:) + real, allocatable :: centers_full(:,:) + + integer :: i, j, k + integer :: Xdim, Ydim + integer :: Xdim_full, Ydim_full + + integer :: IM_WORLD, JM_WORLD + character(len=:), allocatable :: time_name + + + ! keywords in netCDF + time_name = "scanTime" + call MAPL_grid_interior(grid, i_1, i_n, j_1, j_n) + + !- shared mem case in MPI + ! + Xdim=this%im_world + Ydim=this%jm_world + + Xdim_full=this%cell_across_swath + Ydim_full=this%cell_along_swath + + call MAPL_AllocateShared(centers,[Xdim,Ydim],transroot=.true.,_RC) + call MAPL_SyncSharedMemory(_RC) + + + ! read Time and set + if (MAPL_AmNodeRoot .or. (.not. MAPL_ShmInitialized)) then + allocate( centers_full(Xdim_full, Ydim_full)) + call get_v2d_netcdf(this%grid_file_name, time_name, centers_full, Xdim_full, Ydim_full) + k=0 + do j=this%epoch_index(3), this%epoch_index(4) + k=k+1 + centers(1:Xdim, k) = centers_full(1:Xdim, j) + enddo + deallocate (centers_full) + end if + call MAPL_SyncSharedMemory(_RC) + + !(Xdim, Ydim) + obs_time = centers(i_1:i_n,j_1:j_n) + + if(MAPL_ShmInitialized) then + call MAPL_DeAllocNodeArray(centers,_RC) + else + deallocate(centers) + end if + + _RETURN(_SUCCESS) + end subroutine get_obs_time + + +end module MAPL_SwathGridFactoryMod diff --git a/base/Plain_netCDF_Time.F90 b/base/Plain_netCDF_Time.F90 index a13b97c0683b..8be0f62c508f 100644 --- a/base/Plain_netCDF_Time.F90 +++ b/base/Plain_netCDF_Time.F90 @@ -87,7 +87,6 @@ subroutine get_ncfile_dimension(filename, nlon, nlat, tdim, key_lon, key_lat, ke lat_name=trim(key_lat) call check_nc_status(nf90_inq_dimid(ncid, trim(lat_name), dimid), _RC) call check_nc_status(nf90_inquire_dimension(ncid, dimid, len=nlat), _RC) - call check_nc_status(nf90_close(ncid), _RC) endif if(present(key_time)) then diff --git a/gridcomps/History/CMakeLists.txt b/gridcomps/History/CMakeLists.txt index c00678537245..25ba48139cfe 100644 --- a/gridcomps/History/CMakeLists.txt +++ b/gridcomps/History/CMakeLists.txt @@ -5,6 +5,7 @@ set (srcs MAPL_HistoryTrajectoryMod_smod.F90 MAPL_HistoryCollection.F90 MAPL_HistoryGridComp.F90 + MAPL_EpochSwathMod.F90 MAPL_StationSamplerMod.F90 ) diff --git a/gridcomps/History/MAPL_EpochSwathMod.F90 b/gridcomps/History/MAPL_EpochSwathMod.F90 new file mode 100644 index 000000000000..f1961b8c0285 --- /dev/null +++ b/gridcomps/History/MAPL_EpochSwathMod.F90 @@ -0,0 +1,1377 @@ +! +! __ Analogy to GriddedIO.F90 with a twist for Epoch Swath grid +! +#include "MAPL_Generic.h" + +module MAPL_EpochSwathMod + use ESMF + use ESMFL_Mod + use MAPL_AbstractGridFactoryMod + use MAPL_AbstractRegridderMod + use MAPL_GridManagerMod + use MAPL_BaseMod + use MAPL_NewRegridderManager + use MAPL_RegridMethods + use MAPL_TimeDataMod + use MAPL_VerticalDataMod + use MAPL_Constants + use pFIO + use MAPL_GriddedIOItemVectorMod + use MAPL_GriddedIOItemMod + use MAPL_ExceptionHandling + use pFIO_ClientManagerMod + use MAPL_DataCollectionMod + use MAPL_DataCollectionManagerMod + use gFTL_StringVector + use gFTL_StringStringMap + use MAPL_StringGridMapMod + use MAPL_FileMetadataUtilsMod + use MAPL_DownbitMod + use Plain_netCDF_Time + use, intrinsic :: ISO_C_BINDING + use, intrinsic :: iso_fortran_env, only: REAL64 + use ieee_arithmetic, only: isnan => ieee_is_nan + implicit none + + private + + type, public :: samplerHQ + type(ESMF_Clock) :: clock + type(ESMF_Alarm) :: alarm + type(ESMF_Time) :: RingTime + type(ESMF_TimeInterval) :: Frequency_epoch + type(ESMF_config) :: config_grid_save + type(ESMF_grid) :: ogrid + character(len=ESMF_MAXSTR) :: grid_type + real*8 :: arr(2) + + contains + procedure :: create_grid + procedure :: regrid_accumulate => regrid_accumulate_on_xysubset + procedure :: destroy_rh_regen_ogrid + procedure :: fill_time_in_bundle + end type samplerHQ + + interface samplerHQ + module procedure new_samplerHQ + end interface samplerHQ + + type, public :: sampler + type(FileMetaData), allocatable :: metadata + type(fileMetadataUtils), pointer :: current_file_metadata + integer :: write_collection_id + integer :: read_collection_id + integer :: metadata_collection_id + class (AbstractRegridder), pointer :: regrid_handle => null() + type(ESMF_Grid) :: output_grid + logical :: doVertRegrid = .false. + type(ESMF_FieldBundle) :: output_bundle + type(ESMF_FieldBundle) :: input_bundle + type(ESMF_FieldBundle) :: acc_bundle + type(ESMF_Time) :: startTime + integer :: regrid_method = REGRID_METHOD_BILINEAR + integer :: nbits_to_keep = MAPL_NBITS_NOT_SET + real, allocatable :: lons(:,:),lats(:,:) + real, allocatable :: corner_lons(:,:),corner_lats(:,:) + real, allocatable :: times(:) + type(TimeData) :: timeInfo + type(VerticalData) :: vdata + type(GriddedIOitemVector) :: items + integer :: deflateLevel = 0 + integer :: quantizeAlgorithm = 1 + integer :: quantizeLevel = 0 + integer, allocatable :: chunking(:) + logical :: itemOrderAlphabetical = .true. + integer :: fraction + logical :: have_initalized + contains +!! procedure :: CreateFileMetaData + procedure :: Create_bundle_RH + procedure :: CreateVariable + procedure :: regridScalar + procedure :: regridVector + procedure :: set_param + procedure :: set_default_chunking + procedure :: check_chunking + procedure :: alphabatize_variables + procedure :: addVariable_to_acc_bundle + procedure :: addVariable_to_output_bundle + procedure :: interp_accumulate_fields + end type sampler + + interface sampler + module procedure new_sampler + end interface sampler + +contains + + function new_samplerHQ(clock, config, key, rc) result(hq) + implicit none + type(samplerHQ) :: hq + type(ESMF_Clock), intent(in) :: clock + type(ESMF_Config), intent(inout) :: config + character(len=*), intent(in) :: key + integer, optional, intent(out) :: rc + + character(len=ESMF_MAXSTR) :: time_string + integer :: status + integer :: time_integer + type(ESMF_Time) :: RingTime_epoch + type(ESMF_Time) :: startTime + type(ESMF_Time) :: currTime + type(ESMF_TimeInterval) :: timeStep + type(ESMF_TimeInterval) :: Frequency_epoch + + integer :: sec, second + integer :: n1 + type(ESMF_Config) :: cf + + + hq%clock= clock + hq%config_grid_save= config + + hq%arr(1:2) = -2.d0 + call ESMF_ClockGet ( clock, CurrTime=currTime, _RC ) + call ESMF_ClockGet ( clock, timestep=timestep, _RC ) + call ESMF_ClockGet ( clock, startTime=startTime, _RC ) + call ESMF_ConfigGetAttribute(config, value=time_integer, label=trim(key)//'.Epoch:', default=0, _RC) + _ASSERT(time_integer /= 0, 'Epoch value in config wrong') + call hms_2_s (time_integer, second, _RC) + call ESMF_TimeIntervalSet(frequency_epoch, s=second, _RC) + hq%frequency_epoch = frequency_epoch + hq%RingTime = currTime + hq%alarm = ESMF_AlarmCreate( clock=clock, RingInterval=Frequency_epoch, & + RingTime=hq%RingTime, sticky=.false., _RC ) + + _RETURN(_SUCCESS) + + end function new_samplerHQ + + + !--------------------------------------------------! + ! __ set + ! - ogrid via grid_manager%make_grid + ! using currTime and HQ%config_grid_save + !--------------------------------------------------! + function create_grid(this, key, currTime, grid_type, rc) result(ogrid) + type (ESMF_Grid) :: ogrid + class(samplerHQ) :: this + character(len=*), intent(in) :: key + type(ESMF_Time), intent(inout) :: currTime + character(len=*), optional, intent(in) :: grid_type + integer, intent(out), optional :: rc + integer :: status + + type(ESMF_Config) :: config_grid + character(len=ESMF_MAXSTR) :: time_string + + logical :: ispresent + + if (present(grid_type)) this%grid_type = trim(grid_type) + config_grid = this%config_grid_save + call ESMF_TimeGet(currTime, timeString=time_string, _RC) + ! + ! -- the `ESMF_ConfigSetAttribute` shows a risk + ! to overwrite the nextline in config + ! + call ESMF_ConfigSetAttribute( config_grid, trim(time_string), label=trim(key)//'.Epoch_init:', _RC) + ogrid = grid_manager%make_grid(config_grid, prefix=trim(key)//'.', _RC ) + this%ogrid = ogrid + _RETURN(_SUCCESS) + + end function create_grid + + + subroutine regrid_accumulate_on_xysubset (this, sp, rc) + class(samplerHQ) :: this + class(sampler), intent(inout) :: sp + integer, intent(out), optional :: rc + integer :: status + + class(AbstractGridFactory), pointer :: factory + integer :: xy_subset(2,2) + type(ESMF_Time) :: timeset(2) + type(ESMF_Time) :: current_time + type(ESMF_TimeInterval) :: dur + character(len=ESMF_MAXSTR) :: time_string + + integer, allocatable :: global_xy_mask(:,:) + integer, allocatable :: local_xy_mask(:,:) + + integer :: counts(5) + integer :: dims(3) + integer :: m1, m2 + + ! __ s1. get xy_subset + + factory => grid_manager%get_factory(this%ogrid,_RC) + call ESMF_ClockGet(this%clock,currTime=current_time,_RC) + call ESMF_ClockGet(this%clock,timeStep=dur, _RC ) + timeset(1) = current_time - dur + timeset(2) = current_time + call factory%get_xy_subset( timeset, xy_subset, _RC) + + write(6,*) 'xy_subset(:,1)_x', xy_subset(:,1) ! LB, UB + !!write(6,*) 'xy_subset(:,2)_a', xy_subset(:,2) + write(6,*) 'xy_subset(:,2)_a', xy_subset(:,2), xy_subset(2,2)-xy_subset(1,2)+1 ! UB + + ! __ s2. interpolate then save data using xy_mask + + call sp%interp_accumulate_fields (xy_subset, _RC) + + _RETURN(ESMF_SUCCESS) + + end subroutine regrid_accumulate_on_xysubset + + + subroutine destroy_rh_regen_ogrid (this, key_grid_label, output_grids, sp, rc) + implicit none + class(samplerHQ) :: this + class(sampler) :: sp + type (StringGridMap), target, intent(inout) :: output_grids + character(len=*), intent(in) :: key_grid_label + integer, intent(out), optional :: rc + integer :: status + + class(AbstractGridFactory), pointer :: factory + type(ESMF_Time) :: currTime + type(ESMF_TimeInterval) :: dur + character(len=ESMF_MAXSTR) :: time_string + + type(ESMF_Grid), pointer :: pgrid + type(ESMF_Grid) :: ogrid + type(ESMF_Grid) :: input_grid + character(len=ESMF_MAXSTR) :: key_str + type (StringGridMapIterator) :: iter + character(len=:), pointer :: key + type (ESMF_Config) :: config_grid + + integer :: i, numVars + character(len=ESMF_MAXSTR), allocatable :: names(:) + type(ESMF_Field) :: field + + if ( .NOT. ESMF_AlarmIsRinging(this%alarm) ) then + write(6,*) 'ck: regen, not in alarming' + rc=0 + return + endif + + + !__ s1. destroy ogrid + regen ogrid + + key_str=trim(key_grid_label) + pgrid => output_grids%at(trim(key_grid_label)) + call grid_manager%destroy(pgrid,_RC) + + call ESMF_ClockGet (this%clock, CurrTime=currTime, _RC ) + iter = output_grids%begin() + do while (iter /= output_grids%end()) + key => iter%key() + if (trim(key)==trim(key_str)) then + ogrid = this%create_grid (key_str, currTime, _RC) + call output_grids%set(key, ogrid) + this%ogrid = ogrid + endif + call iter%next() + enddo + + + !__ s2. destroy RH + + call sp%regrid_handle%destroy(_RC) + + + !__ s3. destroy acc_bundle / output_bundle + + call ESMF_FieldBundleGet(sp%acc_bundle,fieldCount=numVars,_RC) + allocate(names(numVars),stat=status) + call ESMF_FieldBundleGet(sp%acc_bundle,fieldNameList=names,_RC) + do i=1,numVars + call ESMF_FieldBundleGet(sp%acc_bundle,trim(names(i)),field=field,_RC) + call ESMF_FieldDestroy(field,noGarbage=.true., _RC) + enddo + call ESMF_FieldBundleDestroy(sp%acc_bundle,noGarbage=.true.,_RC) + + call ESMF_FieldBundleGet(sp%output_bundle,fieldCount=numVars,_RC) + allocate(names(numVars),stat=status) + call ESMF_FieldBundleGet(sp%output_bundle,fieldNameList=names,_RC) + do i=1,numVars + call ESMF_FieldBundleGet(sp%output_bundle,trim(names(i)),field=field,_RC) + call ESMF_FieldDestroy(field,noGarbage=.true., _RC) + enddo + call ESMF_FieldBundleDestroy(sp%output_bundle,noGarbage=.true.,_RC) + + _RETURN(ESMF_SUCCESS) + + end subroutine destroy_rh_regen_ogrid + + + subroutine fill_time_in_bundle (this, xname, bundle, rc) + implicit none + class(samplerHQ) :: this + character(len=*), intent(in) :: xname + type(ESMF_FieldBundle), intent(inout) :: bundle + integer, optional, intent(out) :: rc + integer :: status + + class(AbstractGridFactory), pointer :: factory + type(ESMF_Field) :: field + real(kind=ESMF_KIND_R4), pointer :: ptr2d(:,:) + + ! __ get field xname='time' + call ESMF_FieldBundleGet (bundle, xname, field=field, _RC) + call ESMF_FieldGet (field, farrayptr=ptr2d, _RC) + + ! __ obs_time from swath factory + factory => grid_manager%get_factory(this%ogrid,_RC) + call factory%get_obs_time (this%ogrid, ptr2d, _RC) + + _RETURN(ESMF_SUCCESS) + + end subroutine fill_time_in_bundle + + + function new_sampler(metadata,input_bundle,output_bundle,write_collection_id,read_collection_id, & + metadata_collection_id,regrid_method,fraction,items,rc) result(GriddedIO) + type(sampler) :: GriddedIO + type(Filemetadata), intent(in), optional :: metadata + type(ESMF_FieldBundle), intent(in), optional :: input_bundle + type(ESMF_FieldBundle), intent(in), optional :: output_bundle + integer, intent(in), optional :: write_collection_id + integer, intent(in), optional :: read_collection_id + integer, intent(in), optional :: metadata_collection_id + integer, intent(in), optional :: regrid_method + integer, intent(in), optional :: fraction + type(GriddedIOitemVector), intent(in), optional :: items + integer, intent(out), optional :: rc + + if (present(metadata)) GriddedIO%metadata=metadata + if (present(input_bundle)) GriddedIO%input_bundle=input_bundle + if (present(output_bundle)) GriddedIO%output_bundle=output_bundle + if (present(regrid_method)) GriddedIO%regrid_method=regrid_method + if (present(write_collection_id)) GriddedIO%write_collection_id=write_collection_id + if (present(read_collection_id)) GriddedIO%read_collection_id=read_collection_id + if (present(metadata_collection_id)) GriddedIO%metadata_collection_id=metadata_collection_id + if (present(items)) GriddedIO%items=items + if (present(fraction)) GriddedIO%fraction=fraction + _RETURN(ESMF_SUCCESS) + end function new_sampler + + +!! subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attributes,rc) +!! class (sampler), intent(inout) :: this +!! type(GriddedIOitemVector), target, intent(inout) :: items +!! type(ESMF_FieldBundle), intent(inout) :: bundle +!! type(TimeData), optional, intent(inout) :: timeInfo +!! type(VerticalData), intent(inout), optional :: vdata +!! type (ESMF_Grid), intent(inout), pointer, optional :: ogrid +!! type(StringStringMap), target, intent(in), optional :: global_attributes +!! integer, intent(out), optional :: rc +!! +!! type(ESMF_Grid) :: input_grid +!! class (AbstractGridFactory), pointer :: factory +!! +!! type(ESMF_Field) :: new_field +!! type(GriddedIOitemVectorIterator) :: iter +!! type(GriddedIOitem), pointer :: item +!! type(stringVector) :: order +!! integer :: metadataVarsSize +!! type(StringStringMapIterator) :: s_iter +!! character(len=:), pointer :: attr_name, attr_val +!! integer :: status +!! +!! _FAIL('ygyu check: CreateFileMetaData this%regrid_handle => new_regridder_manager%make_regridder in ') +!! +!! this%items = items +!! this%input_bundle = bundle +!! this%output_bundle = ESMF_FieldBundleCreate(rc=status) +!! _VERIFY(status) +!! if(present(timeInfo)) this%timeInfo = timeInfo +!! call ESMF_FieldBundleGet(this%input_bundle,grid=input_grid,rc=status) +!! _VERIFY(status) +!! if (present(ogrid)) then +!! this%output_grid=ogrid +!! else +!! call ESMF_FieldBundleGet(this%input_bundle,grid=this%output_grid,rc=status) +!! _VERIFY(status) +!! end if +!! this%regrid_handle => new_regridder_manager%make_regridder(input_grid,this%output_grid,this%regrid_method,rc=status) +!! _VERIFY(status) +!! +!! ! We get the regrid_method here because in the case of Identity, we set it to +!! ! REGRID_METHOD_IDENTITY in the regridder constructor if identity. Now we need +!! ! to change the regrid_method in the GriddedIO object to be the same as the +!! ! the regridder object. +!! this%regrid_method = this%regrid_handle%get_regrid_method() +!! +!! call ESMF_FieldBundleSet(this%output_bundle,grid=this%output_grid,rc=status) +!! _VERIFY(status) +!! factory => get_factory(this%output_grid,rc=status) +!! _VERIFY(status) +!! call factory%append_metadata(this%metadata) +!! +!! if (present(vdata)) then +!! this%vdata=vdata +!! else +!! this%vdata=VerticalData(rc=status) +!! _VERIFY(status) +!! end if +!! call this%vdata%append_vertical_metadata(this%metadata,this%input_bundle,rc=status) +!! _VERIFY(status) +!! this%doVertRegrid = (this%vdata%regrid_type /= VERTICAL_METHOD_NONE) +!! if (this%vdata%regrid_type == VERTICAL_METHOD_ETA2LEV) call this%vdata%get_interpolating_variable(this%input_bundle,rc=status) +!! _VERIFY(status) +!! +!! if(present(timeInfo)) call this%timeInfo%add_time_to_metadata(this%metadata,_RC) +!! +!! iter = this%items%begin() +!! if (.not.allocated(this%chunking)) then +!! call this%set_default_chunking(rc=status) +!! _VERIFY(status) +!! else +!! call this%check_chunking(this%vdata%lm,_RC) +!! end if +!! +!! order = this%metadata%get_order(rc=status) +!! _VERIFY(status) +!! metadataVarsSize = order%size() +!! +!! do while (iter /= this%items%end()) +!! item => iter%get() +!! if (item%itemType == ItemTypeScalar) then +!! call this%CreateVariable(item%xname,rc=status) +!! _VERIFY(status) +!! else if (item%itemType == ItemTypeVector) then +!! call this%CreateVariable(item%xname,rc=status) +!! _VERIFY(status) +!! call this%CreateVariable(item%yname,rc=status) +!! _VERIFY(status) +!! end if +!! call iter%next() +!! enddo +!! +!! if (this%itemOrderAlphabetical) then +!! call this%alphabatize_variables(metadataVarsSize,rc=status) +!! _VERIFY(status) +!! end if +!! +!! if (present(global_attributes)) then +!! s_iter = global_attributes%begin() +!! do while(s_iter /= global_attributes%end()) +!! attr_name => s_iter%key() +!! attr_val => s_iter%value() +!! call this%metadata%add_attribute(attr_name,attr_val,_RC) +!! call s_iter%next() +!! enddo +!! end if +!! +!! ! __ add acc_bundle and output_bundle +!! ! +!! this%acc_bundle = ESMF_FieldBundleCreate(_RC) +!! call ESMF_FieldBundleSet(this%acc_bundle,grid=this%output_grid,_RC) +!! iter = this%items%begin() +!! do while (iter /= this%items%end()) +!! item => iter%get() +!! call this%addVariable_to_acc_bundle(item%xname,_RC) +!! if (item%itemType == ItemTypeVector) then +!! call this%addVariable_to_acc_bundle(item%yname,_RC) +!! end if +!! call iter%next() +!! enddo +!! +!! new_field = ESMF_FieldCreate(this%output_grid ,name='time', & +!! typekind=ESMF_TYPEKIND_R4,_RC) +!! call MAPL_FieldBundleAdd( this%acc_bundle, new_field, _RC ) +!! +!! _RETURN(_SUCCESS) +!! end subroutine CreateFileMetaData + + + subroutine Create_bundle_RH(this,items,bundle,timeInfo,vdata,ogrid,global_attributes,rc) + class (sampler), intent(inout) :: this + type(GriddedIOitemVector), target, intent(inout) :: items + type(ESMF_FieldBundle), intent(inout) :: bundle + type(TimeData), optional, intent(inout) :: timeInfo + type(VerticalData), intent(inout), optional :: vdata + type (ESMF_Grid), intent(inout), pointer, optional :: ogrid + type(StringStringMap), target, intent(in), optional :: global_attributes + integer, intent(out), optional :: rc + + type(ESMF_Grid) :: input_grid + class (AbstractGridFactory), pointer :: factory + + type(ESMF_Field) :: new_field + type(GriddedIOitemVectorIterator) :: iter + type(GriddedIOitem), pointer :: item + type(stringVector) :: order + integer :: metadataVarsSize + type(StringStringMapIterator) :: s_iter + character(len=:), pointer :: attr_name, attr_val + integer :: status + + this%items = items + this%input_bundle = bundle + this%output_bundle = ESMF_FieldBundleCreate(rc=status) + _VERIFY(status) + if(present(timeInfo)) this%timeInfo = timeInfo + call ESMF_FieldBundleGet(this%input_bundle,grid=input_grid,rc=status) + _VERIFY(status) + if (present(ogrid)) then + this%output_grid=ogrid + else + call ESMF_FieldBundleGet(this%input_bundle,grid=this%output_grid,rc=status) + _VERIFY(status) + end if + this%regrid_handle => new_regridder_manager%make_regridder(input_grid,this%output_grid,this%regrid_method,rc=status) + _VERIFY(status) + + ! We get the regrid_method here because in the case of Identity, we set it to + ! REGRID_METHOD_IDENTITY in the regridder constructor if identity. Now we need + ! to change the regrid_method in the GriddedIO object to be the same as the + ! the regridder object. + this%regrid_method = this%regrid_handle%get_regrid_method() + + call ESMF_FieldBundleSet(this%output_bundle,grid=this%output_grid,rc=status) + _VERIFY(status) + factory => get_factory(this%output_grid,rc=status) + _VERIFY(status) + + ! __ please note, metadata in this section is not used in put_var to netCDF + ! the design used mGriddedIO%metadata in MAPL_HistoryGridComp.F90 + ! + if (allocated(this%metadata)) then + deallocate (this%metadata) + end if + allocate(this%metadata) + call factory%append_metadata(this%metadata) + if (present(vdata)) then + this%vdata=vdata + else + this%vdata=VerticalData(rc=status) + _VERIFY(status) + end if + + call this%vdata%append_vertical_metadata(this%metadata,this%input_bundle,rc=status) + _VERIFY(status) + this%doVertRegrid = (this%vdata%regrid_type /= VERTICAL_METHOD_NONE) + if (this%vdata%regrid_type == VERTICAL_METHOD_ETA2LEV) call this%vdata%get_interpolating_variable(this%input_bundle,rc=status) + _VERIFY(status) + + iter = this%items%begin() + do while (iter /= this%items%end()) + item => iter%get() + if (item%itemType == ItemTypeScalar) then + print*, 'item%xname' + print*, item%xname + call this%CreateVariable(item%xname,rc=status) + _VERIFY(status) + else if (item%itemType == ItemTypeVector) then + call this%CreateVariable(item%xname,rc=status) + _VERIFY(status) + call this%CreateVariable(item%yname,rc=status) + _VERIFY(status) + end if + call iter%next() + enddo + + + ! __ add acc_bundle and output_bundle + ! + this%acc_bundle = ESMF_FieldBundleCreate(_RC) + call ESMF_FieldBundleSet(this%acc_bundle,grid=this%output_grid,_RC) + iter = this%items%begin() + do while (iter /= this%items%end()) + item => iter%get() + call this%addVariable_to_acc_bundle(item%xname,_RC) + if (item%itemType == ItemTypeVector) then + call this%addVariable_to_acc_bundle(item%yname,_RC) + end if + call iter%next() + enddo + + + ! __ add time to acc_bundle + ! + new_field = ESMF_FieldCreate(this%output_grid ,name='time', & + typekind=ESMF_TYPEKIND_R4,_RC) + call MAPL_FieldBundleAdd( this%acc_bundle, new_field, _RC ) + + + _RETURN(_SUCCESS) + end subroutine Create_Bundle_RH + + + subroutine set_param(this,deflation,quantize_algorithm,quantize_level,chunking,nbits_to_keep,regrid_method,itemOrder,write_collection_id,rc) + class (sampler), intent(inout) :: this + integer, optional, intent(in) :: deflation + integer, optional, intent(in) :: quantize_algorithm + integer, optional, intent(in) :: quantize_level + integer, optional, intent(in) :: chunking(:) + integer, optional, intent(in) :: nbits_to_keep + integer, optional, intent(in) :: regrid_method + logical, optional, intent(in) :: itemOrder + integer, optional, intent(in) :: write_collection_id + integer, optional, intent(out) :: rc + + integer :: status + + if (present(regrid_method)) this%regrid_method=regrid_method + if (present(nbits_to_keep)) this%nbits_to_keep=nbits_to_keep + if (present(deflation)) this%deflateLevel = deflation + if (present(quantize_algorithm)) this%quantizeAlgorithm = quantize_algorithm + if (present(quantize_level)) this%quantizeLevel = quantize_level + if (present(chunking)) then + allocate(this%chunking,source=chunking,stat=status) + _VERIFY(status) + end if + if (present(itemOrder)) this%itemOrderAlphabetical = itemOrder + if (present(write_collection_id)) this%write_collection_id=write_collection_id + _RETURN(ESMF_SUCCESS) + + end subroutine set_param + + subroutine set_default_chunking(this,rc) + class (sampler), intent(inout) :: this + integer, optional, intent(out) :: rc + + integer :: global_dim(3) + integer :: status + + call MAPL_GridGet(this%output_grid,globalCellCountPerDim=global_dim,rc=status) + _VERIFY(status) + if (global_dim(1)*6 == global_dim(2)) then + allocate(this%chunking(5)) + this%chunking(1) = global_dim(1) + this%chunking(2) = global_dim(1) + this%chunking(3) = 1 + this%chunking(4) = 1 + this%chunking(5) = 1 + else + allocate(this%chunking(4)) + this%chunking(1) = global_dim(1) + this%chunking(2) = global_dim(2) + this%chunking(3) = 1 + this%chunking(4) = 1 + endif + _RETURN(ESMF_SUCCESS) + + end subroutine set_default_chunking + + subroutine check_chunking(this,lev_size,rc) + class (sampler), intent(inout) :: this + integer, intent(in) :: lev_size + integer, optional, intent(out) :: rc + + integer :: global_dim(3) + integer :: status + character(len=5) :: c1,c2 + + call MAPL_GridGet(this%output_grid,globalCellCountPerDim=global_dim,rc=status) + _VERIFY(status) + if (global_dim(1)*6 == global_dim(2)) then + write(c2,'(I5)')global_dim(1) + write(c1,'(I5)')this%chunking(1) + _ASSERT(this%chunking(1) <= global_dim(1), "Chunk for Xdim "//c1//" must be less than or equal to "//c2) + write(c1,'(I5)')this%chunking(2) + _ASSERT(this%chunking(2) <= global_dim(1), "Chunk for Ydim "//c1//" must be less than or equal to "//c2) + _ASSERT(this%chunking(3) <= 6, "Chunksize for face dimension must be 6 or less") + if (lev_size > 0) then + write(c2,'(I5)')lev_size + write(c1,'(I5)')this%chunking(4) + _ASSERT(this%chunking(4) <= lev_size, "Chunk for level size "//c1//" must be less than or equal to "//c2) + end if + _ASSERT(this%chunking(5) == 1, "Time must have chunk size of 1") + else + write(c2,'(I5)')global_dim(1) + write(c1,'(I5)')this%chunking(1) + _ASSERT(this%chunking(1) <= global_dim(1), "Chunk for lon "//c1//" must be less than or equal to "//c2) + write(c2,'(I5)')global_dim(2) + write(c1,'(I5)')this%chunking(2) + _ASSERT(this%chunking(2) <= global_dim(2), "Chunk for lat "//c1//" must be less than or equal to "//c2) + if (lev_size > 0) then + write(c2,'(I5)')lev_size + write(c1,'(I5)')this%chunking(3) + _ASSERT(this%chunking(3) <= lev_size, "Chunk for level size "//c1//" must be less than or equal to "//c2) + end if + _ASSERT(this%chunking(4) == 1, "Time must have chunk size of 1") + endif + _RETURN(ESMF_SUCCESS) + + end subroutine check_chunking + + subroutine CreateVariable(this,itemName,rc) + class (sampler), intent(inout) :: this + character(len=*), intent(in) :: itemName + integer, optional, intent(out) :: rc + + integer :: status + + type(ESMF_Field) :: field,newField + class (AbstractGridFactory), pointer :: factory + integer :: fieldRank + logical :: isPresent + character(len=ESMF_MAXSTR) :: varName,longName,units + character(len=:), allocatable :: grid_dims + character(len=:), allocatable :: vdims + type(Variable) :: v + + call ESMF_FieldBundleGet(this%input_bundle,itemName,field=field,rc=status) + _VERIFY(status) + factory => get_factory(this%output_grid,rc=status) + _VERIFY(status) + + + call ESMF_FieldGet(field,rank=fieldRank,rc=status) + _VERIFY(status) + call ESMF_FieldGet(field,name=varName,rc=status) + _VERIFY(status) + call ESMF_AttributeGet(field,name="LONG_NAME",isPresent=isPresent,rc=status) + _VERIFY(status) + if ( isPresent ) then + call ESMF_AttributeGet (FIELD, NAME="LONG_NAME",VALUE=LongName, RC=STATUS) + _VERIFY(STATUS) + else + LongName = varName + endif + call ESMF_AttributeGet(field,name="UNITS",isPresent=isPresent,rc=status) + _VERIFY(status) + if ( isPresent ) then + call ESMF_AttributeGet (FIELD, NAME="UNITS",VALUE=units, RC=STATUS) + _VERIFY(STATUS) + else + units = 'unknown' + endif + + + ! finally make a new field if neccessary + if (this%doVertRegrid .and. (fieldRank ==3) ) then + newField = MAPL_FieldCreate(field,this%output_grid,lm=this%vData%lm,rc=status) + _VERIFY(status) + call MAPL_FieldBundleAdd(this%output_bundle,newField,rc=status) + _VERIFY(status) + else + newField = MAPL_FieldCreate(field,this%output_grid,rc=status) + _VERIFY(status) + call MAPL_FieldBundleAdd(this%output_bundle,newField,rc=status) + _VERIFY(status) + end if + _RETURN(_SUCCESS) + + end subroutine CreateVariable + + + subroutine RegridScalar(this,itemName,rc) + class (sampler), intent(inout) :: this + character(len=*), intent(in) :: itemName + integer, optional, intent(out) :: rc + + integer :: status + + type(ESMF_Field) :: field,outField + integer :: fieldRank + real, pointer :: ptr3d(:,:,:),outptr3d(:,:,:) + real, pointer :: ptr2d(:,:), outptr2d(:,:) + real, allocatable, target :: ptr3d_inter(:,:,:) + type(ESMF_Grid) :: gridIn,gridOut + logical :: hasDE_in, hasDE_out + logical :: first_entry + + call ESMF_FieldBundleGet(this%output_bundle,itemName,field=outField,rc=status) + _VERIFY(status) + call ESMF_FieldBundleGet(this%input_bundle,grid=gridIn,rc=status) + _VERIFY(status) + call ESMF_FieldBundleGet(this%output_bundle,grid=gridOut,rc=status) + _VERIFY(status) + hasDE_in = MAPL_GridHasDE(gridIn,rc=status) + _VERIFY(status) + hasDE_out = MAPL_GridHasDE(gridOut,rc=status) + _VERIFY(status) + first_entry = .true. + if (this%doVertRegrid) then + call ESMF_FieldBundleGet(this%input_bundle,itemName,field=field,rc=status) + _VERIFY(status) + call ESMF_FieldGet(Field,rank=fieldRank,rc=status) + _VERIFY(status) + if (fieldRank==3) then + if (hasDE_in) then + call ESMF_FieldGet(field,farrayPtr=ptr3d,rc=status) + _VERIFY(status) + else + allocate(ptr3d(0,0,0)) + end if + allocate(ptr3d_inter(size(ptr3d,1),size(ptr3d,2),this%vdata%lm),stat=status) + _VERIFY(status) + if (this%vdata%regrid_type==VERTICAL_METHOD_SELECT) then + call this%vdata%regrid_select_level(ptr3d,ptr3d_inter,rc=status) + _VERIFY(status) + else if (this%vdata%regrid_type==VERTICAL_METHOD_ETA2LEV) then + call this%vdata%regrid_eta_to_pressure(ptr3d,ptr3d_inter,rc=status) + _VERIFY(status) + else if (this%vdata%regrid_type==VERTICAL_METHOD_FLIP) then + call this%vdata%flip_levels(ptr3d,ptr3d_inter,rc=status) + _VERIFY(status) + end if + ptr3d => ptr3d_inter + end if + else + if (first_entry) then + nullify(ptr3d) + first_entry = .false. + end if + end if + + call ESMF_FieldBundleGet(this%input_bundle,itemName,field=field,rc=status) + _VERIFY(status) + call ESMF_FieldGet(field,rank=fieldRank,rc=status) + _VERIFY(status) + if (fieldRank==2) then + if (hasDE_in) then + call MAPL_FieldGetPointer(field,ptr2d,rc=status) + _VERIFY(status) + else + allocate(ptr2d(0,0)) + end if + if (hasDE_out) then + call MAPL_FieldGetPointer(OutField,outptr2d,rc=status) + _VERIFY(status) + else + allocate(outptr2d(0,0)) + end if + if (gridIn==gridOut) then + outPtr2d=ptr2d + else + if (this%regrid_method==REGRID_METHOD_FRACTION) ptr2d=ptr2d-this%fraction + call this%regrid_handle%regrid(ptr2d,outPtr2d,rc=status) + _VERIFY(status) + end if + +!! print *, maxval(ptr2d) +!! print *, minval(ptr2d) +!! print *, maxval(outptr2d) +!! print *, minval(outptr2d) + + else if (fieldRank==3) then + if (.not.associated(ptr3d)) then + if (hasDE_in) then + call ESMF_FieldGet(field,farrayPtr=ptr3d,rc=status) + _VERIFY(status) + else + allocate(ptr3d(0,0,0)) + end if + end if + if (hasDE_out) then + call MAPL_FieldGetPointer(OutField,outptr3d,rc=status) + _VERIFY(status) + else + allocate(outptr3d(0,0,0)) + end if + if (gridIn==gridOut) then + outPtr3d=Ptr3d + else + if (this%regrid_method==REGRID_METHOD_FRACTION) ptr3d=ptr3d-this%fraction + call this%regrid_handle%regrid(ptr3d,outPtr3d,rc=status) + _VERIFY(status) + end if + else + _FAIL('rank not supported') + end if + + if (allocated(ptr3d_inter)) deallocate(ptr3d_inter) + _RETURN(_SUCCESS) + + end subroutine RegridScalar + + subroutine RegridVector(this,xName,yName,rc) + class (sampler), intent(inout) :: this + character(len=*), intent(in) :: xName + character(len=*), intent(in) :: yName + integer, optional, intent(out) :: rc + + integer :: status + + type(ESMF_Field) :: xfield,xoutField + type(ESMF_Field) :: yfield,youtField + integer :: fieldRank + real, pointer :: xptr3d(:,:,:),xoutptr3d(:,:,:) + real, pointer :: xptr2d(:,:), xoutptr2d(:,:) + real, allocatable, target :: xptr3d_inter(:,:,:) + real, pointer :: yptr3d(:,:,:),youtptr3d(:,:,:) + real, pointer :: yptr2d(:,:), youtptr2d(:,:) + real, allocatable, target :: yptr3d_inter(:,:,:) + type(ESMF_Grid) :: gridIn, gridOut + logical :: hasDE_in, hasDE_out + + call ESMF_FieldBundleGet(this%output_bundle,xName,field=xoutField,rc=status) + _VERIFY(status) + call ESMF_FieldBundleGet(this%output_bundle,yName,field=youtField,rc=status) + _VERIFY(status) + call ESMF_FieldBundleGet(this%input_bundle,grid=gridIn,rc=status) + _VERIFY(status) + call ESMF_FieldBundleGet(this%output_bundle,grid=gridOut,rc=status) + _VERIFY(status) + hasDE_in = MAPL_GridHasDE(gridIn,rc=status) + _VERIFY(status) + hasDE_out = MAPL_GridHasDE(gridOut,rc=status) + _VERIFY(status) + + if (this%doVertRegrid) then + call ESMF_FieldBundleGet(this%input_bundle,xName,field=xfield,rc=status) + _VERIFY(status) + call ESMF_FieldGet(xField,rank=fieldRank,rc=status) + _VERIFY(status) + if (fieldRank==3) then + if (hasDE_in) then + call ESMF_FieldGet(xfield,farrayPtr=xptr3d,rc=status) + _VERIFY(status) + else + allocate(xptr3d(0,0,0)) + end if + allocate(xptr3d_inter(size(xptr3d,1),size(xptr3d,2),this%vdata%lm),stat=status) + _VERIFY(status) + if (this%vdata%regrid_type==VERTICAL_METHOD_SELECT) then + call this%vdata%regrid_select_level(xptr3d,xptr3d_inter,rc=status) + _VERIFY(status) + else if (this%vdata%regrid_type==VERTICAL_METHOD_ETA2LEV) then + call this%vdata%regrid_eta_to_pressure(xptr3d,xptr3d_inter,rc=status) + _VERIFY(status) + else if (this%vdata%regrid_type==VERTICAL_METHOD_FLIP) then + call this%vdata%flip_levels(xptr3d,xptr3d_inter,rc=status) + _VERIFY(status) + end if + xptr3d => xptr3d_inter + end if + call ESMF_FieldBundleGet(this%input_bundle,yName,field=yfield,rc=status) + _VERIFY(status) + call ESMF_FieldGet(yField,rank=fieldRank,rc=status) + _VERIFY(status) + if (fieldRank==3) then + if (hasDE_in) then + call ESMF_FieldGet(yfield,farrayPtr=yptr3d,rc=status) + _VERIFY(status) + else + allocate(yptr3d(0,0,0)) + end if + allocate(yptr3d_inter(size(yptr3d,1),size(yptr3d,2),this%vdata%lm),stat=status) + _VERIFY(status) + if (this%vdata%regrid_type==VERTICAL_METHOD_SELECT) then + call this%vdata%regrid_select_level(yptr3d,yptr3d_inter,rc=status) + _VERIFY(status) + else if (this%vdata%regrid_type==VERTICAL_METHOD_ETA2LEV) then + call this%vdata%regrid_eta_to_pressure(yptr3d,yptr3d_inter,rc=status) + _VERIFY(status) + else if (this%vdata%regrid_type==VERTICAL_METHOD_FLIP) then + call this%vdata%flip_levels(yptr3d,yptr3d_inter,rc=status) + _VERIFY(status) + end if + yptr3d => yptr3d_inter + end if + else + if (associated(xptr3d)) nullify(xptr3d) + if (associated(yptr3d)) nullify(yptr3d) + end if + + call ESMF_FieldBundleGet(this%input_bundle,xname,field=xfield,rc=status) + _VERIFY(status) + call ESMF_FieldBundleGet(this%input_bundle,yname,field=yfield,rc=status) + _VERIFY(status) + call ESMF_FieldGet(xfield,rank=fieldRank,rc=status) + _VERIFY(status) + if (fieldRank==2) then + if (hasDE_in) then + call MAPL_FieldGetPointer(xfield,xptr2d,rc=status) + _VERIFY(status) + call MAPL_FieldGetPointer(yfield,yptr2d,rc=status) + _VERIFY(status) + else + allocate(xptr2d(0,0)) + allocate(yptr2d(0,0)) + end if + + if (hasDE_in) then + call MAPL_FieldGetPointer(xOutField,xoutptr2d,rc=status) + _VERIFY(status) + call MAPL_FieldGetPointer(yOutField,youtptr2d,rc=status) + _VERIFY(status) + else + allocate(xoutptr2d(0,0)) + allocate(youtptr2d(0,0)) + end if + + + if (gridIn==gridOut) then + xoutPtr2d=xptr2d + youtPtr2d=yptr2d + else + call this%regrid_handle%regrid(xptr2d,yptr2d,xoutPtr2d,youtPtr2d,rc=status) + _VERIFY(status) + end if + else if (fieldRank==3) then + if (.not.associated(xptr3d)) then + if (hasDE_in) then + call MAPL_FieldGetPointer(xfield,xptr3d,rc=status) + _VERIFY(status) + else + allocate(xptr3d(0,0,0)) + end if + end if + if (.not.associated(yptr3d)) then + if (hasDE_in) then + call MAPL_FieldGetPointer(yfield,yptr3d,rc=status) + _VERIFY(status) + else + allocate(yptr3d(0,0,0)) + end if + end if + + if (hasDE_out) then + call MAPL_FieldGetPointer(xOutField,xoutptr3d,rc=status) + _VERIFY(status) + call MAPL_FieldGetPointer(yOutField,youtptr3d,rc=status) + _VERIFY(status) + else + allocate(xoutptr3d(0,0,0)) + allocate(youtptr3d(0,0,0)) + end if + + if (gridIn==gridOut) then + xoutPtr3d=xptr3d + youtPtr3d=yptr3d + else + call this%regrid_handle%regrid(xptr3d,yptr3d,xoutPtr3d,youtPtr3d,rc=status) + _VERIFY(status) + end if + end if + + if (allocated(xptr3d_inter)) deallocate(xptr3d_inter) + if (allocated(yptr3d_inter)) deallocate(yptr3d_inter) + _RETURN(_SUCCESS) + + end subroutine RegridVector + + + subroutine alphabatize_variables(this,nfixedVars,rc) + class (sampler), intent(inout) :: this + integer, intent(in) :: nFixedVars + integer, optional, intent(out) :: rc + + type(StringVector) :: order + type(StringVector) :: newOrder + character(len=:), pointer :: v1 + character(len=ESMF_MAXSTR) :: c1,c2 + character(len=ESMF_MAXSTR), allocatable :: temp(:) + logical :: swapped + integer :: n,i + integer :: status + + order = this%metadata%get_order(rc=status) + _VERIFY(status) + n = Order%size() + allocate(temp(nFixedVars+1:n)) + do i=1,n + v1 => order%at(i) + if ( i > nFixedVars) temp(i)=trim(v1) + enddo + + swapped = .true. + do while(swapped) + swapped = .false. + do i=nFixedVars+1,n-1 + c1 = temp(i) + c2 = temp(i+1) + if (c1 > c2) then + temp(i+1)=c1 + temp(i)=c2 + swapped =.true. + end if + enddo + enddo + + do i=1,nFixedVars + v1 => Order%at(i) + call newOrder%push_back(v1) + enddo + do i=nFixedVars+1,n + call newOrder%push_back(trim(temp(i))) + enddo + call this%metadata%set_order(newOrder,rc=status) + _VERIFY(status) + deallocate(temp) + + _RETURN(_SUCCESS) + + end subroutine alphabatize_variables + + + subroutine addVariable_to_acc_bundle(this,itemName,rc) + class (sampler), intent(inout) :: this + character(len=*), intent(in) :: itemName + integer, optional, intent(out) :: rc + + type(ESMF_Field) :: field,newField + type(ESMF_Array) :: array1 + real(KIND=ESMF_KIND_R4), pointer :: pt2d(:,:) + class (AbstractGridFactory), pointer :: factory + integer :: fieldRank + logical :: isPresent + integer :: status + + call ESMF_FieldBundleGet(this%input_bundle,itemName,field=field,_RC) + call ESMF_FieldGet(field,rank=fieldRank,rc=status) + if (this%doVertRegrid .and. (fieldRank ==3) ) then + newField = MAPL_FieldCreate(field,this%output_grid,lm=this%vData%lm,_RC) + else + newField = MAPL_FieldCreate(field,this%output_grid,_RC) + end if + call MAPL_FieldBundleAdd(this%acc_bundle,newField,_RC) + + _RETURN(_SUCCESS) + + end subroutine addVariable_to_acc_bundle + + + subroutine addVariable_to_output_bundle(this,itemName,rc) + class (sampler), intent(inout) :: this + character(len=*), intent(in) :: itemName + integer, optional, intent(out) :: rc + + type(ESMF_Field) :: field,newField + class (AbstractGridFactory), pointer :: factory + integer :: fieldRank + logical :: isPresent + integer :: status + + call ESMF_FieldBundleGet(this%input_bundle,itemName,field=field,_RC) + call ESMF_FieldGet(field,rank=fieldRank,rc=status) + if (this%doVertRegrid .and. (fieldRank ==3) ) then + newField = MAPL_FieldCreate(field,this%output_grid,lm=this%vData%lm,_RC) + else + newField = MAPL_FieldCreate(field,this%output_grid,_RC) + end if + call MAPL_FieldBundleAdd(this%output_bundle,newField,_RC) + + _RETURN(_SUCCESS) + end subroutine addVariable_to_output_bundle + + + + !! -- based on subroutine bundlepost(this,filename,oClients,rc) + !! + subroutine interp_accumulate_fields (this,xy_subset,rc) + implicit none + class (sampler) :: this + integer, intent(in) :: xy_subset(2,2) + !!integer, intent(in) :: xy_mask(:,:) + integer, optional, intent(out) :: rc + + integer :: status + type(ESMF_Field) :: outField + type(ESMF_Field) :: new_outField + type(ESMF_Grid) :: grid + integer :: tindex + type(ArrayReference) :: ref + + type(GriddedIOitemVectorIterator) :: iter + type(GriddedIOitem), pointer :: item + logical :: have_time + + type(ESMF_Array) :: array1, array2 + integer :: is,ie,js,je + + integer :: rank, rank1, rank2 + real(KIND=ESMF_KIND_R4), pointer :: pt2d(:,:), pt2d_(:,:) + real(KIND=ESMF_KIND_R4), pointer :: pt3d(:,:,:), pt3d_(:,:,:) + + integer :: localDe, localDECount + integer, dimension(:), allocatable :: LB, UB, exclusiveCount + integer, dimension(:), allocatable :: compLB, compUB, compCount + integer :: dimCount + integer :: y1, y2 + integer :: j, jj + integer :: ii1, iin, jj1, jjn + integer, dimension(:), allocatable :: j1, j2 + + is=xy_subset(1,1); ie=xy_subset(2,1) + js=xy_subset(1,2); je=xy_subset(2,2) + + if (this%vdata%regrid_type==VERTICAL_METHOD_ETA2LEV) then + call this%vdata%setup_eta_to_pressure(regrid_handle=this%regrid_handle,output_grid=this%output_grid,rc=status) + _VERIFY(status) + end if + + call ESMF_FieldBundleGet(this%output_bundle, grid=grid, _RC) + call ESMF_GridGet(grid, localDECount=localDECount, dimCount=dimCount, _RC) + allocate ( LB(dimCount), UB(dimCount), exclusiveCount(dimCount) ) + allocate ( compLB(dimCount), compUB(dimCount), compCount(dimCount) ) + + allocate ( j1(0:localDEcount-1) ) ! start + allocate ( j2(0:localDEcount-1) ) ! end + + _ASSERT ( localDEcount == 1, 'failed, due to localDEcount > 1') + call MAPL_GridGetInterior(grid,ii1,iin,jj1,jjn) +!! write(6,*) 'MAPL_GridGetInterior, ii1,iin,jj1,jjn', ii1,iin,jj1,jjn +!! print*, 'js,je ', js, je + + LB(1)=ii1; LB(2)=jj1 + UB(1)=iin; UB(2)=jjn + + do localDe=0, localDEcount-1 + ! + ! is/ie, js/je, [LB, UB] + ! + ! + y1=jj1; y2=jjn + if (y1 < js) then + if (y2 < js) then + j1(localDe)=-1 + j2(localDe)=-1 + elseif (y2 < je) then + j1(localDe)=js + j2(localDe)=y2 + else + j1(localDe)=js + j2(localDe)=je + endif + elseif (y1 <= je) then + j1(localDe)=y1 + if (y2 < je) then + j2(localDe)=y2 + else + j2(localDe)=je + endif + else + j1(localDe)=-1 + j2(localDe)=-1 + endif + enddo + +!! write(6,*) 'ck bundlepost_acc' +!! write(6,*) 'j1(localDe)', j1(0:localDeCount-1) +!! write(6,*) 'j2(localDe)', j2(0:localDeCount-1) + + + iter = this%items%begin() + do while (iter /= this%items%end()) + item => iter%get() + if (item%itemType == ItemTypeScalar) then + +!! write(6,*) 'ck bundlepost_acc, item%xname ', item%xname + + call this%RegridScalar(item%xname,rc=status) + _VERIFY(status) + call ESMF_FieldBundleGet(this%output_bundle,item%xname,field=outField, _RC) + _VERIFY(status) + if (this%vdata%regrid_type==VERTICAL_METHOD_ETA2LEV) then + call this%vdata%correct_topo(outField,rc=status) + _VERIFY(status) + end if + + ! -- mask the time interval + ! store the time interval fields into new bundle + call ESMF_FieldGet(outField, Array=array1, _RC) + call ESMF_FieldBundleGet(this%acc_bundle,item%xname,field=new_outField,_RC) + call ESMF_FieldGet(new_outField, Array=array2, _RC) + call ESMF_ArrayGet(array1, rank=rank, _RC) + if (rank==2) then + call ESMF_ArrayGet(array1, farrayptr=pt2d, _RC) +!! write(6,*) 'shape(pt2d)', shape(pt2d) +!! write(6,*) 'in_pt2d', pt2d(10,10:50:2) + + call ESMF_ArrayGet(array2, farrayptr=pt2d_, _RC) + localDe=0 + if (j1(localDe)>0) then + do j= j1(localDe), j2(localDe) + jj= j-jj1+1 ! j_local +!! write(6,*) 'j, jj', j, jj + pt2d_(:,jj) = pt2d(:,jj) + enddo + endif +!! write(6,*) 'out_pt2d', pt2d_(10,10:50:2) + + elseif (rank==3) then + call ESMF_ArrayGet(array1, farrayptr=pt3d, _RC) + write(6,*) 'shape(pt3d)', shape(pt3d) + call ESMF_ArrayGet(array2, farrayptr=pt3d_, _RC) + do localDe=0, localDEcount-1 + if (j1(localDe)>0) then + do j= j1(localDe), j2(localDe) + jj= j-jj1+1 + pt3d_(:,jj,:) = pt3d(:,jj,:) + enddo + endif + enddo + else + _FAIL('failed interp_accumulate_fields') + endif + + else if (item%itemType == ItemTypeVector) then + _FAIL('ItemTypeVector not implemented') + end if + call iter%next() + enddo + + _RETURN(ESMF_SUCCESS) + + end subroutine interp_accumulate_fields + + + subroutine get_xy_mask(grid, xy_subset, xy_mask, rc) + implicit none + type(ESMF_Grid), intent(in) :: grid + integer, intent(in) :: xy_subset(2,2) + integer, intent(out) :: xy_mask(:,:) + integer, optional, intent(out) :: rc + + integer :: status + integer :: ii1, iin, jj1, jjn ! local box for localDE + integer :: is, ie, js, je ! global box for each time-interval + integer :: j1p, jnp ! local y-index for each time-interval + + integer :: dimCount + integer :: y1, y2 + integer :: j, jj + integer :: j1, j2 + + is=xy_subset(1,1); ie=xy_subset(2,1) + js=xy_subset(1,2); je=xy_subset(2,2) + + call MAPL_GridGetInterior(grid,ii1,iin,jj1,jjn) + write(6,*) 'MAPL_GridGetInterior, ii1,iin,jj1,jjn', ii1,iin,jj1,jjn + + y1=jj1; y2=jjn + if (y1 < js) then + if (y2 < js) then + j1=-1 + j2=-1 + elseif (y2 < je) then + j1=js + j2=y2 + else + j1=js + j2=je + endif + elseif (y1 <= je) then + j1=y1 + if (y2 < je) then + j2=y2 + else + j2=je + endif + else + j1=-1 + j2=-1 + endif + +!! write(6,*) 'get_xy_mask: j1,j2=', j1, j2 + xy_mask(:,:) = 0 + if (j1 > 0) then + do jj = j1, j2 + xy_mask(:, jj) = 1 + enddo + end if + + if(present(rc)) rc=0 + + end subroutine get_xy_mask + + +end module MAPL_EpochSwathMod diff --git a/gridcomps/History/MAPL_HistoryCollection.F90 b/gridcomps/History/MAPL_HistoryCollection.F90 index b5c0c3d35f19..98d434e78416 100644 --- a/gridcomps/History/MAPL_HistoryCollection.F90 +++ b/gridcomps/History/MAPL_HistoryCollection.F90 @@ -11,6 +11,7 @@ module MAPL_HistoryCollectionMod use HistoryTrajectoryMod use StationSamplerMod use gFTL_StringStringMap + use MAPL_EpochSwathMod implicit none private @@ -55,6 +56,7 @@ module MAPL_HistoryCollectionMod integer,pointer :: expSTATE (:) integer :: unit type(ESMF_FieldBundle) :: bundle + type(sampler) :: xsampler type(MAPL_CFIO) :: MCFIO type(MAPL_GriddedIO) :: mGriddedIO type(VerticalData) :: vdata diff --git a/gridcomps/History/MAPL_HistoryGridComp.F90 b/gridcomps/History/MAPL_HistoryGridComp.F90 index aba380203f23..f4d8e93df564 100644 --- a/gridcomps/History/MAPL_HistoryGridComp.F90 +++ b/gridcomps/History/MAPL_HistoryGridComp.F90 @@ -58,6 +58,8 @@ module MAPL_HistoryGridCompMod use MAPL_TimeUtilsMod, only: is_valid_time, is_valid_date use gFTL_StringStringMap !use ESMF_CFIOMOD + use MAPL_EpochSwathMod + use pflogger, only: Logger, logging use mpi @@ -136,13 +138,15 @@ module MAPL_HistoryGridCompMod type HISTORY_ExchangeListWrap type(HISTORY_ExchangeListType), pointer :: PTR end type HISTORY_ExchangeListWrap - + integer, parameter :: MAPL_G2G = 1 integer, parameter :: MAPL_T2G = 2 integer, parameter :: MAPL_T2G2G = 3 public HISTORY_ExchangeListWrap + type(samplerHQ), save :: Hsampler + contains !===================================================================== @@ -484,7 +488,6 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) ! Read User-Supplied History Lists from Config File ! ------------------------------------------------- call ESMF_GridCompGet( gc, config=config, _RC ) - call ESMF_ConfigGetAttribute ( config, value=INTSTATE%expsrc, & label ='EXPSRC:', default='', _RC ) call ESMF_ConfigGetAttribute ( config, value=INTSTATE%expid, & @@ -577,7 +580,6 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) end if call ESMF_ConfigNextLine ( config,tableEnd=tend,_RC ) enddo - if (nlist == 0) then _RETURN(ESMF_SUCCESS) end if @@ -614,13 +616,20 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) call MAPL_ConfigSetAttribute(config, value=nx,label=trim(key)//".NX:",_RC) call MAPL_ConfigSetAttribute(config, value=ny,label=trim(key)//".NY:",_RC) end if - output_grid = grid_manager%make_grid(config, prefix=key//'.', _RC) + + if (trim(grid_type)/='Swath') then + print*, 'ch: bf inside swath ..' + output_grid = grid_manager%make_grid(config, prefix=key//'.', _RC) + print*, 'ch: af inside swath ..' + else + Hsampler = samplerHQ(clock, config, key, _RC) + output_grid = Hsampler%create_grid(key, currTime, grid_type=grid_type, _RC) + end if call IntState%output_grids%set(key, output_grid) call iter%next() end do end block OUTPUT_GRIDS end if - if (intstate%version >= 2) then call ESMF_ConfigFindLabel(config, 'FIELD_SETS:', _RC) table_end = .false. @@ -645,7 +654,6 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) end if - allocate(IntState%Regrid(nlist), _STAT) allocate( Vvarn(nlist), _STAT) allocate(INTSTATE%STAMPOFFSET(nlist), _STAT) @@ -654,17 +662,14 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) ! ---------------------------------------------------------------------------- if( MAPL_AM_I_ROOT(vm) ) then - call ESMF_ConfigGetAttribute(config, value=HIST_CF, & label="HIST_CF:", default="HIST.rc", _RC ) unitr = GETFILE(HIST_CF, FORM='formatted', _RC) - ! for each collection do n = 1, nlist rewind(unitr) string = trim( list(n)%collection ) // '.' unitw = GETFILE(trim(string)//'rcx', FORM='formatted', _RC) - match = .false. contLine = .false. con3 = .false. @@ -698,7 +703,6 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) end if - call ESMF_VMbarrier(vm, _RC) ! Initialize History Lists @@ -1083,7 +1087,7 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) endif LEVS ! selected levels vvarn(n) = vvar - + cubeFormat = 1 list(n)%xyoffset = 0 ! Determine the file-side grid to use for the collection. @@ -1126,7 +1130,7 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) list(n)%output_grid_label='' end if end select - + ! Handle "useNewFormat" mode: this is hidden (i.e. not documented) feature ! Affects only "new" cubed-sphere native output ! Defaults to .true. @@ -1379,7 +1383,6 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) end if enddo enddo - ! Get Output Export States ! ------------------------ @@ -2364,6 +2367,18 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) else list(n)%vdata = VerticalData(positive=list(n)%positive,_RC) end if + if (trim(list(n)%output_grid_label)=='SwathGrid') then + call list(n)%xsampler%set_param(deflation=list(n)%deflate,_RC) + call list(n)%xsampler%set_param(quantize_algorithm=list(n)%quantize_algorithm,_RC) + call list(n)%xsampler%set_param(quantize_level=list(n)%quantize_level,_RC) + call list(n)%xsampler%set_param(chunking=list(n)%chunkSize,_RC) + call list(n)%xsampler%set_param(nbits_to_keep=list(n)%nbits_to_keep,_RC) + call list(n)%xsampler%set_param(regrid_method=list(n)%regrid_method,_RC) + call list(n)%xsampler%set_param(itemOrder=intState%fileOrderAlphabetical,_RC) + endif + ! + ! why I still need griddedio for sampler case? + ! call list(n)%mGriddedIO%set_param(deflation=list(n)%deflate,_RC) call list(n)%mGriddedIO%set_param(quantize_algorithm=list(n)%quantize_algorithm,_RC) call list(n)%mGriddedIO%set_param(quantize_level=list(n)%quantize_level,_RC) @@ -2371,10 +2386,11 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) call list(n)%mGriddedIO%set_param(nbits_to_keep=list(n)%nbits_to_keep,_RC) call list(n)%mGriddedIO%set_param(regrid_method=list(n)%regrid_method,_RC) call list(n)%mGriddedIO%set_param(itemOrder=intState%fileOrderAlphabetical,_RC) + if (list(n)%monthly) then - nextMonth = currTime - oneMonth - dur = nextMonth - currTime - call ESMF_TimeIntervalGet(dur, s=sec, _RC) + nextMonth = currTime - oneMonth + dur = nextMonth - currTime + call ESMF_TimeIntervalGet(dur, s=sec, _RC) list(n)%timeInfo = TimeData(clock,tm,sec,IntState%stampoffset(n),funits='days') else list(n)%timeInfo = TimeData(clock,tm,MAPL_nsecf(list(n)%frequency),IntState%stampoffset(n),integer_time=intstate%integer_time) @@ -2387,14 +2403,20 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) call list(n)%station_sampler%add_metadata_route_handle(list(n)%bundle,list(n)%timeInfo,vdata=list(n)%vdata,_RC) else global_attributes = list(n)%global_atts%define_collection_attributes(_RC) - if (trim(list(n)%output_grid_label)/='') then + if (trim(list(n)%output_grid_label)=='SwathGrid') then pgrid => IntState%output_grids%at(trim(list(n)%output_grid_label)) - call list(n)%mGriddedIO%CreateFileMetaData(list(n)%items,list(n)%bundle,list(n)%timeInfo,ogrid=pgrid,vdata=list(n)%vdata,global_attributes=global_attributes,_RC) + call list(n)%xsampler%Create_bundle_RH(list(n)%items,list(n)%bundle,ogrid=pgrid,vdata=list(n)%vdata,global_attributes=global_attributes,_RC) else - call list(n)%mGriddedIO%CreateFileMetaData(list(n)%items,list(n)%bundle,list(n)%timeInfo,vdata=list(n)%vdata,global_attributes=global_attributes,_RC) - end if - collection_id = o_Clients%add_hist_collection(list(n)%mGriddedIO%metadata, mode = create_mode) - call list(n)%mGriddedIO%set_param(write_collection_id=collection_id) + ! + if (trim(list(n)%output_grid_label)/='') then + pgrid => IntState%output_grids%at(trim(list(n)%output_grid_label)) + call list(n)%mGriddedIO%CreateFileMetaData(list(n)%items,list(n)%bundle,list(n)%timeInfo,ogrid=pgrid,vdata=list(n)%vdata,global_attributes=global_attributes,_RC) + else + call list(n)%mGriddedIO%CreateFileMetaData(list(n)%items,list(n)%bundle,list(n)%timeInfo,vdata=list(n)%vdata,global_attributes=global_attributes,_RC) + end if + collection_id = o_Clients%add_hist_collection(list(n)%mGriddedIO%metadata, mode = create_mode) + call list(n)%mGriddedIO%set_param(write_collection_id=collection_id) + endif end if end if call ESMF_ConfigDestroy(cfg, _RC) @@ -3217,7 +3239,15 @@ subroutine Run ( gc, import, export, clock, rc ) type(ESMF_Time) :: lastMonth type(ESMF_TimeInterval) :: dur, oneMonth integer :: sec - + type (StringGridMap) :: pt_output_grids + character(len=ESMF_MAXSTR) :: key_grid_label + type (ESMF_Grid), pointer :: pgrid + + integer :: collection_id + integer :: create_mode + type(StringStringMap) :: global_attributes + type(timeData) :: timeinfo_uninit + type(ESMF_Grid) :: new_grid ! variables for "backwards" mode logical :: fwd logical, allocatable :: Ignore(:) @@ -3225,12 +3255,13 @@ subroutine Run ( gc, import, export, clock, rc ) ! ErrLog vars integer :: status logical :: file_exists + type(GriddedIOitem) :: item + type(Logger), pointer :: lgr !============================================================================= ! Begin... - _UNUSED_DUMMY(import) _UNUSED_DUMMY(export) @@ -3334,8 +3365,10 @@ subroutine Run ( gc, import, export, clock, rc ) Writing(n) = .false. else if (list(n)%timeseries_output) then Writing(n) = ESMF_AlarmIsRinging ( list(n)%trajectory%alarm ) + else if (trim(list(n)%output_grid_label)=='SwathGrid') then + Writing(n) = ESMF_AlarmIsRinging ( Hsampler%alarm ) else - Writing(n) = ESMF_AlarmIsRinging ( list(n)%his_alarm ) + Writing(n) = ESMF_AlarmIsRinging ( list(n)%his_alarm ) endif ! if(Writing(n)) then @@ -3371,11 +3404,45 @@ subroutine Run ( gc, import, export, clock, rc ) if( NewSeg(n)) then call ESMF_AlarmRingerOff( list(n)%seg_alarm,_RC ) endif - + end do + if(any(Writing)) call WRITE_PARALLEL("") + + + ! swath only + epoch_swath_grid_case: do n=1,nlist + if (trim(list(n)%output_grid_label)=='SwathGrid') then + call Hsampler%regrid_accumulate(list(n)%xsampler,_RC) + + if( ESMF_AlarmIsRinging ( Hsampler%alarm ) ) then + create_mode = PFIO_NOCLOBBER ! defaut no overwrite + if (intState%allow_overwrite) create_mode = PFIO_CLOBBER + + ! add time to items + ! true metadata comes here from mGriddedIO%metadata + ! the mGriddedIO below only touches metadata, collection_id etc., it is safe. + ! + if (.NOT. list(n)%xsampler%have_initalized) then + list(n)%xsampler%have_initalized = .true. + global_attributes = list(n)%global_atts%define_collection_attributes(_RC) + endif + item%itemType = ItemTypeScalar + item%xname = 'time' + call list(n)%items%push_back(item) + call Hsampler%fill_time_in_bundle ('time', list(n)%xsampler%acc_bundle, _RC) + call list(n)%mGriddedIO%destroy(_RC) + call list(n)%mGriddedIO%CreateFileMetaData(list(n)%items,list(n)%xsampler%acc_bundle,timeinfo_uninit,vdata=list(n)%vdata,global_attributes=global_attributes,_RC) + call list(n)%items%pop_back() + + collection_id = o_Clients%add_hist_collection(list(n)%mGriddedIO%metadata, mode = create_mode) + call list(n)%mGriddedIO%set_param(write_collection_id=collection_id) + endif + end if + end do epoch_swath_grid_case + ! Write Id and time ! ----------------- @@ -3466,7 +3533,9 @@ subroutine Run ( gc, import, export, clock, rc ) inquire (file=trim(filename(n)),exist=file_exists) _ASSERT(.not.file_exists,trim(filename(n))//" being created for History output already exists") end if - call list(n)%mGriddedIO%modifyTime(oClients=o_Clients,_RC) + if (trim(list(n)%output_grid_label)/='SwathGrid') then + call list(n)%mGriddedIO%modifyTime(oClients=o_Clients,_RC) + endif list(n)%currentFile = filename(n) list(n)%unit = -1 else @@ -3485,6 +3554,7 @@ subroutine Run ( gc, import, export, clock, rc ) ! enddo OPENLOOP call MAPL_TimerOff(GENSTATE,"----IO Create") + call MAPL_TimerOn(GENSTATE,"----IO Write") call MAPL_TimerOn(GENSTATE,"-----IO Post") @@ -3537,11 +3607,13 @@ subroutine Run ( gc, import, export, clock, rc ) state_out = INTSTATE%GIM(n) end if + write(6,*) 'list(n)%unit=', list(n)%unit + + list(n)%currentFile = filename(n) + if (.not.list(n)%timeseries_output) then IOTYPE: if (list(n)%unit < 0) then ! CFIO - call list(n)%mGriddedIO%bundlepost(list(n)%currentFile,oClients=o_Clients,_RC) - else if( INTSTATE%LCTL(n) ) then @@ -3574,6 +3646,8 @@ subroutine Run ( gc, import, export, clock, rc ) enddo POSTLOOP + + write(6,*) 'test writing=', writing(:) if (any(writing)) then call o_Clients%done_collective_stage(_RC) call o_Clients%post_wait() @@ -3584,6 +3658,23 @@ subroutine Run ( gc, import, export, clock, rc ) call MAPL_TimerOn(GENSTATE,"----IO Write") call MAPL_TimerOn(GENSTATE,"-----IO Wait") + + ! destroy ogrid/RH/acc_bundle, regenerate them + ! swath only + epoch_swath_regen_grid: do n=1,nlist + if (trim(list(n)%output_grid_label)=='SwathGrid') then + if( ESMF_AlarmIsRinging ( Hsampler%alarm ) ) then + key_grid_label = list(n)%output_grid_label + call Hsampler%destroy_rh_regen_ogrid ( key_grid_label, IntState%output_grids, list(n)%xsampler, _RC ) + pgrid => IntState%output_grids%at(trim(list(n)%output_grid_label)) + call list(n)%xsampler%Create_bundle_RH(list(n)%items,list(n)%bundle,ogrid=pgrid,& + vdata=list(n)%vdata,global_attributes=global_attributes,_RC) + write(6,'(///)') + endif + end if + end do epoch_swath_regen_grid + + WAITLOOP: do n=1,nlist if( Writing(n) .and. list(n)%unit < 0) then @@ -3622,6 +3713,8 @@ subroutine Run ( gc, import, export, clock, rc ) enddo WRITELOOP + + call MAPL_TimerOff(GENSTATE,"-----IO Write") call MAPL_TimerOff(GENSTATE,"----IO Write") From c7590326b443ed5f4f057bfdda064b96f787be0d Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 27 Sep 2023 20:41:06 -0600 Subject: [PATCH 04/41] update --- base/MAPL_AbstractGridFactory.F90 | 10 +- base/MAPL_GridManager.F90 | 12 +- base/MAPL_SwathGridFactory.F90 | 4 +- gridcomps/History/MAPL_EpochSwathMod.F90 | 131 +-------------------- gridcomps/History/MAPL_HistoryGridComp.F90 | 49 ++++---- 5 files changed, 31 insertions(+), 175 deletions(-) diff --git a/base/MAPL_AbstractGridFactory.F90 b/base/MAPL_AbstractGridFactory.F90 index b9b912a3a0ad..fabe78cfa803 100644 --- a/base/MAPL_AbstractGridFactory.F90 +++ b/base/MAPL_AbstractGridFactory.F90 @@ -1046,9 +1046,8 @@ subroutine get_xy_subset(this, interval, xy_subset, rc) type(ESMF_Time), intent(in) :: interval(2) integer, intent(out) :: xy_subset(2,2) integer, optional, intent(out) :: rc - integer :: status - + _RETURN(_FAILURE) end subroutine get_xy_subset @@ -1057,9 +1056,8 @@ subroutine get_xy_mask(this, interval, xy_mask, rc) type(ESMF_Time), intent(in) :: interval(2) integer, allocatable, intent(out) :: xy_mask(:,:) integer, optional, intent(out) :: rc - integer :: status - + _RETURN(_FAILURE) end subroutine get_xy_mask @@ -1068,11 +1066,9 @@ end subroutine get_xy_mask subroutine destroy(this, rc) class(AbstractGridFactory), intent(inout) :: this integer, optional, intent(out) :: rc - integer :: status - call ESMF_GridDestroy(this%grid, noGarbage=.true., _RC) - + call ESMF_GridDestroy(this%grid, noGarbage=.true., _RC) _RETURN(_SUCCESS) end subroutine destroy diff --git a/base/MAPL_GridManager.F90 b/base/MAPL_GridManager.F90 index 72ea1abe2758..2d2aca045ad5 100644 --- a/base/MAPL_GridManager.F90 +++ b/base/MAPL_GridManager.F90 @@ -21,7 +21,7 @@ module MAPL_GridManager_private private public :: GridManager - public :: FACTORY_ID_ATTRIBUTE + public :: factory_id_attribute ! singleton type :: GridManager @@ -66,7 +66,7 @@ module MAPL_GridManager_private end type GridManager character(len=*), parameter :: MOD_NAME = 'MAPL_GridManager_private::' - character(len=*), parameter :: FACTORY_ID_ATTRIBUTE = 'MAPL_grid_factory_id' + character(len=*), parameter :: factory_id_attribute = 'MAPL_grid_factory_id' contains @@ -264,7 +264,7 @@ function make_grid_from_factory(this, factory, unusable, rc) result(grid) ! TODO: this should only be done if the grid is new, rather than cached, in which case ! the attribute is already set. - call ESMF_AttributeSet(grid, FACTORY_ID_ATTRIBUTE, factory_id, rc=status) + call ESMF_AttributeSet(grid, factory_id_attribute, factory_id, rc=status) _VERIFY(status) _RETURN(_SUCCESS) @@ -415,7 +415,7 @@ subroutine destroy_grid(this, grid, unusable, rc) class(AbstractGridFactory), pointer :: factory type(Integer64GridFactoryMapIterator) :: iter - call ESMF_AttributeGet(grid, FACTORY_ID_ATTRIBUTE, id, _RC) + call ESMF_AttributeGet(grid, factory_id_attribute, id, _RC) factory => this%factories%at(id) call factory%destroy(_RC) iter = this%factories%find(id) @@ -463,7 +463,7 @@ function get_factory(this, grid, unusable, rc) result(factory) _UNUSED_DUMMY(unusable) - call ESMF_AttributeGet(grid, FACTORY_ID_ATTRIBUTE, id, rc=status) + call ESMF_AttributeGet(grid, factory_id_attribute, id, rc=status) _VERIFY(status) factory => this%factories%at(id) @@ -633,7 +633,7 @@ function get_factory_id(grid, unusable, rc) result(id) _UNUSED_DUMMY(unusable) - call ESMF_AttributeGet(grid, FACTORY_ID_ATTRIBUTE, id, rc=status) + call ESMF_AttributeGet(grid, factory_id_attribute, id, rc=status) _VERIFY(status) _RETURN(_SUCCESS) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 5c3cd5e19db5..a687c2465b79 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -520,8 +520,6 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc this%cell_across_swath = nlon this%cell_along_swath = nlat - -!! stop -11 ! determine im_world from Epoch ! ----------------------------- @@ -536,7 +534,7 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc tunit='seconds since 1993-01-01 00:00:00' this%tunit = tunit call time_esmf_2_nc_int (time0, tunit, j0, _RC) - call hms_2_s (this%Epoch, sec, _RC) + sec = hms_2_s (this%Epoch) j1= j0 + sec jx0= j0 jx1= j1 diff --git a/gridcomps/History/MAPL_EpochSwathMod.F90 b/gridcomps/History/MAPL_EpochSwathMod.F90 index f1961b8c0285..be2ae4fcc3f1 100644 --- a/gridcomps/History/MAPL_EpochSwathMod.F90 +++ b/gridcomps/History/MAPL_EpochSwathMod.F90 @@ -136,7 +136,7 @@ function new_samplerHQ(clock, config, key, rc) result(hq) call ESMF_ClockGet ( clock, startTime=startTime, _RC ) call ESMF_ConfigGetAttribute(config, value=time_integer, label=trim(key)//'.Epoch:', default=0, _RC) _ASSERT(time_integer /= 0, 'Epoch value in config wrong') - call hms_2_s (time_integer, second, _RC) + second = hms_2_s (time_integer) call ESMF_TimeIntervalSet(frequency_epoch, s=second, _RC) hq%frequency_epoch = frequency_epoch hq%RingTime = currTime @@ -358,135 +358,6 @@ function new_sampler(metadata,input_bundle,output_bundle,write_collection_id,rea end function new_sampler -!! subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attributes,rc) -!! class (sampler), intent(inout) :: this -!! type(GriddedIOitemVector), target, intent(inout) :: items -!! type(ESMF_FieldBundle), intent(inout) :: bundle -!! type(TimeData), optional, intent(inout) :: timeInfo -!! type(VerticalData), intent(inout), optional :: vdata -!! type (ESMF_Grid), intent(inout), pointer, optional :: ogrid -!! type(StringStringMap), target, intent(in), optional :: global_attributes -!! integer, intent(out), optional :: rc -!! -!! type(ESMF_Grid) :: input_grid -!! class (AbstractGridFactory), pointer :: factory -!! -!! type(ESMF_Field) :: new_field -!! type(GriddedIOitemVectorIterator) :: iter -!! type(GriddedIOitem), pointer :: item -!! type(stringVector) :: order -!! integer :: metadataVarsSize -!! type(StringStringMapIterator) :: s_iter -!! character(len=:), pointer :: attr_name, attr_val -!! integer :: status -!! -!! _FAIL('ygyu check: CreateFileMetaData this%regrid_handle => new_regridder_manager%make_regridder in ') -!! -!! this%items = items -!! this%input_bundle = bundle -!! this%output_bundle = ESMF_FieldBundleCreate(rc=status) -!! _VERIFY(status) -!! if(present(timeInfo)) this%timeInfo = timeInfo -!! call ESMF_FieldBundleGet(this%input_bundle,grid=input_grid,rc=status) -!! _VERIFY(status) -!! if (present(ogrid)) then -!! this%output_grid=ogrid -!! else -!! call ESMF_FieldBundleGet(this%input_bundle,grid=this%output_grid,rc=status) -!! _VERIFY(status) -!! end if -!! this%regrid_handle => new_regridder_manager%make_regridder(input_grid,this%output_grid,this%regrid_method,rc=status) -!! _VERIFY(status) -!! -!! ! We get the regrid_method here because in the case of Identity, we set it to -!! ! REGRID_METHOD_IDENTITY in the regridder constructor if identity. Now we need -!! ! to change the regrid_method in the GriddedIO object to be the same as the -!! ! the regridder object. -!! this%regrid_method = this%regrid_handle%get_regrid_method() -!! -!! call ESMF_FieldBundleSet(this%output_bundle,grid=this%output_grid,rc=status) -!! _VERIFY(status) -!! factory => get_factory(this%output_grid,rc=status) -!! _VERIFY(status) -!! call factory%append_metadata(this%metadata) -!! -!! if (present(vdata)) then -!! this%vdata=vdata -!! else -!! this%vdata=VerticalData(rc=status) -!! _VERIFY(status) -!! end if -!! call this%vdata%append_vertical_metadata(this%metadata,this%input_bundle,rc=status) -!! _VERIFY(status) -!! this%doVertRegrid = (this%vdata%regrid_type /= VERTICAL_METHOD_NONE) -!! if (this%vdata%regrid_type == VERTICAL_METHOD_ETA2LEV) call this%vdata%get_interpolating_variable(this%input_bundle,rc=status) -!! _VERIFY(status) -!! -!! if(present(timeInfo)) call this%timeInfo%add_time_to_metadata(this%metadata,_RC) -!! -!! iter = this%items%begin() -!! if (.not.allocated(this%chunking)) then -!! call this%set_default_chunking(rc=status) -!! _VERIFY(status) -!! else -!! call this%check_chunking(this%vdata%lm,_RC) -!! end if -!! -!! order = this%metadata%get_order(rc=status) -!! _VERIFY(status) -!! metadataVarsSize = order%size() -!! -!! do while (iter /= this%items%end()) -!! item => iter%get() -!! if (item%itemType == ItemTypeScalar) then -!! call this%CreateVariable(item%xname,rc=status) -!! _VERIFY(status) -!! else if (item%itemType == ItemTypeVector) then -!! call this%CreateVariable(item%xname,rc=status) -!! _VERIFY(status) -!! call this%CreateVariable(item%yname,rc=status) -!! _VERIFY(status) -!! end if -!! call iter%next() -!! enddo -!! -!! if (this%itemOrderAlphabetical) then -!! call this%alphabatize_variables(metadataVarsSize,rc=status) -!! _VERIFY(status) -!! end if -!! -!! if (present(global_attributes)) then -!! s_iter = global_attributes%begin() -!! do while(s_iter /= global_attributes%end()) -!! attr_name => s_iter%key() -!! attr_val => s_iter%value() -!! call this%metadata%add_attribute(attr_name,attr_val,_RC) -!! call s_iter%next() -!! enddo -!! end if -!! -!! ! __ add acc_bundle and output_bundle -!! ! -!! this%acc_bundle = ESMF_FieldBundleCreate(_RC) -!! call ESMF_FieldBundleSet(this%acc_bundle,grid=this%output_grid,_RC) -!! iter = this%items%begin() -!! do while (iter /= this%items%end()) -!! item => iter%get() -!! call this%addVariable_to_acc_bundle(item%xname,_RC) -!! if (item%itemType == ItemTypeVector) then -!! call this%addVariable_to_acc_bundle(item%yname,_RC) -!! end if -!! call iter%next() -!! enddo -!! -!! new_field = ESMF_FieldCreate(this%output_grid ,name='time', & -!! typekind=ESMF_TYPEKIND_R4,_RC) -!! call MAPL_FieldBundleAdd( this%acc_bundle, new_field, _RC ) -!! -!! _RETURN(_SUCCESS) -!! end subroutine CreateFileMetaData - - subroutine Create_bundle_RH(this,items,bundle,timeInfo,vdata,ogrid,global_attributes,rc) class (sampler), intent(inout) :: this type(GriddedIOitemVector), target, intent(inout) :: items diff --git a/gridcomps/History/MAPL_HistoryGridComp.F90 b/gridcomps/History/MAPL_HistoryGridComp.F90 index f4d8e93df564..61e42895ce6a 100644 --- a/gridcomps/History/MAPL_HistoryGridComp.F90 +++ b/gridcomps/History/MAPL_HistoryGridComp.F90 @@ -138,7 +138,7 @@ module MAPL_HistoryGridCompMod type HISTORY_ExchangeListWrap type(HISTORY_ExchangeListType), pointer :: PTR end type HISTORY_ExchangeListWrap - + integer, parameter :: MAPL_G2G = 1 integer, parameter :: MAPL_T2G = 2 integer, parameter :: MAPL_T2G2G = 3 @@ -616,11 +616,9 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) call MAPL_ConfigSetAttribute(config, value=nx,label=trim(key)//".NX:",_RC) call MAPL_ConfigSetAttribute(config, value=ny,label=trim(key)//".NY:",_RC) end if - + if (trim(grid_type)/='Swath') then - print*, 'ch: bf inside swath ..' output_grid = grid_manager%make_grid(config, prefix=key//'.', _RC) - print*, 'ch: af inside swath ..' else Hsampler = samplerHQ(clock, config, key, _RC) output_grid = Hsampler%create_grid(key, currTime, grid_type=grid_type, _RC) @@ -673,7 +671,7 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) match = .false. contLine = .false. con3 = .false. - + do while (.true.) read(unitr, '(A)', end=1234) line j = index( adjustl(line), trim(adjustl(string)) ) @@ -682,7 +680,7 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) j = index(line, trim(string)//'fields:') contLine = (j > 0) k = index(line, trim(string)//'obs_files:') - con3 = (k > 0) + con3 = (k > 0) end if if (match .or. contLine .or. con3) then write(unitw,'(A)') trim(line) @@ -691,7 +689,7 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) if (adjustl(line) == '::') contLine = .false. end if if (con3) then - if (adjustl(line) == '::') con3 = .false. + if (adjustl(line) == '::') con3 = .false. endif end do @@ -887,7 +885,7 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) call ESMF_ConfigGetDim(cfg, nline, ncol, label=trim(string)//'obs_files:', rc=rc) ! here donot check rc on purpose if (rc==0) then if (nline > 0) then - list(n)%timeseries_output = .true. + list(n)%timeseries_output = .true. endif endif call ESMF_ConfigGetAttribute(cfg, value=list(n)%recycle_track, default=.false., & @@ -1087,7 +1085,7 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) endif LEVS ! selected levels vvarn(n) = vvar - + cubeFormat = 1 list(n)%xyoffset = 0 ! Determine the file-side grid to use for the collection. @@ -1130,7 +1128,7 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) list(n)%output_grid_label='' end if end select - + ! Handle "useNewFormat" mode: this is hidden (i.e. not documented) feature ! Affects only "new" cubed-sphere native output ! Defaults to .true. @@ -2376,9 +2374,7 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) call list(n)%xsampler%set_param(regrid_method=list(n)%regrid_method,_RC) call list(n)%xsampler%set_param(itemOrder=intState%fileOrderAlphabetical,_RC) endif - ! - ! why I still need griddedio for sampler case? - ! + call list(n)%mGriddedIO%set_param(deflation=list(n)%deflate,_RC) call list(n)%mGriddedIO%set_param(quantize_algorithm=list(n)%quantize_algorithm,_RC) call list(n)%mGriddedIO%set_param(quantize_level=list(n)%quantize_level,_RC) @@ -2407,7 +2403,6 @@ subroutine Initialize ( gc, import, dumexport, clock, rc ) pgrid => IntState%output_grids%at(trim(list(n)%output_grid_label)) call list(n)%xsampler%Create_bundle_RH(list(n)%items,list(n)%bundle,ogrid=pgrid,vdata=list(n)%vdata,global_attributes=global_attributes,_RC) else - ! if (trim(list(n)%output_grid_label)/='') then pgrid => IntState%output_grids%at(trim(list(n)%output_grid_label)) call list(n)%mGriddedIO%CreateFileMetaData(list(n)%items,list(n)%bundle,list(n)%timeInfo,ogrid=pgrid,vdata=list(n)%vdata,global_attributes=global_attributes,_RC) @@ -3242,7 +3237,7 @@ subroutine Run ( gc, import, export, clock, rc ) type (StringGridMap) :: pt_output_grids character(len=ESMF_MAXSTR) :: key_grid_label type (ESMF_Grid), pointer :: pgrid - + integer :: collection_id integer :: create_mode type(StringStringMap) :: global_attributes @@ -3368,7 +3363,7 @@ subroutine Run ( gc, import, export, clock, rc ) else if (trim(list(n)%output_grid_label)=='SwathGrid') then Writing(n) = ESMF_AlarmIsRinging ( Hsampler%alarm ) else - Writing(n) = ESMF_AlarmIsRinging ( list(n)%his_alarm ) + Writing(n) = ESMF_AlarmIsRinging ( list(n)%his_alarm ) endif ! if(Writing(n)) then @@ -3404,13 +3399,13 @@ subroutine Run ( gc, import, export, clock, rc ) if( NewSeg(n)) then call ESMF_AlarmRingerOff( list(n)%seg_alarm,_RC ) endif - + end do if(any(Writing)) call WRITE_PARALLEL("") - - + + ! swath only epoch_swath_grid_case: do n=1,nlist if (trim(list(n)%output_grid_label)=='SwathGrid') then @@ -3435,14 +3430,13 @@ subroutine Run ( gc, import, export, clock, rc ) call list(n)%mGriddedIO%destroy(_RC) call list(n)%mGriddedIO%CreateFileMetaData(list(n)%items,list(n)%xsampler%acc_bundle,timeinfo_uninit,vdata=list(n)%vdata,global_attributes=global_attributes,_RC) call list(n)%items%pop_back() - + collection_id = o_Clients%add_hist_collection(list(n)%mGriddedIO%metadata, mode = create_mode) call list(n)%mGriddedIO%set_param(write_collection_id=collection_id) endif end if end do epoch_swath_grid_case - ! Write Id and time ! ----------------- @@ -3554,7 +3548,7 @@ subroutine Run ( gc, import, export, clock, rc ) ! enddo OPENLOOP call MAPL_TimerOff(GENSTATE,"----IO Create") - + call MAPL_TimerOn(GENSTATE,"----IO Write") call MAPL_TimerOn(GENSTATE,"-----IO Post") @@ -3607,8 +3601,8 @@ subroutine Run ( gc, import, export, clock, rc ) state_out = INTSTATE%GIM(n) end if - write(6,*) 'list(n)%unit=', list(n)%unit - + call lgr%debug('%a %i','list(n)%unit=', list(n)%unit) + list(n)%currentFile = filename(n) if (.not.list(n)%timeseries_output) then @@ -3647,7 +3641,6 @@ subroutine Run ( gc, import, export, clock, rc ) enddo POSTLOOP - write(6,*) 'test writing=', writing(:) if (any(writing)) then call o_Clients%done_collective_stage(_RC) call o_Clients%post_wait() @@ -3668,8 +3661,8 @@ subroutine Run ( gc, import, export, clock, rc ) call Hsampler%destroy_rh_regen_ogrid ( key_grid_label, IntState%output_grids, list(n)%xsampler, _RC ) pgrid => IntState%output_grids%at(trim(list(n)%output_grid_label)) call list(n)%xsampler%Create_bundle_RH(list(n)%items,list(n)%bundle,ogrid=pgrid,& - vdata=list(n)%vdata,global_attributes=global_attributes,_RC) - write(6,'(///)') + vdata=list(n)%vdata,global_attributes=global_attributes,_RC) + if( MAPL_AM_I_ROOT() ) write(6,'(//)') endif end if end do epoch_swath_regen_grid @@ -3713,8 +3706,6 @@ subroutine Run ( gc, import, export, clock, rc ) enddo WRITELOOP - - call MAPL_TimerOff(GENSTATE,"-----IO Write") call MAPL_TimerOff(GENSTATE,"----IO Write") From db2d7194064dbc29fadff9e854d176e284721b28 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 4 Oct 2023 08:23:09 -0600 Subject: [PATCH 05/41] NC cannot not find 'Cell_Along_Swath\ :mod04'. Try intel. --- base/MAPL_SwathGridFactory.F90 | 27 +++++++++++++++---- base/Plain_netCDF_Time.F90 | 5 ++++ base/StringTemplate.F90 | 17 ++++++++++++ .../MAPL_HistoryTrajectoryMod_smod.F90 | 4 +-- 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index a687c2465b79..3979c608a0c8 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -47,8 +47,10 @@ module MAPL_SwathGridFactoryMod character(len=ESMF_MAXSTR) :: var_name_time character(len=ESMF_MAXSTR) :: var_name_lat character(len=ESMF_MAXSTR) :: var_name_lon + character(len=ESMF_MAXSTR) :: input_template logical :: found_group + ! Domain decomposition: integer :: nx = MAPL_UNDEFINED_INTEGER integer :: ny = MAPL_UNDEFINED_INTEGER @@ -410,24 +412,29 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc logical :: ispresent _UNUSED_DUMMY(unusable) - + lgr => logging%get_logger('HISTORY.sampler') + call ESMF_VmGetCurrent(VM, _RC) - call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'GRIDNAME:', default=MAPL_GRID_NAME_DEFAULT) this%grid_name = trim(tmp) call ESMF_ConfigGetAttribute(config, this%nx, label=prefix//'NX:', default=MAPL_UNDEFINED_INTEGER) call ESMF_ConfigGetAttribute(config, this%ny, label=prefix//'NY:', default=MAPL_UNDEFINED_INTEGER) call ESMF_ConfigGetAttribute(config, this%lm, label=prefix//'LM:', default=MAPL_UNDEFINED_INTEGER) - call ESMF_ConfigGetAttribute(config, filename, label=prefix//'GRIDSPEC:', default='unknown.txt', _RC) + call ESMF_ConfigGetAttribute(config, this%input_template, label=prefix//'GRID_FILE:', default='unknown.txt', _RC) call ESMF_ConfigGetAttribute(config, this%epoch, label=prefix//'Epoch:', default=300, _RC) call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'Epoch_init:', default='2006', _RC) + call lgr%debug(' %a %a', 'input_template =', trim(this%input_template)) + + print*,__FILE__, __LINE__ !!write(6,'(2x,a,/,4i8,/,5(2x,a))') 'nx,ny,lm,epoch -- filename,tmp', & !! this%nx,this%ny,this%lm,this%epoch,& !! trim(filename),trim(tmp) !!print*, 'ck: Epoch_init:', trim(tmp) +! filename + if ( index(tmp, 'T') /= 0 .OR. index(tmp, '-') /= 0 ) then call ESMF_TimeSet(time0, timeString=tmp, _RC) else @@ -471,8 +478,18 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc key_lat=this%var_name_lat key_time=this%var_name_time ! CALL get_ncfile_dimension(filename, nlon, nlat, tdim, key_lon, key_lat, key_time, _RC) - CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, tdim=tdim, & - key_lon=key_lon, key_lat=key_lat, key_time=key_time, _RC) + + filename='/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.hdf' + + + CALL get_ncfile_dimension(filename, nlon=nlon, & + key_lon=key_lon, _RC) + print*, trim(key_lon), ' nlon ', nlon + + _FAIL('stop') + + CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, & + key_lon=key_lon, key_lat=key_lat, _RC) allocate(scanTime(nlon, nlat)) allocate(this%t_alongtrack(nlat)) diff --git a/base/Plain_netCDF_Time.F90 b/base/Plain_netCDF_Time.F90 index af640d32b7d7..4a3e7a96ab70 100644 --- a/base/Plain_netCDF_Time.F90 +++ b/base/Plain_netCDF_Time.F90 @@ -79,7 +79,12 @@ subroutine get_ncfile_dimension(filename, nlon, nlat, tdim, key_lon, key_lat, ke call check_nc_status(nf90_open(trim(fileName), NF90_NOWRITE, ncid), _RC) if(present(key_lon)) then lon_name=trim(key_lon) + print*, 'fileName=', trim(fileName) + print*, 'ncid=', ncid + print*, 'lon_name=', trim(key_lon) + print*, 'ck step 1' call check_nc_status(nf90_inq_dimid(ncid, trim(lon_name), dimid), _RC) + print*, 'ck step 2' call check_nc_status(nf90_inquire_dimension(ncid, dimid, len=nlon), _RC) endif diff --git a/base/StringTemplate.F90 b/base/StringTemplate.F90 index 1b13af15edfa..999e69a2f537 100644 --- a/base/StringTemplate.F90 +++ b/base/StringTemplate.F90 @@ -5,6 +5,7 @@ module MAPL_StringTemplate use MAPL_ExceptionHandling use MAPL_KeywordEnforcerMod + implicit none private @@ -165,6 +166,9 @@ function evaluate_token(token,year,month,day,hour,minute,second,preserve) result logical, intent(in) :: preserve character(len=4) :: buffer character(len=1) :: c1,c2 + type(ESMF_Time) :: time + integer(ESMF_KIND_I4) :: doy + integer :: status, rc c1=token(1:1) c2=token(2:2) select case(c1) @@ -208,6 +212,19 @@ function evaluate_token(token,year,month,day,hour,minute,second,preserve) result else buffer="%"//token end if + case("D") ! dayOfYear + if (.not.skip_token(day,preserve)) then + if (c2 == "3") then + call ESMF_TimeSet(time, yy=year, mm=month, dd=day, _RC) + call ESMF_TimeGet(time, dayOfYear=doy, _RC) + write(buffer,'(i3.3)')doy + write(6,*) 'doy=', doy + else + _FAIL('Day of Year must be %D3') + end if + else + buffer="%"//token + end if case("h") if (.not.skip_token(hour,preserve)) then if (c2 == "3") then diff --git a/gridcomps/History/MAPL_HistoryTrajectoryMod_smod.F90 b/gridcomps/History/MAPL_HistoryTrajectoryMod_smod.F90 index 012c3ba6b48d..3e43e074578b 100644 --- a/gridcomps/History/MAPL_HistoryTrajectoryMod_smod.F90 +++ b/gridcomps/History/MAPL_HistoryTrajectoryMod_smod.F90 @@ -494,9 +494,9 @@ allocate(this%lons(0),this%lats(0),_STAT) allocate(this%times_R8(0),_STAT) allocate(this%obstype_id(0),_STAT) - this%epoch_index(1:2)=0 + this%epoch_index(1:2) = 0 this%nobs_epoch = 0 - rc=0 + rc = 0 return end if From f299349ece8593927eccb4dcd4a22340adb28dfc Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Mon, 9 Oct 2023 12:38:02 -0600 Subject: [PATCH 06/41] Code cannot read in HDF4 . I try to bypass by hard coding numbers for arrays. --- base/MAPL_SwathGridFactory.F90 | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 3979c608a0c8..2f119e2f14e7 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -477,19 +477,16 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc key_lon=this%var_name_lon key_lat=this%var_name_lat key_time=this%var_name_time - ! CALL get_ncfile_dimension(filename, nlon, nlat, tdim, key_lon, key_lat, key_time, _RC) - filename='/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.hdf' - - - CALL get_ncfile_dimension(filename, nlon=nlon, & - key_lon=key_lon, _RC) - print*, trim(key_lon), ' nlon ', nlon - - _FAIL('stop') + filename='/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.hdf' CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, & key_lon=key_lon, key_lat=key_lat, _RC) + ! + !-- bypass mac: Cell_Along_Swath:mod04 nlon -889192448 + ! + nlon=135 + nlat=203 allocate(scanTime(nlon, nlat)) allocate(this%t_alongtrack(nlat)) @@ -501,10 +498,16 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call lgr%debug('%a %i8 %i8 %i8', & 'swath obs nlon,nlat,tdim:', nlon,nlat,tdim ) - call get_v2d_netcdf(filename, 'scanTime', scanTime, nlon, nlat) +!! call get_v2d_netcdf(filename, 'scanTime', scanTime, nlon, nlat) +!! do j=1, nlat +!! this%t_alongtrack(j)= scanTime(1,j) +!! enddo + do j=1, nlat - this%t_alongtrack(j)= scanTime(1,j) + this%t_alongtrack(j)= 765144911.174928 + (765144912.652078 - 765144911.174928)*(j-1) enddo + + ! ! skip un-defined time value ! From 48dd737f73c66637e44661335874eb874a380fed Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Tue, 10 Oct 2023 14:22:06 -0400 Subject: [PATCH 07/41] small udpate with nf90 get dimension --- base/MAPL_SwathGridFactory.F90 | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 2f119e2f14e7..e2e5aa74bd77 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -480,13 +480,14 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc filename='/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.hdf' + filename='/discover/nobackup/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.hdf' + CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, & key_lon=key_lon, key_lat=key_lat, _RC) ! !-- bypass mac: Cell_Along_Swath:mod04 nlon -889192448 ! - nlon=135 - nlat=203 + print*, 'nlon, nlat=', nlon, nlat allocate(scanTime(nlon, nlat)) allocate(this%t_alongtrack(nlat)) @@ -498,14 +499,15 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call lgr%debug('%a %i8 %i8 %i8', & 'swath obs nlon,nlat,tdim:', nlon,nlat,tdim ) -!! call get_v2d_netcdf(filename, 'scanTime', scanTime, nlon, nlat) -!! do j=1, nlat -!! this%t_alongtrack(j)= scanTime(1,j) -!! enddo - + call get_v2d_netcdf(filename, this%nc_time, scanTime, nlon, nlat) do j=1, nlat - this%t_alongtrack(j)= 765144911.174928 + (765144912.652078 - 765144911.174928)*(j-1) + this%t_alongtrack(j)= scanTime(1,j) enddo + + write(6,*) 'this%t_alongtrack(j)=', this%t_alongtrack(::3) +! do j=1, nlat +! this%t_alongtrack(j)= 765144911.174928 + (765144912.652078 - 765144911.174928)*(j-1) +! enddo ! From 96232bdabfd201ae7fd16c44f327321d6c01fadb Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Tue, 10 Oct 2023 20:54:07 -0600 Subject: [PATCH 08/41] h4toh5 conversion nf90_getvar from mod04/Data Fields/Scan_Start_Time netCDF error: NetCDF: Start+count exceeds dimension bound --- base/MAPL_SwathGridFactory.F90 | 64 ++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index e2e5aa74bd77..941e32812f4c 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -398,10 +398,12 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc integer :: nlon, nlat, tdim integer :: Xdim, Ydim, ntime character(len=ESMF_MAXSTR) :: key_lon, key_lat, key_time - character(len=ESMF_MAXSTR) :: filename, tunit, tmp, grp_name + character(len=ESMF_MAXSTR) :: filename, tunit, tmp, grp1, grp2 + ! real(ESMF_KIND_R8), allocatable :: scanTime(:,:) real, allocatable :: scanTime(:,:) integer :: yy, mm, dd, h, m, s, sec integer :: i, j + integer :: ncid, ncid2, varid type(ESMF_Time) :: time0 integer (ESMF_KIND_I8) :: j0, j1, jt, jt1, jt2 @@ -452,26 +454,34 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call ESMF_ConfigGetAttribute(config, this%nc_latitude, & label=prefix // 'nc_Latitude:', default="", _RC) - write(6,'((2x,a),10(2x,a15))') 'nc_time =', trim(this%nc_time) - write(6,'((2x,a),10(2x,a15))') 'nc_lon =', trim(this%nc_longitude) - write(6,'((2x,a),10(2x,a15))') 'nc_lat =', trim(this%nc_latitude) - - - i=index(this%nc_longitude, '/') + i=index(this%nc_time, '/') if (i>0) then this%found_group = .true. - grp_name = this%nc_longitude(1:i-1) + grp1 = this%nc_time(1:i-1) + j=index(this%nc_time(i+1:), '/') + if (j>0) then + grp2=this%nc_time(i+1:i+j-1) + else + grp2='' + endif + i=i+j else this%found_group = .false. - grp_name = '' + grp1 = '' + grp2='' endif + this%var_name_time= this%nc_time(i+1:) + + i=index(this%nc_longitude, '/') this%var_name_lat = this%nc_latitude(i+1:) this%var_name_lon = this%nc_longitude(i+1:) - this%var_name_time= this%nc_time(i+1:) + write(6,'(10(2x,a))') 'name lat, lon, time', & trim(this%var_name_lat), trim(this%var_name_lon), trim(this%var_name_time) + write(6,'(10(2x,a))') 'grp1, grp2', trim(grp1), trim(grp2) + ! read global dim from nc file ! ---------------------------- key_lon=this%var_name_lon @@ -479,14 +489,12 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc key_time=this%var_name_time - filename='/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.hdf' - filename='/discover/nobackup/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.hdf' + filename='/discover/nobackup/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.h5' + filename='/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.h5' + filename='./MOD04_L2.A2017090.0010.051.NRT.h5' CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, & key_lon=key_lon, key_lat=key_lat, _RC) - ! - !-- bypass mac: Cell_Along_Swath:mod04 nlon -889192448 - ! print*, 'nlon, nlat=', nlon, nlat allocate(scanTime(nlon, nlat)) allocate(this%t_alongtrack(nlat)) @@ -496,18 +504,30 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc 'swath Epoch init time:', trim(tmp) ) call lgr%debug('%a %a', & 'swath obs filename: ', trim(filename) ) - call lgr%debug('%a %i8 %i8 %i8', & - 'swath obs nlon,nlat,tdim:', nlon,nlat,tdim ) - - call get_v2d_netcdf(filename, this%nc_time, scanTime, nlon, nlat) + call lgr%debug('%a %i8 %i8', & + 'swath obs nlon,nlat:', nlon,nlat) + + + call check_nc_status(nf90_open(fileName, NF90_NOWRITE, ncid2), _RC) + if ( this%found_group ) then + call check_nc_status(nf90_inq_ncid(ncid2, grp1, ncid), _RC) + print*, 'ck grp1' + if (j>0) then + call check_nc_status(nf90_inq_ncid(ncid, grp2, ncid2), _RC) + ncid=ncid2 + print*, 'ck grp2' + endif + else + ncid=ncid2 + endif + ! call check_nc_status(nf90_inq_varid(ncid, key_time, varid), _RC) + call check_nc_status(nf90_inq_varid(ncid, 'Scan_Start_Time', varid), _RC) + call check_nc_status(nf90_get_var(ncid, varid, scanTime), _RC) do j=1, nlat this%t_alongtrack(j)= scanTime(1,j) enddo write(6,*) 'this%t_alongtrack(j)=', this%t_alongtrack(::3) -! do j=1, nlat -! this%t_alongtrack(j)= 765144911.174928 + (765144912.652078 - 765144911.174928)*(j-1) -! enddo ! From b089265c76ac0d4ae12845ee273da432ddf0421d Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Sun, 29 Oct 2023 19:49:43 -0600 Subject: [PATCH 09/41] modified: GriddedIO.F90; it should be the version I worked with Ben --- griddedio/GriddedIO.F90 | 39 +++++++-------------------------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/griddedio/GriddedIO.F90 b/griddedio/GriddedIO.F90 index 602ea72f74fc..7b62d2e0dacf 100644 --- a/griddedio/GriddedIO.F90 +++ b/griddedio/GriddedIO.F90 @@ -31,7 +31,7 @@ module MAPL_GriddedIOMod private type, public :: MAPL_GriddedIO - type(FileMetaData), allocatable :: metadata + type(FileMetaData) :: metadata type(fileMetadataUtils), pointer :: current_file_metadata integer :: write_collection_id integer :: read_collection_id @@ -73,7 +73,6 @@ module MAPL_GriddedIOMod procedure :: request_data_from_file procedure :: process_data_from_file procedure :: swap_undef_value - procedure :: destroy end type MAPL_GriddedIO interface MAPL_GriddedIO @@ -115,7 +114,7 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr type(TimeData), intent(inout) :: timeInfo type(VerticalData), intent(inout), optional :: vdata type (ESMF_Grid), intent(inout), pointer, optional :: ogrid - type(StringStringMap), target, intent(in), optional :: global_attributes + type(StringStringMap), intent(in), optional :: global_attributes integer, intent(out), optional :: rc type(ESMF_Grid) :: input_grid @@ -129,11 +128,6 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr character(len=:), pointer :: attr_name, attr_val integer :: status - if ( allocated (this%metadata) ) deallocate(this%metadata) - allocate(this%metadata) - - call MAPL_FieldBundleDestroy(this%output_bundle, _RC) - this%items = items this%input_bundle = bundle this%output_bundle = ESMF_FieldBundleCreate(rc=status) @@ -147,11 +141,9 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr call ESMF_FieldBundleGet(this%input_bundle,grid=this%output_grid,rc=status) _VERIFY(status) end if - this%regrid_handle => new_regridder_manager%make_regridder(input_grid,this%output_grid,this%regrid_method,rc=status) _VERIFY(status) - ! We get the regrid_method here because in the case of Identity, we set it to ! REGRID_METHOD_IDENTITY in the regridder constructor if identity. Now we need ! to change the regrid_method in the GriddedIO object to be the same as the @@ -164,7 +156,6 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr _VERIFY(status) call factory%append_metadata(this%metadata) - if (present(vdata)) then this%vdata=vdata else @@ -188,7 +179,6 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr call this%check_chunking(this%vdata%lm,_RC) end if - order = this%metadata%get_order(rc=status) _VERIFY(status) metadataVarsSize = order%size() @@ -223,16 +213,7 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr end if _RETURN(_SUCCESS) - end subroutine CreateFileMetaData - - - subroutine destroy(this, rc) - class (MAPL_GriddedIO), intent(inout) :: this - integer, intent(out), optional :: rc - if(allocated(this%chunking)) deallocate(this%chunking) - _RETURN(_SUCCESS) - end subroutine destroy - + end subroutine CreateFileMetaData subroutine set_param(this,deflation,quantize_algorithm,quantize_level,chunking,nbits_to_keep,regrid_method,itemOrder,write_collection_id,rc) class (MAPL_GriddedIO), intent(inout) :: this @@ -502,7 +483,6 @@ subroutine bundlepost(this,filename,oClients,rc) end if else tindex = -1 - call this%stage2DLatLon(filename,oClients=oClients,_RC) end if if (this%vdata%regrid_type==VERTICAL_METHOD_ETA2LEV) then @@ -861,9 +841,8 @@ subroutine stage2DLatLon(this, fileName, oClients, rc) _VERIFY(STATUS) this%lons=ptr2d*MAPL_RADIANS_TO_DEGREES ref = ArrayReference(this%lons) - call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lons', & - ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) - + call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lons', & + ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) call ESMF_GridGetCoord(this%output_grid, localDE=0, coordDim=2, & staggerloc=ESMF_STAGGERLOC_CENTER, & farrayPtr=ptr2d, rc=status) @@ -904,7 +883,6 @@ subroutine stage2DLatLon(this, fileName, oClients, rc) call oClients%collective_stage_data(this%write_collection_id,trim(filename),'corner_lats', & ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) end if - _RETURN(_SUCCESS) end subroutine stage2DLatLon @@ -958,12 +936,11 @@ subroutine stageData(this, field, fileName, tIndex, oClients, rc) allocate(ptr2d(0,0)) end if ref = factory%generate_file_reference2D(Ptr2D) + allocate(localStart,source=[gridLocalStart,1]) if (tindex > -1) then - allocate(localStart,source=[gridLocalStart,1]) allocate(globalStart,source=[gridGlobalStart,tindex]) allocate(globalCount,source=[gridGlobalCount,1]) else - allocate(localStart,source=[gridLocalStart]) allocate(globalStart,source=gridGlobalStart) allocate(globalCount,source=gridGlobalCount) end if @@ -980,19 +957,17 @@ subroutine stageData(this, field, fileName, tIndex, oClients, rc) allocate(ptr3d(0,0,0)) end if ref = factory%generate_file_reference3D(Ptr3D) + allocate(localStart,source=[gridLocalStart,1,1]) if (tindex > -1) then - allocate(localStart,source=[gridLocalStart,1,1]) allocate(globalStart,source=[gridGlobalStart,1,tindex]) allocate(globalCount,source=[gridGlobalCount,lm,1]) else - allocate(localStart,source=[gridLocalStart,1]) allocate(globalStart,source=[gridGlobalStart,1]) allocate(globalCount,source=[gridGlobalCount,lm]) end if else _FAIL( "Rank not supported") end if - call oClients%collective_stage_data(this%write_collection_id,trim(filename),trim(fieldName), & ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) _RETURN(_SUCCESS) From bb7a46e4994abedba2507602f59de5939d4a2326 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Sun, 29 Oct 2023 19:50:36 -0600 Subject: [PATCH 10/41] . --- griddedio/GriddedIO.F90 | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/griddedio/GriddedIO.F90 b/griddedio/GriddedIO.F90 index 7b62d2e0dacf..602ea72f74fc 100644 --- a/griddedio/GriddedIO.F90 +++ b/griddedio/GriddedIO.F90 @@ -31,7 +31,7 @@ module MAPL_GriddedIOMod private type, public :: MAPL_GriddedIO - type(FileMetaData) :: metadata + type(FileMetaData), allocatable :: metadata type(fileMetadataUtils), pointer :: current_file_metadata integer :: write_collection_id integer :: read_collection_id @@ -73,6 +73,7 @@ module MAPL_GriddedIOMod procedure :: request_data_from_file procedure :: process_data_from_file procedure :: swap_undef_value + procedure :: destroy end type MAPL_GriddedIO interface MAPL_GriddedIO @@ -114,7 +115,7 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr type(TimeData), intent(inout) :: timeInfo type(VerticalData), intent(inout), optional :: vdata type (ESMF_Grid), intent(inout), pointer, optional :: ogrid - type(StringStringMap), intent(in), optional :: global_attributes + type(StringStringMap), target, intent(in), optional :: global_attributes integer, intent(out), optional :: rc type(ESMF_Grid) :: input_grid @@ -128,6 +129,11 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr character(len=:), pointer :: attr_name, attr_val integer :: status + if ( allocated (this%metadata) ) deallocate(this%metadata) + allocate(this%metadata) + + call MAPL_FieldBundleDestroy(this%output_bundle, _RC) + this%items = items this%input_bundle = bundle this%output_bundle = ESMF_FieldBundleCreate(rc=status) @@ -141,9 +147,11 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr call ESMF_FieldBundleGet(this%input_bundle,grid=this%output_grid,rc=status) _VERIFY(status) end if + this%regrid_handle => new_regridder_manager%make_regridder(input_grid,this%output_grid,this%regrid_method,rc=status) _VERIFY(status) + ! We get the regrid_method here because in the case of Identity, we set it to ! REGRID_METHOD_IDENTITY in the regridder constructor if identity. Now we need ! to change the regrid_method in the GriddedIO object to be the same as the @@ -156,6 +164,7 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr _VERIFY(status) call factory%append_metadata(this%metadata) + if (present(vdata)) then this%vdata=vdata else @@ -179,6 +188,7 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr call this%check_chunking(this%vdata%lm,_RC) end if + order = this%metadata%get_order(rc=status) _VERIFY(status) metadataVarsSize = order%size() @@ -213,7 +223,16 @@ subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attr end if _RETURN(_SUCCESS) - end subroutine CreateFileMetaData + end subroutine CreateFileMetaData + + + subroutine destroy(this, rc) + class (MAPL_GriddedIO), intent(inout) :: this + integer, intent(out), optional :: rc + if(allocated(this%chunking)) deallocate(this%chunking) + _RETURN(_SUCCESS) + end subroutine destroy + subroutine set_param(this,deflation,quantize_algorithm,quantize_level,chunking,nbits_to_keep,regrid_method,itemOrder,write_collection_id,rc) class (MAPL_GriddedIO), intent(inout) :: this @@ -483,6 +502,7 @@ subroutine bundlepost(this,filename,oClients,rc) end if else tindex = -1 + call this%stage2DLatLon(filename,oClients=oClients,_RC) end if if (this%vdata%regrid_type==VERTICAL_METHOD_ETA2LEV) then @@ -841,8 +861,9 @@ subroutine stage2DLatLon(this, fileName, oClients, rc) _VERIFY(STATUS) this%lons=ptr2d*MAPL_RADIANS_TO_DEGREES ref = ArrayReference(this%lons) - call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lons', & - ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) + call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lons', & + ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) + call ESMF_GridGetCoord(this%output_grid, localDE=0, coordDim=2, & staggerloc=ESMF_STAGGERLOC_CENTER, & farrayPtr=ptr2d, rc=status) @@ -883,6 +904,7 @@ subroutine stage2DLatLon(this, fileName, oClients, rc) call oClients%collective_stage_data(this%write_collection_id,trim(filename),'corner_lats', & ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) end if + _RETURN(_SUCCESS) end subroutine stage2DLatLon @@ -936,11 +958,12 @@ subroutine stageData(this, field, fileName, tIndex, oClients, rc) allocate(ptr2d(0,0)) end if ref = factory%generate_file_reference2D(Ptr2D) - allocate(localStart,source=[gridLocalStart,1]) if (tindex > -1) then + allocate(localStart,source=[gridLocalStart,1]) allocate(globalStart,source=[gridGlobalStart,tindex]) allocate(globalCount,source=[gridGlobalCount,1]) else + allocate(localStart,source=[gridLocalStart]) allocate(globalStart,source=gridGlobalStart) allocate(globalCount,source=gridGlobalCount) end if @@ -957,17 +980,19 @@ subroutine stageData(this, field, fileName, tIndex, oClients, rc) allocate(ptr3d(0,0,0)) end if ref = factory%generate_file_reference3D(Ptr3D) - allocate(localStart,source=[gridLocalStart,1,1]) if (tindex > -1) then + allocate(localStart,source=[gridLocalStart,1,1]) allocate(globalStart,source=[gridGlobalStart,1,tindex]) allocate(globalCount,source=[gridGlobalCount,lm,1]) else + allocate(localStart,source=[gridLocalStart,1]) allocate(globalStart,source=[gridGlobalStart,1]) allocate(globalCount,source=[gridGlobalCount,lm]) end if else _FAIL( "Rank not supported") end if + call oClients%collective_stage_data(this%write_collection_id,trim(filename),trim(fieldName), & ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) _RETURN(_SUCCESS) From 196d6b1b467e5b81419b28f4e77da4c8e41b39e3 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Mon, 6 Nov 2023 09:00:46 -0700 Subject: [PATCH 11/41] Save this version - I seem to find some config problems related to the position history.rc entries are laid out in file. - File names needs to be in template, - Stick to every 5 minute inteval for template --- base/MAPL_SwathGridFactory.F90 | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 941e32812f4c..515396f04e69 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -435,7 +435,6 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc !! trim(filename),trim(tmp) !!print*, 'ck: Epoch_init:', trim(tmp) -! filename if ( index(tmp, 'T') /= 0 .OR. index(tmp, '-') /= 0 ) then call ESMF_TimeSet(time0, timeString=tmp, _RC) @@ -447,13 +446,16 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call ESMF_ConfigGetAttribute(config, value=this%nc_index, default="", & label=prefix // 'nc_Index:', _RC) - call ESMF_ConfigGetAttribute(config, value=this%nc_time, default="", & + call ESMF_ConfigGetAttribute(config, this%nc_time, default="", & label=prefix//'nc_Time:', _RC) call ESMF_ConfigGetAttribute(config, this%nc_longitude, & label=prefix // 'nc_Longitude:', default="", _RC) call ESMF_ConfigGetAttribute(config, this%nc_latitude, & label=prefix // 'nc_Latitude:', default="", _RC) + write(6,*) 'this%nc index, time, long, lat=', & + trim(this%nc_index), trim(this%nc_time), trim(this%nc_longitude), trim(this%nc_latitude) + i=index(this%nc_time, '/') if (i>0) then this%found_group = .true. @@ -488,13 +490,14 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc key_lat=this%var_name_lat key_time=this%var_name_time - - filename='/discover/nobackup/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.h5' - filename='/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.h5' +! filename='/discover/nobackup/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.h5' +! filename='/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.h5' +! I am taking short cuts + filename='./MOD04_L2.A2017090.0010.051.NRT.h5' - CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, & key_lon=key_lon, key_lat=key_lat, _RC) + print*, 'filename input', trim(filename) print*, 'nlon, nlat=', nlon, nlat allocate(scanTime(nlon, nlat)) allocate(this%t_alongtrack(nlat)) @@ -506,6 +509,7 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc 'swath obs filename: ', trim(filename) ) call lgr%debug('%a %i8 %i8', & 'swath obs nlon,nlat:', nlon,nlat) + print*, 'key_time=', trim(key_time) call check_nc_status(nf90_open(fileName, NF90_NOWRITE, ncid2), _RC) @@ -521,7 +525,7 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc ncid=ncid2 endif ! call check_nc_status(nf90_inq_varid(ncid, key_time, varid), _RC) - call check_nc_status(nf90_inq_varid(ncid, 'Scan_Start_Time', varid), _RC) + call check_nc_status(nf90_inq_varid(ncid, key_time, varid), _RC) call check_nc_status(nf90_get_var(ncid, varid, scanTime), _RC) do j=1, nlat this%t_alongtrack(j)= scanTime(1,j) From 576022ef465fd21e9c14d8195fb0b6915bba5cd8 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 8 Nov 2023 10:03:58 -0700 Subject: [PATCH 12/41] add MAPL_ObsUtil.F90 --- base/CMakeLists.txt | 2 +- base/MAPL_ObsUtil.F90 | 271 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 base/MAPL_ObsUtil.F90 diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index b39685cd5bcd..268d7291f6f4 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -55,7 +55,7 @@ set (srcs MAPL_Resource.F90 MAPL_XYGridFactory.F90 MAPL_NetCDF.F90 Plain_netCDF_Time.F90 - MAPL_DateTime_Parsing_ESMF.F90 + MAPL_DateTime_Parsing_ESMF.F90 MAPL_ObsUtil.F90 # Orphaned program: should not be in this library. # tstqsat.F90 ) diff --git a/base/MAPL_ObsUtil.F90 b/base/MAPL_ObsUtil.F90 new file mode 100644 index 000000000000..d12da47cdb99 --- /dev/null +++ b/base/MAPL_ObsUtil.F90 @@ -0,0 +1,271 @@ +#include "MAPL_ErrLog.h" +#include "unused_dummy.H" + +module MAPL_ObsUtilMod + use ESMF + use MAPL_FileMetadataUtilsMod + use, intrinsic :: iso_fortran_env, only: REAL32, REAL64 + implicit none + integer, parameter :: mx_ngeoval = 60 +!! private + + public :: obs_unit + type :: obs_unit + integer :: nobs_epoch + integer :: ngeoval + logical :: export_all_geoval + type(FileMetadata), allocatable :: metadata + type(NetCDF4_FileFormatter), allocatable :: file_handle + character(len=ESMF_MAXSTR) :: name + character(len=ESMF_MAXSTR) :: obsFile_output + character(len=ESMF_MAXSTR) :: input_template + character(len=ESMF_MAXSTR) :: geoval_name(mx_ngeoval) + real(kind=REAL64), allocatable :: lons(:) + real(kind=REAL64), allocatable :: lats(:) + real(kind=REAL64), allocatable :: times_R8(:) + real(kind=REAL32), allocatable :: p2d(:) + real(kind=REAL32), allocatable :: p3d(:,:) + end type obs_unit + + interface sort_multi_arrays_by_time + module procedure sort_three_arrays_by_time + module procedure sort_four_arrays_by_time + end interface sort_multi_arrays_by_time + +contains + + subroutine get_obsfile_Tbracket_from_epoch(currTime, & + obsfile_start_time, obsfile_end_time, obsfile_interval, & + epoch_frequency, obsfile_Ts_index, obsfile_Te_index, rc) + implicit none + type(ESMF_Time), intent(in) :: currTime + type(ESMF_Time), intent(in) :: obsfile_start_time, obsfile_end_time + type(ESMF_TimeInterval), intent(in) :: obsfile_interval, epoch_frequency + integer, intent(out) :: obsfile_Ts_index + integer, intent(out) :: obsfile_Te_index + integer, optional, intent(out) :: rc + + type(ESMF_Time) :: T1, Tn + type(ESMF_Time) :: cT1 + type(ESMF_Time) :: Ts, Te + type(ESMF_TimeInterval) :: dT1, dT2, dTs, dTe + real(ESMF_KIND_R8) :: dT0_s, dT1_s, dT2_s + real(ESMF_KIND_R8) :: s1, s2 + integer :: n1, n2 + integer :: status + + T1 = obsfile_start_time + Tn = obsfile_end_time + + cT1 = currTime + dT1 = currTime - T1 + dT2 = currTime + epoch_frequency - T1 + + call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) + call ESMF_TimeIntervalGet(dT1, s_r8=dT1_s, rc=status) + call ESMF_TimeIntervalGet(dT2, s_r8=dT2_s, rc=status) + n1 = floor (dT1_s / dT0_s) + n2 = floor (dT2_s / dT0_s) + s1 = n1 * dT0_s + s2 = n2 * dT0_s + call ESMF_TimeIntervalSet(dTs, s_r8=s1, rc=status) + call ESMF_TimeIntervalSet(dTe, s_r8=s2, rc=status) + Ts = T1 + dTs + Te = T1 + dTe + + obsfile_Ts_index = n1 + if ( dT2_s - n2*dT0_s < 1 ) then + obsfile_Te_index = n2 - 1 + else + obsfile_Te_index = n2 + end if + + _RETURN(ESMF_SUCCESS) + + end subroutine get_obsfile_Tbracket_from_epoch + + function get_filename_from_template (time, file_template, rc) result(filename) + use Plain_netCDF_Time, only : ESMF_time_to_two_integer + use MAPL_StringTemplate, only : fill_grads_template + type(ESMF_Time), intent(in) :: time + character(len=*), intent(in) :: file_template + character(len=ESMF_MAXSTR) :: filename + integer, optional, intent(out) :: rc + + integer :: itime(2) + integer :: nymd, nhms + integer :: status + + stop 'DO not use get_filename_from_template' + call ESMF_time_to_two_integer(time, itime, _RC) + print*, 'two integer time, itime(:)', itime(1:2) + nymd = itime(1) + nhms = itime(2) + call fill_grads_template ( filename, file_template, & + experiment_id='', nymd=nymd, nhms=nhms, _RC ) + print*, 'ck: obsFile_T=', trim(filename) + _RETURN(ESMF_SUCCESS) + + end function get_filename_from_template + + + function get_filename_from_template_use_index (obsfile_start_time, obsfile_interval, & + f_index, file_template, rc) result(filename) + use Plain_netCDF_Time, only : ESMF_time_to_two_integer + use MAPL_StringTemplate, only : fill_grads_template + character(len=ESMF_MAXSTR) :: filename + type(ESMF_Time), intent(in) :: obsfile_start_time + type(ESMF_TimeInterval), intent(in) :: obsfile_interval + character(len=*), intent(in) :: file_template + integer, intent(in) :: f_index + integer, optional, intent(out) :: rc + + integer :: itime(2) + integer :: nymd, nhms + integer :: status + real(ESMF_KIND_R8) :: dT0_s + real(ESMF_KIND_R8) :: s + type(ESMF_TimeInterval) :: dT + type(ESMF_Time) :: time + + call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) + s = dT0_s * f_index + call ESMF_TimeIntervalSet(dT, s_r8=s, rc=status) + time = obsfile_start_time + dT + + call ESMF_time_to_two_integer(time, itime, _RC) + nymd = itime(1) + nhms = itime(2) + call fill_grads_template ( filename, file_template, & + experiment_id='', nymd=nymd, nhms=nhms, _RC ) + + _RETURN(ESMF_SUCCESS) + + end function get_filename_from_template_use_index + + + + subroutine time_real_to_ESMF (times_R8_1d, times_esmf_1d, datetime_units, rc) + use MAPL_NetCDF, only : convert_NetCDF_DateTime_to_ESMF + + real(kind=REAL64), intent(in) :: times_R8_1d(:) + type(ESMF_Time), intent(inout) :: times_esmf_1d(:) + character(len=*), intent(in) :: datetime_units + integer, optional, intent(out) :: rc + + type(ESMF_TimeInterval) :: interval + type(ESMF_Time) :: time0 + type(ESMF_Time) :: time1 + character(len=:), allocatable :: tunit + + integer :: i, len + integer :: int_time + integer :: status + + len = size (times_R8_1d) + do i=1, len + int_time = times_R8_1d(i) + call convert_NetCDF_DateTime_to_ESMF(int_time, datetime_units, interval, & + time0, time=time1, time_unit=tunit, _RC) + times_esmf_1d(i) = time1 + enddo + + _RETURN(_SUCCESS) + end subroutine time_real_to_ESMF + + + subroutine reset_times_to_current_day(current_time, times_1d, rc) + type(ESMF_Time), intent(in) :: current_time + type(ESMF_Time), intent(inout) :: times_1d(:) + integer, optional, intent(out) :: rc + integer :: i,status,h,m,yp,mp,dp,s,ms,us,ns + integer :: year,month,day + + call ESMF_TimeGet(current_time,yy=year,mm=month,dd=day,_RC) + do i=1,size(times_1d) + call ESMF_TimeGet(times_1d(i),yy=yp,mm=mp,dd=dp,h=h,m=m,s=s,ms=ms,us=us,ns=ns,_RC) + call ESMF_TimeSet(times_1d(i),yy=year,mm=month,dd=day,h=h,m=m,s=s,ms=ms,us=us,ns=ns,_RC) + enddo + _RETURN(_SUCCESS) + end subroutine reset_times_to_current_day + + + subroutine sort_three_arrays_by_time(U,V,T,rc) + use MAPL_SortMod + real(ESMF_KIND_R8), intent(inout) :: U(:), V(:), T(:) + integer, optional, intent(out) :: rc + + integer :: i, len + integer, allocatable :: IA(:) + integer(ESMF_KIND_I8), allocatable :: IX(:) + real(ESMF_KIND_R8), allocatable :: X(:) + + _ASSERT (size(U)==size(V), 'U,V different dimension') + _ASSERT (size(U)==size(T), 'U,T different dimension') + len = size (T) + + allocate (IA(len), IX(len), X(len)) + do i=1, len + IX(i)=T(i) + IA(i)=i + enddo + call MAPL_Sort(IX,IA) + + X = U + do i=1, len + U(i) = X(IA(i)) + enddo + X = V + do i=1, len + V(i) = X(IA(i)) + enddo + X = T + do i=1, len + T(i) = X(IA(i)) + enddo + _RETURN(_SUCCESS) + end subroutine sort_three_arrays_by_time + + subroutine sort_four_arrays_by_time(U,V,T,ID,rc) + use MAPL_SortMod + real(ESMF_KIND_R8) :: U(:), V(:), T(:) + integer :: ID(:) + integer, optional, intent(out) :: rc + + integer :: i, len + integer, allocatable :: IA(:) + integer(ESMF_KIND_I8), allocatable :: IX(:) + real(ESMF_KIND_R8), allocatable :: X(:) + integer, allocatable :: NX(:) + + _ASSERT (size(U)==size(V), 'U,V different dimension') + _ASSERT (size(U)==size(T), 'U,T different dimension') + len = size (T) + + allocate (IA(len), IX(len), X(len), NX(len)) + do i=1, len + IX(i)=T(i) + IA(i)=i + enddo + call MAPL_Sort(IX,IA) + + X = U + do i=1, len + U(i) = X(IA(i)) + enddo + X = V + do i=1, len + V(i) = X(IA(i)) + enddo + X = T + do i=1, len + T(i) = X(IA(i)) + enddo + NX = ID + do i=1, len + ID(i) = NX(IA(i)) + enddo + _RETURN(_SUCCESS) + end subroutine sort_four_arrays_by_time + +end module MAPL_ObsUtilMod From 6f0fa534a8f45ef782c57c60d409f91bdfbcee1b Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 8 Nov 2023 17:46:30 -0700 Subject: [PATCH 13/41] update --- base/MAPL_SwathGridFactory.F90 | 270 ++++++++++++++++++++++----------- 1 file changed, 181 insertions(+), 89 deletions(-) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 515396f04e69..bb9aaeaaaca3 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -50,6 +50,13 @@ module MAPL_SwathGridFactoryMod character(len=ESMF_MAXSTR) :: input_template logical :: found_group + type(ESMF_Time) :: obsfile_start_time ! user specify + type(ESMF_Time) :: obsfile_end_time + type(ESMF_TimeInterval) :: obsfile_interval + type(ESMF_TimeInterval) :: EPOCH_FREQUENCY + integer :: obsfile_Ts_index ! for epoch + integer :: obsfile_Te_index + logical :: is_valid ! Domain decomposition: integer :: nx = MAPL_UNDEFINED_INTEGER @@ -398,14 +405,18 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc integer :: nlon, nlat, tdim integer :: Xdim, Ydim, ntime character(len=ESMF_MAXSTR) :: key_lon, key_lat, key_time - character(len=ESMF_MAXSTR) :: filename, tunit, tmp, grp1, grp2 + character(len=ESMF_MAXSTR) :: tunit, grp1, grp2 + character(len=ESMF_MAXSTR) :: filename, STR1, tmp + character(len=ESMF_MAXSTR) :: symd, shms + ! real(ESMF_KIND_R8), allocatable :: scanTime(:,:) real, allocatable :: scanTime(:,:) - integer :: yy, mm, dd, h, m, s, sec - integer :: i, j + integer :: yy, mm, dd, h, m, s, sec, second + integer :: i, j, L integer :: ncid, ncid2, varid + integer :: fid_s, fid_e - type(ESMF_Time) :: time0 + type(ESMF_Time) :: currTime integer (ESMF_KIND_I8) :: j0, j1, jt, jt1, jt2 real(ESMF_KIND_R8) :: jx0, jx1 real(ESMF_KIND_R8) :: x0, x1 @@ -418,32 +429,85 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call ESMF_VmGetCurrent(VM, _RC) + + !__ s1. read in file spec. + ! set time, nc spec. + ! call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'GRIDNAME:', default=MAPL_GRID_NAME_DEFAULT) this%grid_name = trim(tmp) call ESMF_ConfigGetAttribute(config, this%nx, label=prefix//'NX:', default=MAPL_UNDEFINED_INTEGER) call ESMF_ConfigGetAttribute(config, this%ny, label=prefix//'NY:', default=MAPL_UNDEFINED_INTEGER) call ESMF_ConfigGetAttribute(config, this%lm, label=prefix//'LM:', default=MAPL_UNDEFINED_INTEGER) - call ESMF_ConfigGetAttribute(config, this%input_template, label=prefix//'GRID_FILE:', default='unknown.txt', _RC) + call ESMF_ConfigGetAttribute(config, this%input_template, label=prefix//'GRID_FILE_template:', default='unknown.txt', _RC) call ESMF_ConfigGetAttribute(config, this%epoch, label=prefix//'Epoch:', default=300, _RC) call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'Epoch_init:', default='2006', _RC) + ! + + + call ESMF_ConfigGetAttribute(config, value=STR1, default="", & + label= prefix// 'obs_file_begin:', _RC) + if (trim(STR1)=='') then + _FAIL('obs_file_begin missing, code crash') + else + call ESMF_TimeSet(this%obsfile_start_time, STR1, _RC) + if (mapl_am_I_root()) then + write(6,105) 'obs_file_begin provided: ', trim(STR1) + end if + end if + + call ESMF_ConfigGetAttribute(config, value=STR1, default="", & + label=prefix // 'obs_file_end:', _RC) + if (trim(STR1)=='') then + _FAIL('obs_file_end missing, code crash') + else + call ESMF_TimeSet(this%obsfile_end_time, STR1, _RC) + if (mapl_am_I_root()) then + write(6,105) 'obs_file_end provided:', trim(STR1) + end if + end if + + + + + call ESMF_ConfigGetAttribute(config, value=STR1, default="", & + label= prefix// 'obs_file_interval:', _RC) + _ASSERT(STR1/='', 'fatal error: obs_file_interval not provided in RC file') + if (mapl_am_I_root()) write(6,105) 'obs_file_interval:', trim(STR1) + if (mapl_am_I_root()) write(6,106) 'Epoch (second) :', sec + + i= index( trim(STR1), ' ' ) + if (i>0) then + symd=STR1(1:i-1) + shms=STR1(i+1:) + else + symd='' + shms=trim(STR1) + endif + call convert_twostring_2_esmfinterval (symd, shms, this%obsfile_interval, _RC) + - call lgr%debug(' %a %a', 'input_template =', trim(this%input_template)) - print*,__FILE__, __LINE__ - !!write(6,'(2x,a,/,4i8,/,5(2x,a))') 'nx,ny,lm,epoch -- filename,tmp', & - !! this%nx,this%ny,this%lm,this%epoch,& - !! trim(filename),trim(tmp) - !!print*, 'ck: Epoch_init:', trim(tmp) + second = hms_2_s(this%Epoch) + call ESMF_TimeIntervalSet(this%epoch_frequency, s=second, _RC) + if ( index(tmp, 'T') /= 0 .OR. index(tmp, '-') /= 0 ) then - call ESMF_TimeSet(time0, timeString=tmp, _RC) + call ESMF_TimeSet(currTime, timeString=tmp, _RC) else read(tmp,'(i4,5i2)') yy,mm,dd,h,m,s - call ESMF_Timeset(time0, yy=yy, mm=mm, dd=dd, h=h, m=m, s=s, _RC) + call ESMF_Timeset(currTime, yy=yy, mm=mm, dd=dd, h=h, m=m, s=s, _RC) endif - this%grid_file_name = trim(filename) + call lgr%debug(' %a %a', 'input_template =', trim(this%input_template)) + print*,__FILE__, __LINE__ + !!write(6,'(2x,a,/,4i8,/,5(2x,a))') 'nx,ny,lm,epoch -- filename,tmp', & + !! this%nx,this%ny,this%lm,this%epoch,& + !! trim(filename),trim(tmp) + !!print*, 'ck: Epoch_init:', trim(tmp) + + + call ESMF_ConfigGetAttribute(config, value=this%nc_index, default="", & label=prefix // 'nc_Index:', _RC) call ESMF_ConfigGetAttribute(config, this%nc_time, default="", & @@ -452,10 +516,7 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc label=prefix // 'nc_Longitude:', default="", _RC) call ESMF_ConfigGetAttribute(config, this%nc_latitude, & label=prefix // 'nc_Latitude:', default="", _RC) - - write(6,*) 'this%nc index, time, long, lat=', & - trim(this%nc_index), trim(this%nc_time), trim(this%nc_longitude), trim(this%nc_latitude) - + i=index(this%nc_time, '/') if (i>0) then this%found_group = .true. @@ -477,12 +538,6 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc i=index(this%nc_longitude, '/') this%var_name_lat = this%nc_latitude(i+1:) this%var_name_lon = this%nc_longitude(i+1:) - - - write(6,'(10(2x,a))') 'name lat, lon, time', & - trim(this%var_name_lat), trim(this%var_name_lon), trim(this%var_name_time) - write(6,'(10(2x,a))') 'grp1, grp2', trim(grp1), trim(grp2) - ! read global dim from nc file ! ---------------------------- @@ -490,11 +545,42 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc key_lat=this%var_name_lat key_time=this%var_name_time + write(6,*) 'this%nc index, time, long, lat=', & + trim(this%nc_index), trim(this%nc_time), trim(this%nc_longitude), trim(this%nc_latitude) + write(6,'(10(2x,a))') 'name lat, lon, time', & + trim(this%var_name_lat), trim(this%var_name_lon), trim(this%var_name_time) + write(6,'(10(2x,a))') 'grp1, grp2', trim(grp1), trim(grp2) + + + + + + + !__ s2. loop over filenames to get this%t_alongtrack(:) + ! +! call get_obsfile_Tbracket_from_epoch(currTime, & +! this%obsfile_start_time, this%obsfile_end_time, & +! this%obsfile_interval, this%epoch_frequency, & +! this%obsfile_Ts_index, this%obsfile_Te_index, _RC) +! +! +! L=0 +! fid_s=this%obsfile_Ts_index +! fid_e=this%obsfile_Te_index + +!! marker bug + this%grid_file_name = trim(filename) + + + + +!! marker bug ! filename='/discover/nobackup/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.h5' ! filename='/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.h5' -! I am taking short cuts - +! I am taking short cuts filename='./MOD04_L2.A2017090.0010.051.NRT.h5' + + CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, & key_lon=key_lon, key_lat=key_lat, _RC) print*, 'filename input', trim(filename) @@ -566,74 +652,80 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc this%cell_across_swath = nlon this%cell_along_swath = nlat - - ! determine im_world from Epoch - ! ----------------------------- - ! t_axis = t_alongtrack = t_a - ! convert time0 to j0 - ! use Epoch to find j1 - ! search j0, j1 in t_a - - - ! this is a bug - ! - tunit='seconds since 1993-01-01 00:00:00' - this%tunit = tunit - call time_esmf_2_nc_int (time0, tunit, j0, _RC) - sec = hms_2_s (this%Epoch) - j1= j0 + sec - jx0= j0 - jx1= j1 - !!call lgr%debug ('%a %f8 %f8', 'jx0, jx1', jx0, jx1) - call lgr%debug ('%a %i16 %i16', 'j0, j1 ', j0, j1) - - - this%epoch_index(1)= 1 - this%epoch_index(2)= this%cell_across_swath - call bisect( this%t_alongtrack, jx0, jt1, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) - call bisect( this%t_alongtrack, jx1, jt2, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) - - - if (jt1==jt2) then - _FAIL('Epoch Time is too small, empty swath grid is generated, increase Epoch') - endif - jt1 = jt1 + 1 ! (x1,x2] design - this%epoch_index(3)= jt1 - this%epoch_index(4)= jt2 - Xdim = this%cell_across_swath - Ydim = this%epoch_index(4) - this%epoch_index(3) + 1 - - - call lgr%debug ('%a %i4 %i4', 'bisect for j0: rc, jt', rc, jt1) - call lgr%debug ('%a %i4 %i4', 'bisect for j1: rc, jt', rc, jt2) - call lgr%debug ('%a %i4 %i4', 'Xdim, Ydim', Xdim, Ydim) - call lgr%debug ('%a %i4 %i4 %i4 %i4', 'this%epoch_index(4)', & - this%epoch_index(1), this%epoch_index(2), & - this%epoch_index(3), this%epoch_index(4)) - this%im_world = Xdim - this%jm_world = Ydim - - - call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'IMS_FILE:', rc=status) - if ( status == _SUCCESS ) then - call get_ims_from_file(this%ims, trim(tmp),this%nx, _RC) - else - call get_multi_integer(this%ims, 'IMS:', _RC) - endif - call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'JMS_FILE:', rc=status) - if ( status == _SUCCESS ) then - call get_ims_from_file(this%jms, trim(tmp),this%ny, _RC) - else - call get_multi_integer(this%jms, 'JMS:', _RC) - endif - ! ims is set at here - call this%check_and_fill_consistency(_RC) +! P2. +! +! ! determine im_world from Epoch +! ! ----------------------------- +! ! t_axis = t_alongtrack = t_a +! ! convert currTime to j0 +! ! use Epoch to find j1 +! ! search j0, j1 in t_a +! +! +! ! this is a bug +! ! +! tunit='seconds since 1993-01-01 00:00:00' +! this%tunit = tunit +! call time_esmf_2_nc_int (currTime, tunit, j0, _RC) +! sec = hms_2_s (this%Epoch) +! j1= j0 + sec +! jx0= j0 +! jx1= j1 +! !!call lgr%debug ('%a %f8 %f8', 'jx0, jx1', jx0, jx1) +! call lgr%debug ('%a %i16 %i16', 'j0, j1 ', j0, j1) +! +! +! this%epoch_index(1)= 1 +! this%epoch_index(2)= this%cell_across_swath +! call bisect( this%t_alongtrack, jx0, jt1, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) +! call bisect( this%t_alongtrack, jx1, jt2, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) +! +! +! if (jt1==jt2) then +! _FAIL('Epoch Time is too small, empty swath grid is generated, increase Epoch') +! endif +! jt1 = jt1 + 1 ! (x1,x2] design +! this%epoch_index(3)= jt1 +! this%epoch_index(4)= jt2 +! Xdim = this%cell_across_swath +! Ydim = this%epoch_index(4) - this%epoch_index(3) + 1 +! +! +! call lgr%debug ('%a %i4 %i4', 'bisect for j0: rc, jt', rc, jt1) +! call lgr%debug ('%a %i4 %i4', 'bisect for j1: rc, jt', rc, jt2) +! call lgr%debug ('%a %i4 %i4', 'Xdim, Ydim', Xdim, Ydim) +! call lgr%debug ('%a %i4 %i4 %i4 %i4', 'this%epoch_index(4)', & +! this%epoch_index(1), this%epoch_index(2), & +! this%epoch_index(3), this%epoch_index(4)) +! +! +! this%im_world = Xdim +! this%jm_world = Ydim +! +! +! call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'IMS_FILE:', rc=status) +! if ( status == _SUCCESS ) then +! call get_ims_from_file(this%ims, trim(tmp),this%nx, _RC) +! else +! call get_multi_integer(this%ims, 'IMS:', _RC) +! endif +! call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'JMS_FILE:', rc=status) +! if ( status == _SUCCESS ) then +! call get_ims_from_file(this%jms, trim(tmp),this%ny, _RC) +! else +! call get_multi_integer(this%jms, 'JMS:', _RC) +! endif +! ! ims is set at here +! call this%check_and_fill_consistency(_RC) +! _RETURN(_SUCCESS) - + +105 format (1x,a,2x,a) +106 format (1x,a,2x,i8) contains From c115d120c6192a54e40e3fbf5b361d0eca1f37f8 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Fri, 10 Nov 2023 10:12:22 -0700 Subject: [PATCH 14/41] WIP: add and test subroutine Find_M_files in time_ave_util.F90 --- Apps/time_ave_util.F90 | 1877 ++++------------------------------------ 1 file changed, 161 insertions(+), 1716 deletions(-) diff --git a/Apps/time_ave_util.F90 b/Apps/time_ave_util.F90 index 7f0190788d30..9364fd379eaa 100644 --- a/Apps/time_ave_util.F90 +++ b/Apps/time_ave_util.F90 @@ -1,1743 +1,188 @@ -#define I_AM_MAIN -#include "MAPL_Generic.h" +#include "MAPL_ErrLog.h" +#include "unused_dummy.H" -program time_ave - - use ESMF - use MAPL - use MAPL_FileMetadataUtilsMod - use gFTL_StringVector - use MPI - use, intrinsic :: iso_fortran_env, only: int32, int64, int16, real32, real64 - use ieee_arithmetic, only: isnan => ieee_is_nan - - implicit none - - integer comm,myid,npes,ierror - integer imglobal - integer jmglobal - logical root - -! ********************************************************************** -! ********************************************************************** -! **** **** -! **** Program to create time-averaged HDF files **** -! **** **** -! ********************************************************************** -! ********************************************************************** - - integer im,jm,lm - - integer nymd, nhms - integer nymd0,nhms0 - integer nymdp,nhmsp - integer nymdm,nhmsm - integer ntod, ndt, ntods - integer month, year - integer monthp, yearp - integer monthm, yearm - integer begdate, begtime - integer enddate, endtime - - integer id,rc,timeinc,timeid - integer ntime,nvars,ncvid,nvars2 - - character(len=ESMF_MAXSTR), allocatable :: fname(:) - character(len=ESMF_MAXSTR) template - character(len=ESMF_MAXSTR) name - character(len=ESMF_MAXSTR) ext - character(len=ESMF_MAXSTR) output, doutput, hdfile, rcfile - character(len=8) date0 - character(len=2) time0 - character(len=1) char - data output /'monthly_ave'/ - data rcfile /'NULL'/ - data doutput /'NULL'/ - data template/'NULL'/ - - integer n,m,nargs,L,nfiles,nv,km,mvars,mv,ndvars - - real plev,qming,qmaxg - real previous_undef,undef - real, allocatable :: lev(:) - integer, allocatable :: kmvar(:) , kmvar2(:) - integer, allocatable :: yymmdd(:) - integer, allocatable :: hhmmss(:) - integer, allocatable :: nloc(:) - integer, allocatable :: iloc(:) - - character(len=ESMF_MAXSTR), allocatable :: vname(:), vname2(:) - character(len=ESMF_MAXSTR), allocatable :: vtitle(:), vtitle2(:) - character(len=ESMF_MAXSTR), allocatable :: vunits(:), vunits2(:) - - real, allocatable :: qmin(:) - real, allocatable :: qmax(:) - real, allocatable :: dumz1(:,:) - real, allocatable :: dumz2(:,:) - real, allocatable :: dum(:,:,:) - real(REAL64), allocatable :: q(:,:,:,:) - integer, allocatable :: ntimes(:,:,:,:) - - integer timinc,i,j,k,nmax,kbeg,kend,loc1,loc2 - integer nstar - logical tend, first, strict, diurnal, mdiurnal, lquad, ldquad - logical ignore_nan - data first /.true./ - data strict /.true./ - - type(ESMF_Config) :: config - - integer, allocatable :: qloc(:,:) - character(len=ESMF_MAXSTR), allocatable :: quadratics(:,:) - character(len=ESMF_MAXSTR), allocatable :: quadtmp(:,:) - character(len=ESMF_MAXSTR), allocatable :: aliases(:,:) - character(len=ESMF_MAXSTR), allocatable :: aliastmp(:,:) - character(len=ESMF_MAXSTR) name1, name2, name3, dummy - integer nquad - integer nalias - logical, allocatable :: lzstar(:) - - integer ntmin, ntcrit, nc - - type(FileMetadata) :: basic_metadata - type(FileMetadataUtils) :: file_metadata - type(NetCDF4_FileFormatter) :: file_handle - integer :: status - class(AbstractGridfactory), allocatable :: factory - type(ESMF_Grid) :: output_grid,input_grid - character(len=:), allocatable :: output_grid_name - integer :: global_dims(3), local_dims(3) - type(ESMF_Time), allocatable :: time_series(:) - type(ESMF_TIme) :: etime - type(ESMF_Clock) :: clock - type(ESMF_TimeInterval) :: time_interval - type(ESMF_FieldBundle) :: primary_bundle,final_bundle,diurnal_bundle - type(ESMF_Field) :: field - type(ServerManager) :: io_server - type(FieldBundleWriter) :: standard_writer, diurnal_writer - real(ESMF_KIND_R4), pointer :: ptr2d(:,:),ptr3d(:,:,:) - character(len=ESMF_MAXSTR) :: grid_type - logical :: allow_zonal_means - character(len=ESMF_MAXPATHLEN) :: arg_str - character(len=:), allocatable :: lev_name - character(len=ESMF_MAXSTR) :: lev_units - integer :: n_times - type(verticalData) :: vertical_data - logical :: file_has_lev - type(DistributedProfiler), target :: t_prof - type(ProfileReporter) :: reporter - -! ********************************************************************** -! **** Initialization **** -! ********************************************************************** - -!call timebeg ('main') - - call mpi_init ( ierror ) ; comm = mpi_comm_world - call mpi_comm_rank ( comm,myid,ierror ) - call mpi_comm_size ( comm,npes,ierror ) - call ESMF_Initialize(logKindFlag=ESMF_LOGKIND_NONE,mpiCommunicator=MPI_COMM_WORLD, _RC) - call MAPL_Initialize(_RC) - t_prof = DistributedProfiler('time_ave_util',MpiTImerGauge(),MPI_COMM_WORLD) - call t_prof%start(_RC) - call io_server%initialize(MPI_COMM_WORLD,_RC) - root = myid.eq.0 - call ESMF_CalendarSetDefault(ESMF_CALKIND_GREGORIAN,_RC) - -! Read Command Line Arguments -! --------------------------- - begdate = -999 - begtime = -999 - enddate = -999 - endtime = -999 - ndt = -999 - ntod = -999 - ntmin = -999 - nargs = command_argument_count() - if( nargs.eq.0 ) then - call usage(root) - else - lquad = .TRUE. - ldquad = .FALSE. - diurnal = .FALSE. - mdiurnal = .FALSE. - ignore_nan = .FALSE. - do n=1,nargs - call get_command_argument(n,arg_str) - select case(trim(arg_str)) - case('-template') - call get_command_argument(n+1,template) - case('-tag') - call get_command_argument(n+1,output) - case('-rc') - call get_command_argument(n+1,rcfile) - case('-begdate') - call get_command_argument(n+1,arg_str) - read(arg_str,*)begdate - case('-begtime') - call get_command_argument(n+1,arg_str) - read(arg_str,*)begtime - case('-enddate') - call get_command_argument(n+1,arg_str) - read(arg_str,*)enddate - case('-endtime') - call get_command_argument(n+1,arg_str) - read(arg_str,*)endtime - case('-ntmin') - call get_command_argument(n+1,arg_str) - read(arg_str,*)ntmin - case('-ntod') - call get_command_argument(n+1,arg_str) - read(arg_str,*)ntod - case('-ndt') - call get_command_argument(n+1,arg_str) - read(arg_str,*)ndt - case('-strict') - call get_command_argument(n+1,arg_str) - read(arg_str,*)strict - case('-ogrid') - call get_command_argument(n+1,arg_str) - output_grid_name = trim(arg_str) - case('-noquad') - lquad = .FALSE. - case('-ignore_nan') - ignore_nan = .TRUE. - case('-d') - diurnal = .true. - if (n+1 .le. nargs) then - call get_command_argument(n+1,arg_str) - read(arg_str,fmt='(a1)') char - if (char.ne.'-') doutput=arg_str - end if - case('-md') - mdiurnal = .true. - if (n+1 .le. nargs) then - call get_command_argument(n+1,arg_str) - read(arg_str,fmt='(a1)') char - if (char.ne.'-') doutput=arg_str - end if - case('-dv') - ldquad = .true. - diurnal = .true. - if (n+1 .le. nargs) then - call get_command_argument(n+1,arg_str) - read(arg_str,fmt='(a1)') char - if (char.ne.'-') doutput=arg_str - end if - case('-mdv') - ldquad = .true. - mdiurnal = .true. - if (n+1 .le. nargs) then - call get_command_argument(n+1,arg_str) - read(arg_str,fmt='(a1)') char - if (char.ne.'-') doutput=arg_str - end if - case('-eta') - nfiles = 1 - call get_command_argument(n+nfiles,arg_str) - read(arg_str,fmt='(a1)') char - do while (char .ne. '-' .and. n+nfiles.ne.nargs) - nfiles = nfiles + 1 - call get_command_argument(n+nfiles,arg_str) - read(arg_str,fmt='(a1)') char - enddo - if (char.eq.'-') nfiles = nfiles-1 - allocate(fname(nfiles)) - do m=1,nfiles - call get_command_argument(n+m,fname(m)) - enddo - case('-hdf') - nfiles = 1 - call get_command_argument(n+nfiles,arg_str) - read(arg_str,fmt='(a1)') char - do while (char .ne. '-' .and. n+nfiles.ne.nargs) - nfiles = nfiles + 1 - call get_command_argument(n+nfiles,arg_str) - read(arg_str,fmt='(a1)') char - enddo - if (char.eq.'-') nfiles = nfiles-1 - allocate(fname(nfiles)) - do m=1,nfiles - call get_command_argument(n+m,fname(m)) - enddo - end select - enddo - end if - - if( (diurnal.or.mdiurnal) .and. trim(doutput).eq.'NULL' ) then - doutput = trim(output) // "_diurnal" - if( mdiurnal ) diurnal = .FALSE. - endif - - if (root .and. ignore_nan) print *,' ignore nan is true' - - -! Read RC Quadratics -! ------------------ - if( trim(rcfile).eq.'NULL' ) then - nquad = 0 - nalias = 0 - else - config = ESMF_ConfigCreate ( rc=rc ) - call ESMF_ConfigLoadFile ( config, trim(rcfile), rc=rc ) - call ESMF_ConfigFindLabel ( config, 'QUADRATICS:', rc=rc ) - tend = .false. - m = 0 - do while (.not.tend) - m = m+1 - allocate( quadtmp(3,m) ) - call ESMF_ConfigGetAttribute ( config,value=name1, rc=rc ) - call ESMF_ConfigGetAttribute ( config,value=dummy, rc=rc ) - call ESMF_ConfigGetAttribute ( config,value=name2, rc=rc ) - call ESMF_ConfigGetAttribute ( config,value=dummy, rc=rc ) - call ESMF_ConfigGetAttribute ( config,value=name3,default='XXX',rc=rc ) - call ESMF_ConfigNextLine ( config,tableEnd=tend, rc=rc ) - if( m==1 ) then - quadtmp(1,m) = name1 - quadtmp(2,m) = name2 - quadtmp(3,m) = name3 - allocate( quadratics(3,m) ) - quadratics = quadtmp - else - quadtmp(1,1:m-1) = quadratics(1,:) - quadtmp(2,1:m-1) = quadratics(2,:) - quadtmp(3,1:m-1) = quadratics(3,:) - quadtmp(1,m) = name1 - quadtmp(2,m) = name2 - quadtmp(3,m) = name3 - deallocate( quadratics ) - allocate( quadratics(3,m) ) - quadratics = quadtmp - endif - deallocate (quadtmp) - enddo - nquad = m - -! Read RC Aliases -! --------------- - call ESMF_ConfigFindLabel ( config, 'ALIASES:', rc=rc ) - tend = .false. - m = 0 - do while (.not.tend) - m = m+1 - allocate( aliastmp(2,m) ) - call ESMF_ConfigGetAttribute ( config,value=name1, rc=rc ) - call ESMF_ConfigGetAttribute ( config,value=dummy, rc=rc ) - call ESMF_ConfigGetAttribute ( config,value=name2, rc=rc ) - call ESMF_ConfigNextLine ( config,tableEnd=tend ,rc=rc ) - if( m==1 ) then - aliastmp(1,m) = name1 - aliastmp(2,m) = name2 - allocate( aliases(2,m) ) - aliases = aliastmp - else - aliastmp(1,1:m-1) = aliases(1,:) - aliastmp(2,1:m-1) = aliases(2,:) - aliastmp(1,m) = name1 - aliastmp(2,m) = name2 - deallocate( aliases ) - allocate( aliases(2,m) ) - aliases = aliastmp - endif - deallocate (aliastmp) - enddo - nalias = m - endif - if (.not. allocated(aliases)) allocate(aliases(0,0)) - -! ********************************************************************** -! **** Read HDF File **** -! ********************************************************************** - - call t_prof%start('initialize') - - if( trim(template).ne.'NULL' ) then - name = template - else - name = fname(1) - endif - - n = index(trim(name),'.',back=.true.) - ext = trim(name(n+1:)) - - call file_handle%open(trim(name),PFIO_READ,_RC) - basic_metadata = file_handle%read(_RC) - call file_handle%close(_RC) - - allocate(factory, source=grid_manager%make_factory(trim(name))) - input_grid = grid_manager%make_grid(factory) - file_has_lev = has_level(input_grid,_RC) - call MAPL_GridGet(input_grid,globalCellCountPerDim=global_dims,_RC) - lm = global_dims(3) - - if (file_has_lev) then - call get_file_levels(trim(name),vertical_data,_RC) - end if - - if (allocated(output_grid_name)) then - output_grid = create_output_grid(output_grid_name,lm,_RC) - else - output_grid = input_grid - end if - call ESMF_AttributeGet(output_grid,'GridType',grid_type,_RC) - allow_zonal_means = trim(grid_type) == 'LatLon' - if (trim(grid_type) == "Cubed-Sphere") then - _ASSERT(mod(npes,6)==0,"If input files are Cubed-Sphere, must be run on multiple of 6 proccessors") - end if - call MAPL_GridGet(output_grid,localCellCountPerDim=local_dims,globalCellCountPerDim=global_dims,_RC) - im = local_dims(1) - jm = local_dims(2) - lm = local_dims(3) - imglobal = global_dims(1) - jmglobal = global_dims(2) - - call file_metadata%create(basic_metadata,trim(name)) - call get_file_times(file_metadata,ntime,time_series,timinc,yymmdd,hhmmss,_RC) - primary_bundle = ESMF_FieldBundleCreate(name="first_file",_RC) - call ESMF_FieldBundleSet(primary_bundle,grid=output_grid,_RC) - call MAPL_Read_Bundle(primary_bundle,trim(name),time=time_series(1),_RC) - call ESMF_FieldBundleGet(primary_bundle,fieldCount=nvars,_RC) - allocate(vname(nvars)) - call ESMF_FieldBundleGet(primary_bundle,fieldNameList=vname,_RC) - kmvar = get_level_info(primary_bundle,_RC) - vtitle = get_long_names(primary_bundle,_RC) - vunits = get_units(primary_bundle,_RC) - - final_bundle = ESMF_FieldBundleCreate(name="first_file",_RC) - call ESMF_FieldBundleSet(final_bundle,grid=output_grid,_RC) - diurnal_bundle = ESMF_FieldBundleCreate(name="first_file",_RC) - call ESMF_FieldBundleSet(diurnal_bundle,grid=output_grid,_RC) - call copy_bundle_to_bundle(primary_bundle,final_bundle,_RC) - - if (size(time_series)>1) then - time_interval = time_series(2) - time_series(1) - else if (size(time_series)==1) then - call ESMF_TimeIntervalSet(time_interval,h=6,_RC) - end if - clock = ESMF_ClockCreate(startTime=time_series(1),timeStep=time_interval,_RC) - - nvars2 = nvars - - if (file_has_lev) then - lev_name = file_metadata%get_level_name(_RC) - call file_metadata%get_coordinate_info(lev_name,coords=lev,coordUnits=lev_units,_RC) - end if - - previous_undef = file_metadata%var_get_missing_value(trim(vname(1)),_RC) - do i=2,size(vname) - undef = file_metadata%var_get_missing_value(trim(vname(i)),_RC) - _ASSERT(undef == previous_undef,"conflicting undefined values in your variables") - previous_undef = undef - enddo - undef = previous_undef - - -! Set NDT for Strict Time Testing -! ------------------------------- - if( ntod.ne.-999 ) ndt = 86400 - if( ndt .eq.-999 ) ndt = compute_nsecf (timinc) - if( timinc .eq. 0 ) then - timeId = ncvid (id, 'time', rc) - call ncagt (id, timeId, 'time_increment', timinc, rc) - if( timinc .eq. 0 ) then - if( root ) then - print * - print *, 'Warning, GFIO Inquire states TIMINC = ',timinc - print *, ' This will be reset to 060000 ' - print *, ' Use -ndt NNN (in seconds) to overide this' - endif - timinc = 060000 - endif - ndt = compute_nsecf (timinc) - endif - -! Determine Number of Time Periods within 1-Day -! --------------------------------------------- - ntods = 0 - if( diurnal .or. mdiurnal ) then - if( ndt.lt.86400 ) ntods = 86400/ndt - endif - -! Set Minimum Required Times for Time Average (Default: 10 Days for Monthly Mean) -! ------------------------------------------------------------------------------- - if( ntmin.eq.-999 ) then - if( ntod.eq.-999 ) then - ntcrit = 10 * ( 86400.0/real(compute_nsecf(timinc)) ) - else - ntcrit = 10 - endif - else - ntcrit = ntmin - endif - -! Determine Location Index for Each Variable in File -! -------------------------------------------------- - if( root ) print * - allocate ( nloc(nvars) ) - nloc(1) = 1 - if( root ) write(6,7000) 1,trim(vname(1)),nloc(1),trim(vtitle(1)),max(1,kmvar(1)) - do n=2,nvars - nloc(n) = nloc(n-1)+max(1,kmvar(n-1)) - if( root ) write(6,7000) n,trim(vname(n)),nloc(n),trim(vtitle(n)),max(1,kmvar(n)) -7000 format(1x,'Primary Field: ',i4,' Name: ',a12,' at location: ',i4,3x,a40,2x,i2,3x,i2,3x,i2) - enddo - - nmax = nloc(nvars)+max(1,kmvar(nvars))-1 - allocate( dum (im,jm,nmax) ) - allocate( dumz1(im,jm) ) - allocate( dumz2(im,jm) ) - -! Append Default Quadratics to User-Supplied List -! ----------------------------------------------- - if( lquad ) then - if( nquad.eq.0 ) then - allocate( quadratics(3,nvars) ) - do n=1,nvars - quadratics(1,n) = trim( vname(n) ) - quadratics(2,n) = trim( vname(n) ) - quadratics(3,n) = 'XXX' - enddo - nquad = nvars - else - allocate( quadtmp(3,nquad+nvars) ) - quadtmp(1,1:nquad) = quadratics(1,:) - quadtmp(2,1:nquad) = quadratics(2,:) - quadtmp(3,1:nquad) = quadratics(3,:) - do n=1,nvars - quadtmp(1,nquad+n) = trim( vname(n) ) - quadtmp(2,nquad+n) = trim( vname(n) ) - quadtmp(3,nquad+n) = 'XXX' - enddo - nquad = nquad + nvars - deallocate( quadratics ) - allocate( quadratics(3,nquad) ) - quadratics = quadtmp - deallocate( quadtmp ) - endif - endif - - allocate ( qloc(2,nquad) ) - allocate ( lzstar(nquad) ) ; lzstar = .FALSE. - -! Determine Possible Quadratics -! ----------------------------- - km=kmvar(nvars) - m= nvars - do n=1,nquad - call check_quad ( quadratics(1,n),vname,nvars,aliases,nalias,qloc(1,n) ) - if( qloc(1,n)*qloc(2,n).ne.0 ) then - m=m+1 - allocate ( iloc(m) ) - iloc(1:m-1) = nloc - iloc(m) = iloc(m-1)+max(1,km) - deallocate ( nloc ) - allocate ( nloc(m) ) - nloc = iloc - deallocate ( iloc ) - km=kmvar( qloc(1,n) ) - endif - enddo - - mvars = m - nmax = nloc(m)+max(1,km)-1 - - allocate ( vname2( mvars) ) - allocate ( vtitle2( mvars) ) - allocate ( vunits2( mvars) ) - allocate ( kmvar2( mvars) ) - - vname2( 1:nvars) = vname - vtitle2( 1:nvars) = vtitle - vunits2( 1:nvars) = vunits - kmvar2( 1:nvars) = kmvar - - if( root .and. mvars.gt.nvars ) print * - mv= nvars - do nv=1,nquad - if( qloc(1,nv)*qloc(2,nv).ne.0 ) then - mv = mv+1 - - if( trim(quadratics(1,nv)).eq.trim(quadratics(2,nv)) ) then - vname2(mv) = "Var_" // trim(vname(qloc(1,nv))) - vtitle2(mv) = "Variance_of_" // trim(vname(qloc(1,nv))) - else - vname2(mv) = "Cov_" // trim(vname(qloc(1,nv))) // "_" // trim(vname(qloc(2,nv))) - vtitle2(mv) = "Covariance_of_" // trim(vname(qloc(1,nv))) // "_and_" // trim(vname(qloc(2,nv))) - endif - - if( trim(quadratics(3,nv)).ne.'XXX' ) vname2(mv) = trim(quadratics(3,nv)) - - nstar = index( trim(quadratics(1,nv)),'star',back=.true. ) - if( nstar.ne.0 ) then - _ASSERT(allow_zonal_means,"grid is not lat-lon so cannot compute zonal means") - lzstar(nv) = .TRUE. - vtitle2(mv) = "Product_of_Zonal_Mean_Deviations_of_" // trim(vname(qloc(1,nv))) // "_and_" // trim(vname(qloc(2,nv))) - endif - - vunits2(mv) = trim(vunits(qloc(1,nv))) // " " // trim(vunits(qloc(2,nv))) - kmvar2(mv) = kmvar(qloc(1,nv)) - - call add_new_field_to_bundle(final_bundle,output_grid,kmvar(qloc(1,nv)),vname2(mv),vtitle2(mv),vunits2(mv),_RC) - - if( root ) write(6,7001) mv,trim(vname2(mv)),nloc(mv),trim(vtitle2(mv)),max(1,kmvar(qloc(1,nv))),qloc(1,nv),qloc(2,nv) -7001 format(1x,' Quad Field: ',i4,' Name: ',a12,' at location: ',i4,3x,a50,2x,i2,3x,i3,3x,i3) - endif - enddo - -!deallocate ( lev ) - deallocate ( yymmdd ) - deallocate ( hhmmss ) - deallocate ( vname ) - deallocate ( vtitle ) - deallocate ( vunits ) - deallocate ( kmvar ) - - allocate( qmin(nmax) ) - allocate( qmax(nmax) ) - allocate( q(im,jm,nmax,0:ntods) ) - allocate( ntimes(im,jm,nmax,0:ntods) ) - ntimes = 0 - q = 0 - qmin = abs(undef) - qmax = -abs(undef) - - if( root ) then - print * - write(6,7002) mvars,nmax,im,jm,nmax,ntods -7002 format(1x,'Total Number of Variables: ',i3,/ & - 1x,'Total Size: ',i5,/ & - 1x,'Allocating q(',i4,',',i3,',',i5,',0:',i2.2,')') - print * - print *, 'Files: ' - do n=1,nfiles - print *, n,trim(fname(n)) - enddo - print * - if( ntod.eq.-999 ) then - print *, 'Averging Time-Period NHMS: ',ntod,' (ALL Possible Time Periods Used)' - else - print *, 'Averging Time-Period NHMS: ',ntod - endif - if( begdate.ne.-999 .or. begtime.ne.-999 ) print *, 'Beginning Date for Averaging: ',begdate,begtime - if( enddate.ne.-999 .or. endtime.ne.-999 ) print *, ' Ending Date for Averaging: ',enddate,endtime - if( strict ) then - print *, 'Every Time Period Required for Averaging, STRICT = ',strict - else - print *, 'Only Averaging Time Periods Supplied, STRICT = ',strict - endif - write(6,7003) ntcrit -7003 format(1x,'Required Minimum Number of Defined Time Periods: ',i3,' (Otherwise, UNDEF)') - print * - endif - - call t_prof%stop('initialize') - -! ********************************************************************** -! **** Read HDF Files **** -! ********************************************************************** - - k = 0 - - do n=1,nfiles - - if (allocated(time_series)) deallocate(time_series) - if (allocated(yymmdd)) deallocate(yymmdd) - if (allocated(hhmmss)) deallocate(hhmmss) - call file_handle%open(trim(fname(n)),PFIO_READ,_RC) - basic_metadata = file_handle%read(_RC) - call file_handle%close(_RC) - call file_metadata%create(basic_metadata,trim(fname(n))) - call get_file_times(file_metadata,ntime,time_series,timinc,yymmdd,hhmmss,_RC) - - - do m=1,ntime - nymd = yymmdd(m) - nhms = hhmmss(m) - if( nhms<0 ) then - nhms = compute_nhmsf( compute_nsecf(nhms) + 86400 ) - call tick (nymd,nhms,-86400) - endif - - if( ( begdate.ne.-999 .and. begtime.ne.-999 ) .and. & - ( begdate.gt.nymd .or. & - ( begdate.eq.nymd.and.begtime.gt.nhms ) ) ) cycle - - if( ( enddate.ne.-999 .and. endtime.ne.-999 ) .and. & - ( enddate.lt.nymd .or. & - ( enddate.eq.nymd.and.endtime.lt.nhms ) ) ) cycle - - k = k+1 - if( k.gt.ntods ) k = 1 - if( ntod.eq.-999 .or. ntod.eq.nhms ) then - if( root ) write(6,3000) nymd,nhms,timinc,trim(fname(n)),k -3000 format(1x,'Reading nymd: ',i8.8,' nhms: ',i6.6,' TimInc: ',i6.6,' from File: ',a,' tod = ',i2) - year = nymd/10000 - month = mod(nymd,10000)/100 - -! Check for Correct First Dataset -! ------------------------------- - if( strict .and. first ) then - nymdm = nymd - nhmsm = nhms - call tick (nymdm,nhmsm,-ndt) - yearm = nymdm/10000 - monthm = mod(nymdm,10000)/100 - if( year.eq.yearm .and. month.eq.monthm ) then - if( root ) print *, 'Date: ',nymd,' Time: ',nhms,' is NOT correct First Time Period!' - _FAIL("error processing dataset") - endif - endif - -! Check Date and Time for STRICT Time Testing -! ------------------------------------------- - if( strict .and. .not.first ) then - if( nymd.ne.nymdp .or. nhms.ne.nhmsp ) then - if( root ) print *, 'Date: ',nymdp,' Time: ',nhmsp,' not found!' - _FAIL("error processing dataset") - endif - endif - nymdp = nymd - nhmsp = nhms - -! Primary Fields -! -------------- - - etime = local_esmf_timeset(nymd,nhms,_RC) - call MAPL_Read_Bundle(primary_bundle,trim(fname(1)),time=etime,file_override=trim(fname(n)),_RC) - do nv=1,nvars2 - call ESMF_FieldBundleGet(primary_bundle,trim(vname2(nv)),field=field,_RC) - call t_prof%start('PRIME') - if( kmvar2(nv).eq.0 ) then - kbeg = 0 - kend = 1 - call ESMF_FieldGet(field,0,farrayPtr=ptr2d,_RC) - dum(:,:,nloc(nv))=ptr2d - else - kbeg = 1 - kend = kmvar2(nv) - - call ESMF_FieldGet(field,0,farrayPtr=ptr3d,_RC) - dum(:,:,nloc(nv):nloc(nv)+kmvar2(nv)-1) = ptr3d - endif - - rc = 0 - do L=1,max(1,kmvar2(nv)) - do j=1,jm - do i=1,im - if( isnan( dum(i,j,nloc(nv)+L-1) ) .or. ( dum(i,j,nloc(nv)+L-1).gt.HUGE(dum(i,j,nloc(nv)+L-1)) ) ) then -!print *, 'Warning! Nan or Infinity detected for ',trim(vname2(nv)),' at lat: ',lattice%jglobal(j),' lon: ',lattice%iglobal(i) - if( root .and. ignore_nan ) then - print *, 'Setting Nan or Infinity to UNDEF' - print * - else - rc = 1 - endif - dum(i,j,nloc(nv)+L-1) = undef - endif - if( defined(dum(i,j,nloc(nv)+L-1),undef) ) then - q(i,j,nloc(nv)+L-1,0) = q(i,j,nloc(nv)+L-1,0) + dum(i,j,nloc(nv)+L-1) - ntimes(i,j,nloc(nv)+L-1,0) = ntimes(i,j,nloc(nv)+L-1,0) + 1 - if( qmin(nloc(nv)+L-1).gt.dum(i,j,nloc(nv)+L-1) ) qmin(nloc(nv)+L-1) = dum(i,j,nloc(nv)+L-1) - if( qmax(nloc(nv)+L-1).lt.dum(i,j,nloc(nv)+L-1) ) qmax(nloc(nv)+L-1) = dum(i,j,nloc(nv)+L-1) - if( ntods.ne.0 ) then - q(i,j,nloc(nv)+L-1,k) = q(i,j,nloc(nv)+L-1,k) + dum(i,j,nloc(nv)+L-1) - ntimes(i,j,nloc(nv)+L-1,k) = ntimes(i,j,nloc(nv)+L-1,k) + 1 - endif - endif - enddo - enddo - enddo - call t_prof%stop('PRIME') - - enddo - -! Quadratics -! ---------- - call t_prof%start('QUAD') - mv= nvars2 - do nv=1,nquad - if( qloc(1,nv)*qloc(2,nv).ne.0 ) then - mv=mv+1 - do L=1,max(1,kmvar2(qloc(1,nv))) - if( lzstar(nv) ) then - call latlon_zstar (dum(:,:,nloc(qloc(1,nv))+L-1),dumz1,undef,output_grid,_RC) - call latlon_zstar (dum(:,:,nloc(qloc(2,nv))+L-1),dumz2,undef,output_grid,_RC) - do j=1,jm - do i=1,im - if( defined(dumz1(i,j),undef) .and. & - defined(dumz2(i,j),undef) ) then - q(i,j,nloc(mv)+L-1,0) = q(i,j,nloc(mv)+L-1,0) + dumz1(i,j)*dumz2(i,j) - ntimes(i,j,nloc(mv)+L-1,0) = ntimes(i,j,nloc(mv)+L-1,0) + 1 - if( ntods.ne.0 ) then - q(i,j,nloc(mv)+L-1,k) = q(i,j,nloc(mv)+L-1,k) + dumz1(i,j)*dumz2(i,j) - ntimes(i,j,nloc(mv)+L-1,k) = ntimes(i,j,nloc(mv)+L-1,k) + 1 - endif - endif - enddo - enddo - else - do j=1,jm - do i=1,im - if( defined(dum(i,j,nloc(qloc(1,nv))+L-1),undef) .and. & - defined(dum(i,j,nloc(qloc(2,nv))+L-1),undef) ) then - q(i,j,nloc(mv)+L-1,0) = q(i,j,nloc(mv)+L-1,0) + dum(i,j,nloc(qloc(1,nv))+L-1) & - * dum(i,j,nloc(qloc(2,nv))+L-1) - ntimes(i,j,nloc(mv)+L-1,0) = ntimes(i,j,nloc(mv)+L-1,0) + 1 - if( ntods.ne.0 ) then - q(i,j,nloc(mv)+L-1,k) = q(i,j,nloc(mv)+L-1,k) + dum(i,j,nloc(qloc(1,nv))+L-1) & - * dum(i,j,nloc(qloc(2,nv))+L-1) - ntimes(i,j,nloc(mv)+L-1,k) = ntimes(i,j,nloc(mv)+L-1,k) + 1 - endif - endif - enddo - enddo - endif - enddo - endif - enddo - call t_prof%stop('QUAD') - - if( first ) then - nymd0 = nymd - nhms0 = nhms - first = .false. - endif - -! Update Date and Time for Strict Test -! ------------------------------------ - call tick (nymdp,nhmsp,ndt) - yearp = nymdp/10000 - monthp = mod(nymdp,10000)/100 - - endif ! End ntod Test - enddo ! End ntime Loop within file - - call MPI_BARRIER(comm,status) - enddo - - do k=0,ntods - if( k.eq.0 ) then - nc = ntcrit - else - nc = max( 1,ntcrit/ntods ) - endif - do n=1,nmax - do j=1,jm - do i=1,im - if( ntimes(i,j,n,k).lt.nc ) then - q(i,j,n,k) = undef - else - q(i,j,n,k) = q(i,j,n,k)/ntimes(i,j,n,k) - endif - enddo - enddo - enddo - enddo - -! ********************************************************************** -! **** Write HDF Monthly Output File **** -! ********************************************************************** - -call t_prof%start('Write_AVE') - -! Check for Correct Last Dataset -! ------------------------------ - if( strict .and. ( year.eq.yearp .and. month.eq.monthp ) ) then - if( root ) print *, 'Date: ',nymd,' Time: ',nhms,' is NOT correct Last Time Period!' - _FAIL("Error processing dataset") - endif - - write(date0,4000) nymd0/100 - write(time0,2000) nhms0/10000 - - hdfile = trim(output) // "." // trim(date0) // "." // trim(ext) - -1000 format(i8.8) -2000 format(i2.2) -4000 format(i6.6) - - timeinc = 060000 - -! Primary Fields -! -------------- - if( root ) print * - do n=1,nvars2 - call ESMF_FieldBundleGet(final_bundle,trim(vname2(n)),field=field,_RC) - if( kmvar2(n).eq.0 ) then - kbeg = 0 - kend = 1 - call ESMF_FieldGet(field,0,farrayPtr=ptr2d,_RC) - ptr2d = q(:,:,nloc(n),0) - else - kbeg = 1 - kend = kmvar2(n) - call ESMF_FieldGet(field,0,farrayPtr=ptr3d,_RC) - ptr3d = q(:,:,nloc(n):nloc(n)+kend-1,0) - endif - if( root ) write(6,3001) trim(vname2(n)),nloc(n),trim(hdfile) -3001 format(1x,'Writing ',a,' at location ',i6,' into File: ',a) - dum(:,:,1:kend) = q(:,:,nloc(n):nloc(n)+kend-1,0) - enddo - -! Quadratics -! ---------- - mv= nvars2 - do nv=1,nquad - if( qloc(1,nv)*qloc(2,nv).ne.0 ) then - mv=mv+1 - if( root ) write(6,3001) trim(vname2(mv)),nloc(mv),trim(hdfile) - call ESMF_FieldBundleGet(final_bundle,trim(vname2(mv)),field=field,_RC) - - if( kmvar2(qloc(1,nv)).eq.0 ) then - kbeg = 0 - kend = 1 - else - kbeg = 1 - kend = kmvar2(qloc(1,nv)) - endif - loc1 = nloc( qloc(1,nv) ) - loc2 = nloc( qloc(2,nv) ) - if( .not.lzstar(nv) ) then - where( q(:,:,nloc(mv):nloc(mv)+kend-1,0).ne.undef ) - dum(:,:,1:kend) = q(:,:,nloc(mv):nloc(mv)+kend-1,0) - q(:,:,loc1:loc1+kend-1,0) & - * q(:,:,loc2:loc2+kend-1,0) - elsewhere - dum(:,:,1:kend) = undef - endwhere - else - dum(:,:,1:kend) = q(:,:,nloc(mv):nloc(mv)+kend-1,0) - endif - if( kmvar2(qloc(1,nv)).eq.0 ) then - call ESMF_FieldGet(field,0,farrayPtr=ptr2d,_RC) - ptr2d = dum(:,:,1) - else - kend = kmvar2(qloc(1,nv)) - call ESMF_FieldGet(field,0,farrayPtr=ptr3d,_RC) - ptr3d = dum(:,:,1:kend) - endif - endif - enddo - - if( root ) then - print * - print *, 'Created: ',trim(hdfile) - print * - endif - call t_prof%stop('Write_AVE') - etime = local_esmf_timeset(nymd0,nhms0,_RC) - call ESMF_ClockSet(clock,currTime=etime, _RC) - call standard_writer%create_from_bundle(final_bundle,clock,n_steps=1,time_interval=timeinc,vertical_data=vertical_data,_RC) - call standard_writer%start_new_file(trim(hdfile),_RC) - call standard_writer%write_to_file(_RC) - -! ********************************************************************** -! **** Write HDF Monthly Diurnal Output File **** -! ********************************************************************** - - if( ntods.ne.0 ) then - call t_prof%start('Write_Diurnal') - timeinc = compute_nhmsf( 86400/ntods ) - - do k=1,ntods - - if( k.eq.1 .or. mdiurnal ) then - - write(date0,4000) nymd0/100 - write(time0,2000) nhms0/10000 - - if( diurnal ) hdfile = trim(doutput) // "." // trim(date0) // "." // trim(ext) - if( mdiurnal ) hdfile = trim(doutput) // "." // trim(date0) // "_" // trim(time0) // "z." // trim(ext) - - if( ldquad ) then - ndvars = mvars ! Include Quadratics in Diurnal Files - if (k==1) then - call copy_bundle_to_bundle(final_bundle,diurnal_bundle,_RC) - end if - else - ndvars = nvars2 ! Only Include Primary Fields in Diurnal Files (Default) - if (k==1) then - do n=1,nvars - call ESMF_FieldBundleGet(final_bundle,trim(vname2(n)),field=field,_RC) - call MAPL_FieldBundleAdd(diurnal_bundle,field,_RC) - enddo - endif - endif - endif - -! Primary Fields -! -------------- - do n=1,nvars2 - call ESMF_FieldBundleGet(diurnal_bundle,trim(vname2(n)),field=field,_RC) - if( kmvar2(n).eq.0 ) then - kbeg = 0 - kend = 1 - call ESMF_FieldGet(field,0,farrayPtr=ptr2d,_RC) - ptr2d = q(:,:,nloc(n),k) - else - kbeg = 1 - kend = kmvar2(n) - call ESMF_FieldGet(field,0,farrayPtr=ptr3d,_RC) - ptr3d = q(:,:,nloc(n):nloc(n)+kend-1,k) - endif - dum(:,:,1:kend) = q(:,:,nloc(n):nloc(n)+kend-1,k) - enddo - -! Quadratics -! ---------- - if( ndvars.eq.mvars ) then - mv= nvars2 - do nv=1,nquad - if( qloc(1,nv)*qloc(2,nv).ne.0 ) then - mv=mv+1 - call ESMF_FieldBundleGet(diurnal_bundle,trim(vname2(mv)),field=field,_RC) - if( kmvar2(qloc(1,nv)).eq.0 ) then - kbeg = 0 - kend = 1 - else - kbeg = 1 - kend = kmvar2(qloc(1,nv)) - endif - loc1 = nloc( qloc(1,nv) ) - loc2 = nloc( qloc(2,nv) ) - if( .not.lzstar(nv) ) then - where( q(:,:,nloc(mv):nloc(mv)+kend-1,0).ne.undef ) - dum(:,:,1:kend) = q(:,:,nloc(mv):nloc(mv)+kend-1,k) - q(:,:,loc1:loc1+kend-1,k) & - * q(:,:,loc2:loc2+kend-1,k) - elsewhere - dum(:,:,1:kend) = undef - endwhere - else - dum(:,:,1:kend) = q(:,:,nloc(mv):nloc(mv)+kend-1,k) - endif - if( kmvar2(qloc(1,nv)).eq.0 ) then - call ESMF_FieldGet(field,0,farrayPtr=ptr2d,_RC) - ptr2d = dum(:,:,1) - else - kend = kmvar2(qloc(1,nv)) - call ESMF_FieldGet(field,0,farrayPtr=ptr3d,_RC) - ptr3d = dum(:,:,1:kend) - endif - endif - enddo - endif - - - etime = local_esmf_timeset(nymd0,nhms0,_RC) - call ESMF_ClockSet(clock,currTime=etime, _RC) - if (k==1 .or. mdiurnal) then - if (mdiurnal) then - n_times = 1 - else - n_times = ntods - end if - if (k==1) then - call diurnal_writer%create_from_bundle(diurnal_bundle,clock,n_steps=n_times,time_interval=timeinc,vertical_data=vertical_data) - end if - call diurnal_writer%start_new_file(trim(hdfile),_RC) - end if - call diurnal_writer%write_to_file(_RC) - if( root .and. mdiurnal ) then - print *, 'Created: ',trim(hdfile) - endif - call tick (nymd0,nhms0,ndt) - enddo - - if( root .and. diurnal ) then - print *, 'Created: ',trim(hdfile) - endif - if( root ) print * - - call t_prof%stop('Write_Diurnal') - endif - -! ********************************************************************** -! **** Write Min/Max Information **** -! ********************************************************************** - - if( root ) print * - do n=1,nvars2 - do L=1,max(1,kmvar2(n)) - if( kmvar2(n).eq.0 ) then - plev = 0 - else - plev = lev(L) - endif - - call mpi_reduce( qmin(nloc(n)+L-1),qming,1,mpi_real,mpi_min,0,comm,ierror ) - call mpi_reduce( qmax(nloc(n)+L-1),qmaxg,1,mpi_real,mpi_max,0,comm,ierror ) - if( root ) then - if(L.eq.1) then - write(6,3101) trim(vname2(n)),plev,qming,qmaxg - else - write(6,3102) trim(vname2(n)),plev,qming,qmaxg - endif - endif -3101 format(1x,'Primary Field: ',a20,' Level: ',f9.3,' Min: ',g15.8,' Max: ',g15.8) -3102 format(1x,' ',a20,' Level: ',f9.3,' Min: ',g15.8,' Max: ',g15.8) - enddo - call MPI_BARRIER(comm,status) - if( root ) print * - enddo - if( root ) print * - -! ********************************************************************** -! **** Timing Information **** -! ********************************************************************** - - call io_server%finalize() - call t_prof%stop() - call t_prof%reduce() - call t_prof%finalize() - call generate_report() - call MAPL_Finalize() - call MPI_Finalize(status) - stop +module MAPL_ObsUtilMod + use ESMF + use MAPL_ErrorHandlingMod + use MAPL_KeywordEnforcerMod + use, intrinsic :: iso_fortran_env, only: REAL32, REAL64 + implicit none + integer, parameter :: mx_ngeoval = 60 contains - function create_output_grid(grid_name,lm,rc) result(new_grid) - type(ESMF_Grid) :: new_grid - character(len=*), intent(inout) :: grid_name - integer, intent(in) :: lm - integer, optional, intent(out) :: rc - - type(ESMF_Config) :: cf - integer :: nn,im_world,jm_world,nx, ny - character(len=5) :: imsz,jmsz - character(len=2) :: pole,dateline - - nn = len_trim(grid_name) - imsz = grid_name(3:index(grid_name,'x')-1) - jmsz = grid_name(index(grid_name,'x')+1:nn-3) - pole = grid_name(1:2) - dateline = grid_name(nn-1:nn) - read(IMSZ,*) im_world - read(JMSZ,*) jm_world - - cf = MAPL_ConfigCreate(_RC) - call MAPL_ConfigSetAttribute(cf,value=lm, label=trim(grid_name)//".LM:",_RC) - if (dateline=='CF') then - call MAPL_MakeDecomposition(nx,ny,reduceFactor=6,_RC) - call MAPL_ConfigSetAttribute(cf,value=NX, label=trim(grid_name)//".NX:",_RC) - call MAPL_ConfigSetAttribute(cf,value="Cubed-Sphere", label=trim(grid_name)//".GRID_TYPE:",_RC) - call MAPL_ConfigSetAttribute(cf,value=6, label=trim(grid_name)//".NF:",_RC) - call MAPL_ConfigSetAttribute(cf,value=im_world,label=trim(grid_name)//".IM_WORLD:",_RC) - call MAPL_ConfigSetAttribute(cf,value=ny, label=trim(grid_name)//".NY:",_RC) - else if (dateline=='TM') then - _FAIL("Tripolar not yet implemented for outpout") - else - call MAPL_MakeDecomposition(nx,ny,_RC) - call MAPL_ConfigSetAttribute(cf,value=NX, label=trim(grid_name)//".NX:",_RC) - call MAPL_ConfigSetAttribute(cf,value="LatLon", label=trim(grid_name)//".GRID_TYPE:",_RC) - call MAPL_ConfigSetAttribute(cf,value=im_world,label=trim(grid_name)//".IM_WORLD:",_RC) - call MAPL_ConfigSetAttribute(cf,value=jm_world,label=trim(grid_name)//".JM_WORLD:",_RC) - call MAPL_ConfigSetAttribute(cf,value=ny, label=trim(grid_name)//".NY:",_RC) - call MAPL_ConfigSetAttribute(cf,value=pole, label=trim(grid_name)//".POLE:",_RC) - call MAPL_ConfigSetAttribute(cf,value=dateline, label=trim(grid_name)//".DATELINE:",_RC) - if (pole=='XY' .and. dateline=='XY') then - _FAIL("regional lat-lon output not supported") - end if - end if - - new_grid = grid_manager%make_grid(cf,prefix=trim(grid_name)//".",_RC) - if (present(rc)) then - rc=_SUCCESS - end if - end function create_output_grid - - subroutine get_file_levels(filename,vertical_data,rc) - character(len=*), intent(in) :: filename - type(VerticalData), intent(inout) :: vertical_data - integer, intent(out), optional :: rc - - integer :: status - type(NetCDF4_fileFormatter) :: formatter - type(FileMetadata) :: basic_metadata - type(FileMetadataUtils) :: metadata - character(len=:), allocatable :: lev_name - character(len=ESMF_MAXSTR) :: long_name - character(len=ESMF_MAXSTR) :: standard_name - character(len=ESMF_MAXSTR) :: vcoord - character(len=ESMF_MAXSTR) :: lev_units - real, allocatable, target :: levs(:) - real, pointer :: plevs(:) - - call formatter%open(trim(filename),pFIO_Read,_RC) - basic_metadata=formatter%read(_RC) - call metadata%create(basic_metadata,trim(filename)) - lev_name = metadata%get_level_name(_RC) - if (lev_name /= '') then - call metadata%get_coordinate_info(lev_name,coords=levs,coordUnits=lev_units,long_name=long_name,& - standard_name=standard_name,coordinate_attr=vcoord,_RC) - plevs => levs - vertical_data = VerticalData(levels=plevs,vunit=lev_units,vcoord=vcoord,standard_name=standard_name,long_name=long_name, & - force_no_regrid=.true.,_RC) - nullify(plevs) - end if - - if (present(rc)) then - rc=_SUCCESS - end if - - end subroutine get_file_levels - - function has_level(grid,rc) result(grid_has_level) - logical :: grid_has_level - type(ESMF_Grid), intent(in) :: grid - integer, intent(out), optional :: rc - integer :: status, global_dims(3) - call MAPL_GridGet(grid,globalCellCountPerDim=global_dims,_RC) - grid_has_level = (global_dims(3)>1) - if (present(rc)) then - RC=_SUCCESS - end if - end function has_level - - subroutine copy_bundle_to_bundle(input_bundle,output_bundle,rc) - type(ESMF_FieldBundle), intent(inout) :: input_bundle - type(ESMF_FieldBundle), intent(inout) :: output_bundle - integer, intent(out), optional :: rc - integer :: status - character(len=ESMF_MAXSTR), allocatable :: field_list(:) - type(ESMF_Field) :: field - integer :: i,num_fields - call ESMF_FieldBundleGet(input_bundle,fieldCount=num_fields,_RC) - allocate(field_list(num_fields)) - call ESMF_FieldBundleGet(input_bundle,fieldNameList=field_list,_RC) - do i=1,num_fields - call ESMF_FieldBundleGet(input_bundle,field_list(i),field=field,_RC) - call MAPL_FieldBundleAdd(output_bundle,field,_RC) - enddo - if (present(rc)) then - RC=_SUCCESS - end if - end subroutine copy_bundle_to_bundle - - subroutine add_new_field_to_bundle(bundle,grid,lm,field_name,long_name,units,rc) - type(ESMF_FieldBundle), intent(inout) :: bundle - type(ESMF_Grid), intent(in) :: grid - integer, intent(in) :: lm - character(len=*), intent(in) :: field_name - character(len=*), intent(in) :: long_name - character(len=*), intent(in) :: units - integer, intent(out), optional :: rc - - integer :: status - type(ESMF_Field) :: field - - if (lm == 0) then - field = ESMF_FieldCreate(grid,name=trim(field_name),typekind=ESMF_TYPEKIND_R4,_RC) - else if (lm > 0) then - field = ESMF_FieldCreate(grid,name=trim(field_name),typekind=ESMF_TYPEKIND_R4, & - ungriddedLBound=[1],ungriddedUBound=[lm],_RC) - end if - call ESMF_AttributeSet(field,name='LONG_NAME',value=trim(long_name),_RC) - call ESMF_AttributeSet(field,name='UNITS',value=trim(units),_RC) - if (lm == 0) then - call ESMF_AttributeSet(field,name='DIMS',value=MAPL_DimsHorzOnly,_RC) - call ESMF_AttributeSet(field,name='VLOCATION',value=MAPL_VLocationNone,_RC) - else if (lm > 0) then - call ESMF_AttributeSet(field,name='DIMS',value=MAPL_DimsHorzVert,_RC) - call ESMF_AttributeSet(field,name='VLOCATION',value=MAPL_VLocationCenter,_RC) - end if - call MAPL_FieldBundleAdd(bundle,field,_RC) - if (present(rc)) then - RC=_SUCCESS - end if - end subroutine add_new_field_to_bundle - - subroutine get_file_times(file_metadata,num_times,time_series,time_interval,yymmdd,hhmmss,rc) - type(FileMetadataUtils), intent(inout) :: file_metadata - integer, intent(out) :: num_times - type(ESMF_Time), allocatable, intent(inout) :: time_series(:) - integer, intent(inout), allocatable :: yymmdd(:) - integer, intent(inout), allocatable :: hhmmss(:) - integer, intent(out) :: time_interval - integer, intent(out), optional :: rc + ! --//-------------------------------------//-> + ! files + ! o o o o o o o o o o T: filename + ! <--- off set + ! o o o o o o o o o o T: file content start + ! | | + ! curr curr+Epoch + ! + + subroutine Find_M_files_for_currTime (currTime, & + obsfile_start_time, obsfile_end_time, obsfile_interval, & + epoch_frequency, file_template, M, filenames, & + T_offset_in_file_content, rc) + implicit none + type(ESMF_Time), intent(in) :: currTime + type(ESMF_Time), intent(in) :: obsfile_start_time, obsfile_end_time + type(ESMF_TimeInterval), intent(in) :: obsfile_interval, epoch_frequency + type(ESMF_TimeInterval), intent(in), optional :: T_offset_in_file_content + character(len=*), intent(in) :: file_template + integer, intent(out) :: M + character(len=ESMF_MAXSTR) :: filenames(200) + integer, optional, intent(out) :: rc + + type(ESMF_Time) :: T1, Tn + type(ESMF_Time) :: cT1 + type(ESMF_Time) :: Ts, Te + type(ESMF_TimeInterval) :: dT1, dT2, dTs, dTe + type(ESMF_TimeInterval) :: Toff + real(ESMF_KIND_R8) :: dT0_s, dT1_s, dT2_s + real(ESMF_KIND_R8) :: s1, s2 + + integer :: obsfile_Ts_index, obsfile_Te_index + integer :: n1, n2 + integer :: i, j + integer :: status + + !__ s1. Arithmetic index list + ! + + if (present(T_offset_in_file_content)) then + Toff = T_offset_in_file_content + else + s1 = 0 + call ESMF_TimeIntervalSet(Toff, s_r8=s1, rc=status) + endif + + T1 = obsfile_start_time + Toff + Tn = obsfile_end_time + Toff + + cT1 = currTime + dT1 = currTime - T1 + dT2 = currTime + epoch_frequency - T1 + + call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) + call ESMF_TimeIntervalGet(dT1, s_r8=dT1_s, rc=status) + call ESMF_TimeIntervalGet(dT2, s_r8=dT2_s, rc=status) + n1 = floor (dT1_s / dT0_s) + n2 = floor (dT2_s / dT0_s) + + obsfile_Ts_index = n1 + if ( dT2_s - n2*dT0_s < 1 ) then + obsfile_Te_index = n2 - 1 + else + obsfile_Te_index = n2 + end if + + ! put back + n1 = obsfile_Ts_index + n2 = obsfile_Te_index + + + !__ s2. further test file existence + ! + j=0 + do i= n1, n2 + j=j+1 + filenames(j) = get_filename_from_template_use_index & + (obsfile_start_time, obsfile_interval, & + i, file_template, rc=rc) + end do + + + end subroutine Find_M_files_for_currTime - integer :: status - type(ESMF_TimeInterval) :: esmf_time_interval - integer :: hour, minute, second, year, month, day, i - - num_times = file_metadata%get_dimension('time',_RC) - call file_metadata%get_time_info(timeVector=time_series,_RC) - if (num_times == 1) then - time_interval = file_metadata%get_var_attr_int32('time','time_increment',_RC) - else if (num_times > 1) then - esmf_time_interval = time_series(2)-time_series(1) - call ESMF_TimeIntervalGet(esmf_time_interval,h=hour,m=minute,s=second,_RC) - time_interval = hour*10000+minute*100+second - end if - - allocate(yymmdd(num_times),hhmmss(num_times)) - do i = 1,num_times - call ESMF_TimeGet(time_series(i),yy=year,mm=month,dd=day,h=hour,m=minute,s=second,_RC) - yymmdd(i)=year*10000+month*100+day - hhmmss(i)=hour*10000+minute*100+second - enddo - if (present(rc)) then - rc=_SUCCESS - end if - end subroutine get_file_times - - function get_level_info(bundle,rc) result(kmvar) - integer, allocatable :: kmvar(:) - type(ESMF_FieldBundle), intent(in) :: bundle - integer, optional, intent(out) :: rc - - integer :: status - character(len=ESMF_MAXSTR), allocatable :: field_list(:) - type(ESMF_Field) :: field - integer :: rank,i,num_fields,lb(1),ub(1) - call ESMF_FieldBundleGet(bundle,fieldCount=num_fields,_RC) - allocate(field_list(num_fields)) - allocate(kmvar(num_fields)) - call ESMF_FieldBundleGet(bundle,fieldNameList=field_list,_RC) - do i=1,num_fields - call ESMF_FieldBundleGet(bundle,field_list(i),field=field,_RC) - call ESMF_FieldGet(field,rank=rank,_RC) - if (rank==2) then - kmvar(i)=0 - else if (rank==3) then - call ESMF_FieldGet(field,ungriddedLBound=lb,ungriddedUBound=ub,_RC) - kmvar(i)=ub(1)-lb(1)+1 - else - _FAIL("Unsupported rank") - end if - end do - if (present(rc)) then - RC=_SUCCESS - end if - end function get_level_info - - function get_long_names(bundle,rc) result(long_names) - character(len=ESMF_MAXSTR), allocatable :: long_names(:) - type(ESMF_FieldBundle), intent(in) :: bundle - integer, optional, intent(out) :: rc - - integer :: status - character(len=ESMF_MAXSTR), allocatable :: field_list(:) - type(ESMF_Field) :: field - integer :: i,num_fields - - call ESMF_FieldBundleGet(bundle,fieldCount=num_fields,_RC) - allocate(field_list(num_fields)) - allocate(long_names(num_fields)) - call ESMF_FieldBundleGet(bundle,fieldNameList=field_list,_RC) - do i=1,num_fields - call ESMF_FieldBundleGet(bundle,field_list(i),field=field,_RC) - call ESMF_AttributeGet(field,name='LONG_NAME',value=long_names(i),_RC) - enddo - if (present(rc)) then - RC=_SUCCESS - end if - end function get_long_names - - function get_units(bundle,rc) result(units) - character(len=ESMF_MAXSTR), allocatable :: units(:) - type(ESMF_FieldBundle), intent(in) :: bundle - integer, optional, intent(out) :: rc - - integer :: status - character(len=ESMF_MAXSTR), allocatable :: field_list(:) - type(ESMF_Field) :: field - integer :: i,num_fields - - call ESMF_FieldBundleGet(bundle,fieldCount=num_fields,_RC) - allocate(field_list(num_fields)) - allocate(units(num_fields)) - call ESMF_FieldBundleGet(bundle,fieldNameList=field_list,_RC) - do i=1,num_fields - call ESMF_FieldBundleGet(bundle,field_list(i),field=field,_RC) - call ESMF_AttributeGet(field,name='UNITS',value=units(i),_RC) - enddo - if (present(rc)) then - RC=_SUCCESS - end if - end function get_units - - function local_esmf_timeset(yymmdd,hhmmss,rc) result(etime) - type(ESMF_Time) :: etime - integer, intent(in) :: yymmdd - integer, intent(in) :: hhmmss - integer, intent(out), optional :: rc - - integer :: year,month,day,hour,minute,second,status - year = yymmdd/10000 - month = mod(yymmdd/100,100) - day = mod(yymmdd,100) - - hour = hhmmss/10000 - minute = mod(hhmmss/100,100) - second = mod(hhmmss,100) - - call ESMF_TimeSet(etime,yy=year,mm=month,dd=day,h=hour,m=minute,s=second,_RC) - if (present(rc)) then - rc=_SUCCESS - endif - end function local_esmf_timeset - - function defined ( q,undef ) - implicit none - logical defined - real q,undef - defined = q /= undef - end function defined - - subroutine latlon_zstar (q,qp,undef,grid,rc) - real, intent(inout) :: q(:,:) - real, intent(out) :: qp(:,:) - real, intent(in) :: undef - type (ESMF_Grid), intent(inout) :: grid - integer, optional, intent(out) :: rc - - integer :: local_dims(3) - integer im,jm,i,j,status - real, allocatable :: qz(:) - - call MAPL_GridGet(grid,localCellCountPerDim=local_dims,_RC) - im = local_dims(1) - jm = local_dims(2) - allocate(qz(jm)) - - call latlon_zmean ( q,qz,undef,grid ) - do j=1,jm - if( qz(j).eq. undef ) then - qp(:,j) = undef - else - do i=1,im - if( defined( q(i,j),undef) ) then - qp(i,j) = q(i,j) - qz(j) - else - qp(i,j) = undef - endif - enddo - endif - enddo - if (present(rc)) then - rc=_SUCCESS - endif - end subroutine latlon_zstar - - subroutine latlon_zmean ( q,qz,undef,grid,rc) - real, intent(inout) :: q(:,:) - real, intent(inout) :: qz(:) - real, intent(in) :: undef - type(ESMF_Grid), intent(inout) :: grid - integer, optional, intent(out) :: rc - - integer :: im,jm,im_global,jm_global,local_dims(3),global_dims(3),status,nx,ny - real, allocatable :: qg(:,:) - real, allocatable :: buf(:,:) - real :: qsum - integer :: mpistatus(mpi_status_size) - integer, allocatable :: ims(:),jms(:) - integer j,n,peid,peid0,i1,j1,in,jn,mypet,i_start,i_end,isum - type(ESMF_VM) :: vm - - call ESMF_VMGetCurrent(vm,_RC) - call ESMF_VMGet(vm,localPet=mypet,_RC) - call MAPL_GridGet(grid,localCellCountPerDim=local_dims,globalCellCountPerDim=global_dims,_RC) - im = local_dims(1) - jm = local_dims(2) - im_global = global_dims(1) - jm_global = global_dims(2) - call get_esmf_grid_layout(grid,nx,ny,ims,jms,_RC) - call mapl_grid_interior(grid,i1,in,j1,jn) - - qz = 0.0 - allocate( qg(im_global,jm) ) - peid0 = (mypet/nx)*ny - if (i1==1) then - i_start = 1 - i_end = ims(1) - qg(i_start:i_end,:)=q - do n=1,nx-1 - allocate(buf(ims(n+1),jm)) - peid = mypet + n - call mpi_recv(buf,ims(n+1)*jm,MPI_FLOAT,peid,peid,MPI_COMM_WORLD,mpistatus,status) - _VERIFY(status) - i_start=i_end+1 - i_end = i_start+ims(n)-1 - qg(i_start:i_end,:)=buf - deallocate(buf) - enddo - else - call mpi_send(q,im*jm,MPI_FLOAT,peid0,mypet,MPI_COMM_WORLD,status) - _VERIFY(status) - end if - -! compute zonal mean - if (i1 == 1) then - do j=1,jm - isum = count(qg(:,j) /= undef) - qsum = sum(qg(:,j),mask=qg(:,j)/=undef) - if (isum == 0) then - qz(j)=undef - else - qz(j)=qsum/real(isum) - end if - enddo - -! send mean back to other ranks - do n=1,nx-1 - peid = peid0+n - call mpi_send(qz,jm,MPI_FLOAT,peid,peid0,MPI_COMM_WORLD,status) - _VERIFY(status) - enddo - else - call mpi_recv(qz,jm,MPI_FLOAT,peid0,peid0,MPI_COMM_WORLD,mpistatus,status) - _VERIFY(status) - end if - - if (present(rc)) then - rc=_SUCCESS - endif - - end subroutine latlon_zmean - - subroutine get_esmf_grid_layout(grid,nx,ny,ims_out,jms_out,rc) - type(ESMF_Grid), intent(inout) :: grid - integer, intent(out) :: nx - integer, intent(out) :: ny - integer, intent(inout), allocatable :: ims_out(:) - integer, intent(inout), allocatable :: jms_out(:) - integer, optional, intent(out) :: rc +! +! subroutine read_M_files ( filenames, Xdim, Y_dim, & +! lon_name, lat_name, time_name, & +! lon, lat, time ) +! + - type(ESMF_VM) :: vm - integer :: status - type(ESMF_DistGrid) :: dist_grid - integer, allocatable :: minindex(:,:),maxindex(:,:) - integer :: dim_count, ndes - integer, pointer :: ims(:),jms(:) - call ESMF_VMGetCurrent(vm,_RC) - call ESMF_VMGet(vm,petCount=ndes,_RC) - call ESMF_GridGet(grid,distgrid=dist_grid,dimCOunt=dim_count,_RC) - allocate(minindex(dim_count,ndes),maxindex(dim_count,ndes)) - call MAPL_DistGridGet(dist_grid,minIndex=minindex,maxIndex=maxindex,_RC) - call MAPL_GetImsJms(minindex(1,:),maxindex(1,:),minindex(2,:),maxindex(2,:),ims,jms,_RC) - nx = size(ims) - ny = size(jms) - allocate(ims_out(nx),jms_out(ny)) - ims_out = ims - jms_out = jms - if (present(rc)) then - rc=_SUCCESS - endif + function get_filename_from_template_use_index (obsfile_start_time, obsfile_interval, & + f_index, file_template, rc) result(filename) + use Plain_netCDF_Time, only : ESMF_time_to_two_integer + use MAPL_StringTemplate, only : fill_grads_template + character(len=ESMF_MAXSTR) :: filename + type(ESMF_Time), intent(in) :: obsfile_start_time + type(ESMF_TimeInterval), intent(in) :: obsfile_interval + character(len=*), intent(in) :: file_template + integer, intent(in) :: f_index + integer, optional, intent(out) :: rc - end subroutine get_esmf_grid_layout + integer :: itime(2) + integer :: nymd, nhms + integer :: status + real(ESMF_KIND_R8) :: dT0_s + real(ESMF_KIND_R8) :: s + type(ESMF_TimeInterval) :: dT + type(ESMF_Time) :: time - subroutine check_quad ( quad,vname,nvars,aliases,nalias,qloc ) - integer :: nvars, nalias - character(len=ESMF_MAXSTR) quad(2), aliases(2,nalias), vname(nvars) - integer qloc(2) - integer m,n + call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) + s = dT0_s * f_index + call ESMF_TimeIntervalSet(dT, s_r8=s, rc=status) + time = obsfile_start_time + dT -! Initialize Location of Quadratics -! --------------------------------- - qloc = 0 + call ESMF_time_to_two_integer(time, itime, _RC) + nymd = itime(1) + nhms = itime(2) + call fill_grads_template ( filename, file_template, & + experiment_id='', nymd=nymd, nhms=nhms, _RC ) -! Check Quadratic Name against HDF Variable Names -! ----------------------------------------------- - do n=1,nvars - if( trim(vname(n)).eq.trim(quad(1)) ) qloc(1) = n - if( trim(vname(n)).eq.trim(quad(2)) ) qloc(2) = n - enddo + rc=0 -! Check Quadratic Name against Aliases -! ------------------------------------ - do m=1,nalias - if( trim(quad(1)).eq.trim(aliases(1,m)) ) then - do n=1,nvars - if( trim(vname(n)).eq.trim(quad(1)) .or. & - trim(vname(n)).eq.trim(aliases(2,m)) ) then - qloc(1) = n - exit - endif - enddo - endif - if( trim(quad(2)).eq.trim(aliases(1,m)) ) then - do n=1,nvars - if( trim(vname(n)).eq.trim(quad(2)) .or. & - trim(vname(n)).eq.trim(aliases(2,m)) ) then - qloc(2) = n - exit - endif - enddo - endif - enddo + end function get_filename_from_template_use_index - end subroutine check_quad +end module MAPL_ObsUtilMod - function compute_nsecf (nhms) result(seconds) - integer :: seconds - integer, intent(in) :: nhms - seconds = nhms/10000*3600 + mod(nhms,10000)/100*60 + mod(nhms,100) - end function compute_nsecf - function compute_nhmsf (nsec) result(nhmsf) - integer :: nhmsf - integer, intent(in) :: nsec - nhmsf = nsec/3600*10000 + mod(nsec,3600)/60*100 + mod(nsec,60) - end function compute_nhmsf - subroutine tick (nymd,nhms,ndt) - integer, intent(inout) :: nymd - integer, intent(inout) :: nhms - integer, intent(in) :: ndt +program main + use ESMF + use MAPL_ObsUtilMod + implicit none - integer :: nsec + type(ESMF_Time) :: currTime + type(ESMF_Time) :: obsfile_start_time, obsfile_end_time + type(ESMF_TimeInterval) :: obsfile_interval, epoch_frequency + type(ESMF_TimeInterval) :: Toff + character(len=ESMF_MAXSTR) :: file_template + character(len=ESMF_MAXSTR) :: STR1 + character(len=ESMF_MAXSTR) :: filenames(200) + integer :: M + integer :: sec - if(ndt.ne.0) then - nsec = compute_nsecf(nhms) + ndt + integer :: rc - if (nsec.gt.86400) then - do while (nsec.gt.86400) - nsec = nsec - 86400 - nymd = compute_incymd (nymd,1) - enddo - endif - if (nsec.eq.86400) then - nsec = 0 - nymd = compute_incymd (nymd,1) - endif + file_template = '/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A%y4%D3.%h2%n2.*.hdf' - if (nsec.lt.00000) then - do while (nsec.lt.0) - nsec = 86400 + nsec - nymd = compute_incymd (nymd,-1) - enddo - endif + STR1='20170331T000000' + call ESMF_TimeSet(obsfile_start_time, STR1, rc=rc) - nhms = compute_nhmsf (nsec) - endif + STR1='20170331T230000' + call ESMF_TimeSet(obsfile_end_time, STR1, rc=rc) - end subroutine tick + sec = 300 + call ESMF_TimeIntervalSet(obsfile_interval, s_r8=300., rc=status) - function compute_incymd (nymd,m) result(incymd) - integer :: incymd - integer, intent(in) :: nymd - integer, intent(in) :: m -!*********************************************************************** -! purpose -! incymd: nymd changed by one day -! modymd: nymd converted to julian date -! description of parameters -! nymd current date in yymmdd format -! m +/- 1 (day adjustment) +! STR1='20170331T010000' +! call ESMF_TimeSet(currTime, STR1, rc=rc) ! -!*********************************************************************** -!* goddard laboratory for atmospheres * -!*********************************************************************** - - integer ndpm(12) - data ndpm /31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/ - integer :: ny,nm,nd -!*********************************************************************** +! sec = 3600 +! call ESMF_TimeIntervalSet(Epoch_frequency, s=3600, rc=status) ! - ny = nymd / 10000 - nm = mod(nymd,10000) / 100 - nd = mod(nymd,100) + m - - if (nd.eq.0) then - nm = nm - 1 - if (nm.eq.0) then - nm = 12 - ny = ny - 1 - endif - nd = ndpm(nm) - if (nm.eq.2 .and. is_leap_year(ny)) nd = 29 - endif - - if (nd.eq.29 .and. nm.eq.2 .and. is_leap_year(ny)) go to 20 - - if (nd.gt.ndpm(nm)) then - nd = 1 - nm = nm + 1 - if (nm.gt.12) then - nm = 1 - ny = ny + 1 - endif - endif - -20 continue - incymd = ny*10000 + nm*100 + nd - return - - end function compute_incymd - - logical function is_leap_year(year) - integer, intent(in) :: year - is_leap_year = (mod(year,4) == 0) .and. (mod(year,100) == 0 .or. mod(year,400) == 0) - end function is_leap_year - - subroutine usage(root) - logical, intent(in) :: root - integer :: status,errorcode - if(root) then - write(6,100) -100 format( "usage: ",/,/ & - " time_ave.x -hdf filenames (in hdf format)",/ & - " <-template template>" ,/ & - " <-tag tag>" ,/ & - " <-rc rcfile>" ,/ & - " <-ntod ntod>" ,/ & - " <-ntmin ntmin>" ,/ & - " <-strict strict>" ,/ & - " <-d>" ,/ & - " <-md>" ,/,/ & - "where:",/,/ & - " -hdf filenames: filenames (in hdf format) to average",/ & - " -template template: filename to use as template if hdf files differ (default: 1st filename)",/ & - " -begdate yyyymmdd: optional parameter for date to begin averaging",/ & - " -begtime hhmmss: optional parameter for time to begin averaging",/ & - " -enddate yyyymmdd: optional parameter for date to end averaging",/ & - " -endtime hhmmss: optional parameter for time to end averaging",/ & - " -tag tag: optional tag for output file (default: monthly_ave)",/ & - " -rc rcfile: optional resource filename for quadratics (default: no quadratics)",/ & - " -ntod ntod: optional time-of-day (hhmmss) to average (default: all time periods)",/ & - " -ntmin ntmin: optional parameter for required min. timeperiods (default: 10 days equiv)",/ & - " -strict strict: optional logical parameter for strict time testing (default: .true.)",/ & - " -d dtag: optional parameter to create & tag monthly mean diurnal file ", & - "(all times included)",/ & - " -md dtag: optional parameter to create & tag multiple monthly mean diurnal files ", & - "(one time per file)",/ & - " -dv dtag: like -d but includes diurnal variances",/ & - " -mdv dtag: like -md but includes diurnal variances",/ & - ) - endif - call MPI_Abort(MPI_COMM_WORLD,errorcode,status) - end subroutine usage - - subroutine generate_report() - - character(:), allocatable :: report_lines(:) - integer :: i - character(1) :: empty(0) - - reporter = ProfileReporter(empty) - call reporter%add_column(NameColumn(20)) - call reporter%add_column(FormattedTextColumn('Inclusive','(f9.6)', 9, InclusiveColumn('MEAN'))) - call reporter%add_column(FormattedTextColumn('% Incl','(f6.2)', 6, PercentageColumn(InclusiveColumn('MEAN'),'MAX'))) - call reporter%add_column(FormattedTextColumn('Exclusive','(f9.6)', 9, ExclusiveColumn('MEAN'))) - call reporter%add_column(FormattedTextColumn('% Excl','(f6.2)', 6, PercentageColumn(ExclusiveColumn('MEAN')))) - call reporter%add_column(FormattedTextColumn(' Max Excl)','(f9.6)', 9, ExclusiveColumn('MAX'))) - call reporter%add_column(FormattedTextColumn(' Min Excl)','(f9.6)', 9, ExclusiveColumn('MIN'))) - call reporter%add_column(FormattedTextColumn('Max PE)','(1x,i4.4,1x)', 6, ExclusiveColumn('MAX_PE'))) - call reporter%add_column(FormattedTextColumn('Min PE)','(1x,i4.4,1x)', 6, ExclusiveColumn('MIN_PE'))) - report_lines = reporter%generate_report(t_prof) - if (mapl_am_I_root()) then - write(*,'(a)')'Final profile' - write(*,'(a)')'=============' - do i = 1, size(report_lines) - write(*,'(a)') report_lines(i) - end do - write(*,'(a)') '' - end if - end subroutine generate_report - - -end program time_ave +! sec = 60 +! call ESMF_TimeIntervalSet(Toff, s=60, rc=status) +! +! call Find_M_files_for_currTime (currTime, & +! obsfile_start_time, obsfile_end_time, obsfile_interval, & +! epoch_frequency, file_template, M, filenames, & +! T_offset_in_file_content = Toff, rc = rc) + + end program main From 4f8569c90263d5560cf69ffa699cee2af8b0c7f7 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Sat, 11 Nov 2023 07:35:46 -0700 Subject: [PATCH 15/41] . --- Apps/time_ave_util.F90 | 96 ++++++++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 32 deletions(-) diff --git a/Apps/time_ave_util.F90 b/Apps/time_ave_util.F90 index 9364fd379eaa..a38f55c3e22b 100644 --- a/Apps/time_ave_util.F90 +++ b/Apps/time_ave_util.F90 @@ -31,7 +31,7 @@ subroutine Find_M_files_for_currTime (currTime, & type(ESMF_TimeInterval), intent(in), optional :: T_offset_in_file_content character(len=*), intent(in) :: file_template integer, intent(out) :: M - character(len=ESMF_MAXSTR) :: filenames(200) + character(len=ESMF_MAXSTR), intent(out) :: filenames(200) integer, optional, intent(out) :: rc type(ESMF_Time) :: T1, Tn @@ -47,22 +47,26 @@ subroutine Find_M_files_for_currTime (currTime, & integer :: i, j integer :: status - !__ s1. Arithmetic index list + !__ s1. Arithmetic index list based on s,e,interval ! - + print*, __LINE__, __FILE__ if (present(T_offset_in_file_content)) then Toff = T_offset_in_file_content else - s1 = 0 + s1 = 0.d0 call ESMF_TimeIntervalSet(Toff, s_r8=s1, rc=status) endif - T1 = obsfile_start_time + Toff - Tn = obsfile_end_time + Toff +! T1 = obsfile_start_time + Toff +! Tn = obsfile_end_time + Toff + + T1 = obsfile_start_time + Tn = obsfile_end_time cT1 = currTime dT1 = currTime - T1 - dT2 = currTime + epoch_frequency - T1 + ! dT2 = currTime + epoch_frequency - T1 + dT2 = dT1 + epoch_frequency call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) call ESMF_TimeIntervalGet(dT1, s_r8=dT1_s, rc=status) @@ -70,6 +74,11 @@ subroutine Find_M_files_for_currTime (currTime, & n1 = floor (dT1_s / dT0_s) n2 = floor (dT2_s / dT0_s) + print*, '1st n1, n2', n1, n2 + print*, 'ck dT0_s, dT1_s, dT2_s', dT0_s, dT1_s, dT2_s + stop -3 + + obsfile_Ts_index = n1 if ( dT2_s - n2*dT0_s < 1 ) then obsfile_Te_index = n2 - 1 @@ -81,6 +90,8 @@ subroutine Find_M_files_for_currTime (currTime, & n1 = obsfile_Ts_index n2 = obsfile_Te_index + print*, __LINE__, __FILE__ + print*, '2nd n1, n2', n1, n2 !__ s2. further test file existence ! @@ -99,10 +110,6 @@ end subroutine Find_M_files_for_currTime ! subroutine read_M_files ( filenames, Xdim, Y_dim, & ! lon_name, lat_name, time_name, & ! lon, lat, time ) -! - - - function get_filename_from_template_use_index (obsfile_start_time, obsfile_interval, & f_index, file_template, rc) result(filename) @@ -122,18 +129,32 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter real(ESMF_KIND_R8) :: s type(ESMF_TimeInterval) :: dT type(ESMF_Time) :: time + integer :: j + + print*, __LINE__, __FILE__ call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) s = dT0_s * f_index call ESMF_TimeIntervalSet(dT, s_r8=s, rc=status) time = obsfile_start_time + dT + print*, __LINE__, __FILE__ call ESMF_time_to_two_integer(time, itime, _RC) nymd = itime(1) nhms = itime(2) + + j= index(file_template, '*') + if (j>0) then + ! wild char exist + print*, 'pos of * in template =', j + endif + call fill_grads_template ( filename, file_template, & experiment_id='', nymd=nymd, nhms=nhms, _RC ) + print*, 'new filename=', trim(filename) + stop -1 + rc=0 end function get_filename_from_template_use_index @@ -155,34 +176,45 @@ program main character(len=ESMF_MAXSTR) :: STR1 character(len=ESMF_MAXSTR) :: filenames(200) integer :: M - integer :: sec - - integer :: rc - + integer :: i + real(KIND=ESMF_KIND_R8) :: sec + integer :: rc, status + type(ESMF_Calendar) :: gregorianCalendar file_template = '/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A%y4%D3.%h2%n2.*.hdf' + gregorianCalendar = ESMF_CalendarCreate(ESMF_CALKIND_GREGORIAN, name='Gregorian_obs' , rc=rc) + + + STR1='2017-03-31T00:00:00' + call ESMF_TimeSet(currTime, STR1, rc=rc) - STR1='20170331T000000' + STR1='2017-03-31T00:00:00' call ESMF_TimeSet(obsfile_start_time, STR1, rc=rc) - STR1='20170331T230000' + STR1='2017-04-01T00:00:00' call ESMF_TimeSet(obsfile_end_time, STR1, rc=rc) - sec = 300 - call ESMF_TimeIntervalSet(obsfile_interval, s_r8=300., rc=status) + sec = 300.d0 + call ESMF_TimeIntervalSet(obsfile_interval, s_r8=sec, rc=status) -! STR1='20170331T010000' -! call ESMF_TimeSet(currTime, STR1, rc=rc) -! -! sec = 3600 -! call ESMF_TimeIntervalSet(Epoch_frequency, s=3600, rc=status) -! -! sec = 60 -! call ESMF_TimeIntervalSet(Toff, s=60, rc=status) -! -! call Find_M_files_for_currTime (currTime, & -! obsfile_start_time, obsfile_end_time, obsfile_interval, & -! epoch_frequency, file_template, M, filenames, & -! T_offset_in_file_content = Toff, rc = rc) +! sec = 3600.d0 +! call ESMF_TimeIntervalSet(Epoch_frequency, s_r8=sec, rc=status) + + call ESMF_TimeIntervalSet(Epoch_frequency, m=59, rc=status) + + ! sec = 60.d0 + sec = 0.d0 + call ESMF_TimeIntervalSet(Toff, s_r8=sec, rc=status) + + call Find_M_files_for_currTime (currTime, & + obsfile_start_time, obsfile_end_time, obsfile_interval, & + epoch_frequency, file_template, M, filenames, & + T_offset_in_file_content = Toff, rc = rc) + + stop -2 + write(6,*) 'M=', M + do i=1, M + write(6,*) 'filenames(i)=', trim(filenames(i)) + end do end program main From e5caaa31f3ae3e46a0b7ac032dc586d996d14dd4 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Mon, 13 Nov 2023 11:49:05 -0700 Subject: [PATCH 16/41] wip --- Apps/time_ave_util.F90 | 59 ++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/Apps/time_ave_util.F90 b/Apps/time_ave_util.F90 index a38f55c3e22b..92d651b4404f 100644 --- a/Apps/time_ave_util.F90 +++ b/Apps/time_ave_util.F90 @@ -28,10 +28,10 @@ subroutine Find_M_files_for_currTime (currTime, & type(ESMF_Time), intent(in) :: currTime type(ESMF_Time), intent(in) :: obsfile_start_time, obsfile_end_time type(ESMF_TimeInterval), intent(in) :: obsfile_interval, epoch_frequency - type(ESMF_TimeInterval), intent(in), optional :: T_offset_in_file_content character(len=*), intent(in) :: file_template integer, intent(out) :: M character(len=ESMF_MAXSTR), intent(out) :: filenames(200) + type(ESMF_TimeInterval), intent(in), optional :: T_offset_in_file_content integer, optional, intent(out) :: rc type(ESMF_Time) :: T1, Tn @@ -53,8 +53,7 @@ subroutine Find_M_files_for_currTime (currTime, & if (present(T_offset_in_file_content)) then Toff = T_offset_in_file_content else - s1 = 0.d0 - call ESMF_TimeIntervalSet(Toff, s_r8=s1, rc=status) + call ESMF_TimeIntervalSet(Toff, h=0, m=0, s=60, rc=status) endif ! T1 = obsfile_start_time + Toff @@ -65,18 +64,17 @@ subroutine Find_M_files_for_currTime (currTime, & cT1 = currTime dT1 = currTime - T1 - ! dT2 = currTime + epoch_frequency - T1 - dT2 = dT1 + epoch_frequency - + dT2 = currTime + epoch_frequency - T1 + call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) call ESMF_TimeIntervalGet(dT1, s_r8=dT1_s, rc=status) call ESMF_TimeIntervalGet(dT2, s_r8=dT2_s, rc=status) + n1 = floor (dT1_s / dT0_s) n2 = floor (dT2_s / dT0_s) - print*, '1st n1, n2', n1, n2 print*, 'ck dT0_s, dT1_s, dT2_s', dT0_s, dT1_s, dT2_s - stop -3 + print*, '1st n1, n2', n1, n2 obsfile_Ts_index = n1 @@ -131,6 +129,11 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter type(ESMF_Time) :: time integer :: j + character(len=ESMF_MAXSTR) :: file_template_left + character(len=ESMF_MAXSTR) :: file_template_right + character(len=ESMF_MAXSTR) :: filename_left + character(len=ESMF_MAXSTR) :: filename_full + print*, __LINE__, __FILE__ call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) @@ -147,12 +150,18 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter if (j>0) then ! wild char exist print*, 'pos of * in template =', j + file_template_left = file_template(1:j-1) + else + file_template_left = file_template endif - - call fill_grads_template ( filename, file_template, & + write(6,*) 'file_template_left=', trim(file_template_left) + + call fill_grads_template ( filename_left, file_template_left, & experiment_id='', nymd=nymd, nhms=nhms, _RC ) - print*, 'new filename=', trim(filename) + print*, 'new filename_left=', trim(filename_left) + + print*, 'new filename=', trim(filename) stop -1 rc=0 @@ -185,24 +194,28 @@ program main gregorianCalendar = ESMF_CalendarCreate(ESMF_CALKIND_GREGORIAN, name='Gregorian_obs' , rc=rc) - STR1='2017-03-31T00:00:00' - call ESMF_TimeSet(currTime, STR1, rc=rc) +! STR1='2017-03-31T00:00:00' +! call ESMF_TimeSet(currTime, trim(STR1), rc=rc) + +! STR1='2017-03-31T00:00:00' +! call ESMF_TimeSet(obsfile_start_time, trim(STR1), rc=rc) - STR1='2017-03-31T00:00:00' - call ESMF_TimeSet(obsfile_start_time, STR1, rc=rc) +! STR1='2017-04-01T00:00:00' +! call ESMF_TimeSet(obsfile_end_time, trim(STR1), rc=rc) - STR1='2017-04-01T00:00:00' - call ESMF_TimeSet(obsfile_end_time, STR1, rc=rc) + call ESMF_TimeSet(currTime, yy=2007, mm=3, dd=31, h=0, m=0, s=0, & + calendar=gregorianCalendar, rc=rc) + obsfile_start_time = currTime + call ESMF_TimeSet(obsfile_end_time, yy=2008, mm=3, dd=31, h=0, m=0, s=0, & + calendar=gregorianCalendar, rc=rc) + sec = 300.d0 - call ESMF_TimeIntervalSet(obsfile_interval, s_r8=sec, rc=status) - -! sec = 3600.d0 -! call ESMF_TimeIntervalSet(Epoch_frequency, s_r8=sec, rc=status) + call ESMF_TimeIntervalSet(obsfile_interval, h=0, m=5, s=0, rc=rc) - call ESMF_TimeIntervalSet(Epoch_frequency, m=59, rc=status) + sec = 3600.d0 + call ESMF_TimeIntervalSet(Epoch_frequency, h=1, m=0, s=0, rc=rc) - ! sec = 60.d0 sec = 0.d0 call ESMF_TimeIntervalSet(Toff, s_r8=sec, rc=status) From 88f60f8c3e5d82dce5e65313bac1da4b304f2dbc Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Tue, 14 Nov 2023 09:07:12 -0700 Subject: [PATCH 17/41] make it work with - DOY - cmd=bash -c 'ls /Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.*.hdf' &> zzz_MAPL --- Apps/time_ave_util.F90 | 35 ++++++++++++++++++++++++++++------- base/StringTemplate.F90 | 9 +++++++-- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/Apps/time_ave_util.F90 b/Apps/time_ave_util.F90 index 92d651b4404f..e9d89dcb305d 100644 --- a/Apps/time_ave_util.F90 +++ b/Apps/time_ave_util.F90 @@ -127,12 +127,13 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter real(ESMF_KIND_R8) :: s type(ESMF_TimeInterval) :: dT type(ESMF_Time) :: time - integer :: j + integer :: i, j character(len=ESMF_MAXSTR) :: file_template_left character(len=ESMF_MAXSTR) :: file_template_right character(len=ESMF_MAXSTR) :: filename_left - character(len=ESMF_MAXSTR) :: filename_full + character(len=ESMF_MAXSTR) :: filename_full + character(len=ESMF_MAXSTR) :: cmd print*, __LINE__, __FILE__ @@ -146,6 +147,9 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter nymd = itime(1) nhms = itime(2) + print*, 'nymd, nhms=', nymd, nhms + + j= index(file_template, '*') if (j>0) then ! wild char exist @@ -158,13 +162,30 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter call fill_grads_template ( filename_left, file_template_left, & experiment_id='', nymd=nymd, nhms=nhms, _RC ) + print*, 'new filename_left=', trim(filename_left) + filename= trim(filename_left)//trim(file_template(j:)) - print*, 'new filename=', trim(filename) - stop -1 + cmd="bash -c 'ls "//trim(filename)//"' &> zzz_MAPL" + print*, 'cmd=', trim(cmd) + CALL execute_command_line(trim(cmd)) + + open(7213, file='zzz_MAPL', status='unknown') + read(7213, '(a)') filename + print*, 'readin filename=', trim(filename) + + i=index(trim(filename), 'ls') + if (i==1) then + filename='' + write(6,*) 'No such file or directory:', trim(filename_left)//trim(file_template(j:)) + end if + + cmd="rm -f ./zzz_MAPL" + CALL execute_command_line(trim(cmd)) + close(7213) - rc=0 + _RETURN(_SUCCESS) end function get_filename_from_template_use_index @@ -204,10 +225,10 @@ program main ! call ESMF_TimeSet(obsfile_end_time, trim(STR1), rc=rc) - call ESMF_TimeSet(currTime, yy=2007, mm=3, dd=31, h=0, m=0, s=0, & + call ESMF_TimeSet(currTime, yy=2017, mm=3, dd=31, h=0, m=0, s=0, & calendar=gregorianCalendar, rc=rc) obsfile_start_time = currTime - call ESMF_TimeSet(obsfile_end_time, yy=2008, mm=3, dd=31, h=0, m=0, s=0, & + call ESMF_TimeSet(obsfile_end_time, yy=2018, mm=3, dd=31, h=0, m=0, s=0, & calendar=gregorianCalendar, rc=rc) sec = 300.d0 diff --git a/base/StringTemplate.F90 b/base/StringTemplate.F90 index 999e69a2f537..6b6773dae07a 100644 --- a/base/StringTemplate.F90 +++ b/base/StringTemplate.F90 @@ -12,7 +12,7 @@ module MAPL_StringTemplate public fill_grads_template public StrTemplate -character(len=2), parameter :: valid_tokens(14) = ["y4","y2","m1","m2","mc","Mc","MC","d1","d2","h1","h2","h3","n2","S2"] +character(len=2), parameter :: valid_tokens(15) = ["y4","y2","m1","m2","mc","Mc","MC","d1","d2","h1","h2","h3","n2","S2","D3"] character(len=3),parameter :: mon_lc(12) = [& 'jan','feb','mar','apr','may','jun', & 'jul','aug','sep','oct','nov','dec'] @@ -169,6 +169,7 @@ function evaluate_token(token,year,month,day,hour,minute,second,preserve) result type(ESMF_Time) :: time integer(ESMF_KIND_I4) :: doy integer :: status, rc + type(ESMF_Calendar) :: gregorianCalendar c1=token(1:1) c2=token(2:2) select case(c1) @@ -215,8 +216,12 @@ function evaluate_token(token,year,month,day,hour,minute,second,preserve) result case("D") ! dayOfYear if (.not.skip_token(day,preserve)) then if (c2 == "3") then - call ESMF_TimeSet(time, yy=year, mm=month, dd=day, _RC) + gregorianCalendar = ESMF_CalendarCreate(ESMF_CALKIND_GREGORIAN, & + name='Gregorian_obs' , rc=rc) + call ESMF_TimeSet(time, yy=year, mm=month, dd=day, & + calendar=gregorianCalendar, _RC) call ESMF_TimeGet(time, dayOfYear=doy, _RC) + call ESMF_CalendarDestroy(gregorianCalendar) write(buffer,'(i3.3)')doy write(6,*) 'doy=', doy else From 0980cca3ea091ba558596b0388505605bc0bb195 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Tue, 14 Nov 2023 16:46:53 -0700 Subject: [PATCH 18/41] update --- Apps/time_ave_util.F90 | 217 ++++++++++++++++++++++++++------- base/MAPL_SwathGridFactory.F90 | 8 +- 2 files changed, 172 insertions(+), 53 deletions(-) diff --git a/Apps/time_ave_util.F90 b/Apps/time_ave_util.F90 index e9d89dcb305d..fe5f52c993d1 100644 --- a/Apps/time_ave_util.F90 +++ b/Apps/time_ave_util.F90 @@ -5,6 +5,8 @@ module MAPL_ObsUtilMod use ESMF use MAPL_ErrorHandlingMod use MAPL_KeywordEnforcerMod + use Plain_netCDF_Time + use netCDF use, intrinsic :: iso_fortran_env, only: REAL32, REAL64 implicit none integer, parameter :: mx_ngeoval = 60 @@ -41,6 +43,7 @@ subroutine Find_M_files_for_currTime (currTime, & type(ESMF_TimeInterval) :: Toff real(ESMF_KIND_R8) :: dT0_s, dT1_s, dT2_s real(ESMF_KIND_R8) :: s1, s2 + character(len=ESMF_MAXSTR) :: test_file integer :: obsfile_Ts_index, obsfile_Te_index integer :: n1, n2 @@ -75,8 +78,7 @@ subroutine Find_M_files_for_currTime (currTime, & print*, 'ck dT0_s, dT1_s, dT2_s', dT0_s, dT1_s, dT2_s print*, '1st n1, n2', n1, n2 - - + obsfile_Ts_index = n1 if ( dT2_s - n2*dT0_s < 1 ) then obsfile_Te_index = n2 - 1 @@ -95,19 +97,79 @@ subroutine Find_M_files_for_currTime (currTime, & ! j=0 do i= n1, n2 - j=j+1 - filenames(j) = get_filename_from_template_use_index & + test_file = get_filename_from_template_use_index & (obsfile_start_time, obsfile_interval, & i, file_template, rc=rc) + if (test_file /= '') then + j=j+1 + filenames(j) = test_file + end if end do + M=j + + _RETURN(_SUCCESS) - end subroutine Find_M_files_for_currTime -! -! subroutine read_M_files ( filenames, Xdim, Y_dim, & -! lon_name, lat_name, time_name, & -! lon, lat, time ) + + subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & + index_name_lon, index_name_lat,& + var_name_lon, var_name_lat, var_name_time, & + lon, lat, time_R8, rc ) + + character(len=ESMF_MAXSTR), intent(in) :: filenames(:) + integer, intent(out) :: Xdim + integer, intent(out) :: Ydim + character(len=ESMF_MAXSTR), intent(in) :: index_name_lon + character(len=ESMF_MAXSTR), intent(in) :: index_name_lat + character(len=ESMF_MAXSTR), optional, intent(in) :: var_name_lon + character(len=ESMF_MAXSTR), optional, intent(in) :: var_name_lat + character(len=ESMF_MAXSTR), optional, intent(in) :: var_name_time + + real, optional, intent(inout) :: lon(:,:) + real, optional, intent(inout) :: lat(:,:) + real(ESMF_KIND_R8), optional, intent(inout) :: time_R8(:,:) + + integer, optional, intent(out) :: rc + + integer :: M + integer :: i, j, jx, status + integer :: nlon, nlat + integer :: ncid, ncid2 + character(len=ESMF_MAXSTR) :: grp1, grp2 + integer :: varid + logical :: found_group + + character(len=ESMF_MAXSTR) :: filename + + M = size(filenames) + jx=0 + do i = 1, M + filename = filenames(i) + print*, 'ck filename input', trim(filename) + CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, & + key_lon=index_name_lon, key_lat=index_name_lat, _RC) + print*, 'nlon, nlat=', nlon, nlat + jx=jx+nlat + end do + +Xdim=nlon +Ydim=jx + + if (present(var_name_time).AND.present(time_R8)) then + call get_var_from_name_w_group (var_name_time, time_R8, filename, _RC) + end if + + +! allocate(scanTime(nlon, nlat)) +! allocate(this%t_alongtrack(nlat)) + + rc=0 +!! _RETURN(_SUCCESS) + end subroutine read_M_files_4_swath + + + function get_filename_from_template_use_index (obsfile_start_time, obsfile_interval, & f_index, file_template, rc) result(filename) @@ -135,59 +197,105 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter character(len=ESMF_MAXSTR) :: filename_full character(len=ESMF_MAXSTR) :: cmd - print*, __LINE__, __FILE__ - call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) s = dT0_s * f_index call ESMF_TimeIntervalSet(dT, s_r8=s, rc=status) time = obsfile_start_time + dT - print*, __LINE__, __FILE__ call ESMF_time_to_two_integer(time, itime, _RC) nymd = itime(1) nhms = itime(2) - - print*, 'nymd, nhms=', nymd, nhms - - + j= index(file_template, '*') if (j>0) then ! wild char exist - print*, 'pos of * in template =', j + !!print*, 'pos of * in template =', j file_template_left = file_template(1:j-1) + call fill_grads_template ( filename_left, file_template_left, & + experiment_id='', nymd=nymd, nhms=nhms, _RC ) + filename= trim(filename_left)//trim(file_template(j:)) + cmd="bash -c 'ls "//trim(filename)//"' &> zzz_MAPL" + CALL execute_command_line(trim(cmd)) + open(7213, file='zzz_MAPL', status='unknown') + read(7213, '(a)') filename + i=index(trim(filename), 'ls') + if (i==1) then + filename='' + end if + cmd="rm -f ./zzz_MAPL" + CALL execute_command_line(trim(cmd)) + close(7213) else - file_template_left = file_template - endif - write(6,*) 'file_template_left=', trim(file_template_left) - - call fill_grads_template ( filename_left, file_template_left, & - experiment_id='', nymd=nymd, nhms=nhms, _RC ) + ! exact file name + call fill_grads_template ( filename, file_template, & + experiment_id='', nymd=nymd, nhms=nhms, _RC ) + end if + _RETURN(_SUCCESS) - print*, 'new filename_left=', trim(filename_left) + end function get_filename_from_template_use_index - filename= trim(filename_left)//trim(file_template(j:)) - cmd="bash -c 'ls "//trim(filename)//"' &> zzz_MAPL" - print*, 'cmd=', trim(cmd) - CALL execute_command_line(trim(cmd)) - open(7213, file='zzz_MAPL', status='unknown') - read(7213, '(a)') filename - print*, 'readin filename=', trim(filename) + subroutine get_var_from_name_w_group (var_name, var2d, filename, rc) + character(len=ESMF_MAXSTR), intent(in) :: var_name, filename + real(ESMF_KIND_R8), intent(inout) :: var2d(:,:) + integer, optional, intent(out) :: rc + + integer :: i, j + character(len=ESMF_MAXSTR) :: grp1, grp2 + character(len=ESMF_MAXSTR) :: short_name + integer :: ncid, ncid2, varid + logical :: found_group + integer :: status - i=index(trim(filename), 'ls') - if (i==1) then - filename='' - write(6,*) 'No such file or directory:', trim(filename_left)//trim(file_template(j:)) - end if - - cmd="rm -f ./zzz_MAPL" - CALL execute_command_line(trim(cmd)) - close(7213) - _RETURN(_SUCCESS) + i=index(var_name, '/') + if (i>0) then + found_group = .true. + grp1 = var_name(1:i-1) + j=index(var_name(i+1:), '/') + if (j>0) then + grp2=var_name(i+1:i+j-1) + short_name=var_name(i+j+1:) + else + grp2='' + short_name=var_name(i+1:) + endif + i=i+j + else + found_group = .false. + grp1 = '' + grp2='' + short_name=var_name + endif + + print*, 'ck grp1, grp2', trim(grp1), trim(grp2) + + stop -11 + + call check_nc_status(nf90_open(filename, NF90_NOWRITE, ncid2), _RC) + if ( found_group ) then + call check_nc_status(nf90_inq_ncid(ncid2, grp1, ncid), _RC) + print*, 'ck grp1' + if (j>0) then + call check_nc_status(nf90_inq_ncid(ncid, grp2, ncid2), _RC) + ncid=ncid2 + print*, 'ck grp2' + endif + else + print*, 'no grp name' + ncid=ncid2 + endif + call check_nc_status(nf90_inq_varid(ncid, var_name, varid), _RC) + call check_nc_status(nf90_get_var(ncid, varid, var2d), _RC) + + write(6,*) var2d(::10,::10) + + _RETURN(_SUCCESS) + + end subroutine get_var_from_name_w_group + - end function get_filename_from_template_use_index end module MAPL_ObsUtilMod @@ -211,9 +319,22 @@ program main integer :: rc, status type(ESMF_Calendar) :: gregorianCalendar - file_template = '/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A%y4%D3.%h2%n2.*.hdf' - gregorianCalendar = ESMF_CalendarCreate(ESMF_CALKIND_GREGORIAN, name='Gregorian_obs' , rc=rc) + character(len=ESMF_MAXSTR) :: index_name_lon + character(len=ESMF_MAXSTR) :: index_name_lat + character(len=ESMF_MAXSTR) :: index_name_time + character(len=ESMF_MAXSTR) :: var_name_lon + character(len=ESMF_MAXSTR) :: var_name_lat + character(len=ESMF_MAXSTR) :: var_name_time + integer :: Xdim, Ydim + + + file_template = '/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A%y4%D3.%h2%n2.*.h5' + index_name_lon= 'Cell_Across_Swath:mod04' + index_name_lat= 'Cell_Along_Swath:mod04' + var_name_time= 'mod04/Data Fields/Scan_Start_Time' + + gregorianCalendar = ESMF_CalendarCreate(ESMF_CALKIND_GREGORIAN, name='Gregorian_obs' , rc=rc) ! STR1='2017-03-31T00:00:00' ! call ESMF_TimeSet(currTime, trim(STR1), rc=rc) @@ -224,7 +345,6 @@ program main ! STR1='2017-04-01T00:00:00' ! call ESMF_TimeSet(obsfile_end_time, trim(STR1), rc=rc) - call ESMF_TimeSet(currTime, yy=2017, mm=3, dd=31, h=0, m=0, s=0, & calendar=gregorianCalendar, rc=rc) obsfile_start_time = currTime @@ -245,10 +365,15 @@ program main epoch_frequency, file_template, M, filenames, & T_offset_in_file_content = Toff, rc = rc) - stop -2 write(6,*) 'M=', M do i=1, M write(6,*) 'filenames(i)=', trim(filenames(i)) end do + call read_M_files_4_swath (filenames(1:M), Xdim, Ydim, & + index_name_lon, index_name_lat, & + var_name_time=var_name_time, rc=rc) + end program main + + diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index bb9aaeaaaca3..59c679313add 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -552,27 +552,21 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc write(6,'(10(2x,a))') 'grp1, grp2', trim(grp1), trim(grp2) - - - !__ s2. loop over filenames to get this%t_alongtrack(:) ! ! call get_obsfile_Tbracket_from_epoch(currTime, & ! this%obsfile_start_time, this%obsfile_end_time, & ! this%obsfile_interval, this%epoch_frequency, & ! this%obsfile_Ts_index, this%obsfile_Te_index, _RC) -! ! ! L=0 ! fid_s=this%obsfile_Ts_index ! fid_e=this%obsfile_Te_index + !! marker bug this%grid_file_name = trim(filename) - - - !! marker bug ! filename='/discover/nobackup/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.h5' From b77033be59ffb6b46dcb803047d8bdcee3cf6cd4 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Tue, 14 Nov 2023 22:36:54 -0700 Subject: [PATCH 19/41] . --- Apps/time_ave_util.F90 | 301 ++++++++++++++++++++++------------------- 1 file changed, 164 insertions(+), 137 deletions(-) diff --git a/Apps/time_ave_util.F90 b/Apps/time_ave_util.F90 index fe5f52c993d1..26ab7ff785b3 100644 --- a/Apps/time_ave_util.F90 +++ b/Apps/time_ave_util.F90 @@ -21,7 +21,7 @@ module MAPL_ObsUtilMod ! | | ! curr curr+Epoch ! - + subroutine Find_M_files_for_currTime (currTime, & obsfile_start_time, obsfile_end_time, obsfile_interval, & epoch_frequency, file_template, M, filenames, & @@ -59,26 +59,26 @@ subroutine Find_M_files_for_currTime (currTime, & call ESMF_TimeIntervalSet(Toff, h=0, m=0, s=60, rc=status) endif -! T1 = obsfile_start_time + Toff -! Tn = obsfile_end_time + Toff + ! T1 = obsfile_start_time + Toff + ! Tn = obsfile_end_time + Toff T1 = obsfile_start_time Tn = obsfile_end_time - + cT1 = currTime dT1 = currTime - T1 dT2 = currTime + epoch_frequency - T1 - + call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) call ESMF_TimeIntervalGet(dT1, s_r8=dT1_s, rc=status) call ESMF_TimeIntervalGet(dT2, s_r8=dT2_s, rc=status) - + n1 = floor (dT1_s / dT0_s) n2 = floor (dT2_s / dT0_s) print*, 'ck dT0_s, dT1_s, dT2_s', dT0_s, dT1_s, dT2_s print*, '1st n1, n2', n1, n2 - + obsfile_Ts_index = n1 if ( dT2_s - n2*dT0_s < 1 ) then obsfile_Te_index = n2 - 1 @@ -92,7 +92,7 @@ subroutine Find_M_files_for_currTime (currTime, & print*, __LINE__, __FILE__ print*, '2nd n1, n2', n1, n2 - + !__ s2. further test file existence ! j=0 @@ -106,9 +106,9 @@ subroutine Find_M_files_for_currTime (currTime, & end if end do M=j - + _RETURN(_SUCCESS) - + end subroutine Find_M_files_for_currTime @@ -129,9 +129,9 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & real, optional, intent(inout) :: lon(:,:) real, optional, intent(inout) :: lat(:,:) real(ESMF_KIND_R8), optional, intent(inout) :: time_R8(:,:) - + integer, optional, intent(out) :: rc - + integer :: M integer :: i, j, jx, status integer :: nlon, nlat @@ -141,31 +141,53 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & logical :: found_group character(len=ESMF_MAXSTR) :: filename - + integer, allocatable :: nlons(:), nlats(:) + real(ESMF_KIND_R8), allocatable :: time_loc_R8(:,:) + real, allocatable :: lon_loc(:) + real, allocatable :: lat_loc(:) + + + !__ s1. get Xdim Ydim M = size(filenames) - jx=0 - do i = 1, M - filename = filenames(i) - print*, 'ck filename input', trim(filename) - CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, & - key_lon=index_name_lon, key_lat=index_name_lat, _RC) - print*, 'nlon, nlat=', nlon, nlat - jx=jx+nlat - end do - -Xdim=nlon -Ydim=jx - - if (present(var_name_time).AND.present(time_R8)) then - call get_var_from_name_w_group (var_name_time, time_R8, filename, _RC) - end if - - -! allocate(scanTime(nlon, nlat)) -! allocate(this%t_alongtrack(nlat)) + allocate(nlons(M), nlats(M)) + jx=0 + do i = 1, M + filename = filenames(i) + print*, 'ck filename input', trim(filename) + CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, & + key_lon=index_name_lon, key_lat=index_name_lat, _RC) + nlons(i)=nlon + nlats(i)=nlat + print*, 'nlon, nlat=', nlon, nlat + jx=jx+nlat + end do + Xdim=nlon + Ydim=jx + + + !__ s2. get fields + jx=0 + do i = 1, M + filename = filenames(i) + nlon = nlons(i) + nlat = nlats(i) + + if (present(var_name_time).AND.present(time_R8)) then + allocate (time_loc_R8(nlon, nlat)) + call get_var_from_name_w_group (var_name_time, time_loc_R8, filename, _RC) + time_R8(1:nlon,jx+1:jx+nlat) = time_loc_R8(1:nlon,1:nlat) + deallocate(time_loc_R8) + end if + + jx = jx + nlat + + end do + + ! allocate(scanTime(nlon, nlat)) + ! allocate(this%t_alongtrack(nlat)) rc=0 -!! _RETURN(_SUCCESS) + !! _RETURN(_SUCCESS) end subroutine read_M_files_4_swath @@ -205,7 +227,7 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter call ESMF_time_to_two_integer(time, itime, _RC) nymd = itime(1) nhms = itime(2) - + j= index(file_template, '*') if (j>0) then ! wild char exist @@ -229,7 +251,7 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter ! exact file name call fill_grads_template ( filename, file_template, & experiment_id='', nymd=nymd, nhms=nhms, _RC ) - end if + end if _RETURN(_SUCCESS) end function get_filename_from_template_use_index @@ -248,53 +270,52 @@ subroutine get_var_from_name_w_group (var_name, var2d, filename, rc) logical :: found_group integer :: status - - i=index(var_name, '/') - if (i>0) then - found_group = .true. - grp1 = var_name(1:i-1) - j=index(var_name(i+1:), '/') - if (j>0) then - grp2=var_name(i+1:i+j-1) - short_name=var_name(i+j+1:) - else - grp2='' - short_name=var_name(i+1:) - endif - i=i+j + + i=index(var_name, '/') + if (i>0) then + found_group = .true. + grp1 = var_name(1:i-1) + j=index(var_name(i+1:), '/') + if (j>0) then + grp2=var_name(i+1:i+j-1) + short_name=var_name(i+j+1:) else - found_group = .false. - grp1 = '' grp2='' - short_name=var_name + short_name=var_name(i+1:) endif + i=i+j + else + found_group = .false. + grp1 = '' + grp2='' + short_name=var_name + endif - print*, 'ck grp1, grp2', trim(grp1), trim(grp2) + print*, 'ck grp1, grp2, short_name:', trim(grp1), trim(grp2), trim(short_name) - stop -11 - - call check_nc_status(nf90_open(filename, NF90_NOWRITE, ncid2), _RC) - if ( found_group ) then - call check_nc_status(nf90_inq_ncid(ncid2, grp1, ncid), _RC) - print*, 'ck grp1' - if (j>0) then - call check_nc_status(nf90_inq_ncid(ncid, grp2, ncid2), _RC) - ncid=ncid2 - print*, 'ck grp2' - endif - else - print*, 'no grp name' + + call check_nc_status(nf90_open(filename, NF90_NOWRITE, ncid2), _RC) + if ( found_group ) then + call check_nc_status(nf90_inq_ncid(ncid2, grp1, ncid), _RC) + print*, 'ck grp1' + if (j>0) then + call check_nc_status(nf90_inq_ncid(ncid, grp2, ncid2), _RC) ncid=ncid2 + print*, 'ck grp2' endif - call check_nc_status(nf90_inq_varid(ncid, var_name, varid), _RC) - call check_nc_status(nf90_get_var(ncid, varid, var2d), _RC) + else + print*, 'no grp name' + ncid=ncid2 + endif + call check_nc_status(nf90_inq_varid(ncid, short_name, varid), _RC) + call check_nc_status(nf90_get_var(ncid, varid, var2d), _RC) - write(6,*) var2d(::10,::10) + write(6,*) var2d(::100,::100) + + _RETURN(_SUCCESS) + + end subroutine get_var_from_name_w_group - _RETURN(_SUCCESS) - - end subroutine get_var_from_name_w_group - end module MAPL_ObsUtilMod @@ -306,74 +327,80 @@ program main use MAPL_ObsUtilMod implicit none - type(ESMF_Time) :: currTime - type(ESMF_Time) :: obsfile_start_time, obsfile_end_time - type(ESMF_TimeInterval) :: obsfile_interval, epoch_frequency - type(ESMF_TimeInterval) :: Toff - character(len=ESMF_MAXSTR) :: file_template - character(len=ESMF_MAXSTR) :: STR1 - character(len=ESMF_MAXSTR) :: filenames(200) - integer :: M - integer :: i - real(KIND=ESMF_KIND_R8) :: sec - integer :: rc, status - type(ESMF_Calendar) :: gregorianCalendar - - character(len=ESMF_MAXSTR) :: index_name_lon - character(len=ESMF_MAXSTR) :: index_name_lat - character(len=ESMF_MAXSTR) :: index_name_time - character(len=ESMF_MAXSTR) :: var_name_lon - character(len=ESMF_MAXSTR) :: var_name_lat - character(len=ESMF_MAXSTR) :: var_name_time - integer :: Xdim, Ydim - - - file_template = '/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A%y4%D3.%h2%n2.*.h5' - index_name_lon= 'Cell_Across_Swath:mod04' - index_name_lat= 'Cell_Along_Swath:mod04' - var_name_time= 'mod04/Data Fields/Scan_Start_Time' - - - gregorianCalendar = ESMF_CalendarCreate(ESMF_CALKIND_GREGORIAN, name='Gregorian_obs' , rc=rc) - -! STR1='2017-03-31T00:00:00' -! call ESMF_TimeSet(currTime, trim(STR1), rc=rc) - -! STR1='2017-03-31T00:00:00' -! call ESMF_TimeSet(obsfile_start_time, trim(STR1), rc=rc) - -! STR1='2017-04-01T00:00:00' -! call ESMF_TimeSet(obsfile_end_time, trim(STR1), rc=rc) - - call ESMF_TimeSet(currTime, yy=2017, mm=3, dd=31, h=0, m=0, s=0, & - calendar=gregorianCalendar, rc=rc) - obsfile_start_time = currTime - call ESMF_TimeSet(obsfile_end_time, yy=2018, mm=3, dd=31, h=0, m=0, s=0, & - calendar=gregorianCalendar, rc=rc) - - sec = 300.d0 - call ESMF_TimeIntervalSet(obsfile_interval, h=0, m=5, s=0, rc=rc) - - sec = 3600.d0 - call ESMF_TimeIntervalSet(Epoch_frequency, h=1, m=0, s=0, rc=rc) - - sec = 0.d0 - call ESMF_TimeIntervalSet(Toff, s_r8=sec, rc=status) - - call Find_M_files_for_currTime (currTime, & + type(ESMF_Time) :: currTime + type(ESMF_Time) :: obsfile_start_time, obsfile_end_time + type(ESMF_TimeInterval) :: obsfile_interval, epoch_frequency + type(ESMF_TimeInterval) :: Toff + character(len=ESMF_MAXSTR) :: file_template + character(len=ESMF_MAXSTR) :: STR1 + character(len=ESMF_MAXSTR) :: filenames(200) + integer :: M + integer :: i + real(KIND=ESMF_KIND_R8) :: sec + integer :: rc, status + type(ESMF_Calendar) :: gregorianCalendar + + character(len=ESMF_MAXSTR) :: index_name_lon + character(len=ESMF_MAXSTR) :: index_name_lat + character(len=ESMF_MAXSTR) :: index_name_time + character(len=ESMF_MAXSTR) :: var_name_lon + character(len=ESMF_MAXSTR) :: var_name_lat + character(len=ESMF_MAXSTR) :: var_name_time + integer :: Xdim, Ydim + + real(ESMF_kind_R8), allocatable :: time_R8(:,:) + + file_template = '/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A%y4%D3.%h2%n2.*.h5' + index_name_lon= 'Cell_Across_Swath:mod04' + index_name_lat= 'Cell_Along_Swath:mod04' + var_name_time= 'mod04/Data Fields/Scan_Start_Time' + + + gregorianCalendar = ESMF_CalendarCreate(ESMF_CALKIND_GREGORIAN, name='Gregorian_obs' , rc=rc) + + ! STR1='2017-03-31T00:00:00' + ! call ESMF_TimeSet(currTime, trim(STR1), rc=rc) + + ! STR1='2017-03-31T00:00:00' + ! call ESMF_TimeSet(obsfile_start_time, trim(STR1), rc=rc) + + ! STR1='2017-04-01T00:00:00' + ! call ESMF_TimeSet(obsfile_end_time, trim(STR1), rc=rc) + + call ESMF_TimeSet(currTime, yy=2017, mm=3, dd=31, h=0, m=0, s=0, & + calendar=gregorianCalendar, rc=rc) + obsfile_start_time = currTime + call ESMF_TimeSet(obsfile_end_time, yy=2018, mm=3, dd=31, h=0, m=0, s=0, & + calendar=gregorianCalendar, rc=rc) + + sec = 300.d0 + call ESMF_TimeIntervalSet(obsfile_interval, h=0, m=5, s=0, rc=rc) + + sec = 3600.d0 + call ESMF_TimeIntervalSet(Epoch_frequency, h=1, m=0, s=0, rc=rc) + + sec = 0.d0 + call ESMF_TimeIntervalSet(Toff, s_r8=sec, rc=status) + + call Find_M_files_for_currTime (currTime, & obsfile_start_time, obsfile_end_time, obsfile_interval, & epoch_frequency, file_template, M, filenames, & T_offset_in_file_content = Toff, rc = rc) - write(6,*) 'M=', M - do i=1, M - write(6,*) 'filenames(i)=', trim(filenames(i)) - end do + write(6,*) 'M=', M + do i=1, M + write(6,*) 'filenames(i)=', trim(filenames(i)) + end do - call read_M_files_4_swath (filenames(1:M), Xdim, Ydim, & - index_name_lon, index_name_lat, & - var_name_time=var_name_time, rc=rc) + call read_M_files_4_swath (filenames(1:M), Xdim, Ydim, & + index_name_lon, index_name_lat, rc=rc) + allocate( time_R8(Xdim, Ydim) ) - end program main + call read_M_files_4_swath (filenames(1:M), Xdim, Ydim, & + index_name_lon, index_name_lat, & + var_name_time=var_name_time, time_R8=time_R8, rc=rc) + deallocate( time_R8 ) + +end program main From 890dd02bad55b527cfe7752de34b0193015c89c1 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 15 Nov 2023 09:51:56 -0700 Subject: [PATCH 20/41] . --- Apps/time_ave_util.F90 | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/Apps/time_ave_util.F90 b/Apps/time_ave_util.F90 index 26ab7ff785b3..119d1793d9ea 100644 --- a/Apps/time_ave_util.F90 +++ b/Apps/time_ave_util.F90 @@ -143,8 +143,8 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & character(len=ESMF_MAXSTR) :: filename integer, allocatable :: nlons(:), nlats(:) real(ESMF_KIND_R8), allocatable :: time_loc_R8(:,:) - real, allocatable :: lon_loc(:) - real, allocatable :: lat_loc(:) + real(ESMF_KIND_R8), allocatable :: lon_loc(:,:) + real(ESMF_KIND_R8), allocatable :: lat_loc(:,:) !__ s1. get Xdim Ydim @@ -178,6 +178,20 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & time_R8(1:nlon,jx+1:jx+nlat) = time_loc_R8(1:nlon,1:nlat) deallocate(time_loc_R8) end if + + if (present(var_name_lon).AND.present(lon)) then + allocate (lon_loc(nlon, nlat)) + call get_var_from_name_w_group (var_name_lon, lon_loc, filename, _RC) + lon(1:nlon,jx+1:jx+nlat) = lon_loc(1:nlon,1:nlat) + deallocate(lon_loc) + end if + + if (present(var_name_lat).AND.present(lat)) then + allocate (lat_loc(nlon, nlat)) + call get_var_from_name_w_group (var_name_lat, lat_loc, filename, _RC) + lat(1:nlon,jx+1:jx+nlat) = lat_loc(1:nlon,1:nlat) + deallocate(lat_loc) + end if jx = jx + nlat @@ -349,11 +363,14 @@ program main integer :: Xdim, Ydim real(ESMF_kind_R8), allocatable :: time_R8(:,:) + real, allocatable :: lon_center(:,:) file_template = '/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A%y4%D3.%h2%n2.*.h5' index_name_lon= 'Cell_Across_Swath:mod04' index_name_lat= 'Cell_Along_Swath:mod04' var_name_time= 'mod04/Data Fields/Scan_Start_Time' + var_name_lon= 'mod04/Geolocation Fields/Longitude' + var_name_lat= 'mod04/Geolocation Fields/Latitude' gregorianCalendar = ESMF_CalendarCreate(ESMF_CALKIND_GREGORIAN, name='Gregorian_obs' , rc=rc) @@ -395,12 +412,13 @@ program main call read_M_files_4_swath (filenames(1:M), Xdim, Ydim, & index_name_lon, index_name_lat, rc=rc) allocate( time_R8(Xdim, Ydim) ) + allocate( lon_center(Xdim, Ydim) ) call read_M_files_4_swath (filenames(1:M), Xdim, Ydim, & index_name_lon, index_name_lat, & - var_name_time=var_name_time, time_R8=time_R8, rc=rc) - deallocate( time_R8 ) + var_name_time=var_name_time, time_R8=time_R8, & + var_name_lon=var_name_lon, lon=lon_center, rc=rc) + + deallocate( time_R8, lon_center ) end program main - - From d7c53ed4d640b8a8d962ad8e7e3994a91fe2a5f9 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 15 Nov 2023 10:30:01 -0700 Subject: [PATCH 21/41] Adding standalone subr. into MAPL_ObsUtil.F90 --- base/MAPL_ObsUtil.F90 | 361 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 325 insertions(+), 36 deletions(-) diff --git a/base/MAPL_ObsUtil.F90 b/base/MAPL_ObsUtil.F90 index d12da47cdb99..13f7b88f9140 100644 --- a/base/MAPL_ObsUtil.F90 +++ b/base/MAPL_ObsUtil.F90 @@ -4,10 +4,12 @@ module MAPL_ObsUtilMod use ESMF use MAPL_FileMetadataUtilsMod + use Plain_netCDF_Time + use netCDF use, intrinsic :: iso_fortran_env, only: REAL32, REAL64 implicit none integer, parameter :: mx_ngeoval = 60 -!! private + !! private public :: obs_unit type :: obs_unit @@ -84,6 +86,7 @@ subroutine get_obsfile_Tbracket_from_epoch(currTime, & end subroutine get_obsfile_Tbracket_from_epoch + function get_filename_from_template (time, file_template, rc) result(filename) use Plain_netCDF_Time, only : ESMF_time_to_two_integer use MAPL_StringTemplate, only : fill_grads_template @@ -109,41 +112,6 @@ function get_filename_from_template (time, file_template, rc) result(filename) end function get_filename_from_template - function get_filename_from_template_use_index (obsfile_start_time, obsfile_interval, & - f_index, file_template, rc) result(filename) - use Plain_netCDF_Time, only : ESMF_time_to_two_integer - use MAPL_StringTemplate, only : fill_grads_template - character(len=ESMF_MAXSTR) :: filename - type(ESMF_Time), intent(in) :: obsfile_start_time - type(ESMF_TimeInterval), intent(in) :: obsfile_interval - character(len=*), intent(in) :: file_template - integer, intent(in) :: f_index - integer, optional, intent(out) :: rc - - integer :: itime(2) - integer :: nymd, nhms - integer :: status - real(ESMF_KIND_R8) :: dT0_s - real(ESMF_KIND_R8) :: s - type(ESMF_TimeInterval) :: dT - type(ESMF_Time) :: time - - call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) - s = dT0_s * f_index - call ESMF_TimeIntervalSet(dT, s_r8=s, rc=status) - time = obsfile_start_time + dT - - call ESMF_time_to_two_integer(time, itime, _RC) - nymd = itime(1) - nhms = itime(2) - call fill_grads_template ( filename, file_template, & - experiment_id='', nymd=nymd, nhms=nhms, _RC ) - - _RETURN(ESMF_SUCCESS) - - end function get_filename_from_template_use_index - - subroutine time_real_to_ESMF (times_R8_1d, times_esmf_1d, datetime_units, rc) use MAPL_NetCDF, only : convert_NetCDF_DateTime_to_ESMF @@ -190,6 +158,327 @@ subroutine reset_times_to_current_day(current_time, times_1d, rc) end subroutine reset_times_to_current_day + + + ! --//-------------------------------------//-> + ! files + ! o o o o o o o o o o T: filename + ! <--- off set + ! o o o o o o o o o o T: file content start + ! | | + ! curr curr+Epoch + ! + + subroutine Find_M_files_for_currTime (currTime, & + obsfile_start_time, obsfile_end_time, obsfile_interval, & + epoch_frequency, file_template, M, filenames, & + T_offset_in_file_content, rc) + implicit none + type(ESMF_Time), intent(in) :: currTime + type(ESMF_Time), intent(in) :: obsfile_start_time, obsfile_end_time + type(ESMF_TimeInterval), intent(in) :: obsfile_interval, epoch_frequency + character(len=*), intent(in) :: file_template + integer, intent(out) :: M + character(len=ESMF_MAXSTR), intent(out) :: filenames(200) + type(ESMF_TimeInterval), intent(in), optional :: T_offset_in_file_content + integer, optional, intent(out) :: rc + + type(ESMF_Time) :: T1, Tn + type(ESMF_Time) :: cT1 + type(ESMF_Time) :: Ts, Te + type(ESMF_TimeInterval) :: dT1, dT2, dTs, dTe + type(ESMF_TimeInterval) :: Toff + real(ESMF_KIND_R8) :: dT0_s, dT1_s, dT2_s + real(ESMF_KIND_R8) :: s1, s2 + character(len=ESMF_MAXSTR) :: test_file + + integer :: obsfile_Ts_index, obsfile_Te_index + integer :: n1, n2 + integer :: i, j + integer :: status + + !__ s1. Arithmetic index list based on s,e,interval + ! + print*, __LINE__, __FILE__ + if (present(T_offset_in_file_content)) then + Toff = T_offset_in_file_content + else + call ESMF_TimeIntervalSet(Toff, h=0, m=0, s=60, rc=status) + endif + + ! T1 = obsfile_start_time + Toff + ! Tn = obsfile_end_time + Toff + + T1 = obsfile_start_time + Tn = obsfile_end_time + + cT1 = currTime + dT1 = currTime - T1 + dT2 = currTime + epoch_frequency - T1 + + call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) + call ESMF_TimeIntervalGet(dT1, s_r8=dT1_s, rc=status) + call ESMF_TimeIntervalGet(dT2, s_r8=dT2_s, rc=status) + + n1 = floor (dT1_s / dT0_s) + n2 = floor (dT2_s / dT0_s) + + print*, 'ck dT0_s, dT1_s, dT2_s', dT0_s, dT1_s, dT2_s + print*, '1st n1, n2', n1, n2 + + obsfile_Ts_index = n1 + if ( dT2_s - n2*dT0_s < 1 ) then + obsfile_Te_index = n2 - 1 + else + obsfile_Te_index = n2 + end if + + ! put back + n1 = obsfile_Ts_index + n2 = obsfile_Te_index + + print*, __LINE__, __FILE__ + print*, '2nd n1, n2', n1, n2 + + !__ s2. further test file existence + ! + j=0 + do i= n1, n2 + test_file = get_filename_from_template_use_index & + (obsfile_start_time, obsfile_interval, & + i, file_template, rc=rc) + if (test_file /= '') then + j=j+1 + filenames(j) = test_file + end if + end do + M=j + + _RETURN(_SUCCESS) + + end subroutine Find_M_files_for_currTime + + + subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & + index_name_lon, index_name_lat,& + var_name_lon, var_name_lat, var_name_time, & + lon, lat, time_R8, rc ) + + character(len=ESMF_MAXSTR), intent(in) :: filenames(:) + integer, intent(out) :: Xdim + integer, intent(out) :: Ydim + character(len=ESMF_MAXSTR), intent(in) :: index_name_lon + character(len=ESMF_MAXSTR), intent(in) :: index_name_lat + character(len=ESMF_MAXSTR), optional, intent(in) :: var_name_lon + character(len=ESMF_MAXSTR), optional, intent(in) :: var_name_lat + character(len=ESMF_MAXSTR), optional, intent(in) :: var_name_time + + real, optional, intent(inout) :: lon(:,:) + real, optional, intent(inout) :: lat(:,:) + real(ESMF_KIND_R8), optional, intent(inout) :: time_R8(:,:) + + integer, optional, intent(out) :: rc + + integer :: M + integer :: i, j, jx, status + integer :: nlon, nlat + integer :: ncid, ncid2 + character(len=ESMF_MAXSTR) :: grp1, grp2 + integer :: varid + logical :: found_group + + character(len=ESMF_MAXSTR) :: filename + integer, allocatable :: nlons(:), nlats(:) + real(ESMF_KIND_R8), allocatable :: time_loc_R8(:,:) + real(ESMF_KIND_R8), allocatable :: lon_loc(:,:) + real(ESMF_KIND_R8), allocatable :: lat_loc(:,:) + + + !__ s1. get Xdim Ydim + M = size(filenames) + allocate(nlons(M), nlats(M)) + jx=0 + do i = 1, M + filename = filenames(i) + print*, 'ck filename input', trim(filename) + CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, & + key_lon=index_name_lon, key_lat=index_name_lat, _RC) + nlons(i)=nlon + nlats(i)=nlat + print*, 'nlon, nlat=', nlon, nlat + jx=jx+nlat + end do + Xdim=nlon + Ydim=jx + + + !__ s2. get fields + jx=0 + do i = 1, M + filename = filenames(i) + nlon = nlons(i) + nlat = nlats(i) + + if (present(var_name_time).AND.present(time_R8)) then + allocate (time_loc_R8(nlon, nlat)) + call get_var_from_name_w_group (var_name_time, time_loc_R8, filename, _RC) + time_R8(1:nlon,jx+1:jx+nlat) = time_loc_R8(1:nlon,1:nlat) + deallocate(time_loc_R8) + end if + + if (present(var_name_lon).AND.present(lon)) then + allocate (lon_loc(nlon, nlat)) + call get_var_from_name_w_group (var_name_lon, lon_loc, filename, _RC) + lon(1:nlon,jx+1:jx+nlat) = lon_loc(1:nlon,1:nlat) + deallocate(lon_loc) + end if + + if (present(var_name_lat).AND.present(lat)) then + allocate (lat_loc(nlon, nlat)) + call get_var_from_name_w_group (var_name_lat, lat_loc, filename, _RC) + lat(1:nlon,jx+1:jx+nlat) = lat_loc(1:nlon,1:nlat) + deallocate(lat_loc) + end if + + jx = jx + nlat + + end do + + ! allocate(scanTime(nlon, nlat)) + ! allocate(this%t_alongtrack(nlat)) + + rc=0 + !! _RETURN(_SUCCESS) + end subroutine read_M_files_4_swath + + + + + function get_filename_from_template_use_index (obsfile_start_time, obsfile_interval, & + f_index, file_template, rc) result(filename) + use Plain_netCDF_Time, only : ESMF_time_to_two_integer + use MAPL_StringTemplate, only : fill_grads_template + character(len=ESMF_MAXSTR) :: filename + type(ESMF_Time), intent(in) :: obsfile_start_time + type(ESMF_TimeInterval), intent(in) :: obsfile_interval + character(len=*), intent(in) :: file_template + integer, intent(in) :: f_index + integer, optional, intent(out) :: rc + + integer :: itime(2) + integer :: nymd, nhms + integer :: status + real(ESMF_KIND_R8) :: dT0_s + real(ESMF_KIND_R8) :: s + type(ESMF_TimeInterval) :: dT + type(ESMF_Time) :: time + integer :: i, j + + character(len=ESMF_MAXSTR) :: file_template_left + character(len=ESMF_MAXSTR) :: file_template_right + character(len=ESMF_MAXSTR) :: filename_left + character(len=ESMF_MAXSTR) :: filename_full + character(len=ESMF_MAXSTR) :: cmd + + call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) + s = dT0_s * f_index + call ESMF_TimeIntervalSet(dT, s_r8=s, rc=status) + time = obsfile_start_time + dT + + call ESMF_time_to_two_integer(time, itime, _RC) + nymd = itime(1) + nhms = itime(2) + + j= index(file_template, '*') + if (j>0) then + ! wild char exist + !!print*, 'pos of * in template =', j + file_template_left = file_template(1:j-1) + call fill_grads_template ( filename_left, file_template_left, & + experiment_id='', nymd=nymd, nhms=nhms, _RC ) + filename= trim(filename_left)//trim(file_template(j:)) + cmd="bash -c 'ls "//trim(filename)//"' &> zzz_MAPL" + CALL execute_command_line(trim(cmd)) + open(7213, file='zzz_MAPL', status='unknown') + read(7213, '(a)') filename + i=index(trim(filename), 'ls') + if (i==1) then + filename='' + end if + cmd="rm -f ./zzz_MAPL" + CALL execute_command_line(trim(cmd)) + close(7213) + else + ! exact file name + call fill_grads_template ( filename, file_template, & + experiment_id='', nymd=nymd, nhms=nhms, _RC ) + end if + _RETURN(_SUCCESS) + + end function get_filename_from_template_use_index + + + + subroutine get_var_from_name_w_group (var_name, var2d, filename, rc) + character(len=ESMF_MAXSTR), intent(in) :: var_name, filename + real(ESMF_KIND_R8), intent(inout) :: var2d(:,:) + integer, optional, intent(out) :: rc + + integer :: i, j + character(len=ESMF_MAXSTR) :: grp1, grp2 + character(len=ESMF_MAXSTR) :: short_name + integer :: ncid, ncid2, varid + logical :: found_group + integer :: status + + + i=index(var_name, '/') + if (i>0) then + found_group = .true. + grp1 = var_name(1:i-1) + j=index(var_name(i+1:), '/') + if (j>0) then + grp2=var_name(i+1:i+j-1) + short_name=var_name(i+j+1:) + else + grp2='' + short_name=var_name(i+1:) + endif + i=i+j + else + found_group = .false. + grp1 = '' + grp2='' + short_name=var_name + endif + + print*, 'ck grp1, grp2, short_name:', trim(grp1), trim(grp2), trim(short_name) + + + call check_nc_status(nf90_open(filename, NF90_NOWRITE, ncid2), _RC) + if ( found_group ) then + call check_nc_status(nf90_inq_ncid(ncid2, grp1, ncid), _RC) + print*, 'ck grp1' + if (j>0) then + call check_nc_status(nf90_inq_ncid(ncid, grp2, ncid2), _RC) + ncid=ncid2 + print*, 'ck grp2' + endif + else + print*, 'no grp name' + ncid=ncid2 + endif + call check_nc_status(nf90_inq_varid(ncid, short_name, varid), _RC) + call check_nc_status(nf90_get_var(ncid, varid, var2d), _RC) + + write(6,*) var2d(::100,::100) + + _RETURN(_SUCCESS) + + end subroutine get_var_from_name_w_group + + + subroutine sort_three_arrays_by_time(U,V,T,rc) use MAPL_SortMod real(ESMF_KIND_R8), intent(inout) :: U(:), V(:), T(:) From 1e957b83d8391636a4b6d3048ebac4a90459a6e6 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 15 Nov 2023 11:15:30 -0700 Subject: [PATCH 22/41] save a copy Fatal Error: /Users/yyu11/repos/br_mapl_traj_all_compilers/MAPL/base/FileMetadataUtilities.F90, line 5: Cannot find module MAPL_GRIDMANAGERMOD detected at MAPL_GRIDMANAGERMOD@ Next merge develop to see if this can solve the problem. --- base/MAPL_ObsUtil.F90 | 3 +- base/MAPL_SwathGridFactory.F90 | 116 +++++++++++++++++---------------- 2 files changed, 63 insertions(+), 56 deletions(-) diff --git a/base/MAPL_ObsUtil.F90 b/base/MAPL_ObsUtil.F90 index 13f7b88f9140..dfe0db7da469 100644 --- a/base/MAPL_ObsUtil.F90 +++ b/base/MAPL_ObsUtil.F90 @@ -179,7 +179,7 @@ subroutine Find_M_files_for_currTime (currTime, & type(ESMF_TimeInterval), intent(in) :: obsfile_interval, epoch_frequency character(len=*), intent(in) :: file_template integer, intent(out) :: M - character(len=ESMF_MAXSTR), intent(out) :: filenames(200) + character(len=ESMF_MAXSTR), intent(inout) :: filenames(:) type(ESMF_TimeInterval), intent(in), optional :: T_offset_in_file_content integer, optional, intent(out) :: rc @@ -254,6 +254,7 @@ subroutine Find_M_files_for_currTime (currTime, & end do M=j + _ASSERT ( M < size(filenames) , 'code crash, number of files exceeds upper bound') _RETURN(_SUCCESS) end subroutine Find_M_files_for_currTime diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 59c679313add..2fe313fe7589 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -10,12 +10,13 @@ module MAPL_SwathGridFactoryMod use MAPL_ShmemMod use mapl_ErrorHandlingMod use MAPL_Constants - use Plain_netCDF_Time use MAPL_Base, only : MAPL_GridGetInterior use ESMF use pFIO use MAPL_CommsMod - use netcdf + !!use netcdf + !!use Plain_netCDF_Time + use MAPL_ObsUtilMod use, intrinsic :: iso_fortran_env, only: REAL32 use, intrinsic :: iso_fortran_env, only: REAL64 implicit none @@ -40,10 +41,8 @@ module MAPL_SwathGridFactoryMod integer(ESMF_KIND_I8) :: epoch_index(4) ! is,ie,js,je character(len=ESMF_MAXSTR) :: tunit real(ESMF_KIND_R8), allocatable :: t_alongtrack(:) - character(len=ESMF_MAXSTR) :: nc_index - character(len=ESMF_MAXSTR) :: nc_time - character(len=ESMF_MAXSTR) :: nc_latitude - character(len=ESMF_MAXSTR) :: nc_longitude + character(len=ESMF_MAXSTR) :: index_name_lon + character(len=ESMF_MAXSTR) :: index_name_lat character(len=ESMF_MAXSTR) :: var_name_time character(len=ESMF_MAXSTR) :: var_name_lat character(len=ESMF_MAXSTR) :: var_name_lon @@ -394,6 +393,7 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc use esmf use pflogger, only : Logger, logging implicit none + integer, parameter :: mx_file = 300 class (SwathGridFactory), intent(inout) :: this type (ESMF_Config), intent(inout) :: config character(len=*), intent(in) :: prefix @@ -408,13 +408,15 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc character(len=ESMF_MAXSTR) :: tunit, grp1, grp2 character(len=ESMF_MAXSTR) :: filename, STR1, tmp character(len=ESMF_MAXSTR) :: symd, shms - + character(len=ESMF_MAXSTR) :: filenames(mx_file) + ! real(ESMF_KIND_R8), allocatable :: scanTime(:,:) real, allocatable :: scanTime(:,:) integer :: yy, mm, dd, h, m, s, sec, second integer :: i, j, L integer :: ncid, ncid2, varid integer :: fid_s, fid_e + integer :: M_file type(ESMF_Time) :: currTime integer (ESMF_KIND_I8) :: j0, j1, jt, jt1, jt2 @@ -424,6 +426,8 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc type(Logger), pointer :: lgr logical :: ispresent + type(ESMF_TimeInterval) :: Toff + _UNUSED_DUMMY(unusable) lgr => logging%get_logger('HISTORY.sampler') @@ -431,7 +435,6 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc !__ s1. read in file spec. - ! set time, nc spec. ! call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'GRIDNAME:', default=MAPL_GRID_NAME_DEFAULT) this%grid_name = trim(tmp) @@ -441,7 +444,6 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call ESMF_ConfigGetAttribute(config, this%input_template, label=prefix//'GRID_FILE_template:', default='unknown.txt', _RC) call ESMF_ConfigGetAttribute(config, this%epoch, label=prefix//'Epoch:', default=300, _RC) call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'Epoch_init:', default='2006', _RC) - ! call ESMF_ConfigGetAttribute(config, value=STR1, default="", & @@ -467,8 +469,6 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc end if - - call ESMF_ConfigGetAttribute(config, value=STR1, default="", & label= prefix// 'obs_file_interval:', _RC) _ASSERT(STR1/='', 'fatal error: obs_file_interval not provided in RC file') @@ -485,9 +485,6 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc endif call convert_twostring_2_esmfinterval (symd, shms, this%obsfile_interval, _RC) - - - second = hms_2_s(this%Epoch) call ESMF_TimeIntervalSet(this%epoch_frequency, s=second, _RC) @@ -508,53 +505,62 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc - call ESMF_ConfigGetAttribute(config, value=this%nc_index, default="", & - label=prefix // 'nc_Index:', _RC) - call ESMF_ConfigGetAttribute(config, this%nc_time, default="", & - label=prefix//'nc_Time:', _RC) - call ESMF_ConfigGetAttribute(config, this%nc_longitude, & - label=prefix // 'nc_Longitude:', default="", _RC) - call ESMF_ConfigGetAttribute(config, this%nc_latitude, & - label=prefix // 'nc_Latitude:', default="", _RC) + call ESMF_ConfigGetAttribute(config, value=this%index_name_lon, default="", & + label=prefix // 'index_name_lon:', _RC) + call ESMF_ConfigGetAttribute(config, this%var_name_time, default="", & + label=prefix//'var_name_time:', _RC) + call ESMF_ConfigGetAttribute(config, this%var_name_lon, & + label=prefix // 'var_name_Longitude:', default="", _RC) + call ESMF_ConfigGetAttribute(config, this%var_name_lat, & + label=prefix // 'var_name_Latitude:', default="", _RC) - i=index(this%nc_time, '/') - if (i>0) then - this%found_group = .true. - grp1 = this%nc_time(1:i-1) - j=index(this%nc_time(i+1:), '/') - if (j>0) then - grp2=this%nc_time(i+1:i+j-1) - else - grp2='' - endif - i=i+j - else - this%found_group = .false. - grp1 = '' - grp2='' - endif - this%var_name_time= this%nc_time(i+1:) +! i=index(this%nc_time, '/') +! if (i>0) then +! this%found_group = .true. +! grp1 = this%nc_time(1:i-1) +! j=index(this%nc_time(i+1:), '/') +! if (j>0) then +! grp2=this%nc_time(i+1:i+j-1) +! else +! grp2='' +! endif +! i=i+j +! else +! this%found_group = .false. +! grp1 = '' +! grp2='' +! endif +! this%var_name_time= this%nc_time(i+1:) +! +! i=index(this%nc_longitude, '/') +! this%var_name_lat = this%nc_latitude(i+1:) +! this%var_name_lon = this%nc_longitude(i+1:) +! +! ! read global dim from nc file +! ! ---------------------------- +! key_lon=this%var_name_lon +! key_lat=this%var_name_lat +! key_time=this%var_name_time +! +! write(6,*) 'this%nc index, time, long, lat=', & +! trim(this%nc_index), trim(this%nc_time), trim(this%nc_longitude), trim(this%nc_latitude) +! write(6,'(10(2x,a))') 'name lat, lon, time', & +! trim(this%var_name_lat), trim(this%var_name_lon), trim(this%var_name_time) +! write(6,'(10(2x,a))') 'grp1, grp2', trim(grp1), trim(grp2) +! - i=index(this%nc_longitude, '/') - this%var_name_lat = this%nc_latitude(i+1:) - this%var_name_lon = this%nc_longitude(i+1:) - - ! read global dim from nc file - ! ---------------------------- - key_lon=this%var_name_lon - key_lat=this%var_name_lat - key_time=this%var_name_time - write(6,*) 'this%nc index, time, long, lat=', & - trim(this%nc_index), trim(this%nc_time), trim(this%nc_longitude), trim(this%nc_latitude) - write(6,'(10(2x,a))') 'name lat, lon, time', & - trim(this%var_name_lat), trim(this%var_name_lon), trim(this%var_name_time) - write(6,'(10(2x,a))') 'grp1, grp2', trim(grp1), trim(grp2) + !__ s2. find obsFile on disk and get array: this%t_alongtrack(:) + ! + call ESMF_TimeIntervalSet(Toff, h=0, m=0, s=0, _RC) + call Find_M_files_for_currTime (currTime, & + this%obsfile_start_time, this%obsfile_end_time, this%obsfile_interval, & + this%epoch_frequency, this%input_template, M_file, filenames, & + T_offset_in_file_content = Toff, _RC) + stop -1 - !__ s2. loop over filenames to get this%t_alongtrack(:) - ! ! call get_obsfile_Tbracket_from_epoch(currTime, & ! this%obsfile_start_time, this%obsfile_end_time, & ! this%obsfile_interval, this%epoch_frequency, & From 48ff4668e88ccba3b90197b3b9db105ca446bf9b Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 15 Nov 2023 11:18:24 -0700 Subject: [PATCH 23/41] . --- Apps/time_ave_util.F90 | 2161 ++++++++++++++++++++++++++++++++-------- 1 file changed, 1740 insertions(+), 421 deletions(-) diff --git a/Apps/time_ave_util.F90 b/Apps/time_ave_util.F90 index 119d1793d9ea..7f0190788d30 100644 --- a/Apps/time_ave_util.F90 +++ b/Apps/time_ave_util.F90 @@ -1,424 +1,1743 @@ -#include "MAPL_ErrLog.h" -#include "unused_dummy.H" - -module MAPL_ObsUtilMod - use ESMF - use MAPL_ErrorHandlingMod - use MAPL_KeywordEnforcerMod - use Plain_netCDF_Time - use netCDF - use, intrinsic :: iso_fortran_env, only: REAL32, REAL64 - implicit none - integer, parameter :: mx_ngeoval = 60 +#define I_AM_MAIN +#include "MAPL_Generic.h" + +program time_ave + + use ESMF + use MAPL + use MAPL_FileMetadataUtilsMod + use gFTL_StringVector + use MPI + use, intrinsic :: iso_fortran_env, only: int32, int64, int16, real32, real64 + use ieee_arithmetic, only: isnan => ieee_is_nan + + implicit none + + integer comm,myid,npes,ierror + integer imglobal + integer jmglobal + logical root + +! ********************************************************************** +! ********************************************************************** +! **** **** +! **** Program to create time-averaged HDF files **** +! **** **** +! ********************************************************************** +! ********************************************************************** + + integer im,jm,lm + + integer nymd, nhms + integer nymd0,nhms0 + integer nymdp,nhmsp + integer nymdm,nhmsm + integer ntod, ndt, ntods + integer month, year + integer monthp, yearp + integer monthm, yearm + integer begdate, begtime + integer enddate, endtime + + integer id,rc,timeinc,timeid + integer ntime,nvars,ncvid,nvars2 + + character(len=ESMF_MAXSTR), allocatable :: fname(:) + character(len=ESMF_MAXSTR) template + character(len=ESMF_MAXSTR) name + character(len=ESMF_MAXSTR) ext + character(len=ESMF_MAXSTR) output, doutput, hdfile, rcfile + character(len=8) date0 + character(len=2) time0 + character(len=1) char + data output /'monthly_ave'/ + data rcfile /'NULL'/ + data doutput /'NULL'/ + data template/'NULL'/ + + integer n,m,nargs,L,nfiles,nv,km,mvars,mv,ndvars + + real plev,qming,qmaxg + real previous_undef,undef + real, allocatable :: lev(:) + integer, allocatable :: kmvar(:) , kmvar2(:) + integer, allocatable :: yymmdd(:) + integer, allocatable :: hhmmss(:) + integer, allocatable :: nloc(:) + integer, allocatable :: iloc(:) + + character(len=ESMF_MAXSTR), allocatable :: vname(:), vname2(:) + character(len=ESMF_MAXSTR), allocatable :: vtitle(:), vtitle2(:) + character(len=ESMF_MAXSTR), allocatable :: vunits(:), vunits2(:) + + real, allocatable :: qmin(:) + real, allocatable :: qmax(:) + real, allocatable :: dumz1(:,:) + real, allocatable :: dumz2(:,:) + real, allocatable :: dum(:,:,:) + real(REAL64), allocatable :: q(:,:,:,:) + integer, allocatable :: ntimes(:,:,:,:) + + integer timinc,i,j,k,nmax,kbeg,kend,loc1,loc2 + integer nstar + logical tend, first, strict, diurnal, mdiurnal, lquad, ldquad + logical ignore_nan + data first /.true./ + data strict /.true./ + + type(ESMF_Config) :: config + + integer, allocatable :: qloc(:,:) + character(len=ESMF_MAXSTR), allocatable :: quadratics(:,:) + character(len=ESMF_MAXSTR), allocatable :: quadtmp(:,:) + character(len=ESMF_MAXSTR), allocatable :: aliases(:,:) + character(len=ESMF_MAXSTR), allocatable :: aliastmp(:,:) + character(len=ESMF_MAXSTR) name1, name2, name3, dummy + integer nquad + integer nalias + logical, allocatable :: lzstar(:) + + integer ntmin, ntcrit, nc + + type(FileMetadata) :: basic_metadata + type(FileMetadataUtils) :: file_metadata + type(NetCDF4_FileFormatter) :: file_handle + integer :: status + class(AbstractGridfactory), allocatable :: factory + type(ESMF_Grid) :: output_grid,input_grid + character(len=:), allocatable :: output_grid_name + integer :: global_dims(3), local_dims(3) + type(ESMF_Time), allocatable :: time_series(:) + type(ESMF_TIme) :: etime + type(ESMF_Clock) :: clock + type(ESMF_TimeInterval) :: time_interval + type(ESMF_FieldBundle) :: primary_bundle,final_bundle,diurnal_bundle + type(ESMF_Field) :: field + type(ServerManager) :: io_server + type(FieldBundleWriter) :: standard_writer, diurnal_writer + real(ESMF_KIND_R4), pointer :: ptr2d(:,:),ptr3d(:,:,:) + character(len=ESMF_MAXSTR) :: grid_type + logical :: allow_zonal_means + character(len=ESMF_MAXPATHLEN) :: arg_str + character(len=:), allocatable :: lev_name + character(len=ESMF_MAXSTR) :: lev_units + integer :: n_times + type(verticalData) :: vertical_data + logical :: file_has_lev + type(DistributedProfiler), target :: t_prof + type(ProfileReporter) :: reporter + +! ********************************************************************** +! **** Initialization **** +! ********************************************************************** + +!call timebeg ('main') + + call mpi_init ( ierror ) ; comm = mpi_comm_world + call mpi_comm_rank ( comm,myid,ierror ) + call mpi_comm_size ( comm,npes,ierror ) + call ESMF_Initialize(logKindFlag=ESMF_LOGKIND_NONE,mpiCommunicator=MPI_COMM_WORLD, _RC) + call MAPL_Initialize(_RC) + t_prof = DistributedProfiler('time_ave_util',MpiTImerGauge(),MPI_COMM_WORLD) + call t_prof%start(_RC) + call io_server%initialize(MPI_COMM_WORLD,_RC) + root = myid.eq.0 + call ESMF_CalendarSetDefault(ESMF_CALKIND_GREGORIAN,_RC) + +! Read Command Line Arguments +! --------------------------- + begdate = -999 + begtime = -999 + enddate = -999 + endtime = -999 + ndt = -999 + ntod = -999 + ntmin = -999 + nargs = command_argument_count() + if( nargs.eq.0 ) then + call usage(root) + else + lquad = .TRUE. + ldquad = .FALSE. + diurnal = .FALSE. + mdiurnal = .FALSE. + ignore_nan = .FALSE. + do n=1,nargs + call get_command_argument(n,arg_str) + select case(trim(arg_str)) + case('-template') + call get_command_argument(n+1,template) + case('-tag') + call get_command_argument(n+1,output) + case('-rc') + call get_command_argument(n+1,rcfile) + case('-begdate') + call get_command_argument(n+1,arg_str) + read(arg_str,*)begdate + case('-begtime') + call get_command_argument(n+1,arg_str) + read(arg_str,*)begtime + case('-enddate') + call get_command_argument(n+1,arg_str) + read(arg_str,*)enddate + case('-endtime') + call get_command_argument(n+1,arg_str) + read(arg_str,*)endtime + case('-ntmin') + call get_command_argument(n+1,arg_str) + read(arg_str,*)ntmin + case('-ntod') + call get_command_argument(n+1,arg_str) + read(arg_str,*)ntod + case('-ndt') + call get_command_argument(n+1,arg_str) + read(arg_str,*)ndt + case('-strict') + call get_command_argument(n+1,arg_str) + read(arg_str,*)strict + case('-ogrid') + call get_command_argument(n+1,arg_str) + output_grid_name = trim(arg_str) + case('-noquad') + lquad = .FALSE. + case('-ignore_nan') + ignore_nan = .TRUE. + case('-d') + diurnal = .true. + if (n+1 .le. nargs) then + call get_command_argument(n+1,arg_str) + read(arg_str,fmt='(a1)') char + if (char.ne.'-') doutput=arg_str + end if + case('-md') + mdiurnal = .true. + if (n+1 .le. nargs) then + call get_command_argument(n+1,arg_str) + read(arg_str,fmt='(a1)') char + if (char.ne.'-') doutput=arg_str + end if + case('-dv') + ldquad = .true. + diurnal = .true. + if (n+1 .le. nargs) then + call get_command_argument(n+1,arg_str) + read(arg_str,fmt='(a1)') char + if (char.ne.'-') doutput=arg_str + end if + case('-mdv') + ldquad = .true. + mdiurnal = .true. + if (n+1 .le. nargs) then + call get_command_argument(n+1,arg_str) + read(arg_str,fmt='(a1)') char + if (char.ne.'-') doutput=arg_str + end if + case('-eta') + nfiles = 1 + call get_command_argument(n+nfiles,arg_str) + read(arg_str,fmt='(a1)') char + do while (char .ne. '-' .and. n+nfiles.ne.nargs) + nfiles = nfiles + 1 + call get_command_argument(n+nfiles,arg_str) + read(arg_str,fmt='(a1)') char + enddo + if (char.eq.'-') nfiles = nfiles-1 + allocate(fname(nfiles)) + do m=1,nfiles + call get_command_argument(n+m,fname(m)) + enddo + case('-hdf') + nfiles = 1 + call get_command_argument(n+nfiles,arg_str) + read(arg_str,fmt='(a1)') char + do while (char .ne. '-' .and. n+nfiles.ne.nargs) + nfiles = nfiles + 1 + call get_command_argument(n+nfiles,arg_str) + read(arg_str,fmt='(a1)') char + enddo + if (char.eq.'-') nfiles = nfiles-1 + allocate(fname(nfiles)) + do m=1,nfiles + call get_command_argument(n+m,fname(m)) + enddo + end select + enddo + end if + + if( (diurnal.or.mdiurnal) .and. trim(doutput).eq.'NULL' ) then + doutput = trim(output) // "_diurnal" + if( mdiurnal ) diurnal = .FALSE. + endif + + if (root .and. ignore_nan) print *,' ignore nan is true' + + +! Read RC Quadratics +! ------------------ + if( trim(rcfile).eq.'NULL' ) then + nquad = 0 + nalias = 0 + else + config = ESMF_ConfigCreate ( rc=rc ) + call ESMF_ConfigLoadFile ( config, trim(rcfile), rc=rc ) + call ESMF_ConfigFindLabel ( config, 'QUADRATICS:', rc=rc ) + tend = .false. + m = 0 + do while (.not.tend) + m = m+1 + allocate( quadtmp(3,m) ) + call ESMF_ConfigGetAttribute ( config,value=name1, rc=rc ) + call ESMF_ConfigGetAttribute ( config,value=dummy, rc=rc ) + call ESMF_ConfigGetAttribute ( config,value=name2, rc=rc ) + call ESMF_ConfigGetAttribute ( config,value=dummy, rc=rc ) + call ESMF_ConfigGetAttribute ( config,value=name3,default='XXX',rc=rc ) + call ESMF_ConfigNextLine ( config,tableEnd=tend, rc=rc ) + if( m==1 ) then + quadtmp(1,m) = name1 + quadtmp(2,m) = name2 + quadtmp(3,m) = name3 + allocate( quadratics(3,m) ) + quadratics = quadtmp + else + quadtmp(1,1:m-1) = quadratics(1,:) + quadtmp(2,1:m-1) = quadratics(2,:) + quadtmp(3,1:m-1) = quadratics(3,:) + quadtmp(1,m) = name1 + quadtmp(2,m) = name2 + quadtmp(3,m) = name3 + deallocate( quadratics ) + allocate( quadratics(3,m) ) + quadratics = quadtmp + endif + deallocate (quadtmp) + enddo + nquad = m + +! Read RC Aliases +! --------------- + call ESMF_ConfigFindLabel ( config, 'ALIASES:', rc=rc ) + tend = .false. + m = 0 + do while (.not.tend) + m = m+1 + allocate( aliastmp(2,m) ) + call ESMF_ConfigGetAttribute ( config,value=name1, rc=rc ) + call ESMF_ConfigGetAttribute ( config,value=dummy, rc=rc ) + call ESMF_ConfigGetAttribute ( config,value=name2, rc=rc ) + call ESMF_ConfigNextLine ( config,tableEnd=tend ,rc=rc ) + if( m==1 ) then + aliastmp(1,m) = name1 + aliastmp(2,m) = name2 + allocate( aliases(2,m) ) + aliases = aliastmp + else + aliastmp(1,1:m-1) = aliases(1,:) + aliastmp(2,1:m-1) = aliases(2,:) + aliastmp(1,m) = name1 + aliastmp(2,m) = name2 + deallocate( aliases ) + allocate( aliases(2,m) ) + aliases = aliastmp + endif + deallocate (aliastmp) + enddo + nalias = m + endif + if (.not. allocated(aliases)) allocate(aliases(0,0)) + +! ********************************************************************** +! **** Read HDF File **** +! ********************************************************************** + + call t_prof%start('initialize') + + if( trim(template).ne.'NULL' ) then + name = template + else + name = fname(1) + endif + + n = index(trim(name),'.',back=.true.) + ext = trim(name(n+1:)) + + call file_handle%open(trim(name),PFIO_READ,_RC) + basic_metadata = file_handle%read(_RC) + call file_handle%close(_RC) + + allocate(factory, source=grid_manager%make_factory(trim(name))) + input_grid = grid_manager%make_grid(factory) + file_has_lev = has_level(input_grid,_RC) + call MAPL_GridGet(input_grid,globalCellCountPerDim=global_dims,_RC) + lm = global_dims(3) + + if (file_has_lev) then + call get_file_levels(trim(name),vertical_data,_RC) + end if + + if (allocated(output_grid_name)) then + output_grid = create_output_grid(output_grid_name,lm,_RC) + else + output_grid = input_grid + end if + call ESMF_AttributeGet(output_grid,'GridType',grid_type,_RC) + allow_zonal_means = trim(grid_type) == 'LatLon' + if (trim(grid_type) == "Cubed-Sphere") then + _ASSERT(mod(npes,6)==0,"If input files are Cubed-Sphere, must be run on multiple of 6 proccessors") + end if + call MAPL_GridGet(output_grid,localCellCountPerDim=local_dims,globalCellCountPerDim=global_dims,_RC) + im = local_dims(1) + jm = local_dims(2) + lm = local_dims(3) + imglobal = global_dims(1) + jmglobal = global_dims(2) + + call file_metadata%create(basic_metadata,trim(name)) + call get_file_times(file_metadata,ntime,time_series,timinc,yymmdd,hhmmss,_RC) + primary_bundle = ESMF_FieldBundleCreate(name="first_file",_RC) + call ESMF_FieldBundleSet(primary_bundle,grid=output_grid,_RC) + call MAPL_Read_Bundle(primary_bundle,trim(name),time=time_series(1),_RC) + call ESMF_FieldBundleGet(primary_bundle,fieldCount=nvars,_RC) + allocate(vname(nvars)) + call ESMF_FieldBundleGet(primary_bundle,fieldNameList=vname,_RC) + kmvar = get_level_info(primary_bundle,_RC) + vtitle = get_long_names(primary_bundle,_RC) + vunits = get_units(primary_bundle,_RC) + + final_bundle = ESMF_FieldBundleCreate(name="first_file",_RC) + call ESMF_FieldBundleSet(final_bundle,grid=output_grid,_RC) + diurnal_bundle = ESMF_FieldBundleCreate(name="first_file",_RC) + call ESMF_FieldBundleSet(diurnal_bundle,grid=output_grid,_RC) + call copy_bundle_to_bundle(primary_bundle,final_bundle,_RC) + + if (size(time_series)>1) then + time_interval = time_series(2) - time_series(1) + else if (size(time_series)==1) then + call ESMF_TimeIntervalSet(time_interval,h=6,_RC) + end if + clock = ESMF_ClockCreate(startTime=time_series(1),timeStep=time_interval,_RC) + + nvars2 = nvars + + if (file_has_lev) then + lev_name = file_metadata%get_level_name(_RC) + call file_metadata%get_coordinate_info(lev_name,coords=lev,coordUnits=lev_units,_RC) + end if + + previous_undef = file_metadata%var_get_missing_value(trim(vname(1)),_RC) + do i=2,size(vname) + undef = file_metadata%var_get_missing_value(trim(vname(i)),_RC) + _ASSERT(undef == previous_undef,"conflicting undefined values in your variables") + previous_undef = undef + enddo + undef = previous_undef + + +! Set NDT for Strict Time Testing +! ------------------------------- + if( ntod.ne.-999 ) ndt = 86400 + if( ndt .eq.-999 ) ndt = compute_nsecf (timinc) + if( timinc .eq. 0 ) then + timeId = ncvid (id, 'time', rc) + call ncagt (id, timeId, 'time_increment', timinc, rc) + if( timinc .eq. 0 ) then + if( root ) then + print * + print *, 'Warning, GFIO Inquire states TIMINC = ',timinc + print *, ' This will be reset to 060000 ' + print *, ' Use -ndt NNN (in seconds) to overide this' + endif + timinc = 060000 + endif + ndt = compute_nsecf (timinc) + endif + +! Determine Number of Time Periods within 1-Day +! --------------------------------------------- + ntods = 0 + if( diurnal .or. mdiurnal ) then + if( ndt.lt.86400 ) ntods = 86400/ndt + endif + +! Set Minimum Required Times for Time Average (Default: 10 Days for Monthly Mean) +! ------------------------------------------------------------------------------- + if( ntmin.eq.-999 ) then + if( ntod.eq.-999 ) then + ntcrit = 10 * ( 86400.0/real(compute_nsecf(timinc)) ) + else + ntcrit = 10 + endif + else + ntcrit = ntmin + endif + +! Determine Location Index for Each Variable in File +! -------------------------------------------------- + if( root ) print * + allocate ( nloc(nvars) ) + nloc(1) = 1 + if( root ) write(6,7000) 1,trim(vname(1)),nloc(1),trim(vtitle(1)),max(1,kmvar(1)) + do n=2,nvars + nloc(n) = nloc(n-1)+max(1,kmvar(n-1)) + if( root ) write(6,7000) n,trim(vname(n)),nloc(n),trim(vtitle(n)),max(1,kmvar(n)) +7000 format(1x,'Primary Field: ',i4,' Name: ',a12,' at location: ',i4,3x,a40,2x,i2,3x,i2,3x,i2) + enddo + + nmax = nloc(nvars)+max(1,kmvar(nvars))-1 + allocate( dum (im,jm,nmax) ) + allocate( dumz1(im,jm) ) + allocate( dumz2(im,jm) ) + +! Append Default Quadratics to User-Supplied List +! ----------------------------------------------- + if( lquad ) then + if( nquad.eq.0 ) then + allocate( quadratics(3,nvars) ) + do n=1,nvars + quadratics(1,n) = trim( vname(n) ) + quadratics(2,n) = trim( vname(n) ) + quadratics(3,n) = 'XXX' + enddo + nquad = nvars + else + allocate( quadtmp(3,nquad+nvars) ) + quadtmp(1,1:nquad) = quadratics(1,:) + quadtmp(2,1:nquad) = quadratics(2,:) + quadtmp(3,1:nquad) = quadratics(3,:) + do n=1,nvars + quadtmp(1,nquad+n) = trim( vname(n) ) + quadtmp(2,nquad+n) = trim( vname(n) ) + quadtmp(3,nquad+n) = 'XXX' + enddo + nquad = nquad + nvars + deallocate( quadratics ) + allocate( quadratics(3,nquad) ) + quadratics = quadtmp + deallocate( quadtmp ) + endif + endif + + allocate ( qloc(2,nquad) ) + allocate ( lzstar(nquad) ) ; lzstar = .FALSE. + +! Determine Possible Quadratics +! ----------------------------- + km=kmvar(nvars) + m= nvars + do n=1,nquad + call check_quad ( quadratics(1,n),vname,nvars,aliases,nalias,qloc(1,n) ) + if( qloc(1,n)*qloc(2,n).ne.0 ) then + m=m+1 + allocate ( iloc(m) ) + iloc(1:m-1) = nloc + iloc(m) = iloc(m-1)+max(1,km) + deallocate ( nloc ) + allocate ( nloc(m) ) + nloc = iloc + deallocate ( iloc ) + km=kmvar( qloc(1,n) ) + endif + enddo + + mvars = m + nmax = nloc(m)+max(1,km)-1 + + allocate ( vname2( mvars) ) + allocate ( vtitle2( mvars) ) + allocate ( vunits2( mvars) ) + allocate ( kmvar2( mvars) ) + + vname2( 1:nvars) = vname + vtitle2( 1:nvars) = vtitle + vunits2( 1:nvars) = vunits + kmvar2( 1:nvars) = kmvar + + if( root .and. mvars.gt.nvars ) print * + mv= nvars + do nv=1,nquad + if( qloc(1,nv)*qloc(2,nv).ne.0 ) then + mv = mv+1 + + if( trim(quadratics(1,nv)).eq.trim(quadratics(2,nv)) ) then + vname2(mv) = "Var_" // trim(vname(qloc(1,nv))) + vtitle2(mv) = "Variance_of_" // trim(vname(qloc(1,nv))) + else + vname2(mv) = "Cov_" // trim(vname(qloc(1,nv))) // "_" // trim(vname(qloc(2,nv))) + vtitle2(mv) = "Covariance_of_" // trim(vname(qloc(1,nv))) // "_and_" // trim(vname(qloc(2,nv))) + endif + + if( trim(quadratics(3,nv)).ne.'XXX' ) vname2(mv) = trim(quadratics(3,nv)) + + nstar = index( trim(quadratics(1,nv)),'star',back=.true. ) + if( nstar.ne.0 ) then + _ASSERT(allow_zonal_means,"grid is not lat-lon so cannot compute zonal means") + lzstar(nv) = .TRUE. + vtitle2(mv) = "Product_of_Zonal_Mean_Deviations_of_" // trim(vname(qloc(1,nv))) // "_and_" // trim(vname(qloc(2,nv))) + endif + + vunits2(mv) = trim(vunits(qloc(1,nv))) // " " // trim(vunits(qloc(2,nv))) + kmvar2(mv) = kmvar(qloc(1,nv)) + + call add_new_field_to_bundle(final_bundle,output_grid,kmvar(qloc(1,nv)),vname2(mv),vtitle2(mv),vunits2(mv),_RC) + + if( root ) write(6,7001) mv,trim(vname2(mv)),nloc(mv),trim(vtitle2(mv)),max(1,kmvar(qloc(1,nv))),qloc(1,nv),qloc(2,nv) +7001 format(1x,' Quad Field: ',i4,' Name: ',a12,' at location: ',i4,3x,a50,2x,i2,3x,i3,3x,i3) + endif + enddo + +!deallocate ( lev ) + deallocate ( yymmdd ) + deallocate ( hhmmss ) + deallocate ( vname ) + deallocate ( vtitle ) + deallocate ( vunits ) + deallocate ( kmvar ) + + allocate( qmin(nmax) ) + allocate( qmax(nmax) ) + allocate( q(im,jm,nmax,0:ntods) ) + allocate( ntimes(im,jm,nmax,0:ntods) ) + ntimes = 0 + q = 0 + qmin = abs(undef) + qmax = -abs(undef) + + if( root ) then + print * + write(6,7002) mvars,nmax,im,jm,nmax,ntods +7002 format(1x,'Total Number of Variables: ',i3,/ & + 1x,'Total Size: ',i5,/ & + 1x,'Allocating q(',i4,',',i3,',',i5,',0:',i2.2,')') + print * + print *, 'Files: ' + do n=1,nfiles + print *, n,trim(fname(n)) + enddo + print * + if( ntod.eq.-999 ) then + print *, 'Averging Time-Period NHMS: ',ntod,' (ALL Possible Time Periods Used)' + else + print *, 'Averging Time-Period NHMS: ',ntod + endif + if( begdate.ne.-999 .or. begtime.ne.-999 ) print *, 'Beginning Date for Averaging: ',begdate,begtime + if( enddate.ne.-999 .or. endtime.ne.-999 ) print *, ' Ending Date for Averaging: ',enddate,endtime + if( strict ) then + print *, 'Every Time Period Required for Averaging, STRICT = ',strict + else + print *, 'Only Averaging Time Periods Supplied, STRICT = ',strict + endif + write(6,7003) ntcrit +7003 format(1x,'Required Minimum Number of Defined Time Periods: ',i3,' (Otherwise, UNDEF)') + print * + endif + + call t_prof%stop('initialize') + +! ********************************************************************** +! **** Read HDF Files **** +! ********************************************************************** + + k = 0 + + do n=1,nfiles + + if (allocated(time_series)) deallocate(time_series) + if (allocated(yymmdd)) deallocate(yymmdd) + if (allocated(hhmmss)) deallocate(hhmmss) + call file_handle%open(trim(fname(n)),PFIO_READ,_RC) + basic_metadata = file_handle%read(_RC) + call file_handle%close(_RC) + call file_metadata%create(basic_metadata,trim(fname(n))) + call get_file_times(file_metadata,ntime,time_series,timinc,yymmdd,hhmmss,_RC) + + + do m=1,ntime + nymd = yymmdd(m) + nhms = hhmmss(m) + if( nhms<0 ) then + nhms = compute_nhmsf( compute_nsecf(nhms) + 86400 ) + call tick (nymd,nhms,-86400) + endif + + if( ( begdate.ne.-999 .and. begtime.ne.-999 ) .and. & + ( begdate.gt.nymd .or. & + ( begdate.eq.nymd.and.begtime.gt.nhms ) ) ) cycle + + if( ( enddate.ne.-999 .and. endtime.ne.-999 ) .and. & + ( enddate.lt.nymd .or. & + ( enddate.eq.nymd.and.endtime.lt.nhms ) ) ) cycle + + k = k+1 + if( k.gt.ntods ) k = 1 + if( ntod.eq.-999 .or. ntod.eq.nhms ) then + if( root ) write(6,3000) nymd,nhms,timinc,trim(fname(n)),k +3000 format(1x,'Reading nymd: ',i8.8,' nhms: ',i6.6,' TimInc: ',i6.6,' from File: ',a,' tod = ',i2) + year = nymd/10000 + month = mod(nymd,10000)/100 + +! Check for Correct First Dataset +! ------------------------------- + if( strict .and. first ) then + nymdm = nymd + nhmsm = nhms + call tick (nymdm,nhmsm,-ndt) + yearm = nymdm/10000 + monthm = mod(nymdm,10000)/100 + if( year.eq.yearm .and. month.eq.monthm ) then + if( root ) print *, 'Date: ',nymd,' Time: ',nhms,' is NOT correct First Time Period!' + _FAIL("error processing dataset") + endif + endif + +! Check Date and Time for STRICT Time Testing +! ------------------------------------------- + if( strict .and. .not.first ) then + if( nymd.ne.nymdp .or. nhms.ne.nhmsp ) then + if( root ) print *, 'Date: ',nymdp,' Time: ',nhmsp,' not found!' + _FAIL("error processing dataset") + endif + endif + nymdp = nymd + nhmsp = nhms + +! Primary Fields +! -------------- + + etime = local_esmf_timeset(nymd,nhms,_RC) + call MAPL_Read_Bundle(primary_bundle,trim(fname(1)),time=etime,file_override=trim(fname(n)),_RC) + do nv=1,nvars2 + call ESMF_FieldBundleGet(primary_bundle,trim(vname2(nv)),field=field,_RC) + call t_prof%start('PRIME') + if( kmvar2(nv).eq.0 ) then + kbeg = 0 + kend = 1 + call ESMF_FieldGet(field,0,farrayPtr=ptr2d,_RC) + dum(:,:,nloc(nv))=ptr2d + else + kbeg = 1 + kend = kmvar2(nv) + + call ESMF_FieldGet(field,0,farrayPtr=ptr3d,_RC) + dum(:,:,nloc(nv):nloc(nv)+kmvar2(nv)-1) = ptr3d + endif + + rc = 0 + do L=1,max(1,kmvar2(nv)) + do j=1,jm + do i=1,im + if( isnan( dum(i,j,nloc(nv)+L-1) ) .or. ( dum(i,j,nloc(nv)+L-1).gt.HUGE(dum(i,j,nloc(nv)+L-1)) ) ) then +!print *, 'Warning! Nan or Infinity detected for ',trim(vname2(nv)),' at lat: ',lattice%jglobal(j),' lon: ',lattice%iglobal(i) + if( root .and. ignore_nan ) then + print *, 'Setting Nan or Infinity to UNDEF' + print * + else + rc = 1 + endif + dum(i,j,nloc(nv)+L-1) = undef + endif + if( defined(dum(i,j,nloc(nv)+L-1),undef) ) then + q(i,j,nloc(nv)+L-1,0) = q(i,j,nloc(nv)+L-1,0) + dum(i,j,nloc(nv)+L-1) + ntimes(i,j,nloc(nv)+L-1,0) = ntimes(i,j,nloc(nv)+L-1,0) + 1 + if( qmin(nloc(nv)+L-1).gt.dum(i,j,nloc(nv)+L-1) ) qmin(nloc(nv)+L-1) = dum(i,j,nloc(nv)+L-1) + if( qmax(nloc(nv)+L-1).lt.dum(i,j,nloc(nv)+L-1) ) qmax(nloc(nv)+L-1) = dum(i,j,nloc(nv)+L-1) + if( ntods.ne.0 ) then + q(i,j,nloc(nv)+L-1,k) = q(i,j,nloc(nv)+L-1,k) + dum(i,j,nloc(nv)+L-1) + ntimes(i,j,nloc(nv)+L-1,k) = ntimes(i,j,nloc(nv)+L-1,k) + 1 + endif + endif + enddo + enddo + enddo + call t_prof%stop('PRIME') + + enddo + +! Quadratics +! ---------- + call t_prof%start('QUAD') + mv= nvars2 + do nv=1,nquad + if( qloc(1,nv)*qloc(2,nv).ne.0 ) then + mv=mv+1 + do L=1,max(1,kmvar2(qloc(1,nv))) + if( lzstar(nv) ) then + call latlon_zstar (dum(:,:,nloc(qloc(1,nv))+L-1),dumz1,undef,output_grid,_RC) + call latlon_zstar (dum(:,:,nloc(qloc(2,nv))+L-1),dumz2,undef,output_grid,_RC) + do j=1,jm + do i=1,im + if( defined(dumz1(i,j),undef) .and. & + defined(dumz2(i,j),undef) ) then + q(i,j,nloc(mv)+L-1,0) = q(i,j,nloc(mv)+L-1,0) + dumz1(i,j)*dumz2(i,j) + ntimes(i,j,nloc(mv)+L-1,0) = ntimes(i,j,nloc(mv)+L-1,0) + 1 + if( ntods.ne.0 ) then + q(i,j,nloc(mv)+L-1,k) = q(i,j,nloc(mv)+L-1,k) + dumz1(i,j)*dumz2(i,j) + ntimes(i,j,nloc(mv)+L-1,k) = ntimes(i,j,nloc(mv)+L-1,k) + 1 + endif + endif + enddo + enddo + else + do j=1,jm + do i=1,im + if( defined(dum(i,j,nloc(qloc(1,nv))+L-1),undef) .and. & + defined(dum(i,j,nloc(qloc(2,nv))+L-1),undef) ) then + q(i,j,nloc(mv)+L-1,0) = q(i,j,nloc(mv)+L-1,0) + dum(i,j,nloc(qloc(1,nv))+L-1) & + * dum(i,j,nloc(qloc(2,nv))+L-1) + ntimes(i,j,nloc(mv)+L-1,0) = ntimes(i,j,nloc(mv)+L-1,0) + 1 + if( ntods.ne.0 ) then + q(i,j,nloc(mv)+L-1,k) = q(i,j,nloc(mv)+L-1,k) + dum(i,j,nloc(qloc(1,nv))+L-1) & + * dum(i,j,nloc(qloc(2,nv))+L-1) + ntimes(i,j,nloc(mv)+L-1,k) = ntimes(i,j,nloc(mv)+L-1,k) + 1 + endif + endif + enddo + enddo + endif + enddo + endif + enddo + call t_prof%stop('QUAD') + + if( first ) then + nymd0 = nymd + nhms0 = nhms + first = .false. + endif + +! Update Date and Time for Strict Test +! ------------------------------------ + call tick (nymdp,nhmsp,ndt) + yearp = nymdp/10000 + monthp = mod(nymdp,10000)/100 + + endif ! End ntod Test + enddo ! End ntime Loop within file + + call MPI_BARRIER(comm,status) + enddo + + do k=0,ntods + if( k.eq.0 ) then + nc = ntcrit + else + nc = max( 1,ntcrit/ntods ) + endif + do n=1,nmax + do j=1,jm + do i=1,im + if( ntimes(i,j,n,k).lt.nc ) then + q(i,j,n,k) = undef + else + q(i,j,n,k) = q(i,j,n,k)/ntimes(i,j,n,k) + endif + enddo + enddo + enddo + enddo + +! ********************************************************************** +! **** Write HDF Monthly Output File **** +! ********************************************************************** + +call t_prof%start('Write_AVE') + +! Check for Correct Last Dataset +! ------------------------------ + if( strict .and. ( year.eq.yearp .and. month.eq.monthp ) ) then + if( root ) print *, 'Date: ',nymd,' Time: ',nhms,' is NOT correct Last Time Period!' + _FAIL("Error processing dataset") + endif + + write(date0,4000) nymd0/100 + write(time0,2000) nhms0/10000 + + hdfile = trim(output) // "." // trim(date0) // "." // trim(ext) + +1000 format(i8.8) +2000 format(i2.2) +4000 format(i6.6) + + timeinc = 060000 + +! Primary Fields +! -------------- + if( root ) print * + do n=1,nvars2 + call ESMF_FieldBundleGet(final_bundle,trim(vname2(n)),field=field,_RC) + if( kmvar2(n).eq.0 ) then + kbeg = 0 + kend = 1 + call ESMF_FieldGet(field,0,farrayPtr=ptr2d,_RC) + ptr2d = q(:,:,nloc(n),0) + else + kbeg = 1 + kend = kmvar2(n) + call ESMF_FieldGet(field,0,farrayPtr=ptr3d,_RC) + ptr3d = q(:,:,nloc(n):nloc(n)+kend-1,0) + endif + if( root ) write(6,3001) trim(vname2(n)),nloc(n),trim(hdfile) +3001 format(1x,'Writing ',a,' at location ',i6,' into File: ',a) + dum(:,:,1:kend) = q(:,:,nloc(n):nloc(n)+kend-1,0) + enddo + +! Quadratics +! ---------- + mv= nvars2 + do nv=1,nquad + if( qloc(1,nv)*qloc(2,nv).ne.0 ) then + mv=mv+1 + if( root ) write(6,3001) trim(vname2(mv)),nloc(mv),trim(hdfile) + call ESMF_FieldBundleGet(final_bundle,trim(vname2(mv)),field=field,_RC) + + if( kmvar2(qloc(1,nv)).eq.0 ) then + kbeg = 0 + kend = 1 + else + kbeg = 1 + kend = kmvar2(qloc(1,nv)) + endif + loc1 = nloc( qloc(1,nv) ) + loc2 = nloc( qloc(2,nv) ) + if( .not.lzstar(nv) ) then + where( q(:,:,nloc(mv):nloc(mv)+kend-1,0).ne.undef ) + dum(:,:,1:kend) = q(:,:,nloc(mv):nloc(mv)+kend-1,0) - q(:,:,loc1:loc1+kend-1,0) & + * q(:,:,loc2:loc2+kend-1,0) + elsewhere + dum(:,:,1:kend) = undef + endwhere + else + dum(:,:,1:kend) = q(:,:,nloc(mv):nloc(mv)+kend-1,0) + endif + if( kmvar2(qloc(1,nv)).eq.0 ) then + call ESMF_FieldGet(field,0,farrayPtr=ptr2d,_RC) + ptr2d = dum(:,:,1) + else + kend = kmvar2(qloc(1,nv)) + call ESMF_FieldGet(field,0,farrayPtr=ptr3d,_RC) + ptr3d = dum(:,:,1:kend) + endif + endif + enddo + + if( root ) then + print * + print *, 'Created: ',trim(hdfile) + print * + endif + call t_prof%stop('Write_AVE') + etime = local_esmf_timeset(nymd0,nhms0,_RC) + call ESMF_ClockSet(clock,currTime=etime, _RC) + call standard_writer%create_from_bundle(final_bundle,clock,n_steps=1,time_interval=timeinc,vertical_data=vertical_data,_RC) + call standard_writer%start_new_file(trim(hdfile),_RC) + call standard_writer%write_to_file(_RC) + +! ********************************************************************** +! **** Write HDF Monthly Diurnal Output File **** +! ********************************************************************** + + if( ntods.ne.0 ) then + call t_prof%start('Write_Diurnal') + timeinc = compute_nhmsf( 86400/ntods ) + + do k=1,ntods + + if( k.eq.1 .or. mdiurnal ) then + + write(date0,4000) nymd0/100 + write(time0,2000) nhms0/10000 + + if( diurnal ) hdfile = trim(doutput) // "." // trim(date0) // "." // trim(ext) + if( mdiurnal ) hdfile = trim(doutput) // "." // trim(date0) // "_" // trim(time0) // "z." // trim(ext) + + if( ldquad ) then + ndvars = mvars ! Include Quadratics in Diurnal Files + if (k==1) then + call copy_bundle_to_bundle(final_bundle,diurnal_bundle,_RC) + end if + else + ndvars = nvars2 ! Only Include Primary Fields in Diurnal Files (Default) + if (k==1) then + do n=1,nvars + call ESMF_FieldBundleGet(final_bundle,trim(vname2(n)),field=field,_RC) + call MAPL_FieldBundleAdd(diurnal_bundle,field,_RC) + enddo + endif + endif + endif + +! Primary Fields +! -------------- + do n=1,nvars2 + call ESMF_FieldBundleGet(diurnal_bundle,trim(vname2(n)),field=field,_RC) + if( kmvar2(n).eq.0 ) then + kbeg = 0 + kend = 1 + call ESMF_FieldGet(field,0,farrayPtr=ptr2d,_RC) + ptr2d = q(:,:,nloc(n),k) + else + kbeg = 1 + kend = kmvar2(n) + call ESMF_FieldGet(field,0,farrayPtr=ptr3d,_RC) + ptr3d = q(:,:,nloc(n):nloc(n)+kend-1,k) + endif + dum(:,:,1:kend) = q(:,:,nloc(n):nloc(n)+kend-1,k) + enddo + +! Quadratics +! ---------- + if( ndvars.eq.mvars ) then + mv= nvars2 + do nv=1,nquad + if( qloc(1,nv)*qloc(2,nv).ne.0 ) then + mv=mv+1 + call ESMF_FieldBundleGet(diurnal_bundle,trim(vname2(mv)),field=field,_RC) + if( kmvar2(qloc(1,nv)).eq.0 ) then + kbeg = 0 + kend = 1 + else + kbeg = 1 + kend = kmvar2(qloc(1,nv)) + endif + loc1 = nloc( qloc(1,nv) ) + loc2 = nloc( qloc(2,nv) ) + if( .not.lzstar(nv) ) then + where( q(:,:,nloc(mv):nloc(mv)+kend-1,0).ne.undef ) + dum(:,:,1:kend) = q(:,:,nloc(mv):nloc(mv)+kend-1,k) - q(:,:,loc1:loc1+kend-1,k) & + * q(:,:,loc2:loc2+kend-1,k) + elsewhere + dum(:,:,1:kend) = undef + endwhere + else + dum(:,:,1:kend) = q(:,:,nloc(mv):nloc(mv)+kend-1,k) + endif + if( kmvar2(qloc(1,nv)).eq.0 ) then + call ESMF_FieldGet(field,0,farrayPtr=ptr2d,_RC) + ptr2d = dum(:,:,1) + else + kend = kmvar2(qloc(1,nv)) + call ESMF_FieldGet(field,0,farrayPtr=ptr3d,_RC) + ptr3d = dum(:,:,1:kend) + endif + endif + enddo + endif + + + etime = local_esmf_timeset(nymd0,nhms0,_RC) + call ESMF_ClockSet(clock,currTime=etime, _RC) + if (k==1 .or. mdiurnal) then + if (mdiurnal) then + n_times = 1 + else + n_times = ntods + end if + if (k==1) then + call diurnal_writer%create_from_bundle(diurnal_bundle,clock,n_steps=n_times,time_interval=timeinc,vertical_data=vertical_data) + end if + call diurnal_writer%start_new_file(trim(hdfile),_RC) + end if + call diurnal_writer%write_to_file(_RC) + if( root .and. mdiurnal ) then + print *, 'Created: ',trim(hdfile) + endif + call tick (nymd0,nhms0,ndt) + enddo + + if( root .and. diurnal ) then + print *, 'Created: ',trim(hdfile) + endif + if( root ) print * + + call t_prof%stop('Write_Diurnal') + endif + +! ********************************************************************** +! **** Write Min/Max Information **** +! ********************************************************************** + + if( root ) print * + do n=1,nvars2 + do L=1,max(1,kmvar2(n)) + if( kmvar2(n).eq.0 ) then + plev = 0 + else + plev = lev(L) + endif + + call mpi_reduce( qmin(nloc(n)+L-1),qming,1,mpi_real,mpi_min,0,comm,ierror ) + call mpi_reduce( qmax(nloc(n)+L-1),qmaxg,1,mpi_real,mpi_max,0,comm,ierror ) + if( root ) then + if(L.eq.1) then + write(6,3101) trim(vname2(n)),plev,qming,qmaxg + else + write(6,3102) trim(vname2(n)),plev,qming,qmaxg + endif + endif +3101 format(1x,'Primary Field: ',a20,' Level: ',f9.3,' Min: ',g15.8,' Max: ',g15.8) +3102 format(1x,' ',a20,' Level: ',f9.3,' Min: ',g15.8,' Max: ',g15.8) + enddo + call MPI_BARRIER(comm,status) + if( root ) print * + enddo + if( root ) print * + +! ********************************************************************** +! **** Timing Information **** +! ********************************************************************** + + call io_server%finalize() + call t_prof%stop() + call t_prof%reduce() + call t_prof%finalize() + call generate_report() + call MAPL_Finalize() + call MPI_Finalize(status) + stop contains - ! --//-------------------------------------//-> - ! files - ! o o o o o o o o o o T: filename - ! <--- off set - ! o o o o o o o o o o T: file content start - ! | | - ! curr curr+Epoch - ! - - subroutine Find_M_files_for_currTime (currTime, & - obsfile_start_time, obsfile_end_time, obsfile_interval, & - epoch_frequency, file_template, M, filenames, & - T_offset_in_file_content, rc) - implicit none - type(ESMF_Time), intent(in) :: currTime - type(ESMF_Time), intent(in) :: obsfile_start_time, obsfile_end_time - type(ESMF_TimeInterval), intent(in) :: obsfile_interval, epoch_frequency - character(len=*), intent(in) :: file_template - integer, intent(out) :: M - character(len=ESMF_MAXSTR), intent(out) :: filenames(200) - type(ESMF_TimeInterval), intent(in), optional :: T_offset_in_file_content - integer, optional, intent(out) :: rc - - type(ESMF_Time) :: T1, Tn - type(ESMF_Time) :: cT1 - type(ESMF_Time) :: Ts, Te - type(ESMF_TimeInterval) :: dT1, dT2, dTs, dTe - type(ESMF_TimeInterval) :: Toff - real(ESMF_KIND_R8) :: dT0_s, dT1_s, dT2_s - real(ESMF_KIND_R8) :: s1, s2 - character(len=ESMF_MAXSTR) :: test_file - - integer :: obsfile_Ts_index, obsfile_Te_index - integer :: n1, n2 - integer :: i, j - integer :: status - - !__ s1. Arithmetic index list based on s,e,interval - ! - print*, __LINE__, __FILE__ - if (present(T_offset_in_file_content)) then - Toff = T_offset_in_file_content - else - call ESMF_TimeIntervalSet(Toff, h=0, m=0, s=60, rc=status) - endif - - ! T1 = obsfile_start_time + Toff - ! Tn = obsfile_end_time + Toff - - T1 = obsfile_start_time - Tn = obsfile_end_time - - cT1 = currTime - dT1 = currTime - T1 - dT2 = currTime + epoch_frequency - T1 - - call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) - call ESMF_TimeIntervalGet(dT1, s_r8=dT1_s, rc=status) - call ESMF_TimeIntervalGet(dT2, s_r8=dT2_s, rc=status) - - n1 = floor (dT1_s / dT0_s) - n2 = floor (dT2_s / dT0_s) - - print*, 'ck dT0_s, dT1_s, dT2_s', dT0_s, dT1_s, dT2_s - print*, '1st n1, n2', n1, n2 - - obsfile_Ts_index = n1 - if ( dT2_s - n2*dT0_s < 1 ) then - obsfile_Te_index = n2 - 1 - else - obsfile_Te_index = n2 - end if - - ! put back - n1 = obsfile_Ts_index - n2 = obsfile_Te_index - - print*, __LINE__, __FILE__ - print*, '2nd n1, n2', n1, n2 - - !__ s2. further test file existence - ! - j=0 - do i= n1, n2 - test_file = get_filename_from_template_use_index & - (obsfile_start_time, obsfile_interval, & - i, file_template, rc=rc) - if (test_file /= '') then - j=j+1 - filenames(j) = test_file - end if - end do - M=j - - _RETURN(_SUCCESS) - - end subroutine Find_M_files_for_currTime - - - subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & - index_name_lon, index_name_lat,& - var_name_lon, var_name_lat, var_name_time, & - lon, lat, time_R8, rc ) - - character(len=ESMF_MAXSTR), intent(in) :: filenames(:) - integer, intent(out) :: Xdim - integer, intent(out) :: Ydim - character(len=ESMF_MAXSTR), intent(in) :: index_name_lon - character(len=ESMF_MAXSTR), intent(in) :: index_name_lat - character(len=ESMF_MAXSTR), optional, intent(in) :: var_name_lon - character(len=ESMF_MAXSTR), optional, intent(in) :: var_name_lat - character(len=ESMF_MAXSTR), optional, intent(in) :: var_name_time - - real, optional, intent(inout) :: lon(:,:) - real, optional, intent(inout) :: lat(:,:) - real(ESMF_KIND_R8), optional, intent(inout) :: time_R8(:,:) - - integer, optional, intent(out) :: rc - - integer :: M - integer :: i, j, jx, status - integer :: nlon, nlat - integer :: ncid, ncid2 - character(len=ESMF_MAXSTR) :: grp1, grp2 - integer :: varid - logical :: found_group - - character(len=ESMF_MAXSTR) :: filename - integer, allocatable :: nlons(:), nlats(:) - real(ESMF_KIND_R8), allocatable :: time_loc_R8(:,:) - real(ESMF_KIND_R8), allocatable :: lon_loc(:,:) - real(ESMF_KIND_R8), allocatable :: lat_loc(:,:) - - - !__ s1. get Xdim Ydim - M = size(filenames) - allocate(nlons(M), nlats(M)) - jx=0 - do i = 1, M - filename = filenames(i) - print*, 'ck filename input', trim(filename) - CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, & - key_lon=index_name_lon, key_lat=index_name_lat, _RC) - nlons(i)=nlon - nlats(i)=nlat - print*, 'nlon, nlat=', nlon, nlat - jx=jx+nlat - end do - Xdim=nlon - Ydim=jx - - - !__ s2. get fields - jx=0 - do i = 1, M - filename = filenames(i) - nlon = nlons(i) - nlat = nlats(i) - - if (present(var_name_time).AND.present(time_R8)) then - allocate (time_loc_R8(nlon, nlat)) - call get_var_from_name_w_group (var_name_time, time_loc_R8, filename, _RC) - time_R8(1:nlon,jx+1:jx+nlat) = time_loc_R8(1:nlon,1:nlat) - deallocate(time_loc_R8) - end if - - if (present(var_name_lon).AND.present(lon)) then - allocate (lon_loc(nlon, nlat)) - call get_var_from_name_w_group (var_name_lon, lon_loc, filename, _RC) - lon(1:nlon,jx+1:jx+nlat) = lon_loc(1:nlon,1:nlat) - deallocate(lon_loc) - end if - - if (present(var_name_lat).AND.present(lat)) then - allocate (lat_loc(nlon, nlat)) - call get_var_from_name_w_group (var_name_lat, lat_loc, filename, _RC) - lat(1:nlon,jx+1:jx+nlat) = lat_loc(1:nlon,1:nlat) - deallocate(lat_loc) - end if - - jx = jx + nlat - - end do - - ! allocate(scanTime(nlon, nlat)) - ! allocate(this%t_alongtrack(nlat)) - - rc=0 - !! _RETURN(_SUCCESS) - end subroutine read_M_files_4_swath - - - - - function get_filename_from_template_use_index (obsfile_start_time, obsfile_interval, & - f_index, file_template, rc) result(filename) - use Plain_netCDF_Time, only : ESMF_time_to_two_integer - use MAPL_StringTemplate, only : fill_grads_template - character(len=ESMF_MAXSTR) :: filename - type(ESMF_Time), intent(in) :: obsfile_start_time - type(ESMF_TimeInterval), intent(in) :: obsfile_interval - character(len=*), intent(in) :: file_template - integer, intent(in) :: f_index - integer, optional, intent(out) :: rc - - integer :: itime(2) - integer :: nymd, nhms - integer :: status - real(ESMF_KIND_R8) :: dT0_s - real(ESMF_KIND_R8) :: s - type(ESMF_TimeInterval) :: dT - type(ESMF_Time) :: time - integer :: i, j - - character(len=ESMF_MAXSTR) :: file_template_left - character(len=ESMF_MAXSTR) :: file_template_right - character(len=ESMF_MAXSTR) :: filename_left - character(len=ESMF_MAXSTR) :: filename_full - character(len=ESMF_MAXSTR) :: cmd - - call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) - s = dT0_s * f_index - call ESMF_TimeIntervalSet(dT, s_r8=s, rc=status) - time = obsfile_start_time + dT - - call ESMF_time_to_two_integer(time, itime, _RC) - nymd = itime(1) - nhms = itime(2) - - j= index(file_template, '*') - if (j>0) then - ! wild char exist - !!print*, 'pos of * in template =', j - file_template_left = file_template(1:j-1) - call fill_grads_template ( filename_left, file_template_left, & - experiment_id='', nymd=nymd, nhms=nhms, _RC ) - filename= trim(filename_left)//trim(file_template(j:)) - cmd="bash -c 'ls "//trim(filename)//"' &> zzz_MAPL" - CALL execute_command_line(trim(cmd)) - open(7213, file='zzz_MAPL', status='unknown') - read(7213, '(a)') filename - i=index(trim(filename), 'ls') - if (i==1) then - filename='' - end if - cmd="rm -f ./zzz_MAPL" - CALL execute_command_line(trim(cmd)) - close(7213) - else - ! exact file name - call fill_grads_template ( filename, file_template, & - experiment_id='', nymd=nymd, nhms=nhms, _RC ) - end if - _RETURN(_SUCCESS) - - end function get_filename_from_template_use_index - - - - subroutine get_var_from_name_w_group (var_name, var2d, filename, rc) - character(len=ESMF_MAXSTR), intent(in) :: var_name, filename - real(ESMF_KIND_R8), intent(inout) :: var2d(:,:) - integer, optional, intent(out) :: rc - - integer :: i, j - character(len=ESMF_MAXSTR) :: grp1, grp2 - character(len=ESMF_MAXSTR) :: short_name - integer :: ncid, ncid2, varid - logical :: found_group - integer :: status - - - i=index(var_name, '/') - if (i>0) then - found_group = .true. - grp1 = var_name(1:i-1) - j=index(var_name(i+1:), '/') - if (j>0) then - grp2=var_name(i+1:i+j-1) - short_name=var_name(i+j+1:) - else - grp2='' - short_name=var_name(i+1:) - endif - i=i+j - else - found_group = .false. - grp1 = '' - grp2='' - short_name=var_name - endif - - print*, 'ck grp1, grp2, short_name:', trim(grp1), trim(grp2), trim(short_name) - - - call check_nc_status(nf90_open(filename, NF90_NOWRITE, ncid2), _RC) - if ( found_group ) then - call check_nc_status(nf90_inq_ncid(ncid2, grp1, ncid), _RC) - print*, 'ck grp1' - if (j>0) then - call check_nc_status(nf90_inq_ncid(ncid, grp2, ncid2), _RC) - ncid=ncid2 - print*, 'ck grp2' - endif - else - print*, 'no grp name' - ncid=ncid2 - endif - call check_nc_status(nf90_inq_varid(ncid, short_name, varid), _RC) - call check_nc_status(nf90_get_var(ncid, varid, var2d), _RC) - - write(6,*) var2d(::100,::100) - - _RETURN(_SUCCESS) - - end subroutine get_var_from_name_w_group - - - -end module MAPL_ObsUtilMod - - - -program main - use ESMF - use MAPL_ObsUtilMod - implicit none - - type(ESMF_Time) :: currTime - type(ESMF_Time) :: obsfile_start_time, obsfile_end_time - type(ESMF_TimeInterval) :: obsfile_interval, epoch_frequency - type(ESMF_TimeInterval) :: Toff - character(len=ESMF_MAXSTR) :: file_template - character(len=ESMF_MAXSTR) :: STR1 - character(len=ESMF_MAXSTR) :: filenames(200) - integer :: M - integer :: i - real(KIND=ESMF_KIND_R8) :: sec - integer :: rc, status - type(ESMF_Calendar) :: gregorianCalendar - - character(len=ESMF_MAXSTR) :: index_name_lon - character(len=ESMF_MAXSTR) :: index_name_lat - character(len=ESMF_MAXSTR) :: index_name_time - character(len=ESMF_MAXSTR) :: var_name_lon - character(len=ESMF_MAXSTR) :: var_name_lat - character(len=ESMF_MAXSTR) :: var_name_time - integer :: Xdim, Ydim - - real(ESMF_kind_R8), allocatable :: time_R8(:,:) - real, allocatable :: lon_center(:,:) - - file_template = '/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A%y4%D3.%h2%n2.*.h5' - index_name_lon= 'Cell_Across_Swath:mod04' - index_name_lat= 'Cell_Along_Swath:mod04' - var_name_time= 'mod04/Data Fields/Scan_Start_Time' - var_name_lon= 'mod04/Geolocation Fields/Longitude' - var_name_lat= 'mod04/Geolocation Fields/Latitude' - - - gregorianCalendar = ESMF_CalendarCreate(ESMF_CALKIND_GREGORIAN, name='Gregorian_obs' , rc=rc) - - ! STR1='2017-03-31T00:00:00' - ! call ESMF_TimeSet(currTime, trim(STR1), rc=rc) - - ! STR1='2017-03-31T00:00:00' - ! call ESMF_TimeSet(obsfile_start_time, trim(STR1), rc=rc) - - ! STR1='2017-04-01T00:00:00' - ! call ESMF_TimeSet(obsfile_end_time, trim(STR1), rc=rc) - - call ESMF_TimeSet(currTime, yy=2017, mm=3, dd=31, h=0, m=0, s=0, & - calendar=gregorianCalendar, rc=rc) - obsfile_start_time = currTime - call ESMF_TimeSet(obsfile_end_time, yy=2018, mm=3, dd=31, h=0, m=0, s=0, & - calendar=gregorianCalendar, rc=rc) - - sec = 300.d0 - call ESMF_TimeIntervalSet(obsfile_interval, h=0, m=5, s=0, rc=rc) - - sec = 3600.d0 - call ESMF_TimeIntervalSet(Epoch_frequency, h=1, m=0, s=0, rc=rc) - - sec = 0.d0 - call ESMF_TimeIntervalSet(Toff, s_r8=sec, rc=status) - - call Find_M_files_for_currTime (currTime, & - obsfile_start_time, obsfile_end_time, obsfile_interval, & - epoch_frequency, file_template, M, filenames, & - T_offset_in_file_content = Toff, rc = rc) - - write(6,*) 'M=', M - do i=1, M - write(6,*) 'filenames(i)=', trim(filenames(i)) - end do - - call read_M_files_4_swath (filenames(1:M), Xdim, Ydim, & - index_name_lon, index_name_lat, rc=rc) - allocate( time_R8(Xdim, Ydim) ) - allocate( lon_center(Xdim, Ydim) ) - - call read_M_files_4_swath (filenames(1:M), Xdim, Ydim, & - index_name_lon, index_name_lat, & - var_name_time=var_name_time, time_R8=time_R8, & - var_name_lon=var_name_lon, lon=lon_center, rc=rc) - - deallocate( time_R8, lon_center ) - -end program main + function create_output_grid(grid_name,lm,rc) result(new_grid) + type(ESMF_Grid) :: new_grid + character(len=*), intent(inout) :: grid_name + integer, intent(in) :: lm + integer, optional, intent(out) :: rc + + type(ESMF_Config) :: cf + integer :: nn,im_world,jm_world,nx, ny + character(len=5) :: imsz,jmsz + character(len=2) :: pole,dateline + + nn = len_trim(grid_name) + imsz = grid_name(3:index(grid_name,'x')-1) + jmsz = grid_name(index(grid_name,'x')+1:nn-3) + pole = grid_name(1:2) + dateline = grid_name(nn-1:nn) + read(IMSZ,*) im_world + read(JMSZ,*) jm_world + + cf = MAPL_ConfigCreate(_RC) + call MAPL_ConfigSetAttribute(cf,value=lm, label=trim(grid_name)//".LM:",_RC) + if (dateline=='CF') then + call MAPL_MakeDecomposition(nx,ny,reduceFactor=6,_RC) + call MAPL_ConfigSetAttribute(cf,value=NX, label=trim(grid_name)//".NX:",_RC) + call MAPL_ConfigSetAttribute(cf,value="Cubed-Sphere", label=trim(grid_name)//".GRID_TYPE:",_RC) + call MAPL_ConfigSetAttribute(cf,value=6, label=trim(grid_name)//".NF:",_RC) + call MAPL_ConfigSetAttribute(cf,value=im_world,label=trim(grid_name)//".IM_WORLD:",_RC) + call MAPL_ConfigSetAttribute(cf,value=ny, label=trim(grid_name)//".NY:",_RC) + else if (dateline=='TM') then + _FAIL("Tripolar not yet implemented for outpout") + else + call MAPL_MakeDecomposition(nx,ny,_RC) + call MAPL_ConfigSetAttribute(cf,value=NX, label=trim(grid_name)//".NX:",_RC) + call MAPL_ConfigSetAttribute(cf,value="LatLon", label=trim(grid_name)//".GRID_TYPE:",_RC) + call MAPL_ConfigSetAttribute(cf,value=im_world,label=trim(grid_name)//".IM_WORLD:",_RC) + call MAPL_ConfigSetAttribute(cf,value=jm_world,label=trim(grid_name)//".JM_WORLD:",_RC) + call MAPL_ConfigSetAttribute(cf,value=ny, label=trim(grid_name)//".NY:",_RC) + call MAPL_ConfigSetAttribute(cf,value=pole, label=trim(grid_name)//".POLE:",_RC) + call MAPL_ConfigSetAttribute(cf,value=dateline, label=trim(grid_name)//".DATELINE:",_RC) + if (pole=='XY' .and. dateline=='XY') then + _FAIL("regional lat-lon output not supported") + end if + end if + + new_grid = grid_manager%make_grid(cf,prefix=trim(grid_name)//".",_RC) + if (present(rc)) then + rc=_SUCCESS + end if + end function create_output_grid + + subroutine get_file_levels(filename,vertical_data,rc) + character(len=*), intent(in) :: filename + type(VerticalData), intent(inout) :: vertical_data + integer, intent(out), optional :: rc + + integer :: status + type(NetCDF4_fileFormatter) :: formatter + type(FileMetadata) :: basic_metadata + type(FileMetadataUtils) :: metadata + character(len=:), allocatable :: lev_name + character(len=ESMF_MAXSTR) :: long_name + character(len=ESMF_MAXSTR) :: standard_name + character(len=ESMF_MAXSTR) :: vcoord + character(len=ESMF_MAXSTR) :: lev_units + real, allocatable, target :: levs(:) + real, pointer :: plevs(:) + + call formatter%open(trim(filename),pFIO_Read,_RC) + basic_metadata=formatter%read(_RC) + call metadata%create(basic_metadata,trim(filename)) + lev_name = metadata%get_level_name(_RC) + if (lev_name /= '') then + call metadata%get_coordinate_info(lev_name,coords=levs,coordUnits=lev_units,long_name=long_name,& + standard_name=standard_name,coordinate_attr=vcoord,_RC) + plevs => levs + vertical_data = VerticalData(levels=plevs,vunit=lev_units,vcoord=vcoord,standard_name=standard_name,long_name=long_name, & + force_no_regrid=.true.,_RC) + nullify(plevs) + end if + + if (present(rc)) then + rc=_SUCCESS + end if + + end subroutine get_file_levels + + function has_level(grid,rc) result(grid_has_level) + logical :: grid_has_level + type(ESMF_Grid), intent(in) :: grid + integer, intent(out), optional :: rc + integer :: status, global_dims(3) + call MAPL_GridGet(grid,globalCellCountPerDim=global_dims,_RC) + grid_has_level = (global_dims(3)>1) + if (present(rc)) then + RC=_SUCCESS + end if + end function has_level + + subroutine copy_bundle_to_bundle(input_bundle,output_bundle,rc) + type(ESMF_FieldBundle), intent(inout) :: input_bundle + type(ESMF_FieldBundle), intent(inout) :: output_bundle + integer, intent(out), optional :: rc + integer :: status + character(len=ESMF_MAXSTR), allocatable :: field_list(:) + type(ESMF_Field) :: field + integer :: i,num_fields + call ESMF_FieldBundleGet(input_bundle,fieldCount=num_fields,_RC) + allocate(field_list(num_fields)) + call ESMF_FieldBundleGet(input_bundle,fieldNameList=field_list,_RC) + do i=1,num_fields + call ESMF_FieldBundleGet(input_bundle,field_list(i),field=field,_RC) + call MAPL_FieldBundleAdd(output_bundle,field,_RC) + enddo + if (present(rc)) then + RC=_SUCCESS + end if + end subroutine copy_bundle_to_bundle + + subroutine add_new_field_to_bundle(bundle,grid,lm,field_name,long_name,units,rc) + type(ESMF_FieldBundle), intent(inout) :: bundle + type(ESMF_Grid), intent(in) :: grid + integer, intent(in) :: lm + character(len=*), intent(in) :: field_name + character(len=*), intent(in) :: long_name + character(len=*), intent(in) :: units + integer, intent(out), optional :: rc + + integer :: status + type(ESMF_Field) :: field + + if (lm == 0) then + field = ESMF_FieldCreate(grid,name=trim(field_name),typekind=ESMF_TYPEKIND_R4,_RC) + else if (lm > 0) then + field = ESMF_FieldCreate(grid,name=trim(field_name),typekind=ESMF_TYPEKIND_R4, & + ungriddedLBound=[1],ungriddedUBound=[lm],_RC) + end if + call ESMF_AttributeSet(field,name='LONG_NAME',value=trim(long_name),_RC) + call ESMF_AttributeSet(field,name='UNITS',value=trim(units),_RC) + if (lm == 0) then + call ESMF_AttributeSet(field,name='DIMS',value=MAPL_DimsHorzOnly,_RC) + call ESMF_AttributeSet(field,name='VLOCATION',value=MAPL_VLocationNone,_RC) + else if (lm > 0) then + call ESMF_AttributeSet(field,name='DIMS',value=MAPL_DimsHorzVert,_RC) + call ESMF_AttributeSet(field,name='VLOCATION',value=MAPL_VLocationCenter,_RC) + end if + call MAPL_FieldBundleAdd(bundle,field,_RC) + if (present(rc)) then + RC=_SUCCESS + end if + end subroutine add_new_field_to_bundle + + subroutine get_file_times(file_metadata,num_times,time_series,time_interval,yymmdd,hhmmss,rc) + type(FileMetadataUtils), intent(inout) :: file_metadata + integer, intent(out) :: num_times + type(ESMF_Time), allocatable, intent(inout) :: time_series(:) + integer, intent(inout), allocatable :: yymmdd(:) + integer, intent(inout), allocatable :: hhmmss(:) + integer, intent(out) :: time_interval + integer, intent(out), optional :: rc + + integer :: status + type(ESMF_TimeInterval) :: esmf_time_interval + integer :: hour, minute, second, year, month, day, i + + num_times = file_metadata%get_dimension('time',_RC) + call file_metadata%get_time_info(timeVector=time_series,_RC) + if (num_times == 1) then + time_interval = file_metadata%get_var_attr_int32('time','time_increment',_RC) + else if (num_times > 1) then + esmf_time_interval = time_series(2)-time_series(1) + call ESMF_TimeIntervalGet(esmf_time_interval,h=hour,m=minute,s=second,_RC) + time_interval = hour*10000+minute*100+second + end if + + allocate(yymmdd(num_times),hhmmss(num_times)) + do i = 1,num_times + call ESMF_TimeGet(time_series(i),yy=year,mm=month,dd=day,h=hour,m=minute,s=second,_RC) + yymmdd(i)=year*10000+month*100+day + hhmmss(i)=hour*10000+minute*100+second + enddo + if (present(rc)) then + rc=_SUCCESS + end if + end subroutine get_file_times + + function get_level_info(bundle,rc) result(kmvar) + integer, allocatable :: kmvar(:) + type(ESMF_FieldBundle), intent(in) :: bundle + integer, optional, intent(out) :: rc + + integer :: status + character(len=ESMF_MAXSTR), allocatable :: field_list(:) + type(ESMF_Field) :: field + integer :: rank,i,num_fields,lb(1),ub(1) + call ESMF_FieldBundleGet(bundle,fieldCount=num_fields,_RC) + allocate(field_list(num_fields)) + allocate(kmvar(num_fields)) + call ESMF_FieldBundleGet(bundle,fieldNameList=field_list,_RC) + do i=1,num_fields + call ESMF_FieldBundleGet(bundle,field_list(i),field=field,_RC) + call ESMF_FieldGet(field,rank=rank,_RC) + if (rank==2) then + kmvar(i)=0 + else if (rank==3) then + call ESMF_FieldGet(field,ungriddedLBound=lb,ungriddedUBound=ub,_RC) + kmvar(i)=ub(1)-lb(1)+1 + else + _FAIL("Unsupported rank") + end if + end do + if (present(rc)) then + RC=_SUCCESS + end if + end function get_level_info + + function get_long_names(bundle,rc) result(long_names) + character(len=ESMF_MAXSTR), allocatable :: long_names(:) + type(ESMF_FieldBundle), intent(in) :: bundle + integer, optional, intent(out) :: rc + + integer :: status + character(len=ESMF_MAXSTR), allocatable :: field_list(:) + type(ESMF_Field) :: field + integer :: i,num_fields + + call ESMF_FieldBundleGet(bundle,fieldCount=num_fields,_RC) + allocate(field_list(num_fields)) + allocate(long_names(num_fields)) + call ESMF_FieldBundleGet(bundle,fieldNameList=field_list,_RC) + do i=1,num_fields + call ESMF_FieldBundleGet(bundle,field_list(i),field=field,_RC) + call ESMF_AttributeGet(field,name='LONG_NAME',value=long_names(i),_RC) + enddo + if (present(rc)) then + RC=_SUCCESS + end if + end function get_long_names + + function get_units(bundle,rc) result(units) + character(len=ESMF_MAXSTR), allocatable :: units(:) + type(ESMF_FieldBundle), intent(in) :: bundle + integer, optional, intent(out) :: rc + + integer :: status + character(len=ESMF_MAXSTR), allocatable :: field_list(:) + type(ESMF_Field) :: field + integer :: i,num_fields + + call ESMF_FieldBundleGet(bundle,fieldCount=num_fields,_RC) + allocate(field_list(num_fields)) + allocate(units(num_fields)) + call ESMF_FieldBundleGet(bundle,fieldNameList=field_list,_RC) + do i=1,num_fields + call ESMF_FieldBundleGet(bundle,field_list(i),field=field,_RC) + call ESMF_AttributeGet(field,name='UNITS',value=units(i),_RC) + enddo + if (present(rc)) then + RC=_SUCCESS + end if + end function get_units + + function local_esmf_timeset(yymmdd,hhmmss,rc) result(etime) + type(ESMF_Time) :: etime + integer, intent(in) :: yymmdd + integer, intent(in) :: hhmmss + integer, intent(out), optional :: rc + + integer :: year,month,day,hour,minute,second,status + year = yymmdd/10000 + month = mod(yymmdd/100,100) + day = mod(yymmdd,100) + + hour = hhmmss/10000 + minute = mod(hhmmss/100,100) + second = mod(hhmmss,100) + + call ESMF_TimeSet(etime,yy=year,mm=month,dd=day,h=hour,m=minute,s=second,_RC) + if (present(rc)) then + rc=_SUCCESS + endif + end function local_esmf_timeset + + function defined ( q,undef ) + implicit none + logical defined + real q,undef + defined = q /= undef + end function defined + + subroutine latlon_zstar (q,qp,undef,grid,rc) + real, intent(inout) :: q(:,:) + real, intent(out) :: qp(:,:) + real, intent(in) :: undef + type (ESMF_Grid), intent(inout) :: grid + integer, optional, intent(out) :: rc + + integer :: local_dims(3) + integer im,jm,i,j,status + real, allocatable :: qz(:) + + call MAPL_GridGet(grid,localCellCountPerDim=local_dims,_RC) + im = local_dims(1) + jm = local_dims(2) + allocate(qz(jm)) + + call latlon_zmean ( q,qz,undef,grid ) + do j=1,jm + if( qz(j).eq. undef ) then + qp(:,j) = undef + else + do i=1,im + if( defined( q(i,j),undef) ) then + qp(i,j) = q(i,j) - qz(j) + else + qp(i,j) = undef + endif + enddo + endif + enddo + if (present(rc)) then + rc=_SUCCESS + endif + end subroutine latlon_zstar + + subroutine latlon_zmean ( q,qz,undef,grid,rc) + real, intent(inout) :: q(:,:) + real, intent(inout) :: qz(:) + real, intent(in) :: undef + type(ESMF_Grid), intent(inout) :: grid + integer, optional, intent(out) :: rc + + integer :: im,jm,im_global,jm_global,local_dims(3),global_dims(3),status,nx,ny + real, allocatable :: qg(:,:) + real, allocatable :: buf(:,:) + real :: qsum + integer :: mpistatus(mpi_status_size) + integer, allocatable :: ims(:),jms(:) + integer j,n,peid,peid0,i1,j1,in,jn,mypet,i_start,i_end,isum + type(ESMF_VM) :: vm + + call ESMF_VMGetCurrent(vm,_RC) + call ESMF_VMGet(vm,localPet=mypet,_RC) + call MAPL_GridGet(grid,localCellCountPerDim=local_dims,globalCellCountPerDim=global_dims,_RC) + im = local_dims(1) + jm = local_dims(2) + im_global = global_dims(1) + jm_global = global_dims(2) + call get_esmf_grid_layout(grid,nx,ny,ims,jms,_RC) + call mapl_grid_interior(grid,i1,in,j1,jn) + + qz = 0.0 + allocate( qg(im_global,jm) ) + peid0 = (mypet/nx)*ny + if (i1==1) then + i_start = 1 + i_end = ims(1) + qg(i_start:i_end,:)=q + do n=1,nx-1 + allocate(buf(ims(n+1),jm)) + peid = mypet + n + call mpi_recv(buf,ims(n+1)*jm,MPI_FLOAT,peid,peid,MPI_COMM_WORLD,mpistatus,status) + _VERIFY(status) + i_start=i_end+1 + i_end = i_start+ims(n)-1 + qg(i_start:i_end,:)=buf + deallocate(buf) + enddo + else + call mpi_send(q,im*jm,MPI_FLOAT,peid0,mypet,MPI_COMM_WORLD,status) + _VERIFY(status) + end if + +! compute zonal mean + if (i1 == 1) then + do j=1,jm + isum = count(qg(:,j) /= undef) + qsum = sum(qg(:,j),mask=qg(:,j)/=undef) + if (isum == 0) then + qz(j)=undef + else + qz(j)=qsum/real(isum) + end if + enddo + +! send mean back to other ranks + do n=1,nx-1 + peid = peid0+n + call mpi_send(qz,jm,MPI_FLOAT,peid,peid0,MPI_COMM_WORLD,status) + _VERIFY(status) + enddo + else + call mpi_recv(qz,jm,MPI_FLOAT,peid0,peid0,MPI_COMM_WORLD,mpistatus,status) + _VERIFY(status) + end if + + if (present(rc)) then + rc=_SUCCESS + endif + + end subroutine latlon_zmean + + subroutine get_esmf_grid_layout(grid,nx,ny,ims_out,jms_out,rc) + type(ESMF_Grid), intent(inout) :: grid + integer, intent(out) :: nx + integer, intent(out) :: ny + integer, intent(inout), allocatable :: ims_out(:) + integer, intent(inout), allocatable :: jms_out(:) + integer, optional, intent(out) :: rc + + type(ESMF_VM) :: vm + integer :: status + type(ESMF_DistGrid) :: dist_grid + integer, allocatable :: minindex(:,:),maxindex(:,:) + integer :: dim_count, ndes + integer, pointer :: ims(:),jms(:) + + call ESMF_VMGetCurrent(vm,_RC) + call ESMF_VMGet(vm,petCount=ndes,_RC) + call ESMF_GridGet(grid,distgrid=dist_grid,dimCOunt=dim_count,_RC) + allocate(minindex(dim_count,ndes),maxindex(dim_count,ndes)) + call MAPL_DistGridGet(dist_grid,minIndex=minindex,maxIndex=maxindex,_RC) + call MAPL_GetImsJms(minindex(1,:),maxindex(1,:),minindex(2,:),maxindex(2,:),ims,jms,_RC) + nx = size(ims) + ny = size(jms) + allocate(ims_out(nx),jms_out(ny)) + ims_out = ims + jms_out = jms + + if (present(rc)) then + rc=_SUCCESS + endif + + end subroutine get_esmf_grid_layout + + subroutine check_quad ( quad,vname,nvars,aliases,nalias,qloc ) + integer :: nvars, nalias + character(len=ESMF_MAXSTR) quad(2), aliases(2,nalias), vname(nvars) + integer qloc(2) + integer m,n + +! Initialize Location of Quadratics +! --------------------------------- + qloc = 0 + +! Check Quadratic Name against HDF Variable Names +! ----------------------------------------------- + do n=1,nvars + if( trim(vname(n)).eq.trim(quad(1)) ) qloc(1) = n + if( trim(vname(n)).eq.trim(quad(2)) ) qloc(2) = n + enddo + +! Check Quadratic Name against Aliases +! ------------------------------------ + do m=1,nalias + if( trim(quad(1)).eq.trim(aliases(1,m)) ) then + do n=1,nvars + if( trim(vname(n)).eq.trim(quad(1)) .or. & + trim(vname(n)).eq.trim(aliases(2,m)) ) then + qloc(1) = n + exit + endif + enddo + endif + if( trim(quad(2)).eq.trim(aliases(1,m)) ) then + do n=1,nvars + if( trim(vname(n)).eq.trim(quad(2)) .or. & + trim(vname(n)).eq.trim(aliases(2,m)) ) then + qloc(2) = n + exit + endif + enddo + endif + enddo + + end subroutine check_quad + + function compute_nsecf (nhms) result(seconds) + integer :: seconds + integer, intent(in) :: nhms + seconds = nhms/10000*3600 + mod(nhms,10000)/100*60 + mod(nhms,100) + end function compute_nsecf + + function compute_nhmsf (nsec) result(nhmsf) + integer :: nhmsf + integer, intent(in) :: nsec + nhmsf = nsec/3600*10000 + mod(nsec,3600)/60*100 + mod(nsec,60) + end function compute_nhmsf + + subroutine tick (nymd,nhms,ndt) + integer, intent(inout) :: nymd + integer, intent(inout) :: nhms + integer, intent(in) :: ndt + + integer :: nsec + + if(ndt.ne.0) then + nsec = compute_nsecf(nhms) + ndt + + if (nsec.gt.86400) then + do while (nsec.gt.86400) + nsec = nsec - 86400 + nymd = compute_incymd (nymd,1) + enddo + endif + + if (nsec.eq.86400) then + nsec = 0 + nymd = compute_incymd (nymd,1) + endif + + if (nsec.lt.00000) then + do while (nsec.lt.0) + nsec = 86400 + nsec + nymd = compute_incymd (nymd,-1) + enddo + endif + + nhms = compute_nhmsf (nsec) + endif + + end subroutine tick + + function compute_incymd (nymd,m) result(incymd) + integer :: incymd + integer, intent(in) :: nymd + integer, intent(in) :: m +!*********************************************************************** +! purpose +! incymd: nymd changed by one day +! modymd: nymd converted to julian date +! description of parameters +! nymd current date in yymmdd format +! m +/- 1 (day adjustment) +! +!*********************************************************************** +!* goddard laboratory for atmospheres * +!*********************************************************************** + + integer ndpm(12) + data ndpm /31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/ + integer :: ny,nm,nd +!*********************************************************************** +! + ny = nymd / 10000 + nm = mod(nymd,10000) / 100 + nd = mod(nymd,100) + m + + if (nd.eq.0) then + nm = nm - 1 + if (nm.eq.0) then + nm = 12 + ny = ny - 1 + endif + nd = ndpm(nm) + if (nm.eq.2 .and. is_leap_year(ny)) nd = 29 + endif + + if (nd.eq.29 .and. nm.eq.2 .and. is_leap_year(ny)) go to 20 + + if (nd.gt.ndpm(nm)) then + nd = 1 + nm = nm + 1 + if (nm.gt.12) then + nm = 1 + ny = ny + 1 + endif + endif + +20 continue + incymd = ny*10000 + nm*100 + nd + return + + end function compute_incymd + + logical function is_leap_year(year) + integer, intent(in) :: year + is_leap_year = (mod(year,4) == 0) .and. (mod(year,100) == 0 .or. mod(year,400) == 0) + end function is_leap_year + + subroutine usage(root) + logical, intent(in) :: root + integer :: status,errorcode + if(root) then + write(6,100) +100 format( "usage: ",/,/ & + " time_ave.x -hdf filenames (in hdf format)",/ & + " <-template template>" ,/ & + " <-tag tag>" ,/ & + " <-rc rcfile>" ,/ & + " <-ntod ntod>" ,/ & + " <-ntmin ntmin>" ,/ & + " <-strict strict>" ,/ & + " <-d>" ,/ & + " <-md>" ,/,/ & + "where:",/,/ & + " -hdf filenames: filenames (in hdf format) to average",/ & + " -template template: filename to use as template if hdf files differ (default: 1st filename)",/ & + " -begdate yyyymmdd: optional parameter for date to begin averaging",/ & + " -begtime hhmmss: optional parameter for time to begin averaging",/ & + " -enddate yyyymmdd: optional parameter for date to end averaging",/ & + " -endtime hhmmss: optional parameter for time to end averaging",/ & + " -tag tag: optional tag for output file (default: monthly_ave)",/ & + " -rc rcfile: optional resource filename for quadratics (default: no quadratics)",/ & + " -ntod ntod: optional time-of-day (hhmmss) to average (default: all time periods)",/ & + " -ntmin ntmin: optional parameter for required min. timeperiods (default: 10 days equiv)",/ & + " -strict strict: optional logical parameter for strict time testing (default: .true.)",/ & + " -d dtag: optional parameter to create & tag monthly mean diurnal file ", & + "(all times included)",/ & + " -md dtag: optional parameter to create & tag multiple monthly mean diurnal files ", & + "(one time per file)",/ & + " -dv dtag: like -d but includes diurnal variances",/ & + " -mdv dtag: like -md but includes diurnal variances",/ & + ) + endif + call MPI_Abort(MPI_COMM_WORLD,errorcode,status) + end subroutine usage + + subroutine generate_report() + + character(:), allocatable :: report_lines(:) + integer :: i + character(1) :: empty(0) + + reporter = ProfileReporter(empty) + call reporter%add_column(NameColumn(20)) + call reporter%add_column(FormattedTextColumn('Inclusive','(f9.6)', 9, InclusiveColumn('MEAN'))) + call reporter%add_column(FormattedTextColumn('% Incl','(f6.2)', 6, PercentageColumn(InclusiveColumn('MEAN'),'MAX'))) + call reporter%add_column(FormattedTextColumn('Exclusive','(f9.6)', 9, ExclusiveColumn('MEAN'))) + call reporter%add_column(FormattedTextColumn('% Excl','(f6.2)', 6, PercentageColumn(ExclusiveColumn('MEAN')))) + call reporter%add_column(FormattedTextColumn(' Max Excl)','(f9.6)', 9, ExclusiveColumn('MAX'))) + call reporter%add_column(FormattedTextColumn(' Min Excl)','(f9.6)', 9, ExclusiveColumn('MIN'))) + call reporter%add_column(FormattedTextColumn('Max PE)','(1x,i4.4,1x)', 6, ExclusiveColumn('MAX_PE'))) + call reporter%add_column(FormattedTextColumn('Min PE)','(1x,i4.4,1x)', 6, ExclusiveColumn('MIN_PE'))) + report_lines = reporter%generate_report(t_prof) + if (mapl_am_I_root()) then + write(*,'(a)')'Final profile' + write(*,'(a)')'=============' + do i = 1, size(report_lines) + write(*,'(a)') report_lines(i) + end do + write(*,'(a)') '' + end if + end subroutine generate_report + + +end program time_ave From 1ac6d94ffc0105fed4489f664baa408e94c26354 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Thu, 16 Nov 2023 11:05:34 -0700 Subject: [PATCH 24/41] WIP, save a copy --- base/MAPL_ObsUtil.F90 | 21 ----------------- base/MAPL_SwathGridFactory.F90 | 43 +++++++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/base/MAPL_ObsUtil.F90 b/base/MAPL_ObsUtil.F90 index dfe0db7da469..8cf31fdcab83 100644 --- a/base/MAPL_ObsUtil.F90 +++ b/base/MAPL_ObsUtil.F90 @@ -3,31 +3,10 @@ module MAPL_ObsUtilMod use ESMF - use MAPL_FileMetadataUtilsMod use Plain_netCDF_Time use netCDF use, intrinsic :: iso_fortran_env, only: REAL32, REAL64 implicit none - integer, parameter :: mx_ngeoval = 60 - !! private - - public :: obs_unit - type :: obs_unit - integer :: nobs_epoch - integer :: ngeoval - logical :: export_all_geoval - type(FileMetadata), allocatable :: metadata - type(NetCDF4_FileFormatter), allocatable :: file_handle - character(len=ESMF_MAXSTR) :: name - character(len=ESMF_MAXSTR) :: obsFile_output - character(len=ESMF_MAXSTR) :: input_template - character(len=ESMF_MAXSTR) :: geoval_name(mx_ngeoval) - real(kind=REAL64), allocatable :: lons(:) - real(kind=REAL64), allocatable :: lats(:) - real(kind=REAL64), allocatable :: times_R8(:) - real(kind=REAL32), allocatable :: p2d(:) - real(kind=REAL32), allocatable :: p3d(:,:) - end type obs_unit interface sort_multi_arrays_by_time module procedure sort_three_arrays_by_time diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 2fe313fe7589..ab1e67c1590b 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -441,39 +441,42 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call ESMF_ConfigGetAttribute(config, this%nx, label=prefix//'NX:', default=MAPL_UNDEFINED_INTEGER) call ESMF_ConfigGetAttribute(config, this%ny, label=prefix//'NY:', default=MAPL_UNDEFINED_INTEGER) call ESMF_ConfigGetAttribute(config, this%lm, label=prefix//'LM:', default=MAPL_UNDEFINED_INTEGER) - call ESMF_ConfigGetAttribute(config, this%input_template, label=prefix//'GRID_FILE_template:', default='unknown.txt', _RC) + call ESMF_ConfigGetAttribute(config, this%input_template, label=prefix//'GRID_FILE:', default='unknown.txt', _RC) call ESMF_ConfigGetAttribute(config, this%epoch, label=prefix//'Epoch:', default=300, _RC) call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'Epoch_init:', default='2006', _RC) call ESMF_ConfigGetAttribute(config, value=STR1, default="", & label= prefix// 'obs_file_begin:', _RC) + print*, 'obs_file_begin: str1=', trim(STR1) + if (trim(STR1)=='') then _FAIL('obs_file_begin missing, code crash') else - call ESMF_TimeSet(this%obsfile_start_time, STR1, _RC) + call ESMF_TimeSet(this%obsfile_start_time, timestring=STR1, _RC) if (mapl_am_I_root()) then write(6,105) 'obs_file_begin provided: ', trim(STR1) end if end if - + call ESMF_ConfigGetAttribute(config, value=STR1, default="", & label=prefix // 'obs_file_end:', _RC) + print*, 'obs_file_end: str1=', trim(STR1) + if (trim(STR1)=='') then _FAIL('obs_file_end missing, code crash') else - call ESMF_TimeSet(this%obsfile_end_time, STR1, _RC) + call ESMF_TimeSet(this%obsfile_end_time, timestring=STR1, _RC) if (mapl_am_I_root()) then write(6,105) 'obs_file_end provided:', trim(STR1) end if end if - call ESMF_ConfigGetAttribute(config, value=STR1, default="", & label= prefix// 'obs_file_interval:', _RC) _ASSERT(STR1/='', 'fatal error: obs_file_interval not provided in RC file') if (mapl_am_I_root()) write(6,105) 'obs_file_interval:', trim(STR1) - if (mapl_am_I_root()) write(6,106) 'Epoch (second) :', sec + if (mapl_am_I_root()) write(6,106) 'Epoch (hhmmss) :', this%epoch i= index( trim(STR1), ' ' ) if (i>0) then @@ -484,7 +487,6 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc shms=trim(STR1) endif call convert_twostring_2_esmfinterval (symd, shms, this%obsfile_interval, _RC) - second = hms_2_s(this%Epoch) call ESMF_TimeIntervalSet(this%epoch_frequency, s=second, _RC) @@ -497,22 +499,20 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc endif call lgr%debug(' %a %a', 'input_template =', trim(this%input_template)) - print*,__FILE__, __LINE__ !!write(6,'(2x,a,/,4i8,/,5(2x,a))') 'nx,ny,lm,epoch -- filename,tmp', & !! this%nx,this%ny,this%lm,this%epoch,& !! trim(filename),trim(tmp) !!print*, 'ck: Epoch_init:', trim(tmp) - call ESMF_ConfigGetAttribute(config, value=this%index_name_lon, default="", & label=prefix // 'index_name_lon:', _RC) call ESMF_ConfigGetAttribute(config, this%var_name_time, default="", & label=prefix//'var_name_time:', _RC) call ESMF_ConfigGetAttribute(config, this%var_name_lon, & - label=prefix // 'var_name_Longitude:', default="", _RC) + label=prefix // 'var_name_lon:', default="", _RC) call ESMF_ConfigGetAttribute(config, this%var_name_lat, & - label=prefix // 'var_name_Latitude:', default="", _RC) + label=prefix // 'var_name_lat:', default="", _RC) ! i=index(this%nc_time, '/') ! if (i>0) then @@ -559,6 +559,25 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc this%epoch_frequency, this%input_template, M_file, filenames, & T_offset_in_file_content = Toff, _RC) + + write(6,*) 'M_file=', M_file + do i=1, M_file + write(6,*) 'filenames(i)=', trim(filenames(i)) + end do + + call read_M_files_4_swath (filenames(1:M_file), Xdim, Ydim, & + this%index_name_lon, this%index_name_lat, _RC) + allocate( time_R8(Xdim, Ydim) ) + allocate( lon_center(Xdim, Ydim) ) + + call read_M_files_4_swath (filenames(1:M_file), Xdim, Ydim, & + this%index_name_lon, this%index_name_lat, & + var_name_time=this%var_name_time, time_R8=time_R8, & + var_name_lon=this%var_name_lon, lon=lon_center, rc=rc) + + deallocate( time_R8, lon_center ) + + stop -1 ! call get_obsfile_Tbracket_from_epoch(currTime, & @@ -585,6 +604,8 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc key_lon=key_lon, key_lat=key_lat, _RC) print*, 'filename input', trim(filename) print*, 'nlon, nlat=', nlon, nlat + + allocate(scanTime(nlon, nlat)) allocate(this%t_alongtrack(nlat)) From 7694bf37b013c5556d1691f3fc4458ab1499bf81 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Thu, 16 Nov 2023 16:55:52 -0700 Subject: [PATCH 25/41] . --- base/MAPL_ObsUtil.F90 | 14 +- base/MAPL_SwathGridFactory.F90 | 393 +++++++++++++-------------------- base/Plain_netCDF_Time.F90 | 10 +- 3 files changed, 171 insertions(+), 246 deletions(-) diff --git a/base/MAPL_ObsUtil.F90 b/base/MAPL_ObsUtil.F90 index 8cf31fdcab83..3a833570e890 100644 --- a/base/MAPL_ObsUtil.F90 +++ b/base/MAPL_ObsUtil.F90 @@ -242,7 +242,7 @@ end subroutine Find_M_files_for_currTime subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & index_name_lon, index_name_lat,& var_name_lon, var_name_lat, var_name_time, & - lon, lat, time_R8, rc ) + lon, lat, time, rc ) character(len=ESMF_MAXSTR), intent(in) :: filenames(:) integer, intent(out) :: Xdim @@ -255,7 +255,8 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & real, optional, intent(inout) :: lon(:,:) real, optional, intent(inout) :: lat(:,:) - real(ESMF_KIND_R8), optional, intent(inout) :: time_R8(:,:) + !! real(ESMF_KIND_R8), optional, intent(inout) :: time_R8(:,:) + real, optional, intent(inout) :: time(:,:) integer, optional, intent(out) :: rc @@ -299,10 +300,10 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & nlon = nlons(i) nlat = nlats(i) - if (present(var_name_time).AND.present(time_R8)) then + if (present(var_name_time).AND.present(time)) then allocate (time_loc_R8(nlon, nlat)) call get_var_from_name_w_group (var_name_time, time_loc_R8, filename, _RC) - time_R8(1:nlon,jx+1:jx+nlat) = time_loc_R8(1:nlon,1:nlat) + time(1:nlon,jx+1:jx+nlat) = time_loc_R8(1:nlon,1:nlat) deallocate(time_loc_R8) end if @@ -432,17 +433,15 @@ subroutine get_var_from_name_w_group (var_name, var2d, filename, rc) short_name=var_name endif - print*, 'ck grp1, grp2, short_name:', trim(grp1), trim(grp2), trim(short_name) + write(6,'(10(2x,a))') 'ck grp1, grp2, short_name:', trim(grp1), trim(grp2), trim(short_name) call check_nc_status(nf90_open(filename, NF90_NOWRITE, ncid2), _RC) if ( found_group ) then call check_nc_status(nf90_inq_ncid(ncid2, grp1, ncid), _RC) - print*, 'ck grp1' if (j>0) then call check_nc_status(nf90_inq_ncid(ncid, grp2, ncid2), _RC) ncid=ncid2 - print*, 'ck grp2' endif else print*, 'no grp name' @@ -450,6 +449,7 @@ subroutine get_var_from_name_w_group (var_name, var2d, filename, rc) endif call check_nc_status(nf90_inq_varid(ncid, short_name, varid), _RC) call check_nc_status(nf90_get_var(ncid, varid, var2d), _RC) +!! call check_nc_status(nf90_close(ncid), _RC) write(6,*) var2d(::100,::100) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index ab1e67c1590b..66b38016db07 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -21,6 +21,7 @@ module MAPL_SwathGridFactoryMod use, intrinsic :: iso_fortran_env, only: REAL64 implicit none integer, parameter :: gridLabel_max = 20 + integer, parameter :: mx_file = 300 private public :: SwathGridFactory @@ -29,7 +30,9 @@ module MAPL_SwathGridFactoryMod private character(len=:), allocatable :: grid_name character(len=:), allocatable :: grid_file_name - + character(len=ESMF_MAXSTR) :: filenames(mx_file) + integer :: M_file + integer :: cell_across_swath integer :: cell_along_swath integer :: im_world = MAPL_UNDEFINED_INTEGER @@ -39,13 +42,13 @@ module MAPL_SwathGridFactoryMod integer :: epoch ! unit: second integer(ESMF_KIND_I8) :: epoch_index(4) ! is,ie,js,je - character(len=ESMF_MAXSTR) :: tunit - real(ESMF_KIND_R8), allocatable :: t_alongtrack(:) + real(ESMF_KIND_R8), allocatable:: t_alongtrack(:) + character(len=ESMF_MAXSTR) :: tunit character(len=ESMF_MAXSTR) :: index_name_lon character(len=ESMF_MAXSTR) :: index_name_lat - character(len=ESMF_MAXSTR) :: var_name_time - character(len=ESMF_MAXSTR) :: var_name_lat character(len=ESMF_MAXSTR) :: var_name_lon + character(len=ESMF_MAXSTR) :: var_name_lat + character(len=ESMF_MAXSTR) :: var_name_time character(len=ESMF_MAXSTR) :: input_template logical :: found_group @@ -218,21 +221,17 @@ subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) integer :: i, j, k integer :: Xdim, Ydim integer :: Xdim_full, Ydim_full + integer :: nx, ny integer :: IM, JM integer :: IM_WORLD, JM_WORLD integer :: COUNTS(3), DIMS(3) integer :: i_1, i_n, j_1, j_n ! regional array bounds - ! character(len=:), allocatable :: lon_center_name, lat_center_name, time_name - character(len=ESMF_MAXSTR) :: lon_center_name, lat_center_name, time_name type(Logger), pointer :: lgr _UNUSED_DUMMY(unusable) - ! keywords in netCDF - lon_center_name = "clon" - lat_center_name = "clat" - time_name = "scanTime" + Xdim=this%im_world Ydim=this%jm_world Xdim_full=this%cell_across_swath @@ -245,7 +244,10 @@ subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) ! read longitudes if (MAPL_AmNodeRoot .or. (.not. MAPL_ShmInitialized)) then allocate( centers_full(Xdim_full, Ydim_full)) - call get_v2d_netcdf(this%grid_file_name, lon_center_name, centers_full, Xdim_full, Ydim_full) + call read_M_files_4_swath (this%filenames(1:this%M_file), nx, ny, & + this%index_name_lon, this%index_name_lat, & + var_name_lon=this%var_name_lon, lon=centers_full, _RC) + k=0 do j=this%epoch_index(3), this%epoch_index(4) k=k+1 @@ -262,7 +264,9 @@ subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) ! read latitudes if (MAPL_AmNodeRoot .or. (.not. MAPL_ShmInitialized)) then allocate( centers_full(Xdim_full, Ydim_full)) - call get_v2d_netcdf(this%grid_file_name, lat_center_name, centers_full, Xdim_full, Ydim_full) + call read_M_files_4_swath (this%filenames(1:this%M_file), nx, ny, & + this%index_name_lon, this%index_name_lat, & + var_name_lat=this%var_name_lat, lat=centers_full, _RC) k=0 do j=this%epoch_index(3), this%epoch_index(4) k=k+1 @@ -393,7 +397,6 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc use esmf use pflogger, only : Logger, logging implicit none - integer, parameter :: mx_file = 300 class (SwathGridFactory), intent(inout) :: this type (ESMF_Config), intent(inout) :: config character(len=*), intent(in) :: prefix @@ -404,11 +407,12 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc type(ESMF_VM) :: VM integer :: nlon, nlat, tdim integer :: Xdim, Ydim, ntime + integer :: nx, ny character(len=ESMF_MAXSTR) :: key_lon, key_lat, key_time character(len=ESMF_MAXSTR) :: tunit, grp1, grp2 character(len=ESMF_MAXSTR) :: filename, STR1, tmp character(len=ESMF_MAXSTR) :: symd, shms - character(len=ESMF_MAXSTR) :: filenames(mx_file) + ! real(ESMF_KIND_R8), allocatable :: scanTime(:,:) real, allocatable :: scanTime(:,:) @@ -434,6 +438,10 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call ESMF_VmGetCurrent(VM, _RC) + ! + ! Read in specs, crop epoch_index based on scanTime + ! + !__ s1. read in file spec. ! call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'GRIDNAME:', default=MAPL_GRID_NAME_DEFAULT) @@ -506,149 +514,67 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call ESMF_ConfigGetAttribute(config, value=this%index_name_lon, default="", & - label=prefix // 'index_name_lon:', _RC) - call ESMF_ConfigGetAttribute(config, this%var_name_time, default="", & - label=prefix//'var_name_time:', _RC) + label=prefix // 'index_name_lon:', _RC) + call ESMF_ConfigGetAttribute(config, value=this%index_name_lat, default="", & + label=prefix // 'index_name_lat:', _RC) call ESMF_ConfigGetAttribute(config, this%var_name_lon, & label=prefix // 'var_name_lon:', default="", _RC) call ESMF_ConfigGetAttribute(config, this%var_name_lat, & label=prefix // 'var_name_lat:', default="", _RC) + call ESMF_ConfigGetAttribute(config, this%var_name_time, default="", & + label=prefix//'var_name_time:', _RC) + call ESMF_ConfigGetAttribute(config, this%tunit, default="", & + label=prefix//'tunit:', _RC) + -! i=index(this%nc_time, '/') -! if (i>0) then -! this%found_group = .true. -! grp1 = this%nc_time(1:i-1) -! j=index(this%nc_time(i+1:), '/') -! if (j>0) then -! grp2=this%nc_time(i+1:i+j-1) -! else -! grp2='' -! endif -! i=i+j -! else -! this%found_group = .false. -! grp1 = '' -! grp2='' -! endif -! this%var_name_time= this%nc_time(i+1:) -! -! i=index(this%nc_longitude, '/') -! this%var_name_lat = this%nc_latitude(i+1:) -! this%var_name_lon = this%nc_longitude(i+1:) -! -! ! read global dim from nc file -! ! ---------------------------- -! key_lon=this%var_name_lon -! key_lat=this%var_name_lat -! key_time=this%var_name_time -! -! write(6,*) 'this%nc index, time, long, lat=', & -! trim(this%nc_index), trim(this%nc_time), trim(this%nc_longitude), trim(this%nc_latitude) -! write(6,'(10(2x,a))') 'name lat, lon, time', & -! trim(this%var_name_lat), trim(this%var_name_lon), trim(this%var_name_time) -! write(6,'(10(2x,a))') 'grp1, grp2', trim(grp1), trim(grp2) -! + write(6,'(10(2x,a20,2x,a40,/))') & + 'index_name_lon:', trim(this%index_name_lon), & + 'index_name_lat:', trim(this%index_name_lat), & + 'var_name_lon:', trim(this%var_name_lon), & + 'var_name_lat:', trim(this%var_name_lat), & + 'var_name_time:', trim(this%var_name_time), & + 'tunit:', trim(this%tunit) !__ s2. find obsFile on disk and get array: this%t_alongtrack(:) ! - + call ESMF_TimeIntervalSet(Toff, h=0, m=0, s=0, _RC) call Find_M_files_for_currTime (currTime, & this%obsfile_start_time, this%obsfile_end_time, this%obsfile_interval, & - this%epoch_frequency, this%input_template, M_file, filenames, & + this%epoch_frequency, this%input_template, M_file, this%filenames, & T_offset_in_file_content = Toff, _RC) - - - write(6,*) 'M_file=', M_file - do i=1, M_file - write(6,*) 'filenames(i)=', trim(filenames(i)) - end do - - call read_M_files_4_swath (filenames(1:M_file), Xdim, Ydim, & - this%index_name_lon, this%index_name_lat, _RC) - allocate( time_R8(Xdim, Ydim) ) - allocate( lon_center(Xdim, Ydim) ) - - call read_M_files_4_swath (filenames(1:M_file), Xdim, Ydim, & - this%index_name_lon, this%index_name_lat, & - var_name_time=this%var_name_time, time_R8=time_R8, & - var_name_lon=this%var_name_lon, lon=lon_center, rc=rc) - - deallocate( time_R8, lon_center ) - + this%M_file = M_file - stop -1 - -! call get_obsfile_Tbracket_from_epoch(currTime, & -! this%obsfile_start_time, this%obsfile_end_time, & -! this%obsfile_interval, this%epoch_frequency, & -! this%obsfile_Ts_index, this%obsfile_Te_index, _RC) -! -! L=0 -! fid_s=this%obsfile_Ts_index -! fid_e=this%obsfile_Te_index - - -!! marker bug - this%grid_file_name = trim(filename) - -!! marker bug -! filename='/discover/nobackup/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.h5' -! filename='/Users/yyu11/ModelData/earthData/flk_modis_MOD04_2017_090/MOD04_L2.A2017090.0010.051.NRT.h5' -! I am taking short cuts - filename='./MOD04_L2.A2017090.0010.051.NRT.h5' - + write(6,*) 'M_file=', M_file + do i=1, M_file + write(6,*) 'filenames(i)=', trim(this%filenames(i)) + end do + + call read_M_files_4_swath (this%filenames(1:M_file), nx, ny, & + this%index_name_lon, this%index_name_lat, _RC) + nlon=nx + nlat=ny + allocate(scanTime(nlon, nlat)) + allocate(this%t_alongtrack(nlat)) - CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, & - key_lon=key_lon, key_lat=key_lat, _RC) - print*, 'filename input', trim(filename) - print*, 'nlon, nlat=', nlon, nlat + call read_M_files_4_swath (this%filenames(1:M_file), nx, ny, & + this%index_name_lon, this%index_name_lat, & + var_name_time=this%var_name_time, time=scanTime, _RC) + ! lgr => logging%get_logger('HISTORY.sampler') + ! print*, 'key_time=', trim(key_time) - allocate(scanTime(nlon, nlat)) - allocate(this%t_alongtrack(nlat)) - - lgr => logging%get_logger('HISTORY.sampler') - call lgr%debug('%a %a', & - 'swath Epoch init time:', trim(tmp) ) - call lgr%debug('%a %a', & - 'swath obs filename: ', trim(filename) ) - call lgr%debug('%a %i8 %i8', & - 'swath obs nlon,nlat:', nlon,nlat) - print*, 'key_time=', trim(key_time) - - - call check_nc_status(nf90_open(fileName, NF90_NOWRITE, ncid2), _RC) - if ( this%found_group ) then - call check_nc_status(nf90_inq_ncid(ncid2, grp1, ncid), _RC) - print*, 'ck grp1' - if (j>0) then - call check_nc_status(nf90_inq_ncid(ncid, grp2, ncid2), _RC) - ncid=ncid2 - print*, 'ck grp2' - endif - else - ncid=ncid2 - endif - ! call check_nc_status(nf90_inq_varid(ncid, key_time, varid), _RC) - call check_nc_status(nf90_inq_varid(ncid, key_time, varid), _RC) - call check_nc_status(nf90_get_var(ncid, varid, scanTime), _RC) do j=1, nlat - this%t_alongtrack(j)= scanTime(1,j) - enddo - - write(6,*) 'this%t_alongtrack(j)=', this%t_alongtrack(::3) - - - ! - ! skip un-defined time value - ! - ! + this%t_alongtrack(j)= scanTime(1,j) + enddo nstart = 1 + ! + ! redefine nstart to skip un-defined time value + ! If the t_alongtrack contains undefined values, use this code + ! x0 = this%t_alongtrack(1) x1 = 1.d16 - if (x0 > x1) then ! ! bisect backward finding the first index arr[n] < x1 @@ -667,81 +593,76 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call lgr%debug('%a %i4', 'nstart', nstart) call lgr%debug('%a %i4', 'this%t_alongtrack(nstart)', this%t_alongtrack(nstart)) endif - - deallocate(scanTime) - + this%cell_across_swath = nlon this%cell_along_swath = nlat + deallocate(scanTime) - + write(6,*) 'this%t_alongtrack(j)=', this%t_alongtrack(::100) ! P2. -! -! ! determine im_world from Epoch -! ! ----------------------------- -! ! t_axis = t_alongtrack = t_a -! ! convert currTime to j0 -! ! use Epoch to find j1 -! ! search j0, j1 in t_a -! -! -! ! this is a bug -! ! -! tunit='seconds since 1993-01-01 00:00:00' -! this%tunit = tunit -! call time_esmf_2_nc_int (currTime, tunit, j0, _RC) -! sec = hms_2_s (this%Epoch) -! j1= j0 + sec -! jx0= j0 -! jx1= j1 -! !!call lgr%debug ('%a %f8 %f8', 'jx0, jx1', jx0, jx1) -! call lgr%debug ('%a %i16 %i16', 'j0, j1 ', j0, j1) -! -! -! this%epoch_index(1)= 1 -! this%epoch_index(2)= this%cell_across_swath -! call bisect( this%t_alongtrack, jx0, jt1, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) -! call bisect( this%t_alongtrack, jx1, jt2, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) -! -! -! if (jt1==jt2) then -! _FAIL('Epoch Time is too small, empty swath grid is generated, increase Epoch') -! endif -! jt1 = jt1 + 1 ! (x1,x2] design -! this%epoch_index(3)= jt1 -! this%epoch_index(4)= jt2 -! Xdim = this%cell_across_swath -! Ydim = this%epoch_index(4) - this%epoch_index(3) + 1 -! -! -! call lgr%debug ('%a %i4 %i4', 'bisect for j0: rc, jt', rc, jt1) -! call lgr%debug ('%a %i4 %i4', 'bisect for j1: rc, jt', rc, jt2) -! call lgr%debug ('%a %i4 %i4', 'Xdim, Ydim', Xdim, Ydim) -! call lgr%debug ('%a %i4 %i4 %i4 %i4', 'this%epoch_index(4)', & -! this%epoch_index(1), this%epoch_index(2), & -! this%epoch_index(3), this%epoch_index(4)) -! -! -! this%im_world = Xdim -! this%jm_world = Ydim -! -! -! call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'IMS_FILE:', rc=status) -! if ( status == _SUCCESS ) then -! call get_ims_from_file(this%ims, trim(tmp),this%nx, _RC) -! else -! call get_multi_integer(this%ims, 'IMS:', _RC) -! endif -! call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'JMS_FILE:', rc=status) -! if ( status == _SUCCESS ) then -! call get_ims_from_file(this%jms, trim(tmp),this%ny, _RC) -! else -! call get_multi_integer(this%jms, 'JMS:', _RC) -! endif -! ! ims is set at here -! call this%check_and_fill_consistency(_RC) -! + + ! determine im_world from Epoch + ! ----------------------------- + ! t_axis = t_alongtrack = t_a + ! convert currTime to j0 + ! use Epoch to find j1 + ! search j0, j1 in t_a + + + call time_esmf_2_nc_int (currTime, this%tunit, j0, _RC) + sec = hms_2_s (this%Epoch) + j1= j0 + sec + jx0= j0 + jx1= j1 + !!call lgr%debug ('%a %f8 %f8', 'jx0, jx1', jx0, jx1) + call lgr%debug ('%a %i16 %i16', 'j0, j1 ', j0, j1) + + + this%epoch_index(1)= 1 + this%epoch_index(2)= this%cell_across_swath + call bisect( this%t_alongtrack, jx0, jt1, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) + call bisect( this%t_alongtrack, jx1, jt2, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) + + + if (jt1==jt2) then + _FAIL('Epoch Time is too small, empty swath grid is generated, increase Epoch') + endif + jt1 = jt1 + 1 ! (x1,x2] design + this%epoch_index(3)= jt1 + this%epoch_index(4)= jt2 + Xdim = this%cell_across_swath + Ydim = this%epoch_index(4) - this%epoch_index(3) + 1 + + + call lgr%debug ('%a %i4 %i4', 'bisect for j0: rc, jt', rc, jt1) + call lgr%debug ('%a %i4 %i4', 'bisect for j1: rc, jt', rc, jt2) + call lgr%debug ('%a %i4 %i4', 'Xdim, Ydim', Xdim, Ydim) + call lgr%debug ('%a %i4 %i4 %i4 %i4', 'this%epoch_index(4)', & + this%epoch_index(1), this%epoch_index(2), & + this%epoch_index(3), this%epoch_index(4)) + + + this%im_world = Xdim + this%jm_world = Ydim + + + call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'IMS_FILE:', rc=status) + if ( status == _SUCCESS ) then + call get_ims_from_file(this%ims, trim(tmp),this%nx, _RC) + else + call get_multi_integer(this%ims, 'IMS:', _RC) + endif + call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'JMS_FILE:', rc=status) + if ( status == _SUCCESS ) then + call get_ims_from_file(this%jms, trim(tmp),this%ny, _RC) + else + call get_multi_integer(this%jms, 'JMS:', _RC) + endif + ! ims is set at here + call this%check_and_fill_consistency(_RC) + _RETURN(_SUCCESS) @@ -1378,7 +1299,11 @@ subroutine get_xy_subset(this, interval, xy_subset, rc) call time_esmf_2_nc_int (T2, this%tunit, i2, _RC) iT1 = i1 ! int to real*8 iT2 = i2 - jlo = this%epoch_index(3) - 2 + if (this%epoch_index(3) > 2) then + jlo = this%epoch_index(3) - 2 + else + jlo = this%epoch_index(3) + end if jhi = this%epoch_index(4) + 1 call bisect( this%t_alongtrack, iT1, index1, n_LB=int(jlo, ESMF_KIND_I8), n_UB=int(jhi, ESMF_KIND_I8), rc=rc) call bisect( this%t_alongtrack, iT2, index2, n_LB=int(jlo, ESMF_KIND_I8), n_UB=int(jhi, ESMF_KIND_I8), rc=rc) @@ -1440,13 +1365,10 @@ subroutine get_obs_time(this, grid, obs_time, rc) integer :: i, j, k integer :: Xdim, Ydim integer :: Xdim_full, Ydim_full - + integer :: nx, ny integer :: IM_WORLD, JM_WORLD - character(len=:), allocatable :: time_name - - ! keywords in netCDF - time_name = "scanTime" + call MAPL_grid_interior(grid, i_1, i_n, j_1, j_n) !- shared mem case in MPI @@ -1456,33 +1378,36 @@ subroutine get_obs_time(this, grid, obs_time, rc) Xdim_full=this%cell_across_swath Ydim_full=this%cell_along_swath - + call MAPL_AllocateShared(centers,[Xdim,Ydim],transroot=.true.,_RC) call MAPL_SyncSharedMemory(_RC) - - ! read Time and set - if (MAPL_AmNodeRoot .or. (.not. MAPL_ShmInitialized)) then - allocate( centers_full(Xdim_full, Ydim_full)) - call get_v2d_netcdf(this%grid_file_name, time_name, centers_full, Xdim_full, Ydim_full) - k=0 - do j=this%epoch_index(3), this%epoch_index(4) - k=k+1 - centers(1:Xdim, k) = centers_full(1:Xdim, j) - enddo - deallocate (centers_full) - end if - call MAPL_SyncSharedMemory(_RC) - !(Xdim, Ydim) - obs_time = centers(i_1:i_n,j_1:j_n) + ! read Time and set + if (MAPL_AmNodeRoot .or. (.not. MAPL_ShmInitialized)) then + allocate( centers_full(Xdim_full, Ydim_full)) + call read_M_files_4_swath (this%filenames(1:this%M_file), nx, ny, & + this%index_name_lon, this%index_name_lat, & + var_name_time=this%var_name_time, lon=centers_full, _RC) + !!call get_v2d_netcdf(this%grid_file_name, time_name, centers_full, Xdim_full, Ydim_full) + k=0 + do j=this%epoch_index(3), this%epoch_index(4) + k=k+1 + centers(1:Xdim, k) = centers_full(1:Xdim, j) + enddo + deallocate (centers_full) + end if + call MAPL_SyncSharedMemory(_RC) + + !(Xdim, Ydim) + obs_time = centers(i_1:i_n,j_1:j_n) + + if(MAPL_ShmInitialized) then + call MAPL_DeAllocNodeArray(centers,_RC) + else + deallocate(centers) + end if - if(MAPL_ShmInitialized) then - call MAPL_DeAllocNodeArray(centers,_RC) - else - deallocate(centers) - end if - _RETURN(_SUCCESS) end subroutine get_obs_time diff --git a/base/Plain_netCDF_Time.F90 b/base/Plain_netCDF_Time.F90 index 4a3e7a96ab70..ec5bb51aa4ac 100644 --- a/base/Plain_netCDF_Time.F90 +++ b/base/Plain_netCDF_Time.F90 @@ -79,12 +79,12 @@ subroutine get_ncfile_dimension(filename, nlon, nlat, tdim, key_lon, key_lat, ke call check_nc_status(nf90_open(trim(fileName), NF90_NOWRITE, ncid), _RC) if(present(key_lon)) then lon_name=trim(key_lon) - print*, 'fileName=', trim(fileName) - print*, 'ncid=', ncid - print*, 'lon_name=', trim(key_lon) - print*, 'ck step 1' +! print*, 'fileName=', trim(fileName) +! print*, 'ncid=', ncid +! print*, 'lon_name=', trim(key_lon) +! print*, 'ck step 1' call check_nc_status(nf90_inq_dimid(ncid, trim(lon_name), dimid), _RC) - print*, 'ck step 2' +! print*, 'ck step 2' call check_nc_status(nf90_inquire_dimension(ncid, dimid, len=nlon), _RC) endif From bcb194ffbd40cf9e4a7d5b0f9bb593fce583ca83 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Thu, 16 Nov 2023 21:44:03 -0700 Subject: [PATCH 26/41] update --- base/MAPL_SwathGridFactory.F90 | 4 ++-- gridcomps/History/MAPL_HistoryGridComp.F90 | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 66b38016db07..4dc4bbece84a 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -1183,8 +1183,8 @@ function get_grid_vars(this) result(vars) character(len=ESMF_MAXSTR) :: key_lat _UNUSED_DUMMY(this) - key_lon=trim(this%var_name_lon) - key_lat=trim(this%var_name_lat) + !!key_lon=trim(this%var_name_lon) + !!key_lat=trim(this%var_name_lat) vars = 'lon,lat' end function get_grid_vars diff --git a/gridcomps/History/MAPL_HistoryGridComp.F90 b/gridcomps/History/MAPL_HistoryGridComp.F90 index 61e42895ce6a..f1bb5b410de4 100644 --- a/gridcomps/History/MAPL_HistoryGridComp.F90 +++ b/gridcomps/History/MAPL_HistoryGridComp.F90 @@ -3601,7 +3601,8 @@ subroutine Run ( gc, import, export, clock, rc ) state_out = INTSTATE%GIM(n) end if - call lgr%debug('%a %i','list(n)%unit=', list(n)%unit) +!! -- bug, what is this? +!! call lgr%debug('%a %i','list(n)%unit=', list(n)%unit) list(n)%currentFile = filename(n) From ed430947e3e03bb3d50d1895919381db868e6103 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Fri, 17 Nov 2023 09:24:17 -0700 Subject: [PATCH 27/41] . --- base/MAPL_SwathGridFactory.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 4dc4bbece84a..2cc029d93370 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -456,6 +456,8 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call ESMF_ConfigGetAttribute(config, value=STR1, default="", & label= prefix// 'obs_file_begin:', _RC) + + write(6,'(//2x, a)') 'SWATH initialize_from_config_with_prefix' print*, 'obs_file_begin: str1=', trim(STR1) if (trim(STR1)=='') then From 4d09107246a996f86534aeef7deae9930050cfc9 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Fri, 17 Nov 2023 11:12:51 -0700 Subject: [PATCH 28/41] . --- base/MAPL_EsmfRegridder.F90 | 101 ++++++++++++----------- gridcomps/History/MAPL_EpochSwathMod.F90 | 2 +- 2 files changed, 52 insertions(+), 51 deletions(-) diff --git a/base/MAPL_EsmfRegridder.F90 b/base/MAPL_EsmfRegridder.F90 index cea42e1fbf2c..581545b41c57 100644 --- a/base/MAPL_EsmfRegridder.F90 +++ b/base/MAPL_EsmfRegridder.F90 @@ -23,27 +23,27 @@ module MAPL_EsmfRegridderMod ! ESMF Route handles type (RegridderSpecRouteHandleMap), save, target :: route_handles_r4 type (RegridderSpecRouteHandleMap), save, target :: route_handles_r8 - + type (RegridderSpecRouteHandleMap), save, target :: transpose_route_handles_r4 type (RegridderSpecRouteHandleMap), save, target :: transpose_route_handles_r8 - + type, extends(AbstractRegridder) :: EsmfRegridder integer :: regrid_method type (ESMF_DynamicMask) :: dynamic_mask contains procedure :: initialize_subclass procedure, nopass :: supports - + procedure :: regrid_scalar_2d_real32 procedure :: regrid_scalar_2d_real64 procedure :: regrid_scalar_3d_real32 procedure :: regrid_scalar_3d_real64 - + procedure :: regrid_vector_2d_real32 procedure :: regrid_vector_2d_real64 procedure :: regrid_vector_3d_real32 procedure :: regrid_vector_3d_real64 - + procedure :: transpose_regrid_scalar_2d_real32 procedure :: transpose_regrid_scalar_3d_real32 procedure :: transpose_regrid_vector_2d_real32 @@ -55,7 +55,7 @@ module MAPL_EsmfRegridderMod procedure :: select_route_handle procedure :: destroy procedure :: destroy_route_handle - + end type EsmfRegridder interface EsmfRegridder @@ -98,7 +98,7 @@ logical function supports(spec, unusable, rc) _RETURN(_SUCCESS) end function supports - + subroutine regrid_scalar_2d_real32(this, q_in, q_out, rc) class (EsmfRegridder), intent(in) :: this @@ -116,7 +116,7 @@ subroutine regrid_scalar_2d_real32(this, q_in, q_out, rc) logical :: HasDE spec = this%get_spec() - + ! TODO support other staggerings src_field = ESMF_FieldCreate(spec%grid_in, typekind=ESMF_TYPEKIND_R4, & gridToFieldMap=[1,2],& @@ -150,7 +150,7 @@ subroutine regrid_scalar_2d_real32(this, q_in, q_out, rc) _VERIFY(status) call ESMF_FieldDestroy(dst_field, noGarbage=.true., rc=status) _VERIFY(status) - + _RETURN(ESMF_SUCCESS) end subroutine regrid_scalar_2d_real32 @@ -171,7 +171,7 @@ subroutine regrid_scalar_2d_real64(this, q_in, q_out, rc) logical :: HasDE spec = this%get_spec() - + ! TODO support other staggerings src_field = ESMF_FieldCreate(spec%grid_in, typekind=ESMF_TYPEKIND_R8, & gridToFieldMap=[1,2],& @@ -205,11 +205,11 @@ subroutine regrid_scalar_2d_real64(this, q_in, q_out, rc) _VERIFY(status) call ESMF_FieldDestroy(dst_field, noGarbage=.true., rc=status) _VERIFY(status) - + _RETURN(ESMF_SUCCESS) end subroutine regrid_scalar_2d_real64 - + subroutine transpose_regrid_scalar_2d_real32(this, q_in, q_out, rc) class (EsmfRegridder), intent(in) :: this real(kind=REAL32), intent(in) :: q_in(:,:) @@ -236,7 +236,7 @@ subroutine transpose_regrid_scalar_2d_real32(this, q_in, q_out, rc) _VERIFY(status) p_src = q_in end if - + dst_field = ESMF_FieldCreate(spec%grid_in, typekind=ESMF_TYPEKIND_R4, & gridToFieldMap=[1,2],& rc=status) @@ -294,7 +294,7 @@ subroutine regrid_scalar_3d_real32(this, q_in, q_out, rc) end if call ESMF_VMAllReduce(vm,sendData=km,recvData=kin,reduceflag=ESMF_REDUCE_MAX,rc=status) _VERIFY(status) - + if (hasDE) then _ASSERT(kin == size(q_in,3),'inconsistent array shape') end if @@ -308,7 +308,7 @@ subroutine regrid_scalar_3d_real32(this, q_in, q_out, rc) p_src = reshape(q_in,shape(p_src), order=[2,3,1]) end if - + HasDE = MAPL_GridHasDE(spec%grid_out,rc=status) _VERIFY(status) if (hasDE) then @@ -377,7 +377,7 @@ subroutine regrid_scalar_3d_real64(this, q_in, q_out, rc) end if call ESMF_VMAllReduce(vm,sendData=km,recvData=kin,reduceflag=ESMF_REDUCE_MAX,rc=status) _VERIFY(status) - + if (hasDE) then _ASSERT(kin == size(q_in,3),'inconsistent array shape') end if @@ -391,7 +391,7 @@ subroutine regrid_scalar_3d_real64(this, q_in, q_out, rc) p_src = reshape(q_in,shape(p_src), order=[2,3,1]) end if - + HasDE = MAPL_GridHasDE(spec%grid_out,rc=status) _VERIFY(status) if (hasDE) then @@ -427,7 +427,7 @@ subroutine regrid_scalar_3d_real64(this, q_in, q_out, rc) _RETURN(ESMF_SUCCESS) end subroutine regrid_scalar_3d_real64 - + subroutine transpose_regrid_scalar_3d_real32(this, q_in, q_out, rc) class (EsmfRegridder), intent(in) :: this real, intent(in) :: q_in(:,:,:) @@ -473,9 +473,9 @@ subroutine transpose_regrid_scalar_3d_real32(this, q_in, q_out, rc) _VERIFY(status) p_src = reshape(q_in,shape(p_src), order=[2,3,1]) end if - + HasDE = MAPL_GridHasDE(spec%grid_in,rc=status) - _VERIFY(status) + _VERIFY(status) if (hasDE) then km = size(q_out,3) else @@ -497,7 +497,7 @@ subroutine transpose_regrid_scalar_3d_real32(this, q_in, q_out, rc) call this%do_regrid(src_field, dst_field, doTranspose=.true., rc=status) _VERIFY(status) - + if (HasDE) q_out = reshape(p_dst, shape(q_out), order=[3,1,2]) call ESMF_FieldDestroy(src_field, noGarbage=.true., rc=status) @@ -556,7 +556,7 @@ subroutine regrid_vector_2d_real32(this, u_in, v_in, u_out, v_out, rotate, rc) factory => grid_manager%get_factory(spec%grid_in,rc=status) _VERIFY(status) - + ! TODO support other staggerings src_field = ESMF_FieldCreate(spec%grid_in, typekind=ESMF_TYPEKIND_R4, & & gridToFieldMap=[3,4], UngriddedLBound=[1,1], ungriddedUBound=[3,1], & @@ -570,7 +570,7 @@ subroutine regrid_vector_2d_real32(this, u_in, v_in, u_out, v_out, rotate, rc) call factory%spherical_to_cartesian(u_in, v_in, p_src, grid_axis_in, rc=status) _VERIFY(status) end if - + dst_field = ESMF_FieldCreate(spec%grid_out, typekind=ESMF_TYPEKIND_R4, & & gridToFieldMap=[3,4], UngriddedLBound=[1,1], ungriddedUBound=[3,1], & @@ -697,7 +697,7 @@ subroutine regrid_vector_2d_real64(this, u_in, v_in, u_out, v_out, rotate, rc) end subroutine regrid_vector_2d_real64 - + subroutine transpose_regrid_vector_2d_real32(this, u_in, v_in, u_out, v_out, rotate, rc) class (EsmfRegridder), intent(in) :: this real, intent(in) :: u_in(:,:) @@ -755,10 +755,10 @@ subroutine transpose_regrid_vector_2d_real32(this, u_in, v_in, u_out, v_out, rot call factory%spherical_to_cartesian(u_in, v_in, p_src, grid_axis_in, rc=status) _VERIFY(status) end if - + hasDE = MAPL_GridHasDE(spec%grid_in,rc=status) - _VERIFY(status) + _VERIFY(status) dst_field = ESMF_FieldCreate(spec%grid_in, typekind = ESMF_TYPEKIND_R4, & & gridToFieldMap=[3,4],ungriddedLBound=[1,1],ungriddedUBound=[3,1],rc=status) _VERIFY(status) @@ -839,7 +839,7 @@ subroutine regrid_vector_3d_real32(this, u_in, v_in, u_out, v_out, rotate, rc) if (present(rotate)) then if (rotate) then grid_axis_in = 'xyz' - grid_axis_out = 'grid' + grid_axis_out = 'grid' end if end if @@ -863,9 +863,9 @@ subroutine regrid_vector_3d_real32(this, u_in, v_in, u_out, v_out, rotate, rc) call factory%spherical_to_cartesian(u_in, v_in, p_src, grid_axis_in, rc=status) _VERIFY(status) end if - + hasDE = MAPL_GridHasDE(spec%grid_out,rc=status) - _VERIFY(status) + _VERIFY(status) hasDE = MAPL_GridHasDE(spec%grid_out,rc=status) _VERIFY(status) if (hasDE) then @@ -974,7 +974,7 @@ subroutine regrid_vector_3d_real64(this, u_in, v_in, u_out, v_out, rc) end if hasDE = MAPL_GridHasDE(spec%grid_out,rc=status) - _VERIFY(status) + _VERIFY(status) hasDE = MAPL_GridHasDE(spec%grid_out,rc=status) _VERIFY(status) if (hasDE) then @@ -1011,8 +1011,8 @@ subroutine regrid_vector_3d_real64(this, u_in, v_in, u_out, v_out, rc) _RETURN(ESMF_SUCCESS) end subroutine regrid_vector_3d_real64 - - + + subroutine transpose_regrid_vector_3d_real32(this, u_in, v_in, u_out, v_out, rotate, rc) class (EsmfRegridder), intent(in) :: this real, intent(in) :: u_in(:,:,:) @@ -1067,7 +1067,7 @@ subroutine transpose_regrid_vector_3d_real32(this, u_in, v_in, u_out, v_out, rot if (present(rotate)) then if (rotate) then grid_axis_in = 'grid' - grid_axis_out = 'xyz' + grid_axis_out = 'xyz' end if end if @@ -1091,9 +1091,9 @@ subroutine transpose_regrid_vector_3d_real32(this, u_in, v_in, u_out, v_out, rot call factory%spherical_to_cartesian(u_in, v_in, p_src, grid_axis_in, rc=status) _VERIFY(status) end if - + hasDE = MAPL_GridHasDE(spec%grid_in,rc=status) - _VERIFY(status) + _VERIFY(status) if (hasDE) then km = size(u_out,3) else @@ -1127,7 +1127,7 @@ subroutine transpose_regrid_vector_3d_real32(this, u_in, v_in, u_out, v_out, rot deallocate(p_src) deallocate(p_dst) - + _RETURN(ESMF_SUCCESS) end subroutine transpose_regrid_vector_3d_real32 @@ -1156,7 +1156,7 @@ subroutine simpleDynMaskProcV(dynamicMaskList, dynamicSrcMaskValue, & do k = 1, size(dynamicMaskList(i)%srcElement(j)%ptr) if (.not. & match(dynamicSrcMaskValue,dynamicMaskList(i)%srcElement(j)%ptr(k))) then - dynamicMaskList(i)%dstElement(k) = dynamicMaskList(i)%dstElement(k) & + dynamicMaskList(i)%dstElement(k) = dynamicMaskList(i)%dstElement(k) & + dynamicMaskList(i)%factor(j) & * dynamicMaskList(i)%srcElement(j)%ptr(k) renorm(k) = renorm(k) + dynamicMaskList(i)%factor(j) @@ -1228,7 +1228,7 @@ end subroutine monotonicDynMaskProcV logical function match(missing,b) real(kind=REAL32), intent(in) :: missing, b - match = (missing==b) + match = (missing==b) end function match @@ -1335,10 +1335,10 @@ subroutine do_regrid(this, src_field, dst_field, unusable, doTranspose, rc) _ASSERT(src_kind == dst_kind,'inconsistent kinds') route_handle = this%select_route_handle(src_kind, do_transpose = doTranspose, rc = status) - _VERIFY(status) + _VERIFY(status) spec = this%get_spec() - + if (spec%regrid_method /= REGRID_METHOD_NEAREST_STOD) then call ESMF_FieldRegrid(src_field, dst_field, & & routeHandle=route_handle, & @@ -1366,17 +1366,17 @@ subroutine initialize_subclass(this, unusable, rc) integer, optional, intent(out) :: rc - integer :: status + integer :: status character(len=*), parameter :: Iam = 'initialize_subclass' type (RegridderSpec) :: spec - + _UNUSED_DUMMY(unusable) spec = this%get_spec() this%regrid_method = spec%regrid_method - call this%create_route_handle(ESMF_TYPEKIND_R4, rc = status) + call this%create_route_handle(ESMF_TYPEKIND_R4, rc = status) _VERIFY(status) ! TODO: should get missing value from source file @@ -1413,14 +1413,14 @@ subroutine initialize_subclass(this, unusable, rc) _RETURN(_SUCCESS) end subroutine initialize_subclass - + subroutine create_route_handle(this, kind, rc) class (EsmfRegridder), intent(in) :: this type(ESMF_TypeKind_Flag), intent(in) :: kind integer, optional, intent(out) :: rc - integer :: status + integer :: status character(len=*), parameter :: Iam = 'create_route_handle' type (RegridderSpec) :: spec @@ -1436,7 +1436,7 @@ subroutine create_route_handle(this, kind, rc) logical :: global, isPresent type(RegridderSpecRouteHandleMap), pointer :: route_handles, transpose_route_handles type(ESMF_RouteHandle) :: route_handle, transpose_route_handle - + if (kind == ESMF_TYPEKIND_R4) then route_handles => route_handles_r4 transpose_route_handles => transpose_route_handles_r4 @@ -1470,7 +1470,7 @@ subroutine create_route_handle(this, kind, rc) dst_field = ESMF_FieldCreate(spec%grid_out, typekind=kind, & & indexflag=ESMF_INDEX_DELOCAL, staggerloc=ESMF_STAGGERLOC_CENTER, rc=status) - _VERIFY(status) + _VERIFY(status) if (MAPL_GridHasDE(spec%grid_out)) then if (kind == ESMF_TYPEKIND_R4) then call ESMF_FieldGet(dst_field, localDe=0, farrayPtr=dst_dummy_r4, rc=status) @@ -1554,7 +1554,7 @@ subroutine create_route_handle(this, kind, rc) _RETURN(_SUCCESS) end subroutine create_route_handle - + function select_route_handle(this, kind, do_transpose, rc) result(route_handle) type(ESMF_RouteHandle) :: route_handle class (EsmfRegridder), intent(in) :: this @@ -1582,7 +1582,7 @@ function select_route_handle(this, kind, do_transpose, rc) result(route_handle) ! Create route-handle if none exist if (route_handles%count(spec) == 0) then - call this%create_route_handle(kind, rc = status) + call this%create_route_handle(kind, rc = status) _VERIFY(status) end if @@ -1591,7 +1591,7 @@ function select_route_handle(this, kind, do_transpose, rc) result(route_handle) if (present(do_transpose)) then transpose = do_transpose end if - + if (.not. transpose) then route_handle = route_handles%at(spec) else @@ -1612,6 +1612,7 @@ subroutine destroy(this, rc) _RETURN(_SUCCESS) end subroutine destroy + subroutine destroy_route_handle(this, kind, rc) class(EsmfRegridder), intent(inout) :: this type(ESMF_TypeKind_Flag), intent(in) :: kind diff --git a/gridcomps/History/MAPL_EpochSwathMod.F90 b/gridcomps/History/MAPL_EpochSwathMod.F90 index be2ae4fcc3f1..af62bf944fa4 100644 --- a/gridcomps/History/MAPL_EpochSwathMod.F90 +++ b/gridcomps/History/MAPL_EpochSwathMod.F90 @@ -1156,7 +1156,7 @@ subroutine interp_accumulate_fields (this,xy_subset,rc) pt2d_(:,jj) = pt2d(:,jj) enddo endif -!! write(6,*) 'out_pt2d', pt2d_(10,10:50:2) + write(6,*) 'out_pt2d', pt2d_(10,10:50:2) elseif (rank==3) then call ESMF_ArrayGet(array1, farrayptr=pt3d, _RC) From 295d40b227cf74bf1d1d07e548a53c1801c42581 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Fri, 17 Nov 2023 12:39:20 -0700 Subject: [PATCH 29/41] . --- base/MAPL_ObsUtil.F90 | 13 +++++++++++-- base/MAPL_SwathGridFactory.F90 | 8 ++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/base/MAPL_ObsUtil.F90 b/base/MAPL_ObsUtil.F90 index 3a833570e890..6f412442b078 100644 --- a/base/MAPL_ObsUtil.F90 +++ b/base/MAPL_ObsUtil.F90 @@ -370,6 +370,11 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter nymd = itime(1) nhms = itime(2) + + !-- + call ESMF_VMgetcurrent(emsf_vm) + esmf_vmget( esmf_vm, mpi_communicator) + if (rank==0) then j= index(file_template, '*') if (j>0) then ! wild char exist @@ -386,14 +391,18 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter if (i==1) then filename='' end if - cmd="rm -f ./zzz_MAPL" - CALL execute_command_line(trim(cmd)) +! cmd="rm -f ./zzz_MAPL" +! CALL execute_command_line(trim(cmd)) close(7213) else ! exact file name call fill_grads_template ( filename, file_template, & experiment_id='', nymd=nymd, nhms=nhms, _RC ) end if + endrank + call MPI_bcast (filename, mpi_communicator)) + +!-- _RETURN(_SUCCESS) end function get_filename_from_template_use_index diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 2cc029d93370..3175fdd19e2a 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -241,6 +241,14 @@ subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) call MAPL_AllocateShared(centers,[Xdim,Ydim],transroot=.true.,_RC) call MAPL_SyncSharedMemory(_RC) + if (rank==0) + call read_M_files_4_swath (this%filenames(1:this%M_file), nx, ny, & + this%index_name_lon, this%index_name_lat, & + var_name_lon=this%var_name_lon, lon=centers_full, _RC) + endroot + rank=0 to NODEROOT + + ! read longitudes if (MAPL_AmNodeRoot .or. (.not. MAPL_ShmInitialized)) then allocate( centers_full(Xdim_full, Ydim_full)) From 448b33c634428e79c3599c68d45d546a5e61cd3d Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Mon, 20 Nov 2023 10:04:56 -0700 Subject: [PATCH 30/41] Add MPI_Bcast due to using bash ( ls file_*.) --- base/MAPL_ObsUtil.F90 | 97 +++++---- base/MAPL_SwathGridFactory.F90 | 374 ++++++++++++++++++--------------- base/StringTemplate.F90 | 1 - 3 files changed, 258 insertions(+), 214 deletions(-) diff --git a/base/MAPL_ObsUtil.F90 b/base/MAPL_ObsUtil.F90 index 6f412442b078..fda9835fe7d0 100644 --- a/base/MAPL_ObsUtil.F90 +++ b/base/MAPL_ObsUtil.F90 @@ -5,6 +5,7 @@ module MAPL_ObsUtilMod use ESMF use Plain_netCDF_Time use netCDF + use MAPL_CommsMod, only : MAPL_AM_I_ROOT use, intrinsic :: iso_fortran_env, only: REAL32, REAL64 implicit none @@ -178,7 +179,6 @@ subroutine Find_M_files_for_currTime (currTime, & !__ s1. Arithmetic index list based on s,e,interval ! - print*, __LINE__, __FILE__ if (present(T_offset_in_file_content)) then Toff = T_offset_in_file_content else @@ -202,8 +202,8 @@ subroutine Find_M_files_for_currTime (currTime, & n1 = floor (dT1_s / dT0_s) n2 = floor (dT2_s / dT0_s) - print*, 'ck dT0_s, dT1_s, dT2_s', dT0_s, dT1_s, dT2_s - print*, '1st n1, n2', n1, n2 +! print*, 'ck dT0_s, dT1_s, dT2_s', dT0_s, dT1_s, dT2_s +! print*, '1st n1, n2', n1, n2 obsfile_Ts_index = n1 if ( dT2_s - n2*dT0_s < 1 ) then @@ -216,8 +216,8 @@ subroutine Find_M_files_for_currTime (currTime, & n1 = obsfile_Ts_index n2 = obsfile_Te_index - print*, __LINE__, __FILE__ - print*, '2nd n1, n2', n1, n2 +! print*, __LINE__, __FILE__ +! print*, '2nd n1, n2', n1, n2 !__ s2. further test file existence ! @@ -281,12 +281,14 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & jx=0 do i = 1, M filename = filenames(i) - print*, 'ck filename input', trim(filename) CALL get_ncfile_dimension(filename, nlon=nlon, nlat=nlat, & key_lon=index_name_lon, key_lat=index_name_lat, _RC) nlons(i)=nlon nlats(i)=nlat - print*, 'nlon, nlat=', nlon, nlat + if (mapl_am_i_root()) then + print*, 'ck filename input', trim(filename) + print*, 'nlon, nlat=', nlon, nlat + end if jx=jx+nlat end do Xdim=nlon @@ -328,17 +330,16 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & ! allocate(scanTime(nlon, nlat)) ! allocate(this%t_alongtrack(nlat)) - rc=0 - !! _RETURN(_SUCCESS) + !!rc=0 + _RETURN(_SUCCESS) end subroutine read_M_files_4_swath - function get_filename_from_template_use_index (obsfile_start_time, obsfile_interval, & f_index, file_template, rc) result(filename) use Plain_netCDF_Time, only : ESMF_time_to_two_integer - use MAPL_StringTemplate, only : fill_grads_template + use MAPL_StringTemplate, only : fill_grads_template character(len=ESMF_MAXSTR) :: filename type(ESMF_Time), intent(in) :: obsfile_start_time type(ESMF_TimeInterval), intent(in) :: obsfile_interval @@ -359,8 +360,13 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter character(len=ESMF_MAXSTR) :: file_template_right character(len=ESMF_MAXSTR) :: filename_left character(len=ESMF_MAXSTR) :: filename_full + character(len=ESMF_MAXSTR) :: filename2 character(len=ESMF_MAXSTR) :: cmd +! type(ESMF_VM) :: vm +! integer:: mpic +! integer:: irank, ierror + call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) s = dT0_s * f_index call ESMF_TimeIntervalSet(dT, s_r8=s, rc=status) @@ -370,39 +376,43 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter nymd = itime(1) nhms = itime(2) +! call ESMF_VMGetCurrent(vm, _RC) +! call ESMF_VMGet(vm, mpiCommunicator=mpic, _RC) +! call MPI_COMM_RANK(mpic, irank, ierror) - !-- - call ESMF_VMgetcurrent(emsf_vm) - esmf_vmget( esmf_vm, mpi_communicator) - if (rank==0) then - j= index(file_template, '*') - if (j>0) then - ! wild char exist - !!print*, 'pos of * in template =', j - file_template_left = file_template(1:j-1) - call fill_grads_template ( filename_left, file_template_left, & - experiment_id='', nymd=nymd, nhms=nhms, _RC ) - filename= trim(filename_left)//trim(file_template(j:)) - cmd="bash -c 'ls "//trim(filename)//"' &> zzz_MAPL" - CALL execute_command_line(trim(cmd)) - open(7213, file='zzz_MAPL', status='unknown') - read(7213, '(a)') filename - i=index(trim(filename), 'ls') - if (i==1) then - filename='' +!! if (irank==0) then + j= index(file_template, '*') + if (j>0) then + ! wild char exist + !!print*, 'pos of * in template =', j + file_template_left = file_template(1:j-1) + call fill_grads_template ( filename_left, file_template_left, & + experiment_id='', nymd=nymd, nhms=nhms, _RC ) + filename= trim(filename_left)//trim(file_template(j:)) + cmd="bash -c 'ls "//trim(filename)//"' &> zzz_MAPL" + CALL execute_command_line(trim(cmd)) + open(7213, file='zzz_MAPL', status='unknown') + read(7213, '(a)') filename + i=index(trim(filename), 'ls') + if (i==1) then + filename='' + end if + ! cmd="rm -f ./zzz_MAPL" + ! CALL execute_command_line(trim(cmd)) + close(7213) + else + ! exact file name + call fill_grads_template ( filename, file_template, & + experiment_id='', nymd=nymd, nhms=nhms, _RC ) end if -! cmd="rm -f ./zzz_MAPL" -! CALL execute_command_line(trim(cmd)) - close(7213) - else - ! exact file name - call fill_grads_template ( filename, file_template, & - experiment_id='', nymd=nymd, nhms=nhms, _RC ) - end if - endrank - call MPI_bcast (filename, mpi_communicator)) +!! end if + +! call MPI_bcast(filename2, ESMF_MAXSTR, MPI_CHARACTER, 0, mpic, ierror) +! call MPI_Barrier(mpic,ierror) +! filename=filename2 +! write(6,*) 'my irank=', irank +! write(6,*) 'ck MPI filename=', trim(filename) -!-- _RETURN(_SUCCESS) end function get_filename_from_template_use_index @@ -442,8 +452,9 @@ subroutine get_var_from_name_w_group (var_name, var2d, filename, rc) short_name=var_name endif - write(6,'(10(2x,a))') 'ck grp1, grp2, short_name:', trim(grp1), trim(grp2), trim(short_name) - + if (mapl_am_i_root()) then + write(6,'(10(2x,a))') 'ck grp1, grp2, short_name:', trim(grp1), trim(grp2), trim(short_name) + end if call check_nc_status(nf90_open(filename, NF90_NOWRITE, ncid2), _RC) if ( found_group ) then diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 3175fdd19e2a..58c118a8b026 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -241,25 +241,25 @@ subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) call MAPL_AllocateShared(centers,[Xdim,Ydim],transroot=.true.,_RC) call MAPL_SyncSharedMemory(_RC) - if (rank==0) - call read_M_files_4_swath (this%filenames(1:this%M_file), nx, ny, & - this%index_name_lon, this%index_name_lat, & - var_name_lon=this%var_name_lon, lon=centers_full, _RC) - endroot - rank=0 to NODEROOT - - + if (mapl_am_I_root()) then + write(6,'(2x,a,10i8)') & + 'ck: Xdim, Ydim, Xdim_full, Ydim_full', Xdim, Ydim, Xdim_full, Ydim_full + write(6,'(2x,a,10i8)') & + 'ck: i_1, i_n, j_1, j_n', i_1, i_n, j_1, j_n + end if + ! read longitudes if (MAPL_AmNodeRoot .or. (.not. MAPL_ShmInitialized)) then allocate( centers_full(Xdim_full, Ydim_full)) call read_M_files_4_swath (this%filenames(1:this%M_file), nx, ny, & this%index_name_lon, this%index_name_lat, & var_name_lon=this%var_name_lon, lon=centers_full, _RC) - + write(6,*) 'this%epoch_index(3:4)', this%epoch_index(3:4) k=0 do j=this%epoch_index(3), this%epoch_index(4) k=k+1 centers(1:Xdim, k) = centers_full(1:Xdim, j) +!! write(6,'(100f12.2)') centers(1:Xdim:40, k) enddo centers=centers*MAPL_DEGREES_TO_RADIANS_R8 deallocate (centers_full) @@ -269,6 +269,7 @@ subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) staggerloc=ESMF_STAGGERLOC_CENTER, farrayPtr=fptr, _RC) fptr=real(centers(i_1:i_n,j_1:j_n), kind=ESMF_KIND_R8) + ! read latitudes if (MAPL_AmNodeRoot .or. (.not. MAPL_ShmInitialized)) then allocate( centers_full(Xdim_full, Ydim_full)) @@ -404,6 +405,7 @@ end subroutine initialize_from_file_metadata subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc) use esmf use pflogger, only : Logger, logging + use MPI implicit none class (SwathGridFactory), intent(inout) :: this type (ESMF_Config), intent(inout) :: config @@ -413,6 +415,8 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc integer :: status type(ESMF_VM) :: VM + integer:: mpic + integer:: irank, ierror integer :: nlon, nlat, tdim integer :: Xdim, Ydim, ntime integer :: nx, ny @@ -445,7 +449,8 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call ESMF_VmGetCurrent(VM, _RC) - + ! input : config + ! output: this%epoch_index, nx, ny ! ! Read in specs, crop epoch_index based on scanTime ! @@ -464,37 +469,37 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call ESMF_ConfigGetAttribute(config, value=STR1, default="", & label= prefix// 'obs_file_begin:', _RC) - - write(6,'(//2x, a)') 'SWATH initialize_from_config_with_prefix' - print*, 'obs_file_begin: str1=', trim(STR1) if (trim(STR1)=='') then _FAIL('obs_file_begin missing, code crash') else call ESMF_TimeSet(this%obsfile_start_time, timestring=STR1, _RC) - if (mapl_am_I_root()) then - write(6,105) 'obs_file_begin provided: ', trim(STR1) - end if end if call ESMF_ConfigGetAttribute(config, value=STR1, default="", & label=prefix // 'obs_file_end:', _RC) - print*, 'obs_file_end: str1=', trim(STR1) if (trim(STR1)=='') then _FAIL('obs_file_end missing, code crash') else call ESMF_TimeSet(this%obsfile_end_time, timestring=STR1, _RC) - if (mapl_am_I_root()) then - write(6,105) 'obs_file_end provided:', trim(STR1) - end if end if call ESMF_ConfigGetAttribute(config, value=STR1, default="", & label= prefix// 'obs_file_interval:', _RC) _ASSERT(STR1/='', 'fatal error: obs_file_interval not provided in RC file') - if (mapl_am_I_root()) write(6,105) 'obs_file_interval:', trim(STR1) - if (mapl_am_I_root()) write(6,106) 'Epoch (hhmmss) :', this%epoch + + +! if (mapl_am_I_root()) then +! write(6,'(//2x, a)') 'SWATH initialize_from_config_with_prefix' +! print*, 'obs_file_begin: str1=', trim(STR1) +! write(6,105) 'obs_file_begin provided: ', trim(STR1) +! print*, 'obs_file_end: str1=', trim(STR1) +! write(6,105) 'obs_file_end provided:', trim(STR1) +! write(6,105) 'obs_file_interval:', trim(STR1) +! write(6,106) 'Epoch (hhmmss) :', this%epoch +! end if + i= index( trim(STR1), ' ' ) if (i>0) then @@ -536,127 +541,142 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call ESMF_ConfigGetAttribute(config, this%tunit, default="", & label=prefix//'tunit:', _RC) - - write(6,'(10(2x,a20,2x,a40,/))') & + + + !__ s2. find obsFile on disk and get array: this%t_alongtrack(:) + ! + call ESMF_VMGet(vm, mpiCommunicator=mpic, _RC) + call MPI_COMM_RANK(mpic, irank, ierror) + + if (irank==0) & + write(6,'(10(2x,a20,2x,a40,/))') & 'index_name_lon:', trim(this%index_name_lon), & 'index_name_lat:', trim(this%index_name_lat), & 'var_name_lon:', trim(this%var_name_lon), & 'var_name_lat:', trim(this%var_name_lat), & 'var_name_time:', trim(this%var_name_time), & 'tunit:', trim(this%tunit) - - - !__ s2. find obsFile on disk and get array: this%t_alongtrack(:) - ! - - call ESMF_TimeIntervalSet(Toff, h=0, m=0, s=0, _RC) - call Find_M_files_for_currTime (currTime, & - this%obsfile_start_time, this%obsfile_end_time, this%obsfile_interval, & - this%epoch_frequency, this%input_template, M_file, this%filenames, & - T_offset_in_file_content = Toff, _RC) - this%M_file = M_file - write(6,*) 'M_file=', M_file - do i=1, M_file - write(6,*) 'filenames(i)=', trim(this%filenames(i)) - end do - - call read_M_files_4_swath (this%filenames(1:M_file), nx, ny, & - this%index_name_lon, this%index_name_lat, _RC) - nlon=nx - nlat=ny - allocate(scanTime(nlon, nlat)) - allocate(this%t_alongtrack(nlat)) - - call read_M_files_4_swath (this%filenames(1:M_file), nx, ny, & - this%index_name_lon, this%index_name_lat, & - var_name_time=this%var_name_time, time=scanTime, _RC) + if (irank==0) then + call ESMF_TimeIntervalSet(Toff, h=0, m=0, s=0, _RC) + call Find_M_files_for_currTime (currTime, & + this%obsfile_start_time, this%obsfile_end_time, this%obsfile_interval, & + this%epoch_frequency, this%input_template, M_file, this%filenames, & + T_offset_in_file_content = Toff, _RC) + this%M_file = M_file + write(6,*) 'M_file=', M_file +! do i=1, M_file +! write(6,*) 'filenames(i)=', trim(this%filenames(i)) +! end do + + call read_M_files_4_swath (this%filenames(1:M_file), nx, ny, & + this%index_name_lon, this%index_name_lat, _RC) + nlon=nx + nlat=ny + allocate(scanTime(nlon, nlat)) + allocate(this%t_alongtrack(nlat)) + + call read_M_files_4_swath (this%filenames(1:M_file), nx, ny, & + this%index_name_lon, this%index_name_lat, & + var_name_time=this%var_name_time, time=scanTime, _RC) - ! lgr => logging%get_logger('HISTORY.sampler') - ! print*, 'key_time=', trim(key_time) - do j=1, nlat - this%t_alongtrack(j)= scanTime(1,j) - enddo - nstart = 1 - ! - ! redefine nstart to skip un-defined time value - ! If the t_alongtrack contains undefined values, use this code - ! - x0 = this%t_alongtrack(1) - x1 = 1.d16 - if (x0 > x1) then + do j=1, nlat + this%t_alongtrack(j)= scanTime(1,j) + enddo + nstart = 1 ! - ! bisect backward finding the first index arr[n] < x1 - klo=1 - khi=nlat - max_iter = int( log( real(nlat) ) / log(2.d0) ) + 2 - do i=1, max_iter - k = (klo+khi)/2 - if ( this%t_alongtrack(k) < x1 ) then - khi=k - else - nstart = khi - exit - endif - enddo - call lgr%debug('%a %i4', 'nstart', nstart) - call lgr%debug('%a %i4', 'this%t_alongtrack(nstart)', this%t_alongtrack(nstart)) - endif - - this%cell_across_swath = nlon - this%cell_along_swath = nlat - deallocate(scanTime) + ! redefine nstart to skip un-defined time value + ! If the t_alongtrack contains undefined values, use this code + ! + x0 = this%t_alongtrack(1) + x1 = 1.d16 + if (x0 > x1) then + ! + ! bisect backward finding the first index arr[n] < x1 + klo=1 + khi=nlat + max_iter = int( log( real(nlat) ) / log(2.d0) ) + 2 + do i=1, max_iter + k = (klo+khi)/2 + if ( this%t_alongtrack(k) < x1 ) then + khi=k + else + nstart = khi + exit + endif + enddo + call lgr%debug('%a %i4', 'nstart', nstart) + call lgr%debug('%a %i4', 'this%t_alongtrack(nstart)', this%t_alongtrack(nstart)) + endif - write(6,*) 'this%t_alongtrack(j)=', this%t_alongtrack(::100) + this%cell_across_swath = nlon + this%cell_along_swath = nlat + deallocate(scanTime) + write(6,*) 'this%t_alongtrack(j)=', this%t_alongtrack(::100) -! P2. - - ! determine im_world from Epoch - ! ----------------------------- - ! t_axis = t_alongtrack = t_a - ! convert currTime to j0 - ! use Epoch to find j1 - ! search j0, j1 in t_a - - - call time_esmf_2_nc_int (currTime, this%tunit, j0, _RC) - sec = hms_2_s (this%Epoch) - j1= j0 + sec - jx0= j0 - jx1= j1 - !!call lgr%debug ('%a %f8 %f8', 'jx0, jx1', jx0, jx1) - call lgr%debug ('%a %i16 %i16', 'j0, j1 ', j0, j1) + ! P2. + ! determine im_world from Epoch + ! ----------------------------- + ! t_axis = t_alongtrack = t_a + ! convert currTime to j0 + ! use Epoch to find j1 + ! search j0, j1 in t_a - - this%epoch_index(1)= 1 - this%epoch_index(2)= this%cell_across_swath - call bisect( this%t_alongtrack, jx0, jt1, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) - call bisect( this%t_alongtrack, jx1, jt2, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) + call time_esmf_2_nc_int (currTime, this%tunit, j0, _RC) + sec = hms_2_s (this%Epoch) + j1= j0 + sec + jx0= j0 + jx1= j1 + !!call lgr%debug ('%a %f8 %f8', 'jx0, jx1', jx0, jx1) + call lgr%debug ('%a %i16 %i16', 'j0, j1 ', j0, j1) - if (jt1==jt2) then - _FAIL('Epoch Time is too small, empty swath grid is generated, increase Epoch') - endif - jt1 = jt1 + 1 ! (x1,x2] design - this%epoch_index(3)= jt1 - this%epoch_index(4)= jt2 - Xdim = this%cell_across_swath - Ydim = this%epoch_index(4) - this%epoch_index(3) + 1 - - - call lgr%debug ('%a %i4 %i4', 'bisect for j0: rc, jt', rc, jt1) - call lgr%debug ('%a %i4 %i4', 'bisect for j1: rc, jt', rc, jt2) - call lgr%debug ('%a %i4 %i4', 'Xdim, Ydim', Xdim, Ydim) - call lgr%debug ('%a %i4 %i4 %i4 %i4', 'this%epoch_index(4)', & - this%epoch_index(1), this%epoch_index(2), & - this%epoch_index(3), this%epoch_index(4)) + this%epoch_index(1)= 1 + this%epoch_index(2)= this%cell_across_swath + call bisect( this%t_alongtrack, jx0, jt1, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) + call bisect( this%t_alongtrack, jx1, jt2, n_LB=int(nstart, ESMF_KIND_I8), n_UB=int(this%cell_along_swath, ESMF_KIND_I8), rc=rc) - this%im_world = Xdim - this%jm_world = Ydim - + if (jt1==jt2) then + _FAIL('Epoch Time is too small, empty swath grid is generated, increase Epoch') + endif + jt1 = jt1 + 1 ! (x1,x2] design + this%epoch_index(3)= jt1 + this%epoch_index(4)= jt2 + Xdim = this%cell_across_swath + Ydim = this%epoch_index(4) - this%epoch_index(3) + 1 + + call lgr%debug ('%a %i4 %i4', 'bisect for j0: rc, jt', rc, jt1) + call lgr%debug ('%a %i4 %i4', 'bisect for j1: rc, jt', rc, jt2) + call lgr%debug ('%a %i4 %i4', 'Xdim, Ydim', Xdim, Ydim) + call lgr%debug ('%a %i4 %i4 %i4 %i4', 'this%epoch_index(4)', & + this%epoch_index(1), this%epoch_index(2), & + this%epoch_index(3), this%epoch_index(4)) + + this%im_world = Xdim + this%jm_world = Ydim + end if + + call MPI_bcast(this%M_file, 1, MPI_INTEGER, 0, mpic, ierror) + do i=1, this%M_file + call MPI_bcast(this%filenames(i), ESMF_MAXSTR, MPI_CHARACTER, 0, mpic, ierror) + end do + call MPI_bcast(this%epoch_index, 4, MPI_INTEGER8, 0, mpic, ierror) + call MPI_bcast(this%im_world, 1, MPI_INTEGER, 0, mpic, ierror) + call MPI_bcast(this%jm_world, 1, MPI_INTEGER, 0, mpic, ierror) + call MPI_bcast(this%cell_across_swath, 1, MPI_INTEGER, 0, mpic, ierror) + call MPI_bcast(this%cell_along_swath, 1, MPI_INTEGER, 0, mpic, ierror) + ! donot need to bcast this%along_track (root only) + +! if (irank==0) write(6,*) 'af root find_M_files' +! write(6,106) 'my irank, M_file =', irank, this%M_file +! do i=1, this%M_file +! write(6,*) 'my irank=', irank +! write(6,*) 'ck MPI filename=', trim(this%filenames(i)) +! end do +! _FAIL('nail stop') call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'IMS_FILE:', rc=status) if ( status == _SUCCESS ) then @@ -677,7 +697,7 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc _RETURN(_SUCCESS) 105 format (1x,a,2x,a) -106 format (1x,a,2x,i8) +106 format (1x,a,2x,10i8) contains @@ -1284,11 +1304,16 @@ end function generate_file_reference3D subroutine get_xy_subset(this, interval, xy_subset, rc) + use MPI class(SwathGridFactory), intent(in) :: this type(ESMF_Time), intent(in) :: interval(2) integer, intent(out) :: xy_subset(2,2) integer, optional, intent(out) :: rc + type(ESMF_VM) :: VM + integer:: mpic + integer:: irank, ierror + integer :: status type(ESMF_Time) :: T1, T2 integer(ESMF_KIND_I8) :: i1, i2 @@ -1296,53 +1321,62 @@ subroutine get_xy_subset(this, interval, xy_subset, rc) integer(ESMF_KIND_I8) :: index1, index2 integer :: jlo, jhi, je - ! xtrack - xy_subset(1:2,1)=this%epoch_index(1:2) - ! atrack - T1= interval(1) - T2= interval(2) - - ! this%t_alongtrack - ! - call time_esmf_2_nc_int (T1, this%tunit, i1, _RC) - call time_esmf_2_nc_int (T2, this%tunit, i2, _RC) - iT1 = i1 ! int to real*8 - iT2 = i2 - if (this%epoch_index(3) > 2) then - jlo = this%epoch_index(3) - 2 - else - jlo = this%epoch_index(3) + call ESMF_VmGetCurrent(VM, _RC) + call ESMF_VMGet(vm, mpiCommunicator=mpic, _RC) + call MPI_COMM_RANK(mpic, irank, ierror) + + if (irank==0) then + ! xtrack + xy_subset(1:2,1)=this%epoch_index(1:2) + + ! atrack + T1= interval(1) + T2= interval(2) + + ! this%t_alongtrack + ! + call time_esmf_2_nc_int (T1, this%tunit, i1, _RC) + call time_esmf_2_nc_int (T2, this%tunit, i2, _RC) + iT1 = i1 ! int to real*8 + iT2 = i2 + if (this%epoch_index(3) > 2) then + jlo = this%epoch_index(3) - 2 + else + jlo = this%epoch_index(3) + end if + jhi = this%epoch_index(4) + 1 + call bisect( this%t_alongtrack, iT1, index1, n_LB=int(jlo, ESMF_KIND_I8), n_UB=int(jhi, ESMF_KIND_I8), rc=rc) + call bisect( this%t_alongtrack, iT2, index2, n_LB=int(jlo, ESMF_KIND_I8), n_UB=int(jhi, ESMF_KIND_I8), rc=rc) + + !! complex version + !! ! (x1, x2] design in bisect + !! if (index1==jlo-1) then + !! je = index1 + 1 + !! else + !! je = index1 + !! end if + !! xy_subset(1, 2) = je + !! if (index2==jlo-1) then + !! je = index2 + 1 + !! else + !! je = index2 + !! end if + !! xy_subset(2, 2) = je + + ! simple version + xy_subset(1, 2)=index1+1 ! atrack + xy_subset(2, 2)=index2 + + ! + !- relative + ! + xy_subset(1,2)= xy_subset(1,2) - this%epoch_index(3) + 1 + xy_subset(2,2)= xy_subset(2,2) - this%epoch_index(3) + 1 end if - jhi = this%epoch_index(4) + 1 - call bisect( this%t_alongtrack, iT1, index1, n_LB=int(jlo, ESMF_KIND_I8), n_UB=int(jhi, ESMF_KIND_I8), rc=rc) - call bisect( this%t_alongtrack, iT2, index2, n_LB=int(jlo, ESMF_KIND_I8), n_UB=int(jhi, ESMF_KIND_I8), rc=rc) - -!! complex version -!! ! (x1, x2] design in bisect -!! if (index1==jlo-1) then -!! je = index1 + 1 -!! else -!! je = index1 -!! end if -!! xy_subset(1, 2) = je -!! if (index2==jlo-1) then -!! je = index2 + 1 -!! else -!! je = index2 -!! end if -!! xy_subset(2, 2) = je - - ! simple version - xy_subset(1, 2)=index1+1 ! atrack - xy_subset(2, 2)=index2 - - ! - !- relative - ! - xy_subset(1,2)= xy_subset(1,2) - this%epoch_index(3) + 1 - xy_subset(2,2)= xy_subset(2,2) - this%epoch_index(3) + 1 + call MPI_bcast(xy_subset, 4, MPI_INTEGER, 0, mpic, ierror) + _RETURN(_SUCCESS) end subroutine get_xy_subset diff --git a/base/StringTemplate.F90 b/base/StringTemplate.F90 index 6b6773dae07a..c3efbdeecece 100644 --- a/base/StringTemplate.F90 +++ b/base/StringTemplate.F90 @@ -223,7 +223,6 @@ function evaluate_token(token,year,month,day,hour,minute,second,preserve) result call ESMF_TimeGet(time, dayOfYear=doy, _RC) call ESMF_CalendarDestroy(gregorianCalendar) write(buffer,'(i3.3)')doy - write(6,*) 'doy=', doy else _FAIL('Day of Year must be %D3') end if From 99429c6d9c2cf768564f32cf904ad097f69112ca Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Mon, 27 Nov 2023 14:02:49 -0700 Subject: [PATCH 31/41] Values of lon/lat/time in netCDf is wrong. The reason is not found. Suspect griddedio.F90 problem, like what is modified by Ben. --- base/MAPL_SwathGridFactory.F90 | 17 +++++++++++++---- base/Plain_netCDF_Time.F90 | 8 ++++++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 58c118a8b026..062523e7a3a0 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -259,7 +259,7 @@ subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) do j=this%epoch_index(3), this%epoch_index(4) k=k+1 centers(1:Xdim, k) = centers_full(1:Xdim, j) -!! write(6,'(100f12.2)') centers(1:Xdim:40, k) +!! write(6,'(100f12.2)') centers(1:Xdim:1, k) enddo centers=centers*MAPL_DEGREES_TO_RADIANS_R8 deallocate (centers_full) @@ -269,7 +269,12 @@ subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) staggerloc=ESMF_STAGGERLOC_CENTER, farrayPtr=fptr, _RC) fptr=real(centers(i_1:i_n,j_1:j_n), kind=ESMF_KIND_R8) + write(6,'(2x,a,2f30.16)') 'min/max', minval(fptr), maxval(fptr) + write(6,'(2x,a,2f30.16)') 'fptr(::5,::5), fptr(::5,::5)' + write(6,'(6f15.5)') fptr(::20,::20) +!! _FAIL('ck write lon') + ! read latitudes if (MAPL_AmNodeRoot .or. (.not. MAPL_ShmInitialized)) then allocate( centers_full(Xdim_full, Ydim_full)) @@ -454,6 +459,7 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc ! ! Read in specs, crop epoch_index based on scanTime ! + !__ s1. read in file spec. ! @@ -543,7 +549,7 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc - !__ s2. find obsFile on disk and get array: this%t_alongtrack(:) + !__ s2. find obsFile even if missing on disk and get array: this%t_alongtrack(:) ! call ESMF_VMGet(vm, mpiCommunicator=mpic, _RC) call MPI_COMM_RANK(mpic, irank, ierror) @@ -613,7 +619,7 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc this%cell_across_swath = nlon this%cell_along_swath = nlat deallocate(scanTime) - write(6,*) 'this%t_alongtrack(j)=', this%t_alongtrack(::100) +!! write(6,*) 'this%t_alongtrack(j)=', this%t_alongtrack(::100) ! P2. @@ -1346,8 +1352,11 @@ subroutine get_xy_subset(this, interval, xy_subset, rc) jlo = this%epoch_index(3) end if jhi = this%epoch_index(4) + 1 + ! + ! -- it is possible obs files is missing + ! call bisect( this%t_alongtrack, iT1, index1, n_LB=int(jlo, ESMF_KIND_I8), n_UB=int(jhi, ESMF_KIND_I8), rc=rc) - call bisect( this%t_alongtrack, iT2, index2, n_LB=int(jlo, ESMF_KIND_I8), n_UB=int(jhi, ESMF_KIND_I8), rc=rc) + call bisect( this%t_alongtrack, iT2, index2, n_LB=int(jlo, ESMF_KIND_I8), n_UB=int(jhi, ESMF_KIND_I8), rc=rc) !! complex version !! ! (x1, x2] design in bisect diff --git a/base/Plain_netCDF_Time.F90 b/base/Plain_netCDF_Time.F90 index ec5bb51aa4ac..edd3ebd154e5 100644 --- a/base/Plain_netCDF_Time.F90 +++ b/base/Plain_netCDF_Time.F90 @@ -450,10 +450,14 @@ subroutine bisect_find_LB_R8_I8(xa, x, n, n_LB, n_UB, rc) integer :: i, nmax LB=1; UB=size(xa,1) - if(present(n_LB)) LB=n_LB - if(present(n_UB)) UB=n_UB + if(present(n_LB)) LB=max(LB, n_LB) + if(present(n_UB)) UB=min(UB, n_UB) klo=LB; khi=UB; dk=1 + write(6,121) 'size(xa0), n_LB, n_UB', size(xa), n_LB, n_UB + +#include '/Users/yyu11/sftp/myformat.inc' + if ( xa(LB ) > xa(UB) ) then klo= UB khi= LB From 0a2d1c5a51b8b00782ef99b40068578158fb8246 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Tue, 28 Nov 2023 07:26:38 -0700 Subject: [PATCH 32/41] . --- base/Plain_netCDF_Time.F90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/base/Plain_netCDF_Time.F90 b/base/Plain_netCDF_Time.F90 index edd3ebd154e5..a5603dfb9243 100644 --- a/base/Plain_netCDF_Time.F90 +++ b/base/Plain_netCDF_Time.F90 @@ -455,8 +455,8 @@ subroutine bisect_find_LB_R8_I8(xa, x, n, n_LB, n_UB, rc) klo=LB; khi=UB; dk=1 write(6,121) 'size(xa0), n_LB, n_UB', size(xa), n_LB, n_UB - -#include '/Users/yyu11/sftp/myformat.inc' + + if ( xa(LB ) > xa(UB) ) then klo= UB @@ -496,6 +496,7 @@ subroutine bisect_find_LB_R8_I8(xa, x, n, n_LB, n_UB, rc) _RETURN(_SUCCESS) +include '/Users/yyu11/sftp/myformat.inc' end subroutine bisect_find_LB_R8_I8 From f54a6075c668c8a8a1f5cbad502e9e26b239c074 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Tue, 28 Nov 2023 10:45:13 -0700 Subject: [PATCH 33/41] NAG problem: - ArrayReference in stage2DLatLon in GriddedIO.F90 generates strange values in netCDF ?? - Why case4 works with NAG ? --- base/MAPL_ObsUtil.F90 | 6 ++++++ base/MAPL_SwathGridFactory.F90 | 6 ++---- gridcomps/History/MAPL_EpochSwathMod.F90 | 9 +++++++-- griddedio/GriddedIO.F90 | 7 ++++++- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/base/MAPL_ObsUtil.F90 b/base/MAPL_ObsUtil.F90 index fda9835fe7d0..6021be3fdf89 100644 --- a/base/MAPL_ObsUtil.F90 +++ b/base/MAPL_ObsUtil.F90 @@ -234,6 +234,9 @@ subroutine Find_M_files_for_currTime (currTime, & M=j _ASSERT ( M < size(filenames) , 'code crash, number of files exceeds upper bound') + _ASSERT (M/=0, 'M is zero, no files found for currTime') + + _RETURN(_SUCCESS) end subroutine Find_M_files_for_currTime @@ -277,6 +280,9 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & !__ s1. get Xdim Ydim M = size(filenames) + _ASSERT(M/=0, 'M is zero, no files found') + + allocate(nlons(M), nlats(M)) jx=0 do i = 1, M diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 062523e7a3a0..45cdedddc5ac 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -1421,17 +1421,15 @@ subroutine get_obs_time(this, grid, obs_time, rc) integer :: nx, ny integer :: IM_WORLD, JM_WORLD - - call MAPL_grid_interior(grid, i_1, i_n, j_1, j_n) !- shared mem case in MPI ! Xdim=this%im_world Ydim=this%jm_world - Xdim_full=this%cell_across_swath Ydim_full=this%cell_along_swath + call MAPL_grid_interior(grid, i_1, i_n, j_1, j_n) call MAPL_AllocateShared(centers,[Xdim,Ydim],transroot=.true.,_RC) call MAPL_SyncSharedMemory(_RC) @@ -1441,7 +1439,7 @@ subroutine get_obs_time(this, grid, obs_time, rc) allocate( centers_full(Xdim_full, Ydim_full)) call read_M_files_4_swath (this%filenames(1:this%M_file), nx, ny, & this%index_name_lon, this%index_name_lat, & - var_name_time=this%var_name_time, lon=centers_full, _RC) + var_name_time=this%var_name_time, time=centers_full, _RC) !!call get_v2d_netcdf(this%grid_file_name, time_name, centers_full, Xdim_full, Ydim_full) k=0 do j=this%epoch_index(3), this%epoch_index(4) diff --git a/gridcomps/History/MAPL_EpochSwathMod.F90 b/gridcomps/History/MAPL_EpochSwathMod.F90 index af62bf944fa4..e6c8e510fed3 100644 --- a/gridcomps/History/MAPL_EpochSwathMod.F90 +++ b/gridcomps/History/MAPL_EpochSwathMod.F90 @@ -326,6 +326,10 @@ subroutine fill_time_in_bundle (this, xname, bundle, rc) factory => grid_manager%get_factory(this%ogrid,_RC) call factory%get_obs_time (this%ogrid, ptr2d, _RC) + write(6,*) 'print out time: ptr2d(::20,::20)' + write(6,*) ptr2d(::20,::20) + + _RETURN(ESMF_SUCCESS) end subroutine fill_time_in_bundle @@ -409,7 +413,8 @@ subroutine Create_bundle_RH(this,items,bundle,timeInfo,vdata,ogrid,global_attrib ! __ please note, metadata in this section is not used in put_var to netCDF ! the design used mGriddedIO%metadata in MAPL_HistoryGridComp.F90 - ! + ! In other words, factory%append_metadata appeared here and in GriddedIO.F90 + ! if (allocated(this%metadata)) then deallocate (this%metadata) end if @@ -1156,7 +1161,7 @@ subroutine interp_accumulate_fields (this,xy_subset,rc) pt2d_(:,jj) = pt2d(:,jj) enddo endif - write(6,*) 'out_pt2d', pt2d_(10,10:50:2) + write(6,*) 'out_pt2d', pt2d_(::10,::10) elseif (rank==3) then call ESMF_ArrayGet(array1, farrayptr=pt3d, _RC) diff --git a/griddedio/GriddedIO.F90 b/griddedio/GriddedIO.F90 index 602ea72f74fc..e4ef27c2c1bd 100644 --- a/griddedio/GriddedIO.F90 +++ b/griddedio/GriddedIO.F90 @@ -839,7 +839,7 @@ subroutine stage2DLatLon(this, fileName, oClients, rc) integer :: status real(REAL64), pointer :: ptr2d(:,:) - type(ArrayReference) :: ref + type(ArrayReference), target :: ref class (AbstractGridFactory), pointer :: factory integer, allocatable :: localStart(:),globalStart(:),globalCount(:) logical :: hasll @@ -860,6 +860,11 @@ subroutine stage2DLatLon(this, fileName, oClients, rc) farrayPtr=ptr2d, rc=status) _VERIFY(STATUS) this%lons=ptr2d*MAPL_RADIANS_TO_DEGREES + + write(6,*) 'ck ref in stage2dLatLon' + write(6,'(8f12.2)') this%lons(::20,::20) + !-- this is a bug in NAG here + ! ref = ArrayReference(this%lons) call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lons', & ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) From 995887fb3fd487338a4e07088f99a2a595d17862 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Tue, 28 Nov 2023 16:07:27 -0500 Subject: [PATCH 34/41] update --- base/MAPL_SwathGridFactory.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 45cdedddc5ac..6b2a70d0fe87 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -43,6 +43,7 @@ module MAPL_SwathGridFactoryMod integer :: epoch ! unit: second integer(ESMF_KIND_I8) :: epoch_index(4) ! is,ie,js,je real(ESMF_KIND_R8), allocatable:: t_alongtrack(:) + ! note: this var is not deallocated in swathfactory, use caution character(len=ESMF_MAXSTR) :: tunit character(len=ESMF_MAXSTR) :: index_name_lon character(len=ESMF_MAXSTR) :: index_name_lat @@ -1353,7 +1354,7 @@ subroutine get_xy_subset(this, interval, xy_subset, rc) end if jhi = this%epoch_index(4) + 1 ! - ! -- it is possible obs files is missing + ! -- it is possible some obs files are missing ! call bisect( this%t_alongtrack, iT1, index1, n_LB=int(jlo, ESMF_KIND_I8), n_UB=int(jhi, ESMF_KIND_I8), rc=rc) call bisect( this%t_alongtrack, iT2, index2, n_LB=int(jlo, ESMF_KIND_I8), n_UB=int(jhi, ESMF_KIND_I8), rc=rc) From 4f715900eae50cc18bd30173e5420de52b4f5a9b Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 29 Nov 2023 08:21:05 -0500 Subject: [PATCH 35/41] update --- CHANGELOG.md | 6 ++-- base/MAPL_ObsUtil.F90 | 24 ++++--------- base/MAPL_SwathGridFactory.F90 | 41 ++++++++-------------- base/Plain_netCDF_Time.F90 | 10 ------ gridcomps/History/MAPL_EpochSwathMod.F90 | 21 +---------- gridcomps/History/MAPL_HistoryGridComp.F90 | 7 ++-- griddedio/GriddedIO.F90 | 10 +++--- 7 files changed, 34 insertions(+), 85 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02ae77fab03d..f4c58918df06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,9 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Change the verification of the grid in MAPL_GetGlobalHorzIJIndex to avoid collective call -- Swath grid step 1: allow for destroy grid, regridder and metadata. - Modifications made to GriddedIO.F90, MAPL_AbstractRegridder.F90, and MAPL_EsmfRegridder.F90. -- Swath grid step 2: allow for swath grid filename template +- Swath grid step 1: allow for destroying and regenerating swath grid and regenerating regridder route handle, and creating + allocatable metadata in griddedIO. Modifications are made to GriddedIO.F90, MAPL_AbstractRegridder.F90, and MAPL_EsmfRegridder.F90. +- Swath grid step 2: add control keywords for swath grid. Allow for filename template with '*' and DOY. Allow for missing obs files. Specify index_name_lon/lat, var_name_lon/lat/time, tunit, obs_file_begin/end/interval, Epoch and Epoch_init. ### Fixed diff --git a/base/MAPL_ObsUtil.F90 b/base/MAPL_ObsUtil.F90 index 6021be3fdf89..deb84bb0e736 100644 --- a/base/MAPL_ObsUtil.F90 +++ b/base/MAPL_ObsUtil.F90 @@ -6,6 +6,7 @@ module MAPL_ObsUtilMod use Plain_netCDF_Time use netCDF use MAPL_CommsMod, only : MAPL_AM_I_ROOT + use pFlogger, only: logging, Logger, WrapArray use, intrinsic :: iso_fortran_env, only: REAL32, REAL64 implicit none @@ -276,13 +277,13 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & real(ESMF_KIND_R8), allocatable :: time_loc_R8(:,:) real(ESMF_KIND_R8), allocatable :: lon_loc(:,:) real(ESMF_KIND_R8), allocatable :: lat_loc(:,:) - + class(Logger), pointer :: lgr !__ s1. get Xdim Ydim M = size(filenames) _ASSERT(M/=0, 'M is zero, no files found') - - + lgr => logging%get_logger('MAPL.Sampler') + allocate(nlons(M), nlats(M)) jx=0 do i = 1, M @@ -291,11 +292,10 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & key_lon=index_name_lon, key_lat=index_name_lat, _RC) nlons(i)=nlon nlats(i)=nlat - if (mapl_am_i_root()) then - print*, 'ck filename input', trim(filename) - print*, 'nlon, nlat=', nlon, nlat - end if jx=jx+nlat + + call lgr%debug('Input filename: %a', trim(filename)) + call lgr%debug('Input file : nlon, nlat= %i6 %i6', nlon, nlat) end do Xdim=nlon Ydim=jx @@ -333,10 +333,6 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & end do - ! allocate(scanTime(nlon, nlat)) - ! allocate(this%t_alongtrack(nlat)) - - !!rc=0 _RETURN(_SUCCESS) end subroutine read_M_files_4_swath @@ -458,10 +454,6 @@ subroutine get_var_from_name_w_group (var_name, var2d, filename, rc) short_name=var_name endif - if (mapl_am_i_root()) then - write(6,'(10(2x,a))') 'ck grp1, grp2, short_name:', trim(grp1), trim(grp2), trim(short_name) - end if - call check_nc_status(nf90_open(filename, NF90_NOWRITE, ncid2), _RC) if ( found_group ) then call check_nc_status(nf90_inq_ncid(ncid2, grp1, ncid), _RC) @@ -477,8 +469,6 @@ subroutine get_var_from_name_w_group (var_name, var2d, filename, rc) call check_nc_status(nf90_get_var(ncid, varid, var2d), _RC) !! call check_nc_status(nf90_close(ncid), _RC) - write(6,*) var2d(::100,::100) - _RETURN(_SUCCESS) end subroutine get_var_from_name_w_group diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 6b2a70d0fe87..e1984980d2b2 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -17,6 +17,7 @@ module MAPL_SwathGridFactoryMod !!use netcdf !!use Plain_netCDF_Time use MAPL_ObsUtilMod + use pflogger, only : Logger, logging use, intrinsic :: iso_fortran_env, only: REAL32 use, intrinsic :: iso_fortran_env, only: REAL64 implicit none @@ -207,7 +208,6 @@ end function create_basic_grid subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) use MAPL_BaseMod, only: MAPL_grid_interior - use pflogger, only : Logger, logging implicit none class (SwathGridFactory), intent(in) :: this type (ESMF_Grid), intent(inout) :: grid @@ -242,12 +242,14 @@ subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) call MAPL_AllocateShared(centers,[Xdim,Ydim],transroot=.true.,_RC) call MAPL_SyncSharedMemory(_RC) - if (mapl_am_I_root()) then - write(6,'(2x,a,10i8)') & - 'ck: Xdim, Ydim, Xdim_full, Ydim_full', Xdim, Ydim, Xdim_full, Ydim_full - write(6,'(2x,a,10i8)') & - 'ck: i_1, i_n, j_1, j_n', i_1, i_n, j_1, j_n - end if + +! if (mapl_am_I_root()) then +! write(6,'(2x,a,10i8)') & +! 'ck: Xdim, Ydim, Xdim_full, Ydim_full', Xdim, Ydim, Xdim_full, Ydim_full +! write(6,'(2x,a,10i8)') & +! 'ck: i_1, i_n, j_1, j_n', i_1, i_n, j_1, j_n +! end if + ! read longitudes if (MAPL_AmNodeRoot .or. (.not. MAPL_ShmInitialized)) then @@ -255,12 +257,10 @@ subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) call read_M_files_4_swath (this%filenames(1:this%M_file), nx, ny, & this%index_name_lon, this%index_name_lat, & var_name_lon=this%var_name_lon, lon=centers_full, _RC) - write(6,*) 'this%epoch_index(3:4)', this%epoch_index(3:4) k=0 do j=this%epoch_index(3), this%epoch_index(4) k=k+1 centers(1:Xdim, k) = centers_full(1:Xdim, j) -!! write(6,'(100f12.2)') centers(1:Xdim:1, k) enddo centers=centers*MAPL_DEGREES_TO_RADIANS_R8 deallocate (centers_full) @@ -270,11 +270,6 @@ subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) staggerloc=ESMF_STAGGERLOC_CENTER, farrayPtr=fptr, _RC) fptr=real(centers(i_1:i_n,j_1:j_n), kind=ESMF_KIND_R8) - write(6,'(2x,a,2f30.16)') 'min/max', minval(fptr), maxval(fptr) - write(6,'(2x,a,2f30.16)') 'fptr(::5,::5), fptr(::5,::5)' - write(6,'(6f15.5)') fptr(::20,::20) -!! _FAIL('ck write lon') - ! read latitudes if (MAPL_AmNodeRoot .or. (.not. MAPL_ShmInitialized)) then @@ -301,14 +296,6 @@ subroutine add_horz_coordinates_from_file(this, grid, unusable, rc) else deallocate(centers) end if - - lgr => logging%get_logger('HISTORY.sampler') - call lgr%debug('%a', 'test') - call lgr%debug('%a %i8 %i8', 'Xdim, Ydim', Xdim, Ydim) - call lgr%debug('%a %i8 %i8', 'Xdim_full, Ydim_full', Xdim_full, Ydim_full) - call lgr%debug('%a %i8 %i8 %i8 %i8', 'epoch_index(1:4)', & - this%epoch_index(1), this%epoch_index(2), & - this%epoch_index(3), this%epoch_index(4)) _RETURN(_SUCCESS) end subroutine add_horz_coordinates_from_file @@ -571,10 +558,12 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc this%epoch_frequency, this%input_template, M_file, this%filenames, & T_offset_in_file_content = Toff, _RC) this%M_file = M_file - write(6,*) 'M_file=', M_file -! do i=1, M_file -! write(6,*) 'filenames(i)=', trim(this%filenames(i)) -! end do + write(6,'(10(2x,a20,2x,i40))') & + 'M_file:', M_file + do i=1, M_file + write(6,'(10(2x,a20,2x,a))') & + 'filenames(i):', trim(this%filenames(i)) + end do call read_M_files_4_swath (this%filenames(1:M_file), nx, ny, & this%index_name_lon, this%index_name_lat, _RC) diff --git a/base/Plain_netCDF_Time.F90 b/base/Plain_netCDF_Time.F90 index a5603dfb9243..215cfdeeb31e 100644 --- a/base/Plain_netCDF_Time.F90 +++ b/base/Plain_netCDF_Time.F90 @@ -79,12 +79,7 @@ subroutine get_ncfile_dimension(filename, nlon, nlat, tdim, key_lon, key_lat, ke call check_nc_status(nf90_open(trim(fileName), NF90_NOWRITE, ncid), _RC) if(present(key_lon)) then lon_name=trim(key_lon) -! print*, 'fileName=', trim(fileName) -! print*, 'ncid=', ncid -! print*, 'lon_name=', trim(key_lon) -! print*, 'ck step 1' call check_nc_status(nf90_inq_dimid(ncid, trim(lon_name), dimid), _RC) -! print*, 'ck step 2' call check_nc_status(nf90_inquire_dimension(ncid, dimid, len=nlon), _RC) endif @@ -453,10 +448,6 @@ subroutine bisect_find_LB_R8_I8(xa, x, n, n_LB, n_UB, rc) if(present(n_LB)) LB=max(LB, n_LB) if(present(n_UB)) UB=min(UB, n_UB) klo=LB; khi=UB; dk=1 - - write(6,121) 'size(xa0), n_LB, n_UB', size(xa), n_LB, n_UB - - if ( xa(LB ) > xa(UB) ) then klo= UB @@ -496,7 +487,6 @@ subroutine bisect_find_LB_R8_I8(xa, x, n, n_LB, n_UB, rc) _RETURN(_SUCCESS) -include '/Users/yyu11/sftp/myformat.inc' end subroutine bisect_find_LB_R8_I8 diff --git a/gridcomps/History/MAPL_EpochSwathMod.F90 b/gridcomps/History/MAPL_EpochSwathMod.F90 index e6c8e510fed3..62b94145df5f 100644 --- a/gridcomps/History/MAPL_EpochSwathMod.F90 +++ b/gridcomps/History/MAPL_EpochSwathMod.F90 @@ -127,7 +127,7 @@ function new_samplerHQ(clock, config, key, rc) result(hq) type(ESMF_Config) :: cf - hq%clock= clock + hq%clock= clock hq%config_grid_save= config hq%arr(1:2) = -2.d0 @@ -211,10 +211,6 @@ subroutine regrid_accumulate_on_xysubset (this, sp, rc) timeset(2) = current_time call factory%get_xy_subset( timeset, xy_subset, _RC) - write(6,*) 'xy_subset(:,1)_x', xy_subset(:,1) ! LB, UB - !!write(6,*) 'xy_subset(:,2)_a', xy_subset(:,2) - write(6,*) 'xy_subset(:,2)_a', xy_subset(:,2), xy_subset(2,2)-xy_subset(1,2)+1 ! UB - ! __ s2. interpolate then save data using xy_mask call sp%interp_accumulate_fields (xy_subset, _RC) @@ -325,10 +321,6 @@ subroutine fill_time_in_bundle (this, xname, bundle, rc) ! __ obs_time from swath factory factory => grid_manager%get_factory(this%ogrid,_RC) call factory%get_obs_time (this%ogrid, ptr2d, _RC) - - write(6,*) 'print out time: ptr2d(::20,::20)' - write(6,*) ptr2d(::20,::20) - _RETURN(ESMF_SUCCESS) @@ -437,8 +429,6 @@ subroutine Create_bundle_RH(this,items,bundle,timeInfo,vdata,ogrid,global_attrib do while (iter /= this%items%end()) item => iter%get() if (item%itemType == ItemTypeScalar) then - print*, 'item%xname' - print*, item%xname call this%CreateVariable(item%xname,rc=status) _VERIFY(status) else if (item%itemType == ItemTypeVector) then @@ -1129,9 +1119,6 @@ subroutine interp_accumulate_fields (this,xy_subset,rc) do while (iter /= this%items%end()) item => iter%get() if (item%itemType == ItemTypeScalar) then - -!! write(6,*) 'ck bundlepost_acc, item%xname ', item%xname - call this%RegridScalar(item%xname,rc=status) _VERIFY(status) call ESMF_FieldBundleGet(this%output_bundle,item%xname,field=outField, _RC) @@ -1149,9 +1136,6 @@ subroutine interp_accumulate_fields (this,xy_subset,rc) call ESMF_ArrayGet(array1, rank=rank, _RC) if (rank==2) then call ESMF_ArrayGet(array1, farrayptr=pt2d, _RC) -!! write(6,*) 'shape(pt2d)', shape(pt2d) -!! write(6,*) 'in_pt2d', pt2d(10,10:50:2) - call ESMF_ArrayGet(array2, farrayptr=pt2d_, _RC) localDe=0 if (j1(localDe)>0) then @@ -1161,11 +1145,8 @@ subroutine interp_accumulate_fields (this,xy_subset,rc) pt2d_(:,jj) = pt2d(:,jj) enddo endif - write(6,*) 'out_pt2d', pt2d_(::10,::10) - elseif (rank==3) then call ESMF_ArrayGet(array1, farrayptr=pt3d, _RC) - write(6,*) 'shape(pt3d)', shape(pt3d) call ESMF_ArrayGet(array2, farrayptr=pt3d_, _RC) do localDe=0, localDEcount-1 if (j1(localDe)>0) then diff --git a/gridcomps/History/MAPL_HistoryGridComp.F90 b/gridcomps/History/MAPL_HistoryGridComp.F90 index dd76e6946656..ef00d0c9cef8 100644 --- a/gridcomps/History/MAPL_HistoryGridComp.F90 +++ b/gridcomps/History/MAPL_HistoryGridComp.F90 @@ -145,7 +145,7 @@ module MAPL_HistoryGridCompMod public HISTORY_ExchangeListWrap - type(samplerHQ), save :: Hsampler + type(samplerHQ) :: Hsampler ! is 'save' needed here? contains @@ -3518,7 +3518,7 @@ subroutine Run ( gc, import, export, clock, rc ) end if elseif (list(n)%sampler_spec == 'station') then if (list(n)%unit.eq.0) then - if (mapl_am_i_root()) call lgr%debug('%a %a',& + call lgr%debug('%a %a',& "Station_data output to new file:",trim(filename(n))) call list(n)%station_sampler%close_file_handle(_RC) call list(n)%station_sampler%create_file_handle(filename(n),_RC) @@ -3606,9 +3606,6 @@ subroutine Run ( gc, import, export, clock, rc ) state_out = INTSTATE%GIM(n) end if -!! -- bug, what is this? -!! call lgr%debug('%a %i','list(n)%unit=', list(n)%unit) - list(n)%currentFile = filename(n) if (.not.list(n)%timeseries_output) then diff --git a/griddedio/GriddedIO.F90 b/griddedio/GriddedIO.F90 index e4ef27c2c1bd..b48717c14899 100644 --- a/griddedio/GriddedIO.F90 +++ b/griddedio/GriddedIO.F90 @@ -834,7 +834,7 @@ end subroutine RegridVector subroutine stage2DLatLon(this, fileName, oClients, rc) class (MAPL_GriddedIO), intent(inout) :: this character(len=*), intent(in) :: fileName - type (ClientManager), optional, intent(inout) :: oClients + type (ClientManager), optional, target, intent(inout) :: oClients integer, optional, intent(out) :: rc integer :: status @@ -859,12 +859,13 @@ subroutine stage2DLatLon(this, fileName, oClients, rc) staggerloc=ESMF_STAGGERLOC_CENTER, & farrayPtr=ptr2d, rc=status) _VERIFY(STATUS) + ! this%lons= real(ptr2d*MAPL_RADIANS_TO_DEGREES, kind=ESMF_KIND_R4) this%lons=ptr2d*MAPL_RADIANS_TO_DEGREES write(6,*) 'ck ref in stage2dLatLon' - write(6,'(8f12.2)') this%lons(::20,::20) - !-- this is a bug in NAG here - ! + write(6,'(8f12.2)') this%lons(::50,::50) + write(6,'(8f12.2)') 'I think !-- this is a bug in NAG here' + ref = ArrayReference(this%lons) call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lons', & ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) @@ -874,6 +875,7 @@ subroutine stage2DLatLon(this, fileName, oClients, rc) farrayPtr=ptr2d, rc=status) _VERIFY(STATUS) if (.not.allocated(this%lats)) allocate(this%lats(size(ptr2d,1),size(ptr2d,2))) + ! this%lats= real(ptr2d*MAPL_RADIANS_TO_DEGREES, kind=ESMF_KIND_R4) this%lats=ptr2d*MAPL_RADIANS_TO_DEGREES ref = ArrayReference(this%lats) call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lats', & From ed9cf02506a589822e8fd1efc5cf09e98d8d1067 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 29 Nov 2023 08:27:40 -0500 Subject: [PATCH 36/41] . --- griddedio/GriddedIO.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/griddedio/GriddedIO.F90 b/griddedio/GriddedIO.F90 index b48717c14899..0c6de27ec816 100644 --- a/griddedio/GriddedIO.F90 +++ b/griddedio/GriddedIO.F90 @@ -864,7 +864,7 @@ subroutine stage2DLatLon(this, fileName, oClients, rc) write(6,*) 'ck ref in stage2dLatLon' write(6,'(8f12.2)') this%lons(::50,::50) - write(6,'(8f12.2)') 'I think !-- this is a bug in NAG here' + write(6,*) 'I think !-- this is a bug in NAG here' ref = ArrayReference(this%lons) call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lons', & From a1457ceb67bfdaf3e435f0acf2425206203c7455 Mon Sep 17 00:00:00 2001 From: Tom Clune Date: Wed, 29 Nov 2023 12:25:51 -0500 Subject: [PATCH 37/41] Fix for missing TARGET attribute. --- CHANGELOG.md | 1 + griddedio/GriddedIO.F90 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4c58918df06..5929bd41f262 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - [#2433] Implemented workarounds for gfortran-13 +- Missing TARGET in GriddedIO - exposed runtime error when using NAG + debug. ### Removed diff --git a/griddedio/GriddedIO.F90 b/griddedio/GriddedIO.F90 index 0c6de27ec816..b2de934f6228 100644 --- a/griddedio/GriddedIO.F90 +++ b/griddedio/GriddedIO.F90 @@ -832,7 +832,7 @@ subroutine RegridVector(this,xName,yName,rc) end subroutine RegridVector subroutine stage2DLatLon(this, fileName, oClients, rc) - class (MAPL_GriddedIO), intent(inout) :: this + class (MAPL_GriddedIO), target, intent(inout) :: this character(len=*), intent(in) :: fileName type (ClientManager), optional, target, intent(inout) :: oClients integer, optional, intent(out) :: rc From d4e218cc35f0803c28a0b1b6444b46cf1987bde2 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 29 Nov 2023 16:32:50 -0500 Subject: [PATCH 38/41] small clean up --- base/MAPL_ObsUtil.F90 | 25 ++++++---------------- base/MAPL_SwathGridFactory.F90 | 9 -------- gridcomps/History/MAPL_HistoryGridComp.F90 | 2 +- griddedio/GriddedIO.F90 | 6 ------ 4 files changed, 8 insertions(+), 34 deletions(-) diff --git a/base/MAPL_ObsUtil.F90 b/base/MAPL_ObsUtil.F90 index deb84bb0e736..1e3a870de861 100644 --- a/base/MAPL_ObsUtil.F90 +++ b/base/MAPL_ObsUtil.F90 @@ -80,7 +80,7 @@ function get_filename_from_template (time, file_template, rc) result(filename) integer :: nymd, nhms integer :: status - stop 'DO not use get_filename_from_template' + _FAIL ('DO not use get_filename_from_template') call ESMF_time_to_two_integer(time, itime, _RC) print*, 'two integer time, itime(:)', itime(1:2) nymd = itime(1) @@ -337,7 +337,10 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & end subroutine read_M_files_4_swath - + ! + !-- caveat: note call this subr. on head node + ! because of (bash ls) command therein + ! function get_filename_from_template_use_index (obsfile_start_time, obsfile_interval, & f_index, file_template, rc) result(filename) use Plain_netCDF_Time, only : ESMF_time_to_two_integer @@ -365,10 +368,6 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter character(len=ESMF_MAXSTR) :: filename2 character(len=ESMF_MAXSTR) :: cmd -! type(ESMF_VM) :: vm -! integer:: mpic -! integer:: irank, ierror - call ESMF_TimeIntervalGet(obsfile_interval, s_r8=dT0_s, rc=status) s = dT0_s * f_index call ESMF_TimeIntervalSet(dT, s_r8=s, rc=status) @@ -378,11 +377,7 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter nymd = itime(1) nhms = itime(2) -! call ESMF_VMGetCurrent(vm, _RC) -! call ESMF_VMGet(vm, mpiCommunicator=mpic, _RC) -! call MPI_COMM_RANK(mpic, irank, ierror) -!! if (irank==0) then j= index(file_template, '*') if (j>0) then ! wild char exist @@ -407,13 +402,7 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter call fill_grads_template ( filename, file_template, & experiment_id='', nymd=nymd, nhms=nhms, _RC ) end if -!! end if - -! call MPI_bcast(filename2, ESMF_MAXSTR, MPI_CHARACTER, 0, mpic, ierror) -! call MPI_Barrier(mpic,ierror) -! filename=filename2 -! write(6,*) 'my irank=', irank -! write(6,*) 'ck MPI filename=', trim(filename) + _RETURN(_SUCCESS) @@ -474,7 +463,6 @@ subroutine get_var_from_name_w_group (var_name, var2d, filename, rc) end subroutine get_var_from_name_w_group - subroutine sort_three_arrays_by_time(U,V,T,rc) use MAPL_SortMod real(ESMF_KIND_R8), intent(inout) :: U(:), V(:), T(:) @@ -511,6 +499,7 @@ subroutine sort_three_arrays_by_time(U,V,T,rc) _RETURN(_SUCCESS) end subroutine sort_three_arrays_by_time + subroutine sort_four_arrays_by_time(U,V,T,ID,rc) use MAPL_SortMod real(ESMF_KIND_R8) :: U(:), V(:), T(:) diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index e1984980d2b2..86acef352853 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -625,7 +625,6 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc j1= j0 + sec jx0= j0 jx1= j1 - !!call lgr%debug ('%a %f8 %f8', 'jx0, jx1', jx0, jx1) call lgr%debug ('%a %i16 %i16', 'j0, j1 ', j0, j1) @@ -666,14 +665,6 @@ subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc call MPI_bcast(this%cell_along_swath, 1, MPI_INTEGER, 0, mpic, ierror) ! donot need to bcast this%along_track (root only) -! if (irank==0) write(6,*) 'af root find_M_files' -! write(6,106) 'my irank, M_file =', irank, this%M_file -! do i=1, this%M_file -! write(6,*) 'my irank=', irank -! write(6,*) 'ck MPI filename=', trim(this%filenames(i)) -! end do -! _FAIL('nail stop') - call ESMF_ConfigGetAttribute(config, tmp, label=prefix//'IMS_FILE:', rc=status) if ( status == _SUCCESS ) then call get_ims_from_file(this%ims, trim(tmp),this%nx, _RC) diff --git a/gridcomps/History/MAPL_HistoryGridComp.F90 b/gridcomps/History/MAPL_HistoryGridComp.F90 index ef00d0c9cef8..ed86c267a622 100644 --- a/gridcomps/History/MAPL_HistoryGridComp.F90 +++ b/gridcomps/History/MAPL_HistoryGridComp.F90 @@ -145,7 +145,7 @@ module MAPL_HistoryGridCompMod public HISTORY_ExchangeListWrap - type(samplerHQ) :: Hsampler ! is 'save' needed here? + type(samplerHQ) :: Hsampler contains diff --git a/griddedio/GriddedIO.F90 b/griddedio/GriddedIO.F90 index b2de934f6228..6284eb93b996 100644 --- a/griddedio/GriddedIO.F90 +++ b/griddedio/GriddedIO.F90 @@ -859,13 +859,8 @@ subroutine stage2DLatLon(this, fileName, oClients, rc) staggerloc=ESMF_STAGGERLOC_CENTER, & farrayPtr=ptr2d, rc=status) _VERIFY(STATUS) - ! this%lons= real(ptr2d*MAPL_RADIANS_TO_DEGREES, kind=ESMF_KIND_R4) this%lons=ptr2d*MAPL_RADIANS_TO_DEGREES - write(6,*) 'ck ref in stage2dLatLon' - write(6,'(8f12.2)') this%lons(::50,::50) - write(6,*) 'I think !-- this is a bug in NAG here' - ref = ArrayReference(this%lons) call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lons', & ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount) @@ -875,7 +870,6 @@ subroutine stage2DLatLon(this, fileName, oClients, rc) farrayPtr=ptr2d, rc=status) _VERIFY(STATUS) if (.not.allocated(this%lats)) allocate(this%lats(size(ptr2d,1),size(ptr2d,2))) - ! this%lats= real(ptr2d*MAPL_RADIANS_TO_DEGREES, kind=ESMF_KIND_R4) this%lats=ptr2d*MAPL_RADIANS_TO_DEGREES ref = ArrayReference(this%lats) call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lats', & From d04b9fee8daa8288a0cd13ff53ea3f5c2910eee9 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Wed, 29 Nov 2023 22:54:57 -0500 Subject: [PATCH 39/41] Fix intel error for use pFlogger --- base/MAPL_ObsUtil.F90 | 3 +-- base/MAPL_SwathGridFactory.F90 | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/base/MAPL_ObsUtil.F90 b/base/MAPL_ObsUtil.F90 index 1e3a870de861..94eb09e1687d 100644 --- a/base/MAPL_ObsUtil.F90 +++ b/base/MAPL_ObsUtil.F90 @@ -6,7 +6,6 @@ module MAPL_ObsUtilMod use Plain_netCDF_Time use netCDF use MAPL_CommsMod, only : MAPL_AM_I_ROOT - use pFlogger, only: logging, Logger, WrapArray use, intrinsic :: iso_fortran_env, only: REAL32, REAL64 implicit none @@ -247,7 +246,7 @@ subroutine read_M_files_4_swath ( filenames, Xdim, Ydim, & index_name_lon, index_name_lat,& var_name_lon, var_name_lat, var_name_time, & lon, lat, time, rc ) - + use pFlogger, only: logging, Logger character(len=ESMF_MAXSTR), intent(in) :: filenames(:) integer, intent(out) :: Xdim integer, intent(out) :: Ydim diff --git a/base/MAPL_SwathGridFactory.F90 b/base/MAPL_SwathGridFactory.F90 index 86acef352853..591c9eb562cc 100644 --- a/base/MAPL_SwathGridFactory.F90 +++ b/base/MAPL_SwathGridFactory.F90 @@ -396,8 +396,6 @@ end subroutine initialize_from_file_metadata subroutine initialize_from_config_with_prefix(this, config, prefix, unusable, rc) - use esmf - use pflogger, only : Logger, logging use MPI implicit none class (SwathGridFactory), intent(inout) :: this From 1259acb070e47f2073de858ba3b0fe5f26aed824 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Thu, 30 Nov 2023 13:31:54 -0500 Subject: [PATCH 40/41] Add corrections --- base/MAPL_ObsUtil.F90 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/base/MAPL_ObsUtil.F90 b/base/MAPL_ObsUtil.F90 index 94eb09e1687d..8a797c94577e 100644 --- a/base/MAPL_ObsUtil.F90 +++ b/base/MAPL_ObsUtil.F90 @@ -358,7 +358,7 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter real(ESMF_KIND_R8) :: s type(ESMF_TimeInterval) :: dT type(ESMF_Time) :: time - integer :: i, j + integer :: i, j, u character(len=ESMF_MAXSTR) :: file_template_left character(len=ESMF_MAXSTR) :: file_template_right @@ -387,15 +387,15 @@ function get_filename_from_template_use_index (obsfile_start_time, obsfile_inter filename= trim(filename_left)//trim(file_template(j:)) cmd="bash -c 'ls "//trim(filename)//"' &> zzz_MAPL" CALL execute_command_line(trim(cmd)) - open(7213, file='zzz_MAPL', status='unknown') - read(7213, '(a)') filename + open(newunit=u, file='zzz_MAPL', status='unknown') + read(u, '(a)') filename i=index(trim(filename), 'ls') if (i==1) then filename='' end if ! cmd="rm -f ./zzz_MAPL" ! CALL execute_command_line(trim(cmd)) - close(7213) + close(u) else ! exact file name call fill_grads_template ( filename, file_template, & @@ -511,8 +511,8 @@ subroutine sort_four_arrays_by_time(U,V,T,ID,rc) real(ESMF_KIND_R8), allocatable :: X(:) integer, allocatable :: NX(:) - _ASSERT (size(U)==size(V), 'U,V different dimension') - _ASSERT (size(U)==size(T), 'U,T different dimension') + _ASSERT(size(U)==size(V), 'U,V different dimension') + _ASSERT(size(U)==size(T), 'U,T different dimension') len = size (T) allocate (IA(len), IX(len), X(len), NX(len)) From 4f21f0ff3ae9627c416e20258475f927b31c6ff2 Mon Sep 17 00:00:00 2001 From: Yonggang Yu Date: Fri, 1 Dec 2023 11:32:20 -0500 Subject: [PATCH 41/41] -m