Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion diag_manager/diag_axis.F90
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,11 @@ INTEGER FUNCTION diag_axis_init(name, DATA, units, cart_name, long_name, directi
ENDIF

if (use_modern_diag) then
!TODO Passing in the axis_length because of a gnu issue where inside fms_diag_axis_init, the size of DATA
!was 2 which was causing the axis_data to not be written correctly...
Comment on lines +141 to +142

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is a bug with a SPECIFIC gnu version, do we need to fix it or can we just say it's not compatible with that version? Is this a C5, CI, or dev box compiler?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version of gnu is what we used in the CI
I can also reproduce in the dev box.

diag_axis_init = fms_diag_object%fms_diag_axis_init(name, DATA, units, cart_name, long_name=long_name,&
& direction=direction, set_name=set_name, edges=edges, Domain=Domain, Domain2=Domain2, DomainU=DomainU, &
& aux=aux, req=req, tile_count=tile_count, domain_position=domain_position )
& aux=aux, req=req, tile_count=tile_count, domain_position=domain_position, axis_length=size(DATA(:)) )

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rem1776 @thomas-robinson FYI i saw this with gnu 9.3. Let me know if you have a better fix for this.

If I were to print the size(DATA(:)) here it gave me the correct answers, but inside fms_diag_axis_init it was equal to 2

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed this, and it sounded good when we discussed it.

return
endif
IF ( PRESENT(tile_count)) THEN
Expand Down
106 changes: 96 additions & 10 deletions diag_manager/fms_diag_axis_object.F90
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ module fms_diag_axis_object_mod
public :: fmsDiagAxis_type, fms_diag_axis_object_init, fms_diag_axis_object_end, &
& get_domain_and_domain_type, diagDomain_t, &
& DIAGDOMAIN2D_T, fmsDiagSubAxis_type, fmsDiagAxisContainer_type, fmsDiagFullAxis_type, DIAGDOMAINUG_T
public :: define_new_axis, define_subaxis
public :: define_new_axis, define_subaxis, parse_compress_att, get_axis_id_from_name

!> @}

Expand Down Expand Up @@ -95,6 +95,9 @@ module fms_diag_axis_object_mod
procedure :: get_subaxes_id
procedure :: write_axis_metadata
procedure :: write_axis_data
procedure :: add_structured_axis_ids
procedure :: get_structured_axis
procedure :: is_unstructured_grid
END TYPE fmsDiagAxis_type

!> @brief Type to hold the subaxis
Expand Down Expand Up @@ -137,6 +140,8 @@ module fms_diag_axis_object_mod
TYPE(fmsDiagAttribute_type),allocatable , private :: attributes(:) !< Array to hold user definable attributes
INTEGER , private :: num_attributes !< Number of defined attibutes
INTEGER , private :: domain_position !< The position in the doman (NORTH, EAST or CENTER)
integer , private :: structured_ids(2) !< If the axis is in the unstructured grid,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are the mappings from unstructured to structured, correct?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are not mappings, they are the axis IDs of the original structured axis

!! this is the axis ids of the structured axis

contains

Expand All @@ -160,7 +165,7 @@ module fms_diag_axis_object_mod
!!!!!!!!!!!!!!!!! DIAG AXIS PROCEDURES !!!!!!!!!!!!!!!!!
!> @brief Initialize the axis
subroutine register_diag_axis_obj(this, axis_name, axis_data, units, cart_name, long_name, direction,&
& set_name, Domain, Domain2, DomainU, aux, req, tile_count, domain_position )
& set_name, Domain, Domain2, DomainU, aux, req, tile_count, domain_position, axis_length )
class(fmsDiagFullAxis_type),INTENT(out) :: this !< Diag_axis obj
CHARACTER(len=*), INTENT(in) :: axis_name !< Name of the axis
class(*), INTENT(in) :: axis_data(:) !< Array of coordinate values
Expand All @@ -177,6 +182,7 @@ subroutine register_diag_axis_obj(this, axis_name, axis_data, units, cart_name,
CHARACTER(len=*), INTENT(in), OPTIONAL :: req !< Required field names.
INTEGER, INTENT(in), OPTIONAL :: tile_count !< Number of tiles
INTEGER, INTENT(in), OPTIONAL :: domain_position !< Domain position, "NORTH" or "EAST"
integer, intent(in), optional :: axis_length !< The length of the axis size(axis_data(:))

this%axis_name = trim(axis_name)
this%units = trim(units)
Expand All @@ -187,12 +193,14 @@ subroutine register_diag_axis_obj(this, axis_name, axis_data, units, cart_name,

select type (axis_data)
type is (real(kind=r8_kind))
allocate(real(kind=r8_kind) :: this%axis_data(size(axis_data)))
allocate(real(kind=r8_kind) :: this%axis_data(axis_length))
this%axis_data = axis_data
this%length = axis_length
Comment thread
uramirez8707 marked this conversation as resolved.
this%type_of_data = "double" !< This is what fms2_io expects in the register_field call
type is (real(kind=r4_kind))
allocate(real(kind=r4_kind) :: this%axis_data(size(axis_data)))
allocate(real(kind=r4_kind) :: this%axis_data(axis_length))
this%axis_data = axis_data
this%length = axis_length

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is optional. What happens if it's not included?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to a required argument fms_diag_axis_init is only used locally here:

diag_axis_init = fms_diag_object%fms_diag_axis_init(name, DATA, units, cart_name, size(DATA(:)), &
& long_name=long_name, direction=direction, set_name=set_name, edges=edges, Domain=Domain, Domain2=Domain2, &
& DomainU=DomainU, aux=aux, req=req, tile_count=tile_count, domain_position=domain_position)

this%type_of_data = "float" !< This is what fms2_io expects in the register_field call
class default
call mpp_error(FATAL, "The axis_data in your diag_axis_init call is not a supported type. &
Expand Down Expand Up @@ -226,8 +234,6 @@ subroutine register_diag_axis_obj(this, axis_name, axis_data, units, cart_name,
if (present(domain_position)) this%domain_position = domain_position
call check_if_valid_domain_position(this%domain_position)

this%length = size(axis_data)

this%direction = 0
if (present(direction)) this%direction = direction
call check_if_valid_direction(this%direction)
Expand All @@ -237,6 +243,7 @@ subroutine register_diag_axis_obj(this, axis_name, axis_data, units, cart_name,

this%nsubaxis = 0
this%num_attributes = 0
this%structured_ids = diag_null

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be allocatable instead of used for every axis? Or should we make a new type that extends the fmsDiagFullAxis_type

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed this to allocatables

end subroutine register_diag_axis_obj

!> @brief Add an attribute to an axis
Expand Down Expand Up @@ -304,13 +311,13 @@ subroutine write_axis_metadata(this, fileobj, parent_axis)
end select
type is (FmsNetcdfUnstructuredDomainFile_t)
select case (diag_axis%type_of_domain)
case (NO_DOMAIN)
!< Here the fileobj is in the unstructured domain, but the axis is not
!< Unstructured domain fileobjs can have axis that are not domain decomposed (i.e "Z" axis)
call register_axis(fileobj, axis_name, axis_length)
case (UG_DOMAIN)
!< Here the axis is in a unstructured domain
call register_axis(fileobj, axis_name)
case default
!< Here the fileobj is in the unstructured domain, but the axis is not
!< Unstructured domain fileobjs can have axis that are not unstructured (i.e "Z" axis)
call register_axis(fileobj, axis_name, axis_length)
end select
end select

Expand Down Expand Up @@ -377,6 +384,43 @@ subroutine write_axis_data(this, fileobj, parent_axis)
end select
end subroutine write_axis_data

!< @brief Determine if the axis is in the unstructured grid
!! @return .True. if the axis is in unstructured grid
pure logical function is_unstructured_grid(this)
class(fmsDiagAxis_type), target, INTENT(in) :: this !< diag_axis obj

is_unstructured_grid = .false.
select type (this)
type is (fmsDiagFullAxis_type)
is_unstructured_grid = trim(this%cart_name) .eq. "U"
end select
end function is_unstructured_grid

!< @brief Adds the structured axis ids to the axis object
subroutine add_structured_axis_ids(this, axis_ids)
class(fmsDiagAxis_type), target, INTENT(inout) :: this !< diag_axis obj
integer, intent(in) :: axis_ids(2) !< axis ids to add to the axis object

select type (this)
type is (fmsDiagFullAxis_type)
this%structured_ids = axis_ids

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this%structured_ids should be allocated here and then set to axis_ids.

end select
end subroutine add_structured_axis_ids

!< @brief Get the structured axis ids from the axis object
!! @return the structured axis ids
pure function get_structured_axis(this) &
result(rslt)
class(fmsDiagAxis_type), target, INTENT(in) :: this !< diag_axis obj
integer :: rslt(2)

rslt = diag_null
select type (this)
type is (fmsDiagFullAxis_type)
rslt = this%structured_ids
end select
end function get_structured_axis

!> @brief Get the starting and ending indices of the global io domain of the axis
subroutine get_global_io_domain(this, global_io_index)
class(fmsDiagFullAxis_type), intent(in) :: this !< diag_axis obj
Expand Down Expand Up @@ -951,6 +995,48 @@ pure function get_subaxes_id(this) &

end function

!< @brief Parses the "compress" attribute to get the names of the two axis
!! @return the names of the structured axis
pure function parse_compress_att(compress_att) &
result(axis_names)
class(*), intent(in) :: compress_att(:) !< The compress attribute to parse
character(len=120) :: axis_names(2)

integer :: ios !< Errorcode after parsting the compress attribute

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should say "after parsing"


select type (compress_att)
type is (character(len=*))
read(compress_att(1),*, iostat=ios) axis_names
if (ios .ne. 0) axis_names = ""
class default
axis_names = ""
end select
end function parse_compress_att

!< @brief Determine the axis id of a axis
!! @return Axis id
pure function get_axis_id_from_name(axis_name, diag_axis, naxis) &
result(axis_id)
class(fmsDiagAxisContainer_type), intent(in) :: diag_axis(:) !< Array of axis object
character(len=*), intent(in) :: axis_name !< Name of the axis
integer, intent(in) :: naxis !< Number of axis that have been registered
integer :: axis_id

integer :: i !< For do loops

axis_id = diag_null
do i = 1, naxis
select type(axis => diag_axis(i)%axis)
type is (fmsDiagFullAxis_type)
if (trim(axis%axis_name) .eq. trim(axis_name)) then
axis_id = i
return
endif
end select
enddo

end function get_axis_id_from_name

#endif
end module fms_diag_axis_object_mod
!> @}
Expand Down
20 changes: 18 additions & 2 deletions diag_manager/fms_diag_file_object.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1077,9 +1077,10 @@ subroutine write_axis_metadata(this, diag_axis)

class(fmsDiagFile_type), pointer :: diag_file !< Diag_file object to open
class(FmsNetcdfFile_t), pointer :: fileobj !< The fileobj to write to
integer :: i !< For do loops
integer :: i,k !< For do loops
integer :: j !< diag_file%axis_ids(i) (for less typing)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

confusing...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switched this to a pointer

axis_ptr => diag_axis(diag_file%axis_ids(i))

integer :: parent_axis_id !< Id of the parent_axis
integer :: structured_ids(2) !< Ids of the uncompress axis

diag_file => this%FMS_diag_file
fileobj => diag_file%fileobj
Expand All @@ -1092,6 +1093,13 @@ subroutine write_axis_metadata(this, diag_axis)
else
call diag_axis(j)%axis%write_axis_metadata(fileobj, diag_axis(parent_axis_id)%axis)
endif

if (diag_axis(j)%axis%is_unstructured_grid()) then
structured_ids = diag_axis(j)%axis%get_structured_axis()
do k = 1, size(structured_ids)
call diag_axis(structured_ids(k))%axis%write_axis_metadata(fileobj)
enddo
endif
enddo

end subroutine write_axis_metadata
Expand All @@ -1103,9 +1111,10 @@ subroutine write_axis_data(this, diag_axis)

class(fmsDiagFile_type), pointer :: diag_file !< Diag_file object to open
class(FmsNetcdfFile_t), pointer :: fileobj !< The fileobj to write to
integer :: i !< For do loops
integer :: i, k !< For do loops
integer :: j !< diag_file%axis_ids(i) (for less typing)
integer :: parent_axis_id !< Id of the parent_axis
integer :: structured_ids(2) !< Ids of the uncompress axis

diag_file => this%FMS_diag_file
fileobj => diag_file%fileobj
Expand All @@ -1118,6 +1127,13 @@ subroutine write_axis_data(this, diag_axis)
else
call diag_axis(j)%axis%write_axis_data(fileobj, diag_axis(parent_axis_id)%axis)
endif

if (diag_axis(j)%axis%is_unstructured_grid()) then
structured_ids = diag_axis(j)%axis%get_structured_axis()
do k = 1, size(structured_ids)
call diag_axis(structured_ids(k))%axis%write_axis_data(fileobj)
enddo
endif
enddo

end subroutine write_axis_data
Expand Down
30 changes: 27 additions & 3 deletions diag_manager/fms_diag_object.F90
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ module fms_diag_object_mod
& get_diag_files_id, diag_yaml
use fms_diag_axis_object_mod, only: fms_diag_axis_object_init, fmsDiagAxis_type, fmsDiagSubAxis_type, &
&diagDomain_t, get_domain_and_domain_type, diagDomain2d_t, &
&fmsDiagAxisContainer_type, fms_diag_axis_object_end, fmsDiagFullAxis_type
&fmsDiagAxisContainer_type, fms_diag_axis_object_end, fmsDiagFullAxis_type, &
&parse_compress_att, get_axis_id_from_name
use fms_diag_buffer_mod
#endif
use mpp_domains_mod, only: domain1d, domain2d, domainUG, null_domain2d
Expand Down Expand Up @@ -368,7 +369,7 @@ end function fms_register_static_field
!! interface the same
!> @return Axis id
FUNCTION fms_diag_axis_init(this, axis_name, axis_data, units, cart_name, long_name, direction,&
& set_name, edges, Domain, Domain2, DomainU, aux, req, tile_count, domain_position ) &
& set_name, edges, Domain, Domain2, DomainU, aux, req, tile_count, domain_position, axis_length ) &
& result(id)

class(fmsDiagObject_type),TARGET,INTENT(inout):: this !< Diaj_obj to fill
Expand All @@ -388,6 +389,7 @@ FUNCTION fms_diag_axis_init(this, axis_name, axis_data, units, cart_name, long_n
CHARACTER(len=*), INTENT(in), OPTIONAL :: req !< Required field names.
INTEGER, INTENT(in), OPTIONAL :: tile_count !< Number of tiles
INTEGER, INTENT(in), OPTIONAL :: domain_position !< Domain position, "NORTH" or "EAST"
integer, intent(in), OPTIONAL :: axis_length !< The length of the axis size(axis_data(:))
integer :: id

#ifndef use_yaml
Expand Down Expand Up @@ -417,7 +419,7 @@ FUNCTION fms_diag_axis_init(this, axis_name, axis_data, units, cart_name, long_n
endif
call axis%register(axis_name, axis_data, units, cart_name, long_name=long_name, &
& direction=direction, set_name=set_name, Domain=Domain, Domain2=Domain2, DomainU=DomainU, aux=aux, &
& req=req, tile_count=tile_count, domain_position=domain_position)
& req=req, tile_count=tile_count, domain_position=domain_position, axis_length=axis_length)

id = this%registered_axis
call axis%set_axis_id(id)
Expand Down Expand Up @@ -493,6 +495,9 @@ subroutine fms_diag_axis_add_attribute(this, axis_id, att_name, att_value)
character(len=*), intent(in) :: att_name !< Name of the attribute
class(*), intent(in) :: att_value(:) !< The attribute value to add

character(len=20) :: axis_names(2) !< Names of the uncompress axis
integer :: uncmx_ids(2) !< Ids of the uncompress axis
integer :: j !< For do loops
#ifndef use_yaml
CALL MPP_ERROR(FATAL,"You can not use the modern diag manager without compiling with -Duse_yaml")
#else
Expand All @@ -502,6 +507,25 @@ subroutine fms_diag_axis_add_attribute(this, axis_id, att_name, att_value)
select type (axis => this%diag_axis(axis_id)%axis)
type is (fmsDiagFullAxis_type)
call axis%add_axis_attribute(att_name, att_value)

!! Axis that are in the "unstructured" domain require a "compress" attribute for the
!! combiner and PP. This attribute is passed in via a diag_axis_add_attribute call in the model code
!! The compress attribute indicates the names of the axis that were compressed
!! For example grid_index:compress = "grid_yt grid_xt"
!! The metadata and the data for these axis also needs to be written to the file
if (trim(att_name) .eq. "compress") then
!< If the attribute is the "compress" attribute, get the axis names,
!! and the ids of the axis and add it to the axis object so it can be written to netcdf files
!! that use this axis
axis_names = parse_compress_att(att_value)
do j = 1, size(axis_names)
uncmx_ids(j) = get_axis_id_from_name(axis_names(j), this%diag_axis, this%registered_axis)
if (uncmx_ids(j) .eq. diag_null) call mpp_error(FATAL, &
&"Error parsing the compress attribute for axis: "//trim(axis%get_axis_name())//&
&". Be sure that the axes in the compress attribute are registered")
enddo
call axis%add_structured_axis_ids(uncmx_ids)
endif
end select
#endif
end subroutine fms_diag_axis_add_attribute
Expand Down
3 changes: 2 additions & 1 deletion test_fms/diag_manager/test_modern_diag.F90
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,12 @@ program test_modern_diag
set_name="land", DomainU=land_domain, aux="geolon_t geolat_t")

id_z = diag_axis_init('z', z, 'point_Z', 'z', long_name='point_Z')
!TODO call diag_axis_add_attribute (id_z, 'formula', 'p(n,k,j,i) = ap(k) + b(k)*ps(n,j,i)')
call diag_axis_add_attribute (id_z, 'formula', 'p(n,k,j,i) = ap(k) + b(k)*ps(n,j,i)')
call diag_axis_add_attribute (id_z, 'integer', 10)
call diag_axis_add_attribute (id_z, '1d integer', (/10, 10/))
call diag_axis_add_attribute (id_z, 'real', 10.)
call diag_axis_add_attribute (id_x, '1d real', (/10./))
call diag_axis_add_attribute (id_ug, 'compress', 'x y')

if (id_x .ne. 1) call mpp_error(FATAL, "The x axis does not have the expected id")
if (id_y .ne. 2) call mpp_error(FATAL, "The y axis does not have the expected id")
Expand Down