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

Addition of new features to generate ocean boundary conditions for atmosphere-only **forecasts** #47

Merged
merged 22 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b8411d7
1. Add main program: sst_ice_helpers.F90 - to calculate daily clim, 2…
Oct 21, 2023
e02b65d
to generate conservative regridding weights to map original OSTIA dat…
Oct 23, 2023
4078730
Plot difference between conservatively remapped and binned (GEOS FP b…
Oct 23, 2023
b8c592b
Add utility to extract SST and Ice concentration for any given day: e…
Oct 23, 2023
c668923
get rid of commented line
Oct 23, 2023
026c86e
Added time ticker from @rtodling
Nov 9, 2023
78bc8c1
Getting there! Add standard deviation calculation and user input args
Dec 20, 2023
0e00190
Working daily climatology production- including leap year/day (02/29)
Dec 22, 2023
c9c4630
remove hard coded file prefix/suffix
Dec 29, 2023
860920c
Improve readability
Jan 4, 2024
90a3430
Add option to save binary file
Jan 4, 2024
e4ac9c5
Make defaults argument(s), as asked by @rtodling for input BCS data p…
Jan 7, 2024
a1c5752
add utility to generate forecast (persistence), clean up
Jan 14, 2024
3481694
remove commented lines
Jan 14, 2024
69ccffc
Add option to generate BCs using persistence of initial anomaly
Jan 17, 2024
a80a172
update change log
Jan 17, 2024
73bd261
Merge branch 'main' into sanAkel/feature/oceanBCs_clim_anom
sanAkel Jan 18, 2024
3210ede
Update CHANGELOG.md
sanAkel Jan 19, 2024
176f65b
Update gen_wts_regrid_ostia_geos.py
sanAkel Jan 19, 2024
2f44d77
Update plot_diff_ostia_native_regridded_binned.py
sanAkel Jan 19, 2024
7f64f4f
Update CHANGELOG.md
mathomp4 Jan 19, 2024
8f5b1f4
Merge branch 'main' into sanAkel/feature/oceanBCs_clim_anom
sdrabenh Jan 24, 2024
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Addition of SST and FRACI forecast (ocean) boundary conditions generation capability in `pre/prepare_ocnExtData`

### Changed

### Fixed
Expand Down Expand Up @@ -52,6 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [2.0.2] - 2023-06-28


### Fixed

- Updates to fix dates for comparison plots. Updates for plot levels.
Expand Down
19 changes: 19 additions & 0 deletions pre/prepare_ocnExtData/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ esma_set_this()

set ( srcs
sst_ice_helpers.F90
hermes_m_tick.f90
)

esma_add_library (${this} SRCS ${srcs} DEPENDENCIES MAPL NetCDF::NetCDF_Fortran)
Expand All @@ -19,6 +20,24 @@ ecbuild_add_executable (
LIBS ${this})
set_target_properties(sst_sic_eight.x PROPERTIES Fortran_MODULE_DIRECTORY ${include_${this}})

ecbuild_add_executable (
TARGET cal_daily_clim.x
SOURCES daily_clim_SST_FRACI_eight.F90
LIBS ${this})
set_target_properties(cal_daily_clim.x PROPERTIES Fortran_MODULE_DIRECTORY ${include_${this}})

ecbuild_add_executable (
TARGET extract_daily_sst_ice.x
SOURCES extract_day_SST_FRACI_eight.F90
LIBS ${this})
set_target_properties(extract_daily_sst_ice.x PROPERTIES Fortran_MODULE_DIRECTORY ${include_${this}})

ecbuild_add_executable (
TARGET gen_forecast_bcs.x
SOURCES forecast_SST_FRACI_eight.F90
LIBS ${this})
set_target_properties(gen_forecast_bcs.x PROPERTIES Fortran_MODULE_DIRECTORY ${include_${this}})

if (USE_F2PY)
find_package(F2PY2)
if (F2PY2_FOUND)
Expand Down
171 changes: 171 additions & 0 deletions pre/prepare_ocnExtData/daily_clim_SST_FRACI_eight.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
PROGRAM daily_clim_SST_FRACI_eight
!---------------------------------------------------------------------------
USE m_tick, only: INCYMD
USE sst_ice_helpers, only: read_bin_SST_ICE, &
write_bin, &
write_netcdf

IMPLICIT NONE

INTEGER :: month, day
INTEGER :: clim_year, year_start, year_end
CHARACTER (LEN = 200) :: data_path
CHARACTER (LEN = 200) :: sst_file_pref, ice_file_pref
CHARACTER (LEN = 200) :: sst_file_suff, ice_file_suff

INTEGER :: nymd_in, nYears
INTEGER :: nymd_out, NLON, NLAT
REAL :: LON(2880), LAT(1440)

INTEGER :: year
INTEGER :: clim_tom, clim_tom_year, clim_tom_mon, clim_tom_day
CHARACTER (LEN = 200) :: year_str, sst_file, ice_file
CHARACTER (LEN = 8) :: clim_date_str
REAL :: mean_sst(1440, 2880), mean_ice(1440, 2880)
REAL :: sdev_sst(1440, 2880), sdev_ice(1440, 2880)
REAL :: sst(1440, 2880), ice(1440, 2880)
REAL :: dsst(1440, 2880), dice(1440, 2880)

LOGICAL :: verbose

character (len=4) :: arg
integer :: numArgs
numArgs = iargc()

verbose = .false.

! Inputs
if (numArgs < 4) then
print *, "Need 4 inputs, in following format. Try again!"
print *, "start_year end_year month day. Last 2 inputs are for the climatology of MM/DD."
STOP
else ! read user inputs
call getarg(1, arg)
read(arg, '(I4)') year_start !2007
call getarg(2, arg)
read(arg, '(I4)') year_end !2023
call getarg(3, arg)
read(arg, '(I2)') month
call getarg(4, arg)
read(arg, '(I2)') day
end if

! - Set inputs
clim_year = 1 ! Set, can't be "0" since GEOS/ESMF does not like that!
! GMAO OPS has following fixed
data_path= '/discover/nobackup/projects/gmao/share/dao_ops/fvInput/g5gcm/bcs/realtime/OSTIA_REYNOLDS/2880x1440/'
sst_file_pref = 'dataoceanfile_OSTIA_REYNOLDS_SST.2880x1440.'
ice_file_pref = 'dataoceanfile_OSTIA_REYNOLDS_ICE.2880x1440.'
sst_file_suff = '.data'
ice_file_suff = '.data'

! Check input range
if (year_start < 2007) then
print *, "Invalid starting year: ", year_start, "Must be 2007 or later, try again."
STOP
endif
if ( (month < 1) .or. (month > 12)) then
print *, "Invalid month: ", month, "Try again."
STOP
endif
if ( (day < 1) .or. (day > 31)) then
print *, "Invalid day: ", day, "Try again."
STOP
endif
if(verbose) print *, "User inputs: ", year_start, year_end, month, day
!--

print *, " "
! mean and std dev over year_start: year_end
! 1. mean
nYears = 0
do year = year_start, year_end
write (year_str,'(I4.0)') year
sst_file = trim(data_path)//"/"//trim(sst_file_pref)//trim(year_str)//trim(sst_file_suff)
ice_file = trim(data_path)//"/"//trim(ice_file_pref)//trim(year_str)//trim(ice_file_suff)

nymd_in = year*10000 + month*100 + day
if(verbose) then
print *, year, year_str, nymd_in
print *, sst_file, ice_file
print *, nymd_in
endif

CALL read_bin_SST_ICE( sst_file, nymd_in, nymd_out, NLON, NLAT, LON, LAT, sst) ! Read GMAO OPS dataset
CALL read_bin_SST_ICE( ice_file, nymd_in, nymd_out, NLON, NLAT, LON, LAT, ice)

if ( (nymd_out-nymd_in) .eq. 0) then ! Found data for matching dates
print *, "Read SST and FRACI for: ", nymd_out
if (verbose) print *, "Found data in file, number of years =", nYears
nYears = nYears + 1

if (nYears == 1) then
mean_sst = sst
mean_ice = ice
else
mean_sst = mean_sst + sst
mean_ice = mean_ice + ice
endif
endif
end do

print *, " "
print *, "Number of years= ", nYears

mean_sst = mean_sst/REAL(nYears) ! nYears should be _promoted_ to real, being safe!
mean_ice = mean_ice/REAL(nYears)

! 2. sdev
nYears = 0
do year = year_start, year_end

write (year_str,'(I4.0)') year
sst_file = trim(data_path)//"/"//trim(sst_file_pref)//trim(year_str)//trim(sst_file_suff)
ice_file = trim(data_path)//"/"//trim(ice_file_pref)//trim(year_str)//trim(ice_file_suff)

nymd_in = year*10000 + month*100 + day
CALL read_bin_SST_ICE( sst_file, nymd_in, nymd_out, NLON, NLAT, LON, LAT, sst)
CALL read_bin_SST_ICE( ice_file, nymd_in, nymd_out, NLON, NLAT, LON, LAT, ice)

if ( (nymd_out-nymd_in) .eq. 0) then
nYears = nYears + 1

if (nYears == 1) then
dsst = (sst - mean_sst)**2.
dice = (ice - mean_ice)**2.
else
dsst = dsst + (sst - mean_sst)**2.
dice = dice + (ice - mean_ice)**2.
endif
endif
end do

print *, "Number of years= ", nYears
! based on a sample not population
sdev_sst = sqrt( dsst/REAL(nYears-1))
sdev_ice = sqrt( dice/REAL(nYears-1))
! --

print *, " "
clim_tom = INCYMD( clim_year*10000+month*100+day, 1)
clim_tom_year = int(clim_tom/10000)
clim_tom_mon = int((clim_tom-clim_tom_year*10000)/100)
clim_tom_day = clim_tom - (clim_tom_year*10000+clim_tom_mon*100)
if(verbose) print *, "Tomorrow day:", clim_tom_year, clim_tom_mon, clim_tom_day

write (clim_date_str,'(I0.8)') clim_year*10000+month*100+day
if(verbose) print *, clim_date_str

! Only write mean in binary format- good enough.
print *, "Write output ..."
CALL write_bin( 'daily_clim_mean', clim_year, month, day, clim_tom_year, clim_tom_mon, clim_tom_day, clim_date_str, 1440, 2880, transpose(mean_sst), transpose(mean_ice))

! mean
CALL write_netcdf( 'daily_clim_mean_sst_fraci', clim_year, month, day, clim_date_str, 1440, 2880, transpose(mean_sst), transpose(mean_ice))
! std dev
CALL write_netcdf( 'daily_clim_sdev_sst_fraci', clim_year, month, day, clim_date_str, 1440, 2880, transpose(sdev_sst), transpose(sdev_ice))
print *, "Done."
print *, " "

!---------------------------------------------------------------------------
END PROGRAM daily_clim_SST_FRACI_eight
130 changes: 130 additions & 0 deletions pre/prepare_ocnExtData/extract_day_SST_FRACI_eight.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
PROGRAM extract_day_SST_FRACI_eight
!---------------------------------------------------------------------------
USE m_tick, only: INCYMD
USE sst_ice_helpers, only: read_bin_SST_ICE, &
write_bin, &
write_netcdf

IMPLICIT NONE

integer, parameter :: nlon = 2880
integer, parameter :: nlat = 1440
real :: lon(nlon), lat(nlat)
real :: sst(nlat, nlon), ice(nlat, nlon)

integer :: extract_date
integer :: date_out, nlon_out, nlat_out

character (len = 200) :: data_path
character (len = 200) :: sst_file_pref, ice_file_pref
character (len = 200) :: sst_file_suff, ice_file_suff

character (len=8) :: date_str, format_str = "(I8)"
character (len = 200) :: sst_file, ice_file

integer :: i, iarg, argc, iargc
character (len=255) :: argv
integer :: numArgs
integer :: year_s, month_s, day_s
integer :: tom, tom_year, tom_mon, tom_day

logical :: save_bin
!----

argc = iargc()
if (argc < 3) then
print *, "Need minmum 3 inputs, see below examples. Try again!"
print *, "extract_daily_sst_ice.x -year 2010 -month 1 -day 1"
print *, " "
print *, "** 2 additional optional inputs are allowed ** "
print *, "extract_daily_sst_ice.x -year 2010 -month 1 -day 1 -save_bin"
print *, " "
print *, "extract_daily_sst_ice.x -year 2010 -month 1 -day 1 -input_data_path xx"
print *, " "
print *, "extract_daily_sst_ice.x -year 2010 -month 1 -day 1 -save_bin -input_data_path xx"
print *, " "
STOP
end if

! Following 2 variables have defaults that can be overridden by user inputs.
save_bin = .false.
! GMAO OPS data path
data_path= '/discover/nobackup/projects/gmao/share/dao_ops/fvInput/g5gcm/bcs/realtime/OSTIA_REYNOLDS/2880x1440/'

!-- read user inputs
iarg = 0
do i = 1, 99
iarg = iarg + 1
if ( iarg > argc ) exit
call getarg(iarg, argv)

select case (argv)
case ("-year")
iarg = iarg + 1
call getarg ( iarg, argv )
read(argv, '(I14)') year_s
case ("-month")
iarg = iarg + 1
call getarg ( iarg, argv )
read(argv, '(I14)') month_s
case ("-day")
iarg = iarg + 1
call getarg ( iarg, argv )
read(argv, '(I14)') day_s
case ("-save_bin")
save_bin = .true.
case ("-input_data_path")
iarg = iarg + 1
call getarg ( iarg, argv )
read(argv, *) data_path
data_path = trim(data_path)
case default
end select
end do
print *, year_s, month_s, day_s, save_bin, data_path

!-- form a string of input date
extract_date = year_s*10000+month_s*100+day_s
write (date_str, format_str) extract_date

! GMAO OPS has following fixed
sst_file_pref = 'dataoceanfile_OSTIA_REYNOLDS_SST.2880x1440.'
ice_file_pref = 'dataoceanfile_OSTIA_REYNOLDS_ICE.2880x1440.'
sst_file_suff = '.data'
ice_file_suff = '.data'

sst_file = trim(data_path)//"/"//trim(sst_file_pref)//trim(date_str(1:4))//trim(sst_file_suff)
ice_file = trim(data_path)//"/"//trim(ice_file_pref)//trim(date_str(1:4))//trim(ice_file_suff)

print *, " "
print *, "Read: ", sst_file, ice_file
print *, " "

! read sst
CALL read_bin_SST_ICE( sst_file, extract_date, date_out, nlon_out, nlat_out, lon, lat, sst)
! read sea ice
CALL read_bin_SST_ICE( ice_file, extract_date, date_out, nlon_out, nlat_out, lon, lat, ice)

print *, date_out
print *, " "
print *, "Write out the data..."

! binary write
if (save_bin) then
tom = INCYMD( year_s*10000+month_s*100+day_s, 1) ! next day

tom_year = int(tom/10000)
tom_mon = int((tom-tom_year*10000)/100)
tom_day = tom - (tom_year*10000+tom_mon*100)
!print *, "Tomorrow day:", tom_year, tom_mon, tom_day
CALL write_bin( 'bcs_2880x1440', year_s, month_s, day_s, tom_year, tom_mon, tom_day, date_str, nlat, nlon, transpose(sst), transpose(ice))
end if

! netcdf
CALL write_netcdf( 'sst_ice', year_s, month_s, day_s, date_str, nlat, nlon, transpose(sst), transpose(ice))

print *, "Done."
print *, " "

!---------------------------------------------------------------------------
END PROGRAM extract_day_SST_FRACI_eight
Loading