From cf60fdb73003ec6ca0f842207e595c3b13e9c3a2 Mon Sep 17 00:00:00 2001 From: Weiyuan Jiang Date: Wed, 13 Nov 2024 15:07:54 -0500 Subject: [PATCH 01/21] check tableEnd efficiently --- CHANGELOG.md | 1 + gridcomps/Cap/MAPL_CapGridComp.F90 | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e9ee90c14f0..dd4571e4279e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- refactored tableEnd check - Added commandline options to `checkpoint_benchmark.x` and `restart_benchmark.x` to allow for easier testing of different configurations. Note that the old configuration file style of input is allowed via the `--config_file` option (which overrides any other command line options) - Update ESMF version for Baselibs to match that of Spack for consistency - Update `components.yaml` diff --git a/gridcomps/Cap/MAPL_CapGridComp.F90 b/gridcomps/Cap/MAPL_CapGridComp.F90 index 2ee0e4dca2fd..5b26d34718b5 100644 --- a/gridcomps/Cap/MAPL_CapGridComp.F90 +++ b/gridcomps/Cap/MAPL_CapGridComp.F90 @@ -979,12 +979,11 @@ function get_vec_from_config(config, key, rc) result(vec) cap_import = "" if (present) then - - do while(trim(cap_import) /= "::") + do while( .true.) call ESMF_ConfigNextLine(config, tableEnd=tableEnd, _RC) if (tableEnd) exit call ESMF_ConfigGetAttribute(config, cap_import, _RC) - if (trim(cap_import) /= "::") call vec%push_back(trim(cap_import)) + call vec%push_back(trim(cap_import)) end do end if _RETURN(_SUCCESS) From 25c8a5c6bda8e0790cfce175b082804d8a905f6b Mon Sep 17 00:00:00 2001 From: Weiyuan Jiang Date: Wed, 13 Nov 2024 15:32:51 -0500 Subject: [PATCH 02/21] Added return to fetch_data --- CHANGELOG.md | 1 + pfio/AbstractDataReference.F90 | 2 +- pfio/ServerThread.F90 | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e9ee90c14f0..aefa93e3faa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added macro _RETURN(_SUCCESS) to fetch_data - Allow update offsets of ±timestep in ExtData2G - Minor revision (and generalization) of grid-def for GSI purposes - Trajectory sampler: fix a bug when group_name does not exist in netCDF file and a bug that omitted the first time point diff --git a/pfio/AbstractDataReference.F90 b/pfio/AbstractDataReference.F90 index 8c4a06d89597..6ec0b0f235e3 100644 --- a/pfio/AbstractDataReference.F90 +++ b/pfio/AbstractDataReference.F90 @@ -319,7 +319,7 @@ subroutine fetch_data(this,offset_address,global_shape,offset_start, rc) case default _FAIL("dimension not supported yet") end select - + _RETURN(_SUCCESS) end subroutine fetch_data integer function get_length_base(this) result(length) diff --git a/pfio/ServerThread.F90 b/pfio/ServerThread.F90 index bf2d61cd52bf..99874f729d69 100644 --- a/pfio/ServerThread.F90 +++ b/pfio/ServerThread.F90 @@ -1154,7 +1154,7 @@ subroutine get_DataFromMem( this, multi_data_read, rc) offset_address = c_loc(i_ptr(offset+1)) - call mem_data_reference%fetch_data(offset_address,q%global_count,q%start-q%global_start+1) + call mem_data_reference%fetch_data(offset_address,q%global_count,q%start-q%global_start+1, _RC) call this%insert_RequestHandle(q%request_id, & & connection%put(q%request_id, mem_data_reference)) From 84c6832a5117a1f342f41270825762c486110e91 Mon Sep 17 00:00:00 2001 From: Weiyuan Jiang Date: Thu, 14 Nov 2024 09:34:33 -0500 Subject: [PATCH 03/21] rename cap_import to more generic name --- gridcomps/Cap/MAPL_CapGridComp.F90 | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/gridcomps/Cap/MAPL_CapGridComp.F90 b/gridcomps/Cap/MAPL_CapGridComp.F90 index 5b26d34718b5..a8bf1f967b62 100644 --- a/gridcomps/Cap/MAPL_CapGridComp.F90 +++ b/gridcomps/Cap/MAPL_CapGridComp.F90 @@ -967,23 +967,22 @@ end function get_CapGridComp_from_gc function get_vec_from_config(config, key, rc) result(vec) + type(StringVector) :: vec type(ESMF_Config), intent(inout) :: config character(len=*), intent(in) :: key integer, intent(out), optional :: rc logical :: present, tableEnd integer :: status - character(len=ESMF_MAXSTR) :: cap_import - type(StringVector) :: vec + character(len=ESMF_MAXSTR) :: value call ESMF_ConfigFindLabel(config, key//":", isPresent = present, _RC) - cap_import = "" if (present) then - do while( .true.) + do while(.true.) call ESMF_ConfigNextLine(config, tableEnd=tableEnd, _RC) if (tableEnd) exit - call ESMF_ConfigGetAttribute(config, cap_import, _RC) - call vec%push_back(trim(cap_import)) + call ESMF_ConfigGetAttribute(config, value, _RC) + call vec%push_back(trim(value)) end do end if _RETURN(_SUCCESS) From ce10328e6f9986c08ba4451b3480f84f712909cd Mon Sep 17 00:00:00 2001 From: Tom Clune Date: Thu, 14 Nov 2024 10:55:23 -0500 Subject: [PATCH 04/21] Update gridcomps/Cap/MAPL_CapGridComp.F90 --- gridcomps/Cap/MAPL_CapGridComp.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gridcomps/Cap/MAPL_CapGridComp.F90 b/gridcomps/Cap/MAPL_CapGridComp.F90 index a8bf1f967b62..a868c8bd3914 100644 --- a/gridcomps/Cap/MAPL_CapGridComp.F90 +++ b/gridcomps/Cap/MAPL_CapGridComp.F90 @@ -978,7 +978,7 @@ function get_vec_from_config(config, key, rc) result(vec) call ESMF_ConfigFindLabel(config, key//":", isPresent = present, _RC) if (present) then - do while(.true.) + do call ESMF_ConfigNextLine(config, tableEnd=tableEnd, _RC) if (tableEnd) exit call ESMF_ConfigGetAttribute(config, value, _RC) From 87695c350c009923ada53e8fb55e72ab6a464750 Mon Sep 17 00:00:00 2001 From: Benjamin Auer Date: Thu, 21 Nov 2024 15:03:18 -0500 Subject: [PATCH 05/21] updates --- base/MAPL_LatLonGridFactory.F90 | 99 +++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 12 deletions(-) diff --git a/base/MAPL_LatLonGridFactory.F90 b/base/MAPL_LatLonGridFactory.F90 index fbbbfe3a41e7..0e2f59db9a32 100644 --- a/base/MAPL_LatLonGridFactory.F90 +++ b/base/MAPL_LatLonGridFactory.F90 @@ -218,10 +218,16 @@ function create_basic_grid(this, unusable, rc) result(grid) integer, optional, intent(out) :: rc integer :: status + type(ESMF_PoleKind_Flag) :: polekindflag(2) _UNUSED_DUMMY(unusable) if (this%periodic) then + if (this%pole == "XY") then + polekindflag = ESMF_POLEKIND_NONE + else + polekindflag = ESMF_POLEKIND_BIPOLE + end if grid = ESMF_GridCreate1PeriDim( & & name = this%grid_name, & & countsPerDEDim1=this%ims, & @@ -232,6 +238,7 @@ function create_basic_grid(this, unusable, rc) result(grid) & coordDep1=[1,2], & & coordDep2=[1,2], & & coordSys=ESMF_COORDSYS_SPH_RAD, & + & polekindflag=polekindflag, & & rc=status) _VERIFY(status) else @@ -673,7 +680,7 @@ subroutine initialize_from_file_metadata(this, file_metadata, unusable, force_fi 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 + logical :: is_valid, use_file_coords, compute_lons, compute_lats, has_bnds _UNUSED_DUMMY(unusable) @@ -759,6 +766,10 @@ subroutine initialize_from_file_metadata(this, file_metadata, unusable, force_fi where(this%lon_centers > 180) this%lon_centers=this%lon_centers-360 end if + has_bnds = coordinate_has_bounds(file_metadata, lon_name, _RC) + if (has_bnds) then + this%lon_corners = get_coordinate_bounds(file_metadata, lon_name, _RC) + end if v => file_metadata%get_coordinate_variable(lat_name, rc=status) _VERIFY(status) @@ -773,6 +784,11 @@ subroutine initialize_from_file_metadata(this, file_metadata, unusable, force_fi _FAIL('unsupported type of data; must be REAL32 or REAL64') end select + has_bnds = coordinate_has_bounds(file_metadata, lat_name, _RC) + if (has_bnds) then + this%lat_corners = get_coordinate_bounds(file_metadata, lat_name, _RC) + end if + ! Check: is this a "mis-specified" pole-centered grid? if (size(this%lat_centers) >= 4) then @@ -804,14 +820,14 @@ subroutine initialize_from_file_metadata(this, file_metadata, unusable, force_fi end if end if - ! Corners are the midpoints of centers (and extrapolated at the ! poles for lats.) - allocate(this%lon_corners(im+1), this%lat_corners(jm+1)) - - this%lon_corners(1) = (this%lon_centers(im) + this%lon_centers(1))/2 - 180 - this%lon_corners(2:im) = (this%lon_centers(1:im-1) + this%lon_centers(2:im))/2 - this%lon_corners(im+1) = (this%lon_centers(im) + this%lon_centers(1))/2 + 180 + if (.not. allocated(this%lon_corners)) then + allocate(this%lon_corners(im+1)) + this%lon_corners(1) = (this%lon_centers(im) + this%lon_centers(1))/2 - 180 + this%lon_corners(2:im) = (this%lon_centers(1:im-1) + this%lon_centers(2:im))/2 + this%lon_corners(im+1) = (this%lon_centers(im) + this%lon_centers(1))/2 + 180 + end if ! This section about pole/dateline is probably not needed in file data case. if (abs(this%lon_centers(1) + 180) < 1000*epsilon(1.0)) then @@ -826,10 +842,13 @@ subroutine initialize_from_file_metadata(this, file_metadata, unusable, force_fi this%dateline = 'XY' this%lon_range = RealMinMax(this%lon_centers(1), this%lon_centers(jm)) end if - - this%lat_corners(1) = this%lat_centers(1) - (this%lat_centers(2)-this%lat_centers(1))/2 - this%lat_corners(2:jm) = (this%lat_centers(1:jm-1) + this%lat_centers(2:jm))/2 - this%lat_corners(jm+1) = this%lat_centers(jm) - (this%lat_centers(jm-1)-this%lat_centers(jm))/2 + + if (.not. allocated(this%lat_corners)) then + allocate(this%lat_corners(jm+1)) + this%lat_corners(1) = this%lat_centers(1) - (this%lat_centers(2)-this%lat_centers(1))/2 + this%lat_corners(2:jm) = (this%lat_centers(1:jm-1) + this%lat_centers(2:jm))/2 + this%lat_corners(jm+1) = this%lat_centers(jm) - (this%lat_centers(jm-1)-this%lat_centers(jm))/2 + end if if (abs(this%lat_centers(1) + 90) < 1000*epsilon(1.0)) then this%pole = 'PC' @@ -1139,7 +1158,6 @@ subroutine check_and_fill_consistency(this, unusable, rc) ! Check regional vs global if (this%pole == 'XY') then ! regional - this%periodic = .false. _ASSERT(this%lat_range%min /= MAPL_UNDEFINED_REAL, 'uninitialized min for lat_range') _ASSERT(this%lat_range%max /= MAPL_UNDEFINED_REAL, 'uninitialized min for lat_range') else ! global @@ -1928,5 +1946,62 @@ function generate_file_reference3D(this,fpointer,metaData) result(ref) _UNUSED_DUMMY(metaData) end function generate_file_reference3D + function coordinate_has_bounds(metadata, coord_name, rc) result(has_bounds) + logical :: has_bounds + type(FileMetadata), intent(in) :: metadata + character(len=*), intent(in) :: coord_name + integer, optional, intent(out) :: rc + + type(Variable), pointer :: var + integer :: status + + var => metadata%get_variable(coord_name, _RC) + has_bounds = var%is_attribute_present("bounds") + + _RETURN(_SUCCESS) + end function + + function get_coordinate_bounds(metadata, coord_name, rc) result(coord_bounds) + real(kind=REAL64), allocatable :: coord_bounds(:) + type(FileMetadata), intent(in) :: metadata + character(len=*), intent(in) :: coord_name + integer, optional, intent(out) :: rc + + type(Variable), pointer :: var + type(Attribute), pointer :: attr + integer :: status, im, i + class(*), pointer :: attr_val + character(len=:), allocatable :: bnds_name, source_file + real(kind=REAL64), allocatable :: file_bounds(:,:) + type(NetCDF4_FileFormatter) :: file_formatter + + + var => metadata%get_variable(coord_name, _RC) + attr => var%get_attribute("bounds", _RC) + attr_val => attr%get_value() + select type(attr_val) + type is(character(*)) + bnds_name = attr_val + class default + _FAIL('coordinate bounds must be a string') + end select + im = metadata%get_dimension(coord_name, _RC) + allocate(coord_bounds(im+1), _STAT) + allocate(file_bounds(im,2), _STAT) + source_file = metadata%get_source_file() + + call file_formatter%open(source_file, PFIO_READ, _RC) + call file_formatter%get_var(coord_name, file_bounds, _RC) + call file_formatter%close(_RC) + do i=1,im-1 + _ASSERT(file_bounds(i,2)==file_bounds(i+1,1), "Bounds are not contiguous in file") + enddo + do i=1,im + coord_bounds(i) = file_bounds(i,1) + coord_bounds(i+1) = file_bounds(i,2) + enddo + + _RETURN(_SUCCESS) + end function end module MAPL_LatLonGridFactoryMod From 9153589986bc53a1fafb4f91b6e4406cb777783f Mon Sep 17 00:00:00 2001 From: Benjamin Auer Date: Fri, 22 Nov 2024 10:36:23 -0500 Subject: [PATCH 06/21] more updates --- base/MAPL_LatLonGridFactory.F90 | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/base/MAPL_LatLonGridFactory.F90 b/base/MAPL_LatLonGridFactory.F90 index 0e2f59db9a32..260ebc6afd87 100644 --- a/base/MAPL_LatLonGridFactory.F90 +++ b/base/MAPL_LatLonGridFactory.F90 @@ -851,10 +851,13 @@ subroutine initialize_from_file_metadata(this, file_metadata, unusable, force_fi end if if (abs(this%lat_centers(1) + 90) < 1000*epsilon(1.0)) then + write(*,*)'bmaa here 1' this%pole = 'PC' else if (abs(this%lat_corners(1) + 90) < 1000*epsilon(1.0)) then + write(*,*)'bmaa here 2' this%pole = 'PE' else ! assume XY + write(*,*)'bmaa here 3' this%pole = 'XY' this%lat_range = RealMinMax(this%lat_centers(1), this%lat_centers(jm)) end if @@ -1987,18 +1990,18 @@ function get_coordinate_bounds(metadata, coord_name, rc) result(coord_bounds) end select im = metadata%get_dimension(coord_name, _RC) allocate(coord_bounds(im+1), _STAT) - allocate(file_bounds(im,2), _STAT) + allocate(file_bounds(2,im), _STAT) source_file = metadata%get_source_file() - + call file_formatter%open(source_file, PFIO_READ, _RC) - call file_formatter%get_var(coord_name, file_bounds, _RC) + call file_formatter%get_var(bnds_name, file_bounds, _RC) call file_formatter%close(_RC) do i=1,im-1 - _ASSERT(file_bounds(i,2)==file_bounds(i+1,1), "Bounds are not contiguous in file") + _ASSERT(file_bounds(2,i)==file_bounds(1,i+1), "Bounds are not contiguous in file") enddo do i=1,im - coord_bounds(i) = file_bounds(i,1) - coord_bounds(i+1) = file_bounds(i,2) + coord_bounds(i) = file_bounds(1,i) + coord_bounds(i+1) = file_bounds(2,i) enddo _RETURN(_SUCCESS) From ded9a8f8811c7995a4bad6d9e7c59e4fd8c2c105 Mon Sep 17 00:00:00 2001 From: Benjamin Auer Date: Fri, 22 Nov 2024 16:34:53 -0500 Subject: [PATCH 07/21] more updates --- base/MAPL_LatLonGridFactory.F90 | 42 +++++++++++++++++++++++++++++---- griddedio/FieldBundleRead.F90 | 2 +- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/base/MAPL_LatLonGridFactory.F90 b/base/MAPL_LatLonGridFactory.F90 index 260ebc6afd87..7d7adf040f67 100644 --- a/base/MAPL_LatLonGridFactory.F90 +++ b/base/MAPL_LatLonGridFactory.F90 @@ -56,6 +56,8 @@ module MAPL_LatLonGridFactoryMod integer :: px, py logical :: is_halo_initialized = .false. logical :: periodic = .true. + character(len=:), allocatable :: lon_bounds_name + character(len=:), allocatable :: lat_bounds_name contains procedure :: make_new_grid procedure :: create_basic_grid @@ -226,7 +228,7 @@ function create_basic_grid(this, unusable, rc) result(grid) if (this%pole == "XY") then polekindflag = ESMF_POLEKIND_NONE else - polekindflag = ESMF_POLEKIND_BIPOLE + polekindflag = ESMF_POLEKIND_MONOPOLE end if grid = ESMF_GridCreate1PeriDim( & & name = this%grid_name, & @@ -768,6 +770,7 @@ subroutine initialize_from_file_metadata(this, file_metadata, unusable, force_fi has_bnds = coordinate_has_bounds(file_metadata, lon_name, _RC) if (has_bnds) then + this%lon_bounds_name = get_coordinate_bounds_name(file_metadata, lon_name, _RC) this%lon_corners = get_coordinate_bounds(file_metadata, lon_name, _RC) end if @@ -786,6 +789,7 @@ subroutine initialize_from_file_metadata(this, file_metadata, unusable, force_fi has_bnds = coordinate_has_bounds(file_metadata, lat_name, _RC) if (has_bnds) then + this%lat_bounds_name = get_coordinate_bounds_name(file_metadata, lat_name, _RC) this%lat_corners = get_coordinate_bounds(file_metadata, lat_name, _RC) end if @@ -851,13 +855,10 @@ subroutine initialize_from_file_metadata(this, file_metadata, unusable, force_fi end if if (abs(this%lat_centers(1) + 90) < 1000*epsilon(1.0)) then - write(*,*)'bmaa here 1' this%pole = 'PC' else if (abs(this%lat_corners(1) + 90) < 1000*epsilon(1.0)) then - write(*,*)'bmaa here 2' this%pole = 'PE' else ! assume XY - write(*,*)'bmaa here 3' this%pole = 'XY' this%lat_range = RealMinMax(this%lat_centers(1), this%lat_centers(jm)) end if @@ -1872,7 +1873,15 @@ function get_file_format_vars(this) result(vars) character(len=:), allocatable :: vars _UNUSED_DUMMY(this) - vars = 'lon,lat' + if (allocated(this%lon_bounds_name) .and. allocated(this%lat_bounds_name)) then + vars = 'lon,lat,'//this%lon_bounds_name//','//this%lat_bounds_name + else if (allocated(this%lon_bounds_name) .and. (.not. allocated(this%lat_bounds_name))) then + vars = 'lon,lat,'//this%lon_bounds_name + else if (allocated(this%lat_bounds_name) .and. (.not. allocated(this%lon_bounds_name))) then + vars = 'lon,lat,'//this%lat_bounds_name + else if ((.not.allocated(this%lat_bounds_name)) .and. (.not. allocated(this%lon_bounds_name))) then + vars = 'lon,lat' + end if end function get_file_format_vars @@ -1964,6 +1973,29 @@ function coordinate_has_bounds(metadata, coord_name, rc) result(has_bounds) _RETURN(_SUCCESS) end function + function get_coordinate_bounds_name(metadata, coord_name, rc) result(coord_bounds_name) + character(len=:), allocatable :: coord_bounds_name + type(FileMetadata), intent(in) :: metadata + character(len=*), intent(in) :: coord_name + integer, optional, intent(out) :: rc + + type(Variable), pointer :: var + type(Attribute), pointer :: attr + integer :: status + class(*), pointer :: attr_val + + var => metadata%get_variable(coord_name, _RC) + attr => var%get_attribute("bounds", _RC) + attr_val => attr%get_value() + select type(attr_val) + type is(character(*)) + coord_bounds_name = attr_val + class default + _FAIL('coordinate bounds must be a string') + end select + _RETURN(_SUCCESS) + end function + function get_coordinate_bounds(metadata, coord_name, rc) result(coord_bounds) real(kind=REAL64), allocatable :: coord_bounds(:) type(FileMetadata), intent(in) :: metadata diff --git a/griddedio/FieldBundleRead.F90 b/griddedio/FieldBundleRead.F90 index 6f0bd2b09c65..b8da3d92e091 100644 --- a/griddedio/FieldBundleRead.F90 +++ b/griddedio/FieldBundleRead.F90 @@ -71,7 +71,7 @@ subroutine MAPL_create_bundle_from_metdata_id(bundle,metadata_id,file_name,only_ factory => get_factory(file_grid,rc=status) _VERIFY(status) grid_vars = factory%get_file_format_vars() - exclude_vars = grid_vars//",lev,time,lons,lats" + exclude_vars = grid_vars//",lev,time,lons,lats,time_bnds" if (has_vertical_level) lev_size = metadata%get_dimension(trim(lev_name)) variables => metadata%get_variables() From 935a4b8ed847f42a4d6e7664bd42b9ee9ee0ec9e Mon Sep 17 00:00:00 2001 From: Benjamin Auer Date: Fri, 22 Nov 2024 16:37:25 -0500 Subject: [PATCH 08/21] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd4571e4279e..a3599eb08549 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow update offsets of ±timestep in ExtData2G - Minor revision (and generalization) of grid-def for GSI purposes - Trajectory sampler: fix a bug when group_name does not exist in netCDF file and a bug that omitted the first time point +- Allow lat-lon grid factory to detect and use CF compliant lat-lon bounds in a file when making a grid ### Changed @@ -39,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fixed issue of some Baselibs builds appearing to support zstandard. This is not possible due to Baselibs building HDF5 and netCDF as static libraries +- Fixed a bug where the periodicity around the earth of the lat-lon grid was not being set properly when grid did not span from pole to pole ### Removed From 8ce9c6a8757594f1d480f62ac7b91c8c1509d5cd Mon Sep 17 00:00:00 2001 From: Benjamin Auer Date: Mon, 25 Nov 2024 13:35:45 -0500 Subject: [PATCH 09/21] comments --- griddedio/FieldBundleRead.F90 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/griddedio/FieldBundleRead.F90 b/griddedio/FieldBundleRead.F90 index b8da3d92e091..a16ab0597285 100644 --- a/griddedio/FieldBundleRead.F90 +++ b/griddedio/FieldBundleRead.F90 @@ -91,6 +91,15 @@ subroutine MAPL_create_bundle_from_metdata_id(bundle,metadata_id,file_name,only_ enddo end if + write(*,*)'bmaa exclude ',','//trim(exclude_vars)//',' + write(*,*)'bmaa var_name ',trim(var_name) + write(*,*)'bmaa index(exclude_var,var_name) ',index(','//trim(exclude_vars)//',',','//trim(var_name)//',') + write(*,*)'bmaa hardcode string index comma vs no ',index(',lon,lat,lon_bnds,lat_bnds,lev,time,lons,lats,time_bnds,',",lat_bnds,"),index(',lon,lat,lon_bnds,lat_bnds,lev,time,lons,lats,time_bnds,',"lat_bnds") + write(*,*)'bmaa allocatable string index comma vs no ',index(exclude_vars,",lat_bnds,"),index(exclude_vars,"lat_bnds") + write(*,*)'bmaa allocatable string index comma vs no ',index(exclude_vars,",time_bnds,"),index(exclude_vars,"time_bnds") + write(*,*)'bmaa allocatable string index comma vs no ',index(exclude_vars,",time,"),index(exclude_vars,"time") + write(*,*)'bmaa allocatable string index comma vs no ',index(exclude_vars,",lat,"),index(exclude_vars,"lat") + if (index(','//trim(exclude_vars)//',',','//trim(var_name)//',') > 0) then call var_iter%next() cycle @@ -137,6 +146,7 @@ subroutine MAPL_create_bundle_from_metdata_id(bundle,metadata_id,file_name,only_ _VERIFY(status) call ESMF_AttributeSet(field,name='VLOCATION',value=location,rc=status) _VERIFY(status) + write(*,*)"bmaa getting units for ",trim(var_name) units = metadata%get_var_attr_string(var_name,'units',_RC) long_name = metadata%get_var_attr_string(var_name,'long_name',_RC) call ESMF_AttributeSet(field,name='UNITS',value=units,rc=status) From f05d7af7c8a82e81ad7c2c9f2ba0c9fd5a20fe21 Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Wed, 27 Nov 2024 10:37:13 -0500 Subject: [PATCH 10/21] CI changes for GEOSadas --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c9c0f7861d39..01fe02b99c2b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -176,7 +176,8 @@ workflows: fixture_branch: feature/mathomp4/mapldevelop checkout_mapl_branch: true mepodevelop: false - rebuild_procs: 1 + rebuild_procs: 4 + build_type: Release build-and-publish-docker: when: From 5cb22db77b5b467b8385912053d4cbc7b70b8806 Mon Sep 17 00:00:00 2001 From: Benjamin Auer Date: Mon, 2 Dec 2024 13:29:33 -0500 Subject: [PATCH 11/21] fixes #3201 --- CHANGELOG.md | 2 ++ pfio/NetCDF4_FileFormatter.F90 | 3 +++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3669b343278b..cdc1a7c5c2bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fixed bug where c null character is not removed from end of string when reading netcdf attribute in NetCDF4\_FileFormatter.F90 + ### Removed ### Deprecated diff --git a/pfio/NetCDF4_FileFormatter.F90 b/pfio/NetCDF4_FileFormatter.F90 index 1527d8eb5524..d40824c93d00 100644 --- a/pfio/NetCDF4_FileFormatter.F90 +++ b/pfio/NetCDF4_FileFormatter.F90 @@ -20,6 +20,7 @@ module pFIO_NetCDF4_FileFormatterMod use pfio_NetCDF_Supplement use netcdf use mpi + use, intrinsic :: iso_c_binding, only: C_NULL_CHAR implicit none private @@ -992,6 +993,7 @@ subroutine inq_attributes(this, cf, varid, unusable, rc) status = nf90_get_att(this%ncid, varid, trim(attr_name), str) !$omp end critical _VERIFY(status) + if (str(len:len) == C_NULL_CHAR) str = str(1:len-1) call cf%add_attribute(trim(attr_name), str) deallocate(str) case (NF90_STRING) @@ -1088,6 +1090,7 @@ subroutine inq_var_attributes(this, var, varid, unusable, rc) status = nf90_get_att(this%ncid, varid, trim(attr_name), str) !$omp end critical _VERIFY(status) + if (str(len:len) == C_NULL_CHAR) str = str(1:len-1) call var%add_attribute(trim(attr_name), str) deallocate(str) case (NF90_STRING) From 89e5348f2ed679cec79c6ad8b9cc4c48667eb6ac Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Mon, 2 Dec 2024 13:46:50 -0500 Subject: [PATCH 12/21] Update for f2py-meson support --- CHANGELOG.md | 9 +++++++-- CMakeLists.txt | 2 +- components.yaml | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd4571e4279e..4c1be6318f47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- refactored tableEnd check +- Change minimum CMake version to 3.24 + - This is needed for f2py and meson support +- Refactored tableEnd check - Added commandline options to `checkpoint_benchmark.x` and `restart_benchmark.x` to allow for easier testing of different configurations. Note that the old configuration file style of input is allowed via the `--config_file` option (which overrides any other command line options) - Update ESMF version for Baselibs to match that of Spack for consistency - Update `components.yaml` @@ -28,9 +30,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - GSL 2.8 - jpeg 9f - Various build fixes - - ESMA_cmake v3.52.0 + - ESMA_cmake v3.55.0 - Fixes for using MAPL as a library in spack builds of GEOSgcm - Various backports from v4 + - Code for capturing `mepo status` output + - Fixes for f2py and meson (NOTE: Requires CMake minimum version of 3.24 in project for complete functionality) + - Fixes for `MPI_STACK` code run multiple times - Updates to CI - Use v7.27.0 Baselibs - Use GCC 14 for GNU tests diff --git a/CMakeLists.txt b/CMakeLists.txt index 8dc1502bdf3c..2970acee7162 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 3.23) +cmake_minimum_required (VERSION 3.24) get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(NOT is_multi_config AND NOT (CMAKE_BUILD_TYPE OR DEFINED ENV{CMAKE_BUILD_TYPE})) diff --git a/components.yaml b/components.yaml index 271f302b4f9d..3d65a1df9aa4 100644 --- a/components.yaml +++ b/components.yaml @@ -5,13 +5,13 @@ MAPL: ESMA_env: local: ./ESMA_env remote: ../ESMA_env.git - tag: v4.31.0 + tag: v4.32.0 develop: main ESMA_cmake: local: ./ESMA_cmake remote: ../ESMA_cmake.git - tag: v3.52.0 + tag: v3.55.0 develop: develop ecbuild: From a2cedd19ec8c7bf452360387ec102b6b1a9b6ab6 Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Mon, 2 Dec 2024 14:57:33 -0500 Subject: [PATCH 13/21] Update changelog and version for 2.50.3 release --- .circleci/config.yml | 2 +- .github/workflows/workflow.yml | 4 ++-- CHANGELOG.md | 8 ++++++-- CMakeLists.txt | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0de92fb286bb..6050daafddf1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,7 +16,7 @@ parameters: # Anchors to prevent forgetting to update a version os_version: &os_version ubuntu20 -baselibs_version: &baselibs_version v7.25.0 +baselibs_version: &baselibs_version v7.27.0 bcs_version: &bcs_version v11.6.0 tag_build_arg_name: &tag_build_arg_name maplversion diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index d6c9d61fbf4d..967d7aa53f0b 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -35,7 +35,7 @@ jobs: name: Build and Test MAPL GNU runs-on: ubuntu-latest container: - image: gmao/ubuntu20-geos-env-mkl:v7.25.0-openmpi_5.0.2-gcc_13.2.0 + image: gmao/ubuntu20-geos-env-mkl:v7.27.0-openmpi_5.0.5-gcc_14.2.0 # Per https://github.com/actions/virtual-environments/issues/1445#issuecomment-713861495 # It seems like we might not need secrets on GitHub Actions which is good for forked # pull requests @@ -86,7 +86,7 @@ jobs: name: Build and Test MAPL Intel runs-on: ubuntu-latest container: - image: gmao/ubuntu20-geos-env:v7.25.0-intelmpi_2021.13-ifort_2021.13 + image: gmao/ubuntu20-geos-env:v7.27.0-intelmpi_2021.13-ifort_2021.13 # Per https://github.com/actions/virtual-environments/issues/1445#issuecomment-713861495 # It seems like we might not need secrets on GitHub Actions which is good for forked # pull requests diff --git a/CHANGELOG.md b/CHANGELOG.md index cdc1a7c5c2bd..16bea1129ed9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,12 +13,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Fixed bug where c null character is not removed from end of string when reading netcdf attribute in NetCDF4\_FileFormatter.F90 - ### Removed ### Deprecated +## [2.50.3] - 2024-12-02 + +### Fixed + +- Fixed bug where c null character is not removed from end of string when reading netcdf attribute in NetCDF4\_FileFormatter.F90 + ## [2.50.2] - 2024-10-30 ### Fixed diff --git a/CMakeLists.txt b/CMakeLists.txt index c8c6ebf7a5bc..e39c76bf75cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ endif () project ( MAPL - VERSION 2.50.2 + VERSION 2.50.3 LANGUAGES Fortran CXX C) # Note - CXX is required for ESMF # Set the possible values of build type for cmake-gui From fbe9af872cbeae2045c4d331da3913c34f7773b2 Mon Sep 17 00:00:00 2001 From: Benjamin Auer Date: Mon, 2 Dec 2024 15:41:24 -0500 Subject: [PATCH 14/21] protect against 0 length string --- pfio/NetCDF4_FileFormatter.F90 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pfio/NetCDF4_FileFormatter.F90 b/pfio/NetCDF4_FileFormatter.F90 index d40824c93d00..ca06cf590a1c 100644 --- a/pfio/NetCDF4_FileFormatter.F90 +++ b/pfio/NetCDF4_FileFormatter.F90 @@ -993,7 +993,9 @@ subroutine inq_attributes(this, cf, varid, unusable, rc) status = nf90_get_att(this%ncid, varid, trim(attr_name), str) !$omp end critical _VERIFY(status) - if (str(len:len) == C_NULL_CHAR) str = str(1:len-1) + if (len > 0) then + if (str(len:len) == C_NULL_CHAR) str = str(1:len-1) + end if call cf%add_attribute(trim(attr_name), str) deallocate(str) case (NF90_STRING) @@ -1090,7 +1092,9 @@ subroutine inq_var_attributes(this, var, varid, unusable, rc) status = nf90_get_att(this%ncid, varid, trim(attr_name), str) !$omp end critical _VERIFY(status) - if (str(len:len) == C_NULL_CHAR) str = str(1:len-1) + if (len > 0) then + if (str(len:len) == C_NULL_CHAR) str = str(1:len-1) + end if call var%add_attribute(trim(attr_name), str) deallocate(str) case (NF90_STRING) From 398c9b325c2cf51a2339abdb16ccc1cb794ac268 Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Tue, 3 Dec 2024 07:55:56 -0500 Subject: [PATCH 15/21] Backport ADAS CI Fix --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6050daafddf1..de9f64bfa511 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -161,7 +161,8 @@ workflows: fixture_branch: feature/mathomp4/mapldevelop checkout_mapl_branch: true mepodevelop: false - rebuild_procs: 1 + rebuild_procs: 4 + build_type: Release build-and-publish-docker: when: From d9b2fbfea166f7e2260fcf8532726ccf39b0727b Mon Sep 17 00:00:00 2001 From: Benjamin Auer Date: Tue, 3 Dec 2024 09:56:23 -0500 Subject: [PATCH 16/21] fixes #3210 --- base/FileMetadataUtilities.F90 | 79 +++----------------- pfio/Variable.F90 | 133 +++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 68 deletions(-) diff --git a/base/FileMetadataUtilities.F90 b/base/FileMetadataUtilities.F90 index ea8c858f7ccb..b42ff3ba8de1 100644 --- a/base/FileMetadataUtilities.F90 +++ b/base/FileMetadataUtilities.F90 @@ -116,30 +116,15 @@ function get_var_attr_real32(this,var_name,attr_name,rc) result(attr_real32) character(len=*), intent(in) :: attr_name integer, optional, intent(out) :: rc - real(REAL32) :: tmp(1) - real(REAL64) :: tmpd(1) integer :: status character(:), allocatable :: fname - type(Attribute), pointer :: attr type(Variable), pointer :: var - class(*), pointer :: attr_val(:) fname = this%get_file_name(_RC) var => this%get_variable(var_name,_RC) _ASSERT(associated(var),"no variable named "//var_name//" in "//fname) - attr => var%get_attribute(attr_name,_RC) - _ASSERT(associated(attr),"no attribute named "//attr_name//" in "//var_name//" in "//fname) - attr_val => attr%get_values() - select type(attr_val) - type is(real(kind=REAL32)) - tmp = attr_val - attr_real32 = tmp(1) - type is(real(kind=REAL64)) - tmpd = attr_val - attr_real32 = REAL(tmpd(1)) - class default - _FAIL('unsupported subclass (not real32) for units of attribute named '//attr_name//' in '//var_name//' in '//fname) - end select + attr_real32 = var%get_attribute_real32(attr_name, rc=status) + _ASSERT(status /= _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) _RETURN(_SUCCESS) end function get_var_attr_real32 @@ -151,28 +136,17 @@ function get_var_attr_real64(this,var_name,attr_name,rc) result(attr_real64) character(len=*), intent(in) :: attr_name integer, optional, intent(out) :: rc - real(REAL64) :: tmp(1) integer :: status character(:), allocatable :: fname - type(Attribute), pointer :: attr type(Variable), pointer :: var - class(*), pointer :: attr_val(:) fname = this%get_file_name(_RC) var => this%get_variable(var_name,_RC) _ASSERT(associated(var),"no variable named "//var_name//" in "//fname) - attr => var%get_attribute(attr_name,_RC) - _ASSERT(associated(attr),"no attribute named "//attr_name//" in "//var_name//" in "//fname) - attr_val => attr%get_values() - select type(attr_val) - type is(real(kind=REAL64)) - tmp = attr_val - attr_real64 = tmp(1) - class default - _FAIL('unsupported subclass (not real64) for units of attribute named '//attr_name//' in '//var_name//' in '//fname) - end select - + attr_real64 = var%get_attribute_real64(attr_name, rc=status) + _ASSERT(status /= _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) _RETURN(_SUCCESS) + end function get_var_attr_real64 function get_var_attr_int32(this,var_name,attr_name,rc) result(attr_int32) @@ -182,26 +156,15 @@ function get_var_attr_int32(this,var_name,attr_name,rc) result(attr_int32) character(len=*), intent(in) :: attr_name integer, optional, intent(out) :: rc - integer(INT32) :: tmp(1) integer :: status character(:), allocatable :: fname - type(Attribute), pointer :: attr type(Variable), pointer :: var - class(*), pointer :: attr_val(:) fname = this%get_file_name(_RC) var => this%get_variable(var_name,_RC) _ASSERT(associated(var),"no variable named "//var_name//" in "//fname) - attr => var%get_attribute(attr_name,_RC) - _ASSERT(associated(attr),"no attribute named "//attr_name//" in "//var_name//" in "//fname) - attr_val => attr%get_values() - select type(attr_val) - type is(integer(kind=INT32)) - tmp = attr_val - attr_int32 = tmp(1) - class default - _FAIL('unsupported subclass (not int32) for units of attribute named '//attr_name//' in '//var_name//' in '//fname) - end select + attr_int32 = var%get_attribute_int32(attr_name, rc=status) + _ASSERT(status /= _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) _RETURN(_SUCCESS) end function get_var_attr_int32 @@ -213,26 +176,15 @@ function get_var_attr_int64(this,var_name,attr_name,rc) result(attr_int64) character(len=*), intent(in) :: attr_name integer, optional, intent(out) :: rc - integer(INT64) :: tmp(1) integer :: status character(:), allocatable :: fname - type(Attribute), pointer :: attr type(Variable), pointer :: var - class(*), pointer :: attr_val(:) fname = this%get_file_name(_RC) var => this%get_variable(var_name,_RC) _ASSERT(associated(var),"no variable named "//var_name//" in "//fname) - attr => var%get_attribute(attr_name,_RC) - _ASSERT(associated(attr),"no attribute named "//attr_name//" in "//var_name//" in "//fname) - attr_val => attr%get_values() - select type(attr_val) - type is(integer(kind=INT64)) - tmp = attr_val - attr_int64 = tmp(1) - class default - _FAIL('unsupported subclass (not int64) for units of attribute named '//attr_name//' in '//var_name//' in '//fname) - end select + attr_int64 = var%get_attribute_int64(attr_name, rc=status) + _ASSERT(status /= _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) _RETURN(_SUCCESS) end function get_var_attr_int64 @@ -246,22 +198,13 @@ function get_var_attr_string(this,var_name,attr_name,rc) result(attr_string) integer :: status character(:), allocatable :: fname - type(Attribute), pointer :: attr type(Variable), pointer :: var - class(*), pointer :: attr_val fname = this%get_file_name(_RC) var => this%get_variable(var_name,_RC) _ASSERT(associated(var),"no variable named "//var_name//" in "//fname) - attr => var%get_attribute(attr_name,_RC) - _ASSERT(associated(attr),"no attribute named "//attr_name//" in "//var_name//" in "//fname) - attr_val => attr%get_value() - select type(attr_val) - type is(character(*)) - attr_string = attr_val - class default - _FAIL('unsupported subclass (not string) for units of attribute named '//attr_name//' in '//var_name//' in '//fname) - end select + attr_string = var%get_attribute_string(attr_name, rc=status) + _ASSERT(status /= _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) _RETURN(_SUCCESS) end function get_var_attr_string diff --git a/pfio/Variable.F90 b/pfio/Variable.F90 index 84958a172945..001e22a92968 100644 --- a/pfio/Variable.F90 +++ b/pfio/Variable.F90 @@ -12,6 +12,7 @@ module pFIO_VariableMod use pFIO_AttributeMod use pFIO_StringAttributeMapMod use pFIO_StringAttributeMapUtilMod + use, intrinsic :: iso_fortran_env, only: REAL32, REAL64, INT32, INT64 implicit none private @@ -40,6 +41,11 @@ module pFIO_VariableMod procedure :: get_const_value procedure :: get_attribute + procedure :: get_attribute_string + procedure :: get_attribute_int32 + procedure :: get_attribute_int64 + procedure :: get_attribute_real32 + procedure :: get_attribute_real64 generic :: add_attribute => add_attribute_0d generic :: add_attribute => add_attribute_1d procedure :: add_attribute_0d @@ -258,6 +264,133 @@ function get_attribute(this, attr_name, rc) result(attr) _RETURN(_SUCCESS) end function get_attribute + function get_attribute_string(this, attr_name, rc) result(attr_string) + character(len=:), allocatable :: attr_string + class (Variable), target, intent(in) :: this + character(len=*), intent(in) :: attr_name + integer, optional, intent(out) :: rc + + integer :: status + type(Attribute), pointer :: attr + class(*), pointer :: attr_val + + attr => this%get_attribute(attr_name,_RC) + _ASSERT(associated(attr),"no such attribute "//attr_name) + attr_val => attr%get_value() + select type(attr_val) + type is(character(*)) + attr_string = attr_val + class default + _FAIL('unsupported subclass (not string) of attribute named '//attr_name) + end select + + _RETURN(_SUCCESS) + end function get_attribute_string + + function get_attribute_real32(this,attr_name,rc) result(attr_real32) + real(REAL32) :: attr_real32 + class(Variable), intent(inout) :: this + character(len=*), intent(in) :: attr_name + integer, optional, intent(out) :: rc + + real(REAL32) :: tmp(1) + real(REAL64) :: tmpd(1) + integer :: status + type(Attribute), pointer :: attr + class(*), pointer :: attr_val(:) + + attr => this%get_attribute(attr_name,_RC) + _ASSERT(associated(attr),"no attribute named "//attr_name) + attr_val => attr%get_values() + select type(attr_val) + type is(real(kind=REAL32)) + tmp = attr_val + attr_real32 = tmp(1) + type is(real(kind=REAL64)) + tmpd = attr_val + attr_real32 = REAL(tmpd(1)) + class default + _FAIL('unsupported subclass (not real32) for units of attribute named '//attr_name) + end select + + _RETURN(_SUCCESS) + end function get_attribute_real32 + + function get_attribute_real64(this,attr_name,rc) result(attr_real64) + real(REAL64) :: attr_real64 + class(Variable), intent(inout) :: this + character(len=*), intent(in) :: attr_name + integer, optional, intent(out) :: rc + + real(REAL64) :: tmp(1) + integer :: status + type(Attribute), pointer :: attr + class(*), pointer :: attr_val(:) + + attr => this%get_attribute(attr_name,_RC) + _ASSERT(associated(attr),"no such attribute "//attr_name) + attr_val => attr%get_values() + select type(attr_val) + type is(real(kind=REAL64)) + tmp = attr_val + attr_real64 = tmp(1) + class default + _FAIL('unsupported subclass (not real64) for units of attribute named '//attr_name) + end select + + _RETURN(_SUCCESS) + end function get_attribute_real64 + + function get_attribute_int32(this,attr_name,rc) result(attr_int32) + integer(INT32) :: attr_int32 + class(Variable), intent(inout) :: this + character(len=*), intent(in) :: attr_name + integer, optional, intent(out) :: rc + + integer(INT32) :: tmp(1) + integer :: status + type(Attribute), pointer :: attr + class(*), pointer :: attr_val(:) + + attr => this%get_attribute(attr_name,_RC) + _ASSERT(associated(attr),"no attribute named "//attr_name) + attr_val => attr%get_values() + select type(attr_val) + type is(integer(kind=INT32)) + tmp = attr_val + attr_int32 = tmp(1) + class default + _FAIL('unsupported subclass (not int32) for units of attribute named '//attr_name) + end select + + _RETURN(_SUCCESS) + end function get_attribute_int32 + + function get_attribute_int64(this,attr_name,rc) result(attr_int64) + integer(INT64) :: attr_int64 + class(Variable), intent(inout) :: this + character(len=*), intent(in) :: attr_name + integer, optional, intent(out) :: rc + + integer(INT64) :: tmp(1) + integer :: status + type(Attribute), pointer :: attr + class(*), pointer :: attr_val(:) + + attr => this%get_attribute(attr_name,_RC) + _ASSERT(associated(attr),"no attribute named "//attr_name) + attr_val => attr%get_values() + select type(attr_val) + type is(integer(kind=INT64)) + tmp = attr_val + attr_int64 = tmp(1) + class default + _FAIL('unsupported subclass (not int64) for units of attribute named '//attr_name) + end select + + _RETURN(_SUCCESS) + end function get_attribute_int64 + subroutine add_const_value(this, const_value, rc) class (Variable), target, intent(inout) :: this type (UnlimitedEntity), intent(in) :: const_value From daab7d73ad0b5ad26eb1887eaa7672355ae1d4f5 Mon Sep 17 00:00:00 2001 From: Benjamin Auer Date: Tue, 3 Dec 2024 11:18:51 -0500 Subject: [PATCH 17/21] oops --- base/FileMetadataUtilities.F90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/base/FileMetadataUtilities.F90 b/base/FileMetadataUtilities.F90 index b42ff3ba8de1..133037ce3c4a 100644 --- a/base/FileMetadataUtilities.F90 +++ b/base/FileMetadataUtilities.F90 @@ -124,7 +124,7 @@ function get_var_attr_real32(this,var_name,attr_name,rc) result(attr_real32) var => this%get_variable(var_name,_RC) _ASSERT(associated(var),"no variable named "//var_name//" in "//fname) attr_real32 = var%get_attribute_real32(attr_name, rc=status) - _ASSERT(status /= _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) + _ASSERT(status == _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) _RETURN(_SUCCESS) end function get_var_attr_real32 @@ -144,7 +144,7 @@ function get_var_attr_real64(this,var_name,attr_name,rc) result(attr_real64) var => this%get_variable(var_name,_RC) _ASSERT(associated(var),"no variable named "//var_name//" in "//fname) attr_real64 = var%get_attribute_real64(attr_name, rc=status) - _ASSERT(status /= _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) + _ASSERT(status == _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) _RETURN(_SUCCESS) end function get_var_attr_real64 @@ -164,7 +164,7 @@ function get_var_attr_int32(this,var_name,attr_name,rc) result(attr_int32) var => this%get_variable(var_name,_RC) _ASSERT(associated(var),"no variable named "//var_name//" in "//fname) attr_int32 = var%get_attribute_int32(attr_name, rc=status) - _ASSERT(status /= _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) + _ASSERT(status == _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) _RETURN(_SUCCESS) end function get_var_attr_int32 @@ -184,7 +184,7 @@ function get_var_attr_int64(this,var_name,attr_name,rc) result(attr_int64) var => this%get_variable(var_name,_RC) _ASSERT(associated(var),"no variable named "//var_name//" in "//fname) attr_int64 = var%get_attribute_int64(attr_name, rc=status) - _ASSERT(status /= _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) + _ASSERT(status == _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) _RETURN(_SUCCESS) end function get_var_attr_int64 @@ -204,7 +204,7 @@ function get_var_attr_string(this,var_name,attr_name,rc) result(attr_string) var => this%get_variable(var_name,_RC) _ASSERT(associated(var),"no variable named "//var_name//" in "//fname) attr_string = var%get_attribute_string(attr_name, rc=status) - _ASSERT(status /= _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) + _ASSERT(status == _SUCCESS, 'failed to get attribute named '//attr_name//' in '//var_name//' in '//fname) _RETURN(_SUCCESS) end function get_var_attr_string From 5ad02a1936d525e787b89f72b56a2bf172c157e5 Mon Sep 17 00:00:00 2001 From: Benjamin Auer Date: Tue, 3 Dec 2024 11:50:46 -0500 Subject: [PATCH 18/21] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c1be6318f47..0a0293c1ee8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow update offsets of ±timestep in ExtData2G - Minor revision (and generalization) of grid-def for GSI purposes - Trajectory sampler: fix a bug when group_name does not exist in netCDF file and a bug that omitted the first time point +- PFIO/Variable class, new procedures to retrieve string/reals/int attributes from a variable ### Changed From d1b0f0d5c7086836929ac9a59a39e21f6c56575d Mon Sep 17 00:00:00 2001 From: Benjamin Auer Date: Tue, 3 Dec 2024 12:16:48 -0500 Subject: [PATCH 19/21] more updates --- base/MAPL_LatLonGridFactory.F90 | 1 + griddedio/FieldBundleRead.F90 | 33 ++++++++++++--------------------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/base/MAPL_LatLonGridFactory.F90 b/base/MAPL_LatLonGridFactory.F90 index 7d7adf040f67..8d4de3ada406 100644 --- a/base/MAPL_LatLonGridFactory.F90 +++ b/base/MAPL_LatLonGridFactory.F90 @@ -1871,6 +1871,7 @@ function get_file_format_vars(this) result(vars) class (LatLonGridFactory), intent(inout) :: this character(len=:), allocatable :: vars + integer :: i _UNUSED_DUMMY(this) if (allocated(this%lon_bounds_name) .and. allocated(this%lat_bounds_name)) then diff --git a/griddedio/FieldBundleRead.F90 b/griddedio/FieldBundleRead.F90 index a16ab0597285..352dd414c330 100644 --- a/griddedio/FieldBundleRead.F90 +++ b/griddedio/FieldBundleRead.F90 @@ -48,8 +48,8 @@ subroutine MAPL_create_bundle_from_metdata_id(bundle,metadata_id,file_name,only_ type(StringVariableMap), pointer :: variables type(Variable), pointer :: this_variable type(StringVariableMapIterator) :: var_iter - character(len=:), pointer :: var_name,dim_name - character(len=:), allocatable :: lev_name + character(len=:), pointer :: var_name_ptr,dim_name + character(len=:), allocatable :: lev_name,var_name type(ESMF_Field) :: field type (StringVector), pointer :: dimensions type (StringVectorIterator) :: dim_iter @@ -71,14 +71,15 @@ subroutine MAPL_create_bundle_from_metdata_id(bundle,metadata_id,file_name,only_ factory => get_factory(file_grid,rc=status) _VERIFY(status) grid_vars = factory%get_file_format_vars() - exclude_vars = grid_vars//",lev,time,lons,lats,time_bnds" + exclude_vars = ","//grid_vars//",lev,time,time_bnds," if (has_vertical_level) lev_size = metadata%get_dimension(trim(lev_name)) variables => metadata%get_variables() var_iter = variables%begin() do while (var_iter /= variables%end()) var_has_levels = .false. - var_name => var_iter%key() + var_name_ptr => var_iter%key() + var_name = ","//var_name_ptr//"," this_variable => var_iter%value() if (has_vertical_level) then @@ -91,29 +92,20 @@ subroutine MAPL_create_bundle_from_metdata_id(bundle,metadata_id,file_name,only_ enddo end if - write(*,*)'bmaa exclude ',','//trim(exclude_vars)//',' - write(*,*)'bmaa var_name ',trim(var_name) - write(*,*)'bmaa index(exclude_var,var_name) ',index(','//trim(exclude_vars)//',',','//trim(var_name)//',') - write(*,*)'bmaa hardcode string index comma vs no ',index(',lon,lat,lon_bnds,lat_bnds,lev,time,lons,lats,time_bnds,',",lat_bnds,"),index(',lon,lat,lon_bnds,lat_bnds,lev,time,lons,lats,time_bnds,',"lat_bnds") - write(*,*)'bmaa allocatable string index comma vs no ',index(exclude_vars,",lat_bnds,"),index(exclude_vars,"lat_bnds") - write(*,*)'bmaa allocatable string index comma vs no ',index(exclude_vars,",time_bnds,"),index(exclude_vars,"time_bnds") - write(*,*)'bmaa allocatable string index comma vs no ',index(exclude_vars,",time,"),index(exclude_vars,"time") - write(*,*)'bmaa allocatable string index comma vs no ',index(exclude_vars,",lat,"),index(exclude_vars,"lat") - - if (index(','//trim(exclude_vars)//',',','//trim(var_name)//',') > 0) then + if (index(trim(exclude_vars),trim(var_name)) > 0) then call var_iter%next() cycle end if create_variable = .true. if (present(only_vars)) then - if (index(','//trim(only_vars)//',',','//trim(var_name)//',') < 1) create_variable = .false. + if (index(','//trim(only_vars)//',',trim(var_name)) < 1) create_variable = .false. end if if (create_variable) then if(var_has_levels) then if (grid_size(3) == lev_size) then location=MAPL_VLocationCenter dims = MAPL_DimsHorzVert - field= ESMF_FieldCreate(grid,name=trim(var_name),typekind=ESMF_TYPEKIND_R4, & + field= ESMF_FieldCreate(grid,name=trim(var_name_ptr),typekind=ESMF_TYPEKIND_R4, & ungriddedUbound=[grid_size(3)],ungriddedLBound=[1], rc=status) block real, pointer :: ptr3d(:,:,:) @@ -123,7 +115,7 @@ subroutine MAPL_create_bundle_from_metdata_id(bundle,metadata_id,file_name,only_ else if (grid_size(3)+1 == lev_size) then location=MAPL_VLocationEdge dims = MAPL_DimsHorzVert - field= ESMF_FieldCreate(grid,name=trim(var_name),typekind=ESMF_TYPEKIND_R4, & + field= ESMF_FieldCreate(grid,name=trim(var_name_ptr),typekind=ESMF_TYPEKIND_R4, & ungriddedUbound=[grid_size(3)],ungriddedLBound=[0], rc=status) block real, pointer :: ptr3d(:,:,:) @@ -134,7 +126,7 @@ subroutine MAPL_create_bundle_from_metdata_id(bundle,metadata_id,file_name,only_ else location=MAPL_VLocationNone dims = MAPL_DimsHorzOnly - field= ESMF_FieldCreate(grid,name=trim(var_name),typekind=ESMF_TYPEKIND_R4, & + field= ESMF_FieldCreate(grid,name=trim(var_name_ptr),typekind=ESMF_TYPEKIND_R4, & rc=status) block real, pointer :: ptr2d(:,:) @@ -146,9 +138,8 @@ subroutine MAPL_create_bundle_from_metdata_id(bundle,metadata_id,file_name,only_ _VERIFY(status) call ESMF_AttributeSet(field,name='VLOCATION',value=location,rc=status) _VERIFY(status) - write(*,*)"bmaa getting units for ",trim(var_name) - units = metadata%get_var_attr_string(var_name,'units',_RC) - long_name = metadata%get_var_attr_string(var_name,'long_name',_RC) + units = metadata%get_var_attr_string(var_name_ptr,'units',_RC) + long_name = metadata%get_var_attr_string(var_name_ptr,'long_name',_RC) call ESMF_AttributeSet(field,name='UNITS',value=units,rc=status) _VERIFY(status) call ESMF_AttributeSet(field,name='LONG_NAME',value=long_name,rc=status) From 9de255babbb24fbe6d59582f1aee1408e34e82f6 Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Tue, 3 Dec 2024 14:36:43 -0500 Subject: [PATCH 20/21] Fix up CI image code --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 01fe02b99c2b..8b900ee522ae 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -229,8 +229,8 @@ workflows: baselibs_version: *baselibs_version container_name: mapl mpi_name: openmpi - mpi_version: 5.0.2 + mpi_version: 5.0.5 compiler_name: gcc - compiler_version: 13.2.0 + compiler_version: 14.2.0 image_name: geos-env-mkl tag_build_arg_name: *tag_build_arg_name From 9a2fee5d61489747b7799d0a8f07282d2b531034 Mon Sep 17 00:00:00 2001 From: Tom Clune Date: Wed, 4 Dec 2024 16:01:19 -0500 Subject: [PATCH 21/21] Update base/MAPL_LatLonGridFactory.F90 --- base/MAPL_LatLonGridFactory.F90 | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/base/MAPL_LatLonGridFactory.F90 b/base/MAPL_LatLonGridFactory.F90 index 8d4de3ada406..b7d076e5a2a3 100644 --- a/base/MAPL_LatLonGridFactory.F90 +++ b/base/MAPL_LatLonGridFactory.F90 @@ -1874,14 +1874,12 @@ function get_file_format_vars(this) result(vars) integer :: i _UNUSED_DUMMY(this) - if (allocated(this%lon_bounds_name) .and. allocated(this%lat_bounds_name)) then - vars = 'lon,lat,'//this%lon_bounds_name//','//this%lat_bounds_name - else if (allocated(this%lon_bounds_name) .and. (.not. allocated(this%lat_bounds_name))) then - vars = 'lon,lat,'//this%lon_bounds_name - else if (allocated(this%lat_bounds_name) .and. (.not. allocated(this%lon_bounds_name))) then - vars = 'lon,lat,'//this%lat_bounds_name - else if ((.not.allocated(this%lat_bounds_name)) .and. (.not. allocated(this%lon_bounds_name))) then - vars = 'lon,lat' + vars = 'lon,lat' + if (allocated(this%lon_bounds_name)) then + vars = vars // ',' // this%lon_bounds_name + end if + if (allocated(this%lat_bounds_name)) then + vars = vars // ',' // this%lat_bounds_name end if end function get_file_format_vars