Skip to content

Commit f31ebe6

Browse files
authored
Merge pull request #634 from billsacks/handle_rank3_fields
For water tracers: Add handling of rank-3 fields and refactor med_phases_prep_glc_map_lnd2glc ### Description of changes Two sets of changes that will be needed for water tracers - and in particular, for the tracer version of Flgl_qice_elev, which will be the first field in CMEPS that has two ungridded dimensions: (1) Extend various methods to support rank-3 fields (2) Refactor med_phases_prep_glc_map_lnd2glc to pre-compute vertical interpolation weights; this will be helpful when we introduce Flgl_qice_elev_wtracers to avoid duplicating this calculation of vertical interpolation weights between the non-tracer (rank-2 on the lnd grid and rank-1 on the glc grid) and tracer (rank-3 on the lnd grid and rank-2 on the glc grid) fields. ### Specific notes Contributors other than yourself, if any: Claude Code did a lot of the writing of this code, but I have reviewed it all carefully CMEPS Issues Fixed (include github issue #): Are changes expected to change answers? (specify if bfb, different at roundoff, more substantial) bfb when using #633 as a baseline Any User Interface Changes (namelist or namelist defaults changes)? No ### Testing performed In the context of cesm3_0_alpha08e, ran: (1) aux_glc on derecho plus a few extra tests, with comparisons against baselines generated with #633 . The extra tests beyond aux_glc were: ``` SMS_Ly2.f09_g17_gris20.T1850Gg.derecho_intel SMS_Ld5.f10_f10_ais8gris4_mg37.I1850Clm50SpGag.derecho_intel.cism-test_coupling SMS_Lm13.f10_f10_mg37.I1850Clm50SpG.derecho_intel ERS_Ld5.ne30pg3_t232.B1850C_LTso.derecho_intel.allactive-decstart ERS_Ld5.ne30pg3_t232.BHISTC_LTso.derecho_intel.allactive-decstart ``` All tests passed and were bit-for-bit, except for this failure that also failed in the baseline: `FAIL NCK_Ly3.f09_g17_gris20.T1850Gg.derecho_gnu COMPARE_base_multiinst` (2) Full prealpha testing on derecho and izumi with comparison against cesm3_0_alpha08e Tests passed except for tests that also failed in the baselines or seemed to have passed due to tweaks made in the baseline (e.g., increasing wallclock time for `SUB_D_Ln9.ne3pg3_ne3pg3_mt232.FHIST.izumi_nag.cam-outfrq9s`). Baseline failures were all as expected (except that a few B compset tests failed baseline comparison due to a difference in which cpl.hx.ww3 files were present in the run vs. baseline, which presumably is due to something outside of this PR): ``` ERS_Ld5.ne30pg3_t232.B1850C_LTso.derecho_intel.allactive-decstart ERS_Ld5.ne30pg3_t232.BHISTC_LTso.derecho_intel.allactive-decstart ERS_Ly7.f09_g17_gris4.T1850Gg.derecho_intel MULTINOAIS_Ly2.f10_f10_ais8gris4_mg37.I1850Clm50SpRsGag.derecho_intel.cism-change_params SMS_Lm13.f10_f10_mg37.I1850Clm50SpG.derecho_intel SMS_D_Ly1.f09_g17_ais8.T1850Ga.derecho_gnu SMS_D_Ld5_P24x1.f10_f10_ais8gris4_mg37.I1850Clm50SpGag.izumi_nag.cism-test_coupling ``` Note that I showed that these differences go away when comparing against baselines generated with #633 , for similar or identical tests. So I think it's safe to conclude that this is bit-for-bit with #633 .
2 parents e19892b + 536ceb5 commit f31ebe6

4 files changed

Lines changed: 562 additions & 134 deletions

File tree

mediator/med_io_mod.F90

Lines changed: 154 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ subroutine med_io_write_FB(io_file, FB, whead, wdata, nx, ny, nt, &
729729
type(ESMF_CoordSys_Flag) :: coordsys
730730
integer :: rcode
731731
integer :: nf,ns,ng
732-
integer :: k,n
732+
integer :: k,n,n2
733733
integer :: ndims, nelements
734734
integer ,target :: dimid2(2)
735735
integer ,target :: dimid3(3)
@@ -754,15 +754,22 @@ subroutine med_io_write_FB(io_file, FB, whead, wdata, nx, ny, nt, &
754754
integer, pointer :: Dof(:)
755755
real(r8), pointer :: fldptr1(:)
756756
real(r8), pointer :: fldptr2(:,:)
757+
real(r8), pointer :: fldptr3(:,:,:)
757758
real(r8), allocatable :: ownedElemCoords(:), ownedElemCoords_x(:), ownedElemCoords_y(:)
758759
character(CS) :: cnumber
760+
character(CS) :: cnumber2
759761
character(CL) :: tmpstr
760762
type(ESMF_Field) :: lfield
761763
integer :: rank
762-
integer :: ungriddedUBound(1) ! currently the size must equal 1 for rank 2 fields
763-
integer :: gridToFieldMap(1) ! currently the size must equal 1 for rank 2 fields
764764
logical :: tiles
765765
character(CL), allocatable :: fieldNameList(:)
766+
767+
! For a single ungridded dimension, there will be 1 element in ungriddedUBound and 1
768+
! element in gridToFieldMap; for two ungridded dimensions, there will be 2 elements in
769+
! ungriddedUBound but still 1 element in gridToFieldMap.
770+
integer :: ungriddedUBound(2)
771+
integer :: gridToFieldMap(1)
772+
766773
character(*),parameter :: subName = '(med_io_write_FB) '
767774
!-------------------------------------------------------------------------------
768775

@@ -935,12 +942,47 @@ subroutine med_io_write_FB(io_file, FB, whead, wdata, nx, ny, nt, &
935942

936943
! TODO (mvertens, 2019-03-13): this is a temporary mod to NOT write hgt
937944
if (trim(itemc) /= "hgt") then
938-
if (rank == 2) then
945+
if (rank == 3) then
939946
call ESMF_FieldGet(lfield, ungriddedUBound=ungriddedUBound, rc=rc)
940947
if (chkerr(rc,__LINE__,u_FILE_u)) return
941948
write(cnumber,'(i0)') ungriddedUbound(1)
949+
write(cnumber2,'(i0)') ungriddedUbound(2)
942950
call ESMF_LogWrite(trim(subname)//':'//'field '//trim(itemc)// &
943-
' has an griddedUBound of '//trim(cnumber), ESMF_LOGMSG_INFO)
951+
' has an ungriddedUBound of '//trim(cnumber)//' x '//trim(cnumber2), ESMF_LOGMSG_INFO)
952+
953+
! Create a new output variable for each element of the 2 ungridded dimensions
954+
do n2 = 1,ungriddedUBound(2)
955+
do n = 1,ungriddedUBound(1)
956+
write(cnumber,'(i0)') n
957+
write(cnumber2,'(i0)') n2
958+
name1 = trim(lpre)//'_'//trim(itemc)//trim(cnumber)//'_'//trim(cnumber2)
959+
call ESMF_LogWrite(trim(subname)//': defining '//trim(name1), ESMF_LOGMSG_INFO)
960+
if (luse_float) then
961+
rcode = pio_def_var(io_file, trim(name1), PIO_REAL, dimid, varid)
962+
rcode = pio_put_att(io_file, varid,"_FillValue",real(lfillvalue,r4))
963+
else
964+
rcode = pio_def_var(io_file, trim(name1), PIO_DOUBLE, dimid, varid)
965+
rcode = pio_put_att(io_file,varid,"_FillValue",lfillvalue)
966+
end if
967+
if (NUOPC_FieldDictionaryHasEntry(trim(itemc))) then
968+
call NUOPC_FieldDictionaryGetEntry(itemc, canonicalUnits=cunit, rc=rc)
969+
if (chkerr(rc,__LINE__,u_FILE_u)) return
970+
rcode = pio_put_att(io_file, varid, "units", trim(cunit))
971+
end if
972+
rcode = pio_put_att(io_file, varid, "standard_name", trim(name1))
973+
if (present(tavg)) then
974+
if (tavg) then
975+
rcode = pio_put_att(io_file, varid, "cell_methods", "time: mean")
976+
endif
977+
endif
978+
end do
979+
end do
980+
else if (rank == 2) then
981+
call ESMF_FieldGet(lfield, ungriddedUBound=ungriddedUBound, rc=rc)
982+
if (chkerr(rc,__LINE__,u_FILE_u)) return
983+
write(cnumber,'(i0)') ungriddedUbound(1)
984+
call ESMF_LogWrite(trim(subname)//':'//'field '//trim(itemc)// &
985+
' has an ungriddedUBound of '//trim(cnumber), ESMF_LOGMSG_INFO)
944986

945987
! Create a new output variable for each element of the undistributed dimension
946988
do n = 1,ungriddedUBound(1)
@@ -958,7 +1000,7 @@ subroutine med_io_write_FB(io_file, FB, whead, wdata, nx, ny, nt, &
9581000
if (NUOPC_FieldDictionaryHasEntry(trim(itemc))) then
9591001
call NUOPC_FieldDictionaryGetEntry(itemc, canonicalUnits=cunit, rc=rc)
9601002
if (chkerr(rc,__LINE__,u_FILE_u)) return
961-
rcode = pio_put_att(io_file, varid, "units" , trim(cunit))
1003+
rcode = pio_put_att(io_file, varid, "units", trim(cunit))
9621004
end if
9631005
rcode = pio_put_att(io_file, varid, "standard_name", trim(name1))
9641006
if (present(tavg)) then
@@ -968,15 +1010,15 @@ subroutine med_io_write_FB(io_file, FB, whead, wdata, nx, ny, nt, &
9681010
endif
9691011
end if
9701012
end do
971-
else
1013+
else if (rank == 1) then
9721014
name1 = trim(lpre)//'_'//trim(itemc)
973-
call ESMF_LogWrite(trim(subname)//':'//trim(itemc)//':'//trim(name1),ESMF_LOGMSG_INFO)
1015+
call ESMF_LogWrite(trim(subname)//': defining '//trim(name1), ESMF_LOGMSG_INFO)
9741016
if (luse_float) then
9751017
rcode = pio_def_var(io_file, trim(name1), PIO_REAL, dimid, varid)
976-
rcode = pio_put_att(io_file, varid, "_FillValue", real(lfillvalue, r4))
1018+
rcode = pio_put_att(io_file, varid,"_FillValue",real(lfillvalue,r4))
9771019
else
9781020
rcode = pio_def_var(io_file, trim(name1), PIO_DOUBLE, dimid, varid)
979-
rcode = pio_put_att(io_file, varid, "_FillValue", lfillvalue)
1021+
rcode = pio_put_att(io_file,varid,"_FillValue",lfillvalue)
9801022
end if
9811023
if (NUOPC_FieldDictionaryHasEntry(trim(itemc))) then
9821024
call NUOPC_FieldDictionaryGetEntry(itemc, canonicalUnits=cunit, rc=rc)
@@ -988,7 +1030,10 @@ subroutine med_io_write_FB(io_file, FB, whead, wdata, nx, ny, nt, &
9881030
if (tavg) then
9891031
rcode = pio_put_att(io_file, varid, "cell_methods", "time: mean")
9901032
endif
991-
end if
1033+
endif
1034+
else
1035+
call shr_log_error(subname//' ERROR: unhandled rank', line=__LINE__, file=u_FILE_u, rc=rc)
1036+
return
9921037
end if
9931038
end if
9941039
end do
@@ -1039,12 +1084,43 @@ subroutine med_io_write_FB(io_file, FB, whead, wdata, nx, ny, nt, &
10391084
end if
10401085

10411086
call FB_getFldPtr(FB, itemc, &
1042-
fldptr1=fldptr1, fldptr2=fldptr2, rank=rank, rc=rc)
1087+
fldptr1=fldptr1, fldptr2=fldptr2, fldptr3=fldptr3, rank=rank, rc=rc)
10431088
if (chkerr(rc,__LINE__,u_FILE_u)) return
10441089

10451090
! TODO (mvertens, 2019-03-13): this is a temporary mod to NOT write hgt
10461091
if (trim(itemc) /= "hgt") then
1047-
if (rank == 2) then
1092+
if (rank == 3) then
1093+
1094+
! Determine the size of the ungridded dimensions and the index where the distributed dimension is located
1095+
call ESMF_FieldBundleGet(FB, itemc, field=lfield, rc=rc)
1096+
if (chkerr(rc,__LINE__,u_FILE_u)) return
1097+
call ESMF_FieldGet(lfield, ungriddedUBound=ungriddedUBound, gridToFieldMap=gridToFieldMap, rc=rc)
1098+
if (chkerr(rc,__LINE__,u_FILE_u)) return
1099+
1100+
if (gridToFieldMap(1) /= 3) then
1101+
call shr_log_error( &
1102+
subname//' ERROR: For rank-3 fields, currently only gridToFieldMap(1)==3 is supported', &
1103+
line=__LINE__, file=u_FILE_u, rc=rc)
1104+
return
1105+
end if
1106+
1107+
! Output for each combination of ungriddedUbound indices
1108+
do n2 = 1,ungriddedUBound(2)
1109+
do n = 1,ungriddedUBound(1)
1110+
write(cnumber,'(i0)') n
1111+
write(cnumber2,'(i0)') n2
1112+
name1 = trim(lpre)//'_'//trim(itemc)//trim(cnumber)//'_'//trim(cnumber2)
1113+
rcode = pio_inq_varid(io_file, trim(name1), varid)
1114+
call pio_setframe(io_file,varid,frame)
1115+
1116+
if (luse_float) then
1117+
call pio_write_darray(io_file, varid, iodesc, real(fldptr3(n,n2,:),r4), rcode, fillval=real(lfillvalue,r4))
1118+
else
1119+
call pio_write_darray(io_file, varid, iodesc, fldptr3(n,n2,:), rcode, fillval=lfillvalue)
1120+
end if
1121+
end do
1122+
end do
1123+
else if (rank == 2) then
10481124

10491125
! Determine the size of the ungridded dimension and the index where the undistributed dimension is located
10501126
call ESMF_FieldBundleGet(FB, itemc, field=lfield, rc=rc)
@@ -1489,7 +1565,7 @@ subroutine med_io_read_FB(filename, vm, FB, pre, frame, rc)
14891565
type(ESMF_Field) :: lfield
14901566
integer :: rcode
14911567
integer :: nf
1492-
integer :: k,n,l
1568+
integer :: k,n,n2,l
14931569
type(file_desc_t) :: pioid
14941570
type(var_desc_t) :: varid
14951571
type(io_desc_t) :: iodesc
@@ -1500,11 +1576,18 @@ subroutine med_io_read_FB(filename, vm, FB, pre, frame, rc)
15001576
integer :: rank, lsize
15011577
real(r8), pointer :: fldptr1(:), fldptr1_tmp(:)
15021578
real(r8), pointer :: fldptr2(:,:)
1579+
real(r8), pointer :: fldptr3(:,:,:)
15031580
character(CL) :: tmpstr
15041581
character(len=16) :: cnumber
1582+
character(len=16) :: cnumber2
15051583
integer(kind=Pio_Offset_Kind) :: lframe
1506-
integer :: ungriddedUBound(1) ! currently the size must equal 1 for rank 2 fieldds
1507-
integer :: gridToFieldMap(1) ! currently the size must equal 1 for rank 2 fieldds
1584+
1585+
! For a single ungridded dimension, there will be 1 element in ungriddedUBound and 1
1586+
! element in gridToFieldMap; for two ungridded dimensions, there will be 2 elements in
1587+
! ungriddedUBound but still 1 element in gridToFieldMap.
1588+
integer :: ungriddedUBound(2)
1589+
integer :: gridToFieldMap(1)
1590+
15081591
character(*),parameter :: subName = '(med_io_read_FB) '
15091592
!-------------------------------------------------------------------------------
15101593
rc = ESMF_Success
@@ -1569,7 +1652,9 @@ subroutine med_io_read_FB(filename, vm, FB, pre, frame, rc)
15691652
if (chkerr(rc,__LINE__,u_FILE_u)) return
15701653
call ESMF_FieldGet(lfield, rank=rank, rc=rc)
15711654
if (chkerr(rc,__LINE__,u_FILE_u)) return
1572-
if (rank == 2) then
1655+
if (rank == 3) then
1656+
name1 = trim(lpre)//'_'//trim(itemc)//'1_1'
1657+
else if (rank == 2) then
15731658
name1 = trim(lpre)//'_'//trim(itemc)//'1'
15741659
else if (rank == 1) then
15751660
name1 = trim(lpre)//'_'//trim(itemc)
@@ -1582,12 +1667,61 @@ subroutine med_io_read_FB(filename, vm, FB, pre, frame, rc)
15821667
if (chkerr(rc,__LINE__,u_FILE_u)) return
15831668

15841669
! Get pointer to field bundle field
1585-
! Field bundle might be 2d or 1d - but field on mediator history or restart file will always be 1d
1670+
! Field bundle might be 3d, 2d or 1d - but field on mediator history or restart file will always be 1d
15861671
call FB_getFldPtr(FB, itemc, &
1587-
fldptr1=fldptr1, fldptr2=fldptr2, rank=rank, rc=rc)
1672+
fldptr1=fldptr1, fldptr2=fldptr2, fldptr3=fldptr3, rank=rank, rc=rc)
15881673
if (chkerr(rc,__LINE__,u_FILE_u)) return
15891674

1590-
if (rank == 2) then
1675+
if (rank == 3) then
1676+
1677+
! Determine the size of the ungridded dimensions and the
1678+
! index where the distributed dimension is located
1679+
call ESMF_FieldBundleGet(FB, itemc, field=lfield, rc=rc)
1680+
if (chkerr(rc,__LINE__,u_FILE_u)) return
1681+
call ESMF_FieldGet(lfield, ungriddedUBound=ungriddedUBound, gridToFieldMap=gridToFieldMap, rc=rc)
1682+
if (chkerr(rc,__LINE__,u_FILE_u)) return
1683+
1684+
if (gridToFieldMap(1) /= 3) then
1685+
call shr_log_error( &
1686+
subname//' ERROR: For rank-3 fields, currently only gridToFieldMap(1)==3 is supported', &
1687+
line=__LINE__, file=u_FILE_u, rc=rc)
1688+
return
1689+
end if
1690+
1691+
lsize = size(fldptr3, dim=3)
1692+
allocate(fldptr1_tmp(lsize))
1693+
1694+
do n2 = 1,ungriddedUBound(2)
1695+
do n = 1,ungriddedUBound(1)
1696+
! Create a name for the 1d field on the mediator history or restart file based on the
1697+
! ungridded dimension indices of the field bundle 3d field
1698+
write(cnumber,'(i0)') n
1699+
write(cnumber2,'(i0)') n2
1700+
name1 = trim(lpre)//'_'//trim(itemc)//trim(cnumber)//'_'//trim(cnumber2)
1701+
1702+
rcode = pio_inq_varid(pioid, trim(name1), varid)
1703+
if (rcode == pio_noerr) then
1704+
call ESMF_LogWrite(trim(subname)//' read field '//trim(name1), ESMF_LOGMSG_INFO)
1705+
if (chkerr(rc,__LINE__,u_FILE_u)) return
1706+
call pio_setframe(pioid, varid, lframe)
1707+
call pio_read_darray(pioid, varid, iodesc, fldptr1_tmp, rcode)
1708+
rcode = pio_get_att(pioid, varid, "_FillValue", lfillvalue)
1709+
if (rcode /= pio_noerr) then
1710+
lfillvalue = fillvalue
1711+
endif
1712+
do l = 1,size(fldptr1_tmp)
1713+
if (fldptr1_tmp(l) == lfillvalue) fldptr1_tmp(l) = 0.0_r8
1714+
enddo
1715+
else
1716+
fldptr1_tmp = 0.0_r8
1717+
endif
1718+
fldptr3(n,n2,:) = fldptr1_tmp(:)
1719+
end do
1720+
end do
1721+
1722+
deallocate(fldptr1_tmp)
1723+
1724+
else if (rank == 2) then
15911725

15921726
! Determine the size of the ungridded dimension and the
15931727
! index where the undistributed dimension is located

0 commit comments

Comments
 (0)