Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable PIO to Add Attributes to Existing NetCDF Files #1234

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Changes from all 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
187 changes: 142 additions & 45 deletions src/framework/mpas_io.F
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ module mpas_io

#ifdef MPAS_PIO_SUPPORT
integer, private :: io_global_err = PIO_noerr
interface put_att_pio
module procedure put_att_0d_generic_pio
module procedure put_att_1d_generic_pio
end interface put_att_pio
#endif
#ifdef MPAS_SMIOL_SUPPORT
integer, private :: io_global_err = SMIOL_SUCCESS
Expand Down Expand Up @@ -5033,6 +5037,131 @@ subroutine MPAS_io_get_att_real1d(handle, attName, attValue, fieldname, precisio

end subroutine MPAS_io_get_att_real1d

#ifdef MPAS_PIO_SUPPORT

function handle_put_att_pio_redef(handle) result (pio_ierr)
amstokely marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is _put_att_ in these function names? They don't do anything with attributes.

implicit none
type(MPAS_IO_Handle_type), intent(inout) :: handle
integer :: pio_ierr

pio_ierr = PIO_redef(handle % pio_file)
if (pio_ierr /= PIO_noerr) then
io_global_err = pio_ierr
return
amstokely marked this conversation as resolved.
Show resolved Hide resolved
end if

end function handle_put_att_pio_redef

function handle_put_att_pio_enddef(handle) result (pio_ierr)
implicit none
type(MPAS_IO_Handle_type), intent(inout) :: handle
integer :: pio_ierr

pio_ierr = PIO_enddef(handle % pio_file)
if (pio_ierr /= PIO_noerr) then
io_global_err = pio_ierr
return
amstokely marked this conversation as resolved.
Show resolved Hide resolved
end if

end function handle_put_att_pio_enddef

function put_att_0d_generic_pio(handle, varid, attName, attValue, ierr) result(pio_ierr)
implicit none
type(MPAS_IO_Handle_type), intent(inout) :: handle
integer, intent(in) :: varid
character(len=*), intent(in) :: attName
class(*), intent(in) :: attValue
integer, optional :: ierr
integer :: pio_ierr

select type(attValue)
type is (integer)
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
type is (real(kind=R4KIND))
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
type is (real(kind=R8KIND))
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
type is (character(len=*))
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
end select

if (pio_ierr /= PIO_noerr) then
io_global_err = pio_ierr
if (present(ierr)) ierr = MPAS_IO_ERR_BACKEND

if (handle % preexisting_file .and. .not. handle % data_mode) then
if (handle_put_att_pio_redef(handle) /= PIO_noerr) return
amstokely marked this conversation as resolved.
Show resolved Hide resolved

select type(attValue)
type is (integer)
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
type is (real(kind=R4KIND))
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
type is (real(kind=R8KIND))
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
type is (character(len=*))
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
end select

if (pio_ierr /= PIO_noerr) then
io_global_err = pio_ierr
return
end if

if (handle_put_att_pio_enddef(handle) /= PIO_noerr) return

if (present(ierr)) ierr = MPAS_IO_NOERR
end if
return
amstokely marked this conversation as resolved.
Show resolved Hide resolved
end if
end function put_att_0d_generic_pio

function put_att_1d_generic_pio(handle, varid, attName, attValue, ierr) result(pio_ierr)
implicit none
type(MPAS_IO_Handle_type), intent(inout) :: handle
integer, intent(in) :: varid
character(len=*), intent(in) :: attName
class(*), dimension(:), intent(in) :: attValue
integer, optional :: ierr
integer :: pio_ierr

select type(attValue)
type is (integer)
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
type is (real(kind=R4KIND))
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
type is (real(kind=R8KIND))
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
end select

if (pio_ierr /= PIO_noerr) then
io_global_err = pio_ierr
if (present(ierr)) ierr = MPAS_IO_ERR_BACKEND

if (handle % preexisting_file .and. .not. handle % data_mode) then
if (handle_put_att_pio_redef(handle) /= PIO_noerr) return
select type(attValue)
type is (integer)
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
type is (real(kind=R4KIND))
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
type is (real(kind=R8KIND))
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValue)
end select

if (pio_ierr /= PIO_noerr) then
io_global_err = pio_ierr
return
end if

if (handle_put_att_pio_enddef(handle) /= PIO_noerr) return
if (present(ierr)) ierr = MPAS_IO_NOERR
end if
return
Copy link
Contributor

Choose a reason for hiding this comment

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

We could remove this return statement.

end if
end function put_att_1d_generic_pio
#endif


subroutine MPAS_io_get_att_text(handle, attName, attValue, fieldname, ierr)

Expand Down Expand Up @@ -5338,7 +5467,7 @@ subroutine MPAS_io_put_att_int0d(handle, attName, attValue, fieldname, syncVal,
end if

#ifdef MPAS_PIO_SUPPORT
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValueLocal)
pio_ierr = put_att_pio(handle, varid, attName, attValueLocal, ierr=ierr)
if (pio_ierr /= PIO_noerr) then
io_global_err = pio_ierr
if (present(ierr)) ierr = MPAS_IO_ERR_BACKEND
Expand Down Expand Up @@ -5523,7 +5652,7 @@ subroutine MPAS_io_put_att_int1d(handle, attName, attValue, fieldname, syncVal,
end if

#ifdef MPAS_PIO_SUPPORT
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValueLocal)
pio_ierr = put_att_pio(handle, varid, attName, attValueLocal, ierr=ierr)
if (pio_ierr /= PIO_noerr) then
io_global_err = pio_ierr
if (present(ierr)) ierr = MPAS_IO_ERR_BACKEND
Expand Down Expand Up @@ -5689,7 +5818,7 @@ subroutine MPAS_io_put_att_real0d(handle, attName, attValue, fieldname, syncVal,
(MPAS_IO_NATIVE_PRECISION /= MPAS_IO_SINGLE_PRECISION)) then
singleVal = real(attValueLocal,R4KIND)
#ifdef MPAS_PIO_SUPPORT
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, singleVal)
pio_ierr = put_att_pio(handle, varid, attName, singleVal, ierr=ierr)
#endif

#ifdef MPAS_SMIOL_SUPPORT
Expand All @@ -5703,7 +5832,7 @@ subroutine MPAS_io_put_att_real0d(handle, attName, attValue, fieldname, syncVal,
(MPAS_IO_NATIVE_PRECISION /= MPAS_IO_DOUBLE_PRECISION)) then
doubleVal = real(attValueLocal,R8KIND)
#ifdef MPAS_PIO_SUPPORT
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, doubleVal)
pio_ierr = put_att_pio(handle, varid, attName, doubleVal, ierr=ierr)
#endif

#ifdef MPAS_SMIOL_SUPPORT
Expand All @@ -5715,7 +5844,7 @@ subroutine MPAS_io_put_att_real0d(handle, attName, attValue, fieldname, syncVal,
#endif
else
#ifdef MPAS_PIO_SUPPORT
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValueLocal)
pio_ierr = put_att_pio(handle, varid, attName, attValueLocal, ierr=ierr)
#endif

#ifdef MPAS_SMIOL_SUPPORT
Expand All @@ -5734,6 +5863,7 @@ subroutine MPAS_io_put_att_real0d(handle, attName, attValue, fieldname, syncVal,
return
end if
#endif

#ifdef MPAS_SMIOL_SUPPORT
if (local_ierr /= SMIOL_SUCCESS) then
call mpas_log_write('SMIOLf_define_att failed with error $i', intArgs=[local_ierr], messageType=MPAS_LOG_ERR)
Expand Down Expand Up @@ -5919,20 +6049,20 @@ subroutine MPAS_io_put_att_real1d(handle, attName, attValue, fieldname, syncVal,
allocate(singleVal(size(attValueLocal)))
singleVal(:) = real(attValueLocal(:),R4KIND)
#ifdef MPAS_PIO_SUPPORT
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, singleVal)
pio_ierr = put_att_pio(handle, varid, attName, singleVal, ierr=ierr)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think there may be another space of indentation that's needed here to align with other code.

#endif
deallocate(singleVal)
else if ((new_attlist_node % attHandle % precision == MPAS_IO_DOUBLE_PRECISION) .and. &
(MPAS_IO_NATIVE_PRECISION /= MPAS_IO_DOUBLE_PRECISION)) then
allocate(doubleVal(size(attValueLocal)))
doubleVal(:) = real(attValueLocal(:),R8KIND)
#ifdef MPAS_PIO_SUPPORT
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, doubleVal)
pio_ierr = put_att_pio(handle, varid, attName, doubleVal, ierr=ierr)
#endif
deallocate(doubleVal)
else
#ifdef MPAS_PIO_SUPPORT
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, attValueLocal)
pio_ierr = put_att_pio(handle, varid, attName, attValueLocal, ierr=ierr)
#endif
end if
#ifdef MPAS_PIO_SUPPORT
Expand All @@ -5950,6 +6080,9 @@ subroutine MPAS_io_put_att_real1d(handle, attName, attValue, fieldname, syncVal,
end subroutine MPAS_io_put_att_real1d





Copy link
Contributor

Choose a reason for hiding this comment

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

It would be preferable to not add these three blank lines.

subroutine MPAS_io_put_att_text(handle, attName, attValue, fieldname, syncVal, ierr)

implicit none
Expand Down Expand Up @@ -6100,43 +6233,7 @@ subroutine MPAS_io_put_att_text(handle, attName, attValue, fieldname, syncVal, i
end if

#ifdef MPAS_PIO_SUPPORT
pio_ierr = PIO_put_att(handle % pio_file, varid, attName, trim(attValueLocal))
if (pio_ierr /= PIO_noerr) then

io_global_err = pio_ierr
if (present(ierr)) ierr = MPAS_IO_ERR_BACKEND

!
! If we are working with a pre-existing file and the text attribute is larger than in the file, we need
! to enter define mode before writing the attribute. Note the PIO_redef documentation:
! 'Entering and leaving netcdf define mode causes a file sync operation to occur,
! these operations can be very expensive in parallel systems.'
!
if (handle % preexisting_file .and. .not. handle % data_mode) then
pio_ierr = PIO_redef(handle % pio_file)
if (pio_ierr /= PIO_noerr) then
io_global_err = pio_ierr
return
end if

pio_ierr = PIO_put_att(handle % pio_file, varid, attName, trim(attValueLocal))
if (pio_ierr /= PIO_noerr) then
io_global_err = pio_ierr
return
end if

pio_ierr = PIO_enddef(handle % pio_file)
if (pio_ierr /= PIO_noerr) then
io_global_err = pio_ierr
return
end if

if (present(ierr)) ierr = MPAS_IO_NOERR

end if

return
end if
pio_ierr = put_att_pio(handle, varid, attName, attValueLocal, ierr=ierr)
#endif

#ifdef MPAS_SMIOL_SUPPORT
Expand Down