NOAA-GFDL/MOM6

Daily wind cycling error in MOM6 ocean-only idealized model

Opened this issue · 3 comments

Hi! I want to set wind stress with 3 months of variability as input data in the MOM6 ocean-only idealized model, but I found it is constant without varying... could anyone help me with this issue? Thanks!

The tau_mag output (show as constant):
Picture1

My input data showed below:
image

image

Also, my configuration setting:

! Surface forcing
BUOY_CONFIG = "zero"                ! read buoyancy forcing from the file
WIND_CONFIG = "file"       ! read wind forcing from the file
WIND_FILE = "wind.nc"   ! the file in which the wind stresses are found 
WINDSTRESS_X_VAR = "STRESS_X"  ! the name of the x-wind stress variable in WIND_FILE
WINDSTRESS_Y_VAR = "STRESS_Y"  ! the name of the y-wind stress variable in WIND_FILE

WIND_STAGGER = "A"    ! how the wind stress components are staggered in WIND_FILE
RESTOREBUOY = False         ! the buoyancy fluxes drive the model back toward some specified surface state
                           ! with a rate given by FLUXCONST
DT_FORCING = 86400            ! s-1, time step for changing forcing (1 day)

Recent finding: The input data could only be read with 365 days, less or more days will make the MOM6 ocean-only model read wind stress as a constant defaultly. To derive wind stress variability with 3 months effect, I chose to save model output every 360 days, then it worked well.

For reasons I will not defend, the netcdf data needs certain attributes (not standard). I'm not sure where the documentation is (somewhere on the FMS pages) but an example of a file that does work is in ocean_only/global. Here's the top ncdump -h of that file. Try adding the calender, calendar_type and cartesian_axis to the coordinate variables (esp. time).

netcdf ocean_forcing_daily {
dimensions:
        xh = 360 ;
        yh = 210 ;
        time = UNLIMITED ; // (365 currently)
        nv = 2 ;
        xq = 360 ;
        yq = 210 ;
variables:
        double xh(xh) ;
                xh:long_name = "h point nominal longitude" ;
                xh:units = "degrees_E" ;
                xh:cartesian_axis = "X" ;
        double yh(yh) ;
                yh:long_name = "h point nominal latitude" ;
                yh:units = "degrees_N" ;
                yh:cartesian_axis = "Y" ;
        double time(time) ;
                time:long_name = "time" ;
                time:units = "days since 0001-01-01 00:00:00" ;
                time:cartesian_axis = "T" ;
                time:calendar_type = "NOLEAP" ;
                time:calendar = "NOLEAP" ;
                time:bounds = "time_bounds" ;
        double nv(nv) ;
                nv:long_name = "vertex number" ;
                nv:units = "none" ;
                nv:cartesian_axis = "N" ;
        double xq(xq) ;
                xq:long_name = "q point nominal longitude" ;
                xq:units = "degrees_E" ;
                xq:cartesian_axis = "X" ;
        double yq(yq) ;
                yq:long_name = "q point nominal latitude" ;
                yq:units = "degrees_N" ;
                yq:cartesian_axis = "Y" ;
        float SW(time, yh, xh) ;
                SW:long_name = "Shortwave radiation flux into ocean" ;
                SW:units = "Watt meter-2" ;
                SW:missing_value = 1.e+20f ;
                SW:_FillValue = 1.e+20f ;
                SW:cell_methods = "time: mean" ;
                SW:time_avg_info = "average_T1,average_T2,average_DT" ;
                SW:standard_name = "surface_net_downward_shortwave_flux" ;
        float LW(time, yh, xh) ;
                LW:long_name = "Longwave radiation flux into ocean" ;
                LW:units = "Watt meter-2" ;
                LW:missing_value = 1.e+20f ;
                LW:_FillValue = 1.e+20f ;
                LW:cell_methods = "time: mean" ;
                LW:time_avg_info = "average_T1,average_T2,average_DT" ;
                LW:standard_name = "surface_net_downward_longwave_flux" ;
        float latent(time, yh, xh) ;
                latent:long_name = "Latent heat flux into ocean due to fusion and evaporation" ;
                latent:units = "Watt meter-2" ;
                latent:missing_value = 1.e+20f ;
                latent:_FillValue = 1.e+20f ;
                latent:cell_methods = "time: mean" ;
                latent:time_avg_info = "average_T1,average_T2,average_DT" ;
        float sensible(time, yh, xh) ;
                sensible:long_name = "Sensible heat flux into ocean" ;
                sensible:units = "Watt meter-2" ;
                sensible:missing_value = 1.e+20f ;
                sensible:_FillValue = 1.e+20f ;
                sensible:cell_methods = "time: mean" ;
                sensible:time_avg_info = "average_T1,average_T2,average_DT" ;
                sensible:standard_name = "surface_downward_sensible_heat_flux" ;
        float evap(time, yh, xh) ;
                evap:long_name = "Evaporation at ocean surface (usually negative)" ;
                evap:units = "kilogram meter-2 second-1" ;
                evap:missing_value = 1.e+20f ;
                evap:_FillValue = 1.e+20f ;
                evap:cell_methods = "time: mean" ;
                evap:time_avg_info = "average_T1,average_T2,average_DT" ;
        float taux(time, yh, xq) ;
                taux:long_name = "Zonal Wind Stress" ;
                taux:units = "Pascal" ;
                taux:missing_value = 1.e+20f ;
                taux:_FillValue = 1.e+20f ;
                taux:cell_methods = "time: mean" ;
                taux:time_avg_info = "average_T1,average_T2,average_DT" ;
                taux:standard_name = "surface_downward_x_stress" ;
        float tauy(time, yq, xh) ;
                tauy:long_name = "Meridional Wind Stress" ;
                tauy:units = "Pascal" ;
                tauy:missing_value = 1.e+20f ;
                tauy:_FillValue = 1.e+20f ;
                tauy:cell_methods = "time: mean" ;
                tauy:time_avg_info = "average_T1,average_T2,average_DT" ;
                tauy:standard_name = "surface_downward_y_stress" ;
        float ustar(time, yh, xh) ;
                ustar:long_name = "Surface friction velocity" ;
                ustar:units = "meter second-1" ;
                ustar:missing_value = 1.e+20f ;
                ustar:_FillValue = 1.e+20f ;
                ustar:cell_methods = "time: mean" ;
                ustar:time_avg_info = "average_T1,average_T2,average_DT" ;
        float SST(time, yh, xh) ;
                SST:long_name = "Sea Surface Temperature" ;
                SST:units = "Celsius" ;
                SST:missing_value = -1.e+34f ;
                SST:_FillValue = -1.e+34f ;
                SST:cell_methods = "time: mean" ;
                SST:time_avg_info = "average_T1,average_T2,average_DT" ;
        float SSS(time, yh, xh) ;
                SSS:long_name = "Sea Surface Salinity" ;
                SSS:units = "PSU" ;
                SSS:missing_value = -1.e+34f ;
                SSS:_FillValue = -1.e+34f ;
                SSS:cell_methods = "time: mean" ;
                SSS:time_avg_info = "average_T1,average_T2,average_DT" ;
        double average_T1(time) ;
                average_T1:long_name = "Start time for average period" ;
                average_T1:units = "days since 0001-01-01 00:00:00" ;
                average_T1:missing_value = 1.e+20 ;
                average_T1:_FillValue = 1.e+20 ;
        double average_T2(time) ;
                average_T2:long_name = "End time for average period" ;
                average_T2:units = "days since 0001-01-01 00:00:00" ;
                average_T2:missing_value = 1.e+20 ;
                average_T2:_FillValue = 1.e+20 ;
        double average_DT(time) ;
                average_DT:long_name = "Length of average period" ;
                average_DT:units = "days" ;
                average_DT:missing_value = 1.e+20 ;
                average_DT:_FillValue = 1.e+20 ;
        double time_bounds(time, nv) ;
                time_bounds:long_name = "time axis boundaries" ;
                time_bounds:units = "days" ;
                time_bounds:missing_value = 1.e+20 ;
                time_bounds:_FillValue = 1.e+20 ;
...

Sorry, just reread and saw that you had already sorted out the attributes, and found a fix. The 365 days is a good gotcha - another oddity we didn't know about!

Hi! I found something interesting in the MOM6 source code: (directory: MOM6/config_src/drivers/solo_driver/MOM_surface_forcing.F90)

This is within subroutine wind_forcing_from_file(sfc_state, forces, day, G, US, CS):

...
call get_time(day, seconds, days)
time_lev_daily = days - 365*floor(real(days) / 365.0)

if (time_lev_daily < 31) then ; time_lev_monthly = 0
elseif (time_lev_daily < 59) then ; time_lev_monthly = 1
elseif (time_lev_daily < 90) then ; time_lev_monthly = 2
elseif (time_lev_daily < 120) then ; time_lev_monthly = 3
elseif (time_lev_daily < 151) then ; time_lev_monthly = 4
elseif (time_lev_daily < 181) then ; time_lev_monthly = 5
elseif (time_lev_daily < 212) then ; time_lev_monthly = 6
elseif (time_lev_daily < 243) then ; time_lev_monthly = 7
elseif (time_lev_daily < 273) then ; time_lev_monthly = 8
elseif (time_lev_daily < 304) then ; time_lev_monthly = 9
elseif (time_lev_daily < 334) then ; time_lev_monthly = 10
else ; time_lev_monthly = 11
endif

time_lev_daily = time_lev_daily+1
time_lev_monthly = time_lev_monthly+1

select case (CS%wind_nlev)
case (12) ; time_lev = time_lev_monthly
case (365) ; time_lev = time_lev_daily
case default ; time_lev = 1
end select

...

I marked the vital component boldly, you could see there is no case of other time levels except daily cycling and monthly cycling.
So I am thinking how could I add other cases in the source code and make the ball of my project rolling...