-
Notifications
You must be signed in to change notification settings - Fork 21
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
add fortran code for ice or ocn post #25
add fortran code for ice or ocn post #25
Conversation
src/ocnicepost.fd/outputvars.F90
Outdated
|
||
end subroutine ocnvars_typedefine | ||
|
||
subroutine icevars_typedefine |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing should be hard coded. Any options, including variable names to be used, should be read in either via a FORTRAN namelist or a CSV file. Hard-coding features limits the capabilities of the application.
src/ocnicepost.fd/outputvars.F90
Outdated
!set defaults | ||
outvars(:)%input_var_name='' | ||
outvars(:)%var_grid = 'Ct' | ||
outvars(:)%var_remapmethod = 'bilinear' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if a variable requires a different type of interpolation type (e.g., nearest-neighbor)? This should not be hard coded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
State variables should be remapped with linear interpolation. Fluxes could be remapped with nearest neighbor. Is this something desired for MOM6 or CICE6 remapped fields?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DeniseWorthen What happens if an additional variable is needed in the future and requires nearest-neighbor interpolation? How do you do this without needing to rebuild the entire application?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@HenryWinterbottom-NOAA We can address the customization as an improvement activity.
For now, let us focus on this improved functionality that can be leveraged
src/ocnicepost.fd/outputvars.F90
Outdated
integer :: ii = 0 | ||
|
||
!set defaults | ||
outvars(:)%input_var_name='' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This entire subroutine needs to be defined via a namelist or CSV file. Nothing should be hard coded as it limits the capabilities of the software.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand the comments regarding generality. Variables in MOM6/CICE6 output have specified names, on specified grid locations. MOM6 temperature is never written in the output file on anything other than the center grid locations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @HenryWinterbottom-NOAA's point is to make this configurable so that one can add/remove variables without having to rebuild executables. It separates action (code) from options (configuration).
This can be addressed later as an improvement activity.
@@ -0,0 +1,577 @@ | |||
program ocnicepost |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The netCDF interface should be modified to use the https://github.com/NOAA-EMC/NCEPLIBS-ncio. It is operationally supported code and the netCDF interface is redundant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file ocnicepost.F90
is too long and thus difficult to follow. The applications within need to be modified such that they are within standalone modules and subroutines to reduce the bloat of this code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re. ncio, I think we can accept code without nceplibs-ncio. It may make things easier to read, but it requires a template to write. So it doesn't fully satisfy the needs of this program.
src/ocnicepost.fd/ocnicepost.F90
Outdated
integer, parameter :: ndest = 3 | ||
integer, parameter, dimension(ndest) :: nxrs = (/1440, 720, 360/) | ||
integer, parameter, dimension(ndest) :: nyrs = (/ 721, 361, 181/) | ||
character(len=4), dimension(ndest) :: dstgrds = (/'0p25', '0p5 ', '1p0 '/) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard coding of variables is not supported. The hard coded attributes in this instance should be read into the program via either a FORTRAN namelist or a CSV file.
!---------------------------------------------------------- | ||
! write a bare netcdf file of a 2D packed field | ||
!---------------------------------------------------------- | ||
subroutine dumpnc2d(fname, vname, dims, nflds, field) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be accomplished via ncio.
!---------------------------------------------------------- | ||
! handle netcdf errors | ||
!---------------------------------------------------------- | ||
subroutine handle_err(ierr,string) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments regarding ncio.
!---------------------------------------------------------- | ||
! write a bare netcdf file of an unpacked 2D field | ||
!---------------------------------------------------------- | ||
subroutine dumpnc1d(fname, vname, dims, field) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments regarding ncio.
!---------------------------------------------------------- | ||
! write a bare netcdf file of an unpacked 3D field | ||
!---------------------------------------------------------- | ||
subroutine dumpnc3dk(fname, vname, dims, field) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments regarding ncio.
!---------------------------------------------------------- | ||
! write a bare netcdf file of a packed 3D field | ||
!---------------------------------------------------------- | ||
subroutine dumpnc3d(fname, vname, dims, nk, nflds, field) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments regarding ncio.
src/ocnicepost.fd/outputvars.F90
Outdated
ii = ii + 1; outvars(ii)%input_var_name = 'SSH' | ||
ii = ii + 1; outvars(ii)%input_var_name = 'SST' | ||
ii = ii + 1; outvars(ii)%input_var_name = 'SSS' | ||
ii = ii + 1; outvars(ii)%input_var_name = 'speed' | ||
!ii = ii + 1; outvars(ii)%input_var_name = 'mld' | ||
ii = ii + 1; outvars(ii)%input_var_name = 'ePBL' | ||
ii = ii + 1; outvars(ii)%input_var_name = 'MLD_003' | ||
ii = ii + 1; outvars(ii)%input_var_name = 'MLD_0125' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DeniseWorthen You are hard coding variables below (see above). Hard coding paths, variables, etc., that can be read via an external file is not permitted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the PR.
A few comments that would help with the code.
I agree w/ @HenryWinterbottom-NOAA, the main program could be better organized, but I understand and appreciate the contribution when it was not your responsibility.
src/ocnicepost.fd/ocnicepost.F90
Outdated
integer, parameter :: ndest = 3 | ||
integer, parameter, dimension(ndest) :: nxrs = (/1440, 720, 360/) | ||
integer, parameter, dimension(ndest) :: nyrs = (/ 721, 361, 181/) | ||
character(len=4), dimension(ndest) :: dstgrds = (/'0p25', '0p5 ', '1p0 '/) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this namelist configurable so that the number of and the destination grid is not hard-wired.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The number of destination grids is dependent on the source grid in the sense that you don't remap the 1/2 deg tripole to the 1/4deg rectilinear. So for 1/4 deg tripole, you have 3 destination grids, for 1/2 deg tripole there are 2 destination grids and for 1deg tripole there is 1 destination grid. We've never set up a remapping of the 5deg tripole, because there was never any intention of anyone looking at that output.
The dimensions of the destination grids can be set based on whether it is a 1/4 deg, 1/2deg or 1 deg. The grid dimensions of those destination grids are fixed though. They are no more variable than the dimensions of the 1/4deg tripole grid.
! -------------------------------------------------------- | ||
|
||
nvalid = 0 | ||
rc = nf90_open(trim(input_file), nf90_nowrite, ncid) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we please wrap error checking so that the netCDF calls here and below terminate the program in the event of an error?
An example is:
subroutine nc_check(status)
integer, intent ( in) :: status
if(status /= nf90_noerr) then
write(6, '(a)') 'FATAL ERROR: ' // trim(nf90_strerror(status))
stop status
end if
end subroutine nc_check
and then
call nc_check(nf90_open(trim(input_file), nf90_nowrite, ncid))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally do not prefer this style of checking, but I can use it if preferred here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood, but we need to be able to check the return code rc
to be non-zero and exit if it is.
I was merely providing a typical example used in a lot of our codes so it feels familiar.
However, feel free to use whatever you prefer.
src/ocnicepost.fd/ocnicepost.F90
Outdated
rc = nf90_inq_varid(ncid, 'temp', varid) | ||
rc = nf90_get_var(ncid, varid, tmp3d) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not use getfield
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getfield is not used so that I can retain the fill value, which I use to define the 3-D interpolation mask.
src/ocnicepost.fd/ocnicepost.F90
Outdated
character(len=120) :: input_file, wgtsfile, output_file | ||
|
||
! source grid, tripole 1/4 deg, 40 vertical levels | ||
integer, parameter :: nxt = 1440, nyt = 1080, nlevs = 40 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the input file required to be 1/4 degree? Will this program work for MOM6/CICE6 output at any other resolution e.g. 5 degree?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The required weights are generated for 1/4 tripole->(rect 1/4deg, 1/2deg, 1deg), the 1/2 tripole -> (rect 1/2deg, 1deg) and 1deg tripole>rect 1deg. This initial code was intended as a demonstration of how the original NCL scripts could be rewritten in fortran. The NCL scripts could do any of the three tripole resolutions.
The other resolutions can all be added as variations to the fortran version. As noted above however, the 5deg ocean output was never intended as being used for anything other than plumbing. Are you suggesting that the 5deg tripole output will be used for some purpose? Or do you want it for plumbing in this case also?
The destination grid resolutions themselves are fixed. That is, the weights are pre-generated and work only for a rectilinear 1/4deg of 1440x721, for example The code is not expected to operate between completely arbitrary destination and sources.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We discussed this offline.
We will put in place checks to ensure that the target grid resolution does not exceed the input grid resolution; i.e. a 5-deg tripolar input will only produce 5-deg rectilinear output. 1/4-deg tripolar input can produce 1/4, 1/2, 1, 5-deg rectillinear outputs. This will be namelist configurable rather than looping over in the code.
@@ -0,0 +1,577 @@ | |||
program ocnicepost |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DeniseWorthen
At a minimum, please add a few lines of what this code does, what the inputs are, etc.
Note that the weight files have hard-wired names down in this code. Please be sure to document that.
Also include the authorship, so users can know who to ask questions in the case an error is encountered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
* add csv files to set source field info * restrict destination grid to a single resolution
The code has been restructured. Per conversation with @aerorahul, looping over destination grids has been removed. Samples of the input nml and csv files are found in staged directories The code does still hard-wire the name of the time and vertical axis in the source file. The implementation of netcdf-error checking and making the time axis and vertical grid names configurable are relatively minor changes and have not been implemented at this time. Weights are not yet available for mapping the 5-deg tripole or for remapping to a 5-deg rectilinear but there should be no restriction on the code being able to do that once weights are available. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you.
This code is verified to reproduce the original NCL scripts w/in ~O10-8, with the exception of the ocean field
speed
which is now re-calculated from the remapped SSU and SSV fields.The code will remap either ocean or ice model history files via a run-time flag
do_ocnpost
set according to theftype
value in the nml file. It is assumed that the model history file is present in the run directory with the nameftype.nc
, ie eitherocean.nc
orice.nc
.The model history file will be remapped to three rectilinear resolutions, 1/4 deg, 1/2 deg and 1/deg. The output files will be named, for example,
ftype.0p25.nc
for the 1/4 deg case.A
debug
flag is available in the nml file. If set, information will be sent toftype.post.log
to assist debugging. Intermediate netCDF files will also be created during the remapping process.The required ESMF weights are obtained from the location specified in
wgtsdir
. The same weights are used for either the ocean or ice case. The current weights in/scratch1/NCEPDEV/climate/climpara/S2S/FIX/fix_UFSp6/fix_reg2grb2/
need to be updated with the weights generated by the UFS_UTILS cpld_gridgen utility after the PR noted above.Two run directories are available showing how the code works at
/scratch2/NCEPDEV/stmp1/Denise.Worthen/ForRahul