-
Notifications
You must be signed in to change notification settings - Fork 33
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
Shallow water run #391
Comments
Thanks for using SpeedyWeather! No these are absolutely reasonable questions. It seems you have read the julia>] add https://github.com/SpeedyWeather/SpeedyWeather.jl#main instead of julia>] status
...
[9e226e20] SpeedyWeather v0.6.0 `https://github.com/SpeedyWeather/SpeedyWeather.jl#main`
... Sorry! The examples in the documentation are only a few weeks old. Can you post here if you keep having problems running the examples? |
That works fine! Thanks! I installed the |
The shallow water model does not have a vertical coordinate. Velocities here are assumed to be layer averages, whereby the layer starts at the surface (incl some orography) and has a thickness of
julia> u = randn(FullGaussianGrid,24)
julia> v = randn(FullGaussianGrid,24)
julia> RingGrids.scale_coslat⁻¹!(u)
julia> RingGrids.scale_coslat⁻¹!(v)
julia> us = spectral(u,one_more_degree=true)
julia> vs = spectral(u,one_more_degree=true)
julia> div = SpeedyTransforms.divergence(us,vs)
julia> curl = SpeedyTransforms.curl(us,vs) Both div and curl are now divergence and curl in spectral space but scaled with the radius of the Earth. julia> spectral_grid = SpectralGrid(trunc=31,nlev=1)
julia> initial_conditions = StartFromRest()
julia> model = ShallowWaterModel(;spectral_grid,initial_conditions)
julia> simulation = initialize!(model)
simulation.prognostic_variables.layers[1].timesteps[1].vor .= vor/spectral_grid.radius
simulation.prognostic_variables.layers[1].timesteps[1].div .= div/spectral_grid.radius
julia> run!(simulation,n_days=10) |
It's very convenient! Thanks a lots! I wrote some codes to do my job by following yours:
using NCDatasets
ds_u = NCDataset("G:/SpeedyWeather/test/test_IC/u800.nc")
ds_v = NCDataset("G:/SpeedyWeather/test/test_IC/v800.nc")
u = Matrix{Float32}(ds_u["ucomp"])
v = Matrix{Float32}(ds_v["vcomp"])
using SpeedyWeather
u = FullGaussianGrid(u)
v = FullGaussianGrid(v)
RingGrids.scale_coslat⁻¹!(u)
RingGrids.scale_coslat⁻¹!(v)
us = spectral(u,one_more_degree=true)
vs = spectral(v,one_more_degree=true)
div = SpeedyTransforms.divergence(us,vs)
vor = SpeedyTransforms.curl(us,vs)
spectral_grid = SpectralGrid(trunc=31,nlev=1)
initial_conditions = StartFromRest()
output = OutputWriter(spectral_grid,ShallowWater,
output_vars=[:u,:v])
model = ShallowWaterModel(;spectral_grid,initial_conditions,output=output)
simulation = initialize!(model)
simulation.prognostic_variables.layers[1].timesteps[1].vor .= vor/spectral_grid.radius
simulation.prognostic_variables.layers[1].timesteps[1].div .= div/spectral_grid.radius
run!(simulation,n_days=100,output=true) My questions is:
|
Btw thanks for doing this! Based on what users need and functionality they expect I'm planning to provide more convenient functions that will shortcut some of the things I've explained above.
What grid does your original data come on? SpeedyWeather is grid-flexible, in the documentation you can see what grids we support and in the end you just have to define what grid your data comes on, like
In generally doesn't matter. SpeedyWeather uses Float32 as default, but you can use Float64 data too and it'll just use that. You set the number format that's actually used for the simulation in
I assume you mean by matching that it's in geostrophic balance? Technically there is no matching because u,v,h are all independent variables and so you can start with any combination of fields for these three. You can start with which is conveniently if you take the divergence of these two equations (did I miss a minus?) So once you know vorticity you'll need to invert the Laplace operator to get |
Hi @milankl, I guess I have the same need as @mini-DONG. It is like we need to start the SWM from some random pickups of 500 hPa wind and geopotential fields (e.g., from NCEP or ECMWF, regular lat/lon grids). The wind and mass fields are generally not in an exact geostrophic balance, as you suggested (also, it is problematic at equator because |
If you have (The following requires PR #392 to be merged, or use
julia> spectral_grid = SpectralGrid(trunc=31,nlev=1)
julia> forcing = SpeedyWeather.JetStreamForcing(spectral_grid)
julia> drag = QuadraticDrag(spectral_grid)
julia> model = ShallowWaterModel(;spectral_grid,forcing,drag)
julia> simulation = initialize!(model);
julia> run!(simulation,n_days=30)
julia> u = simulation.diagnostic_variables.layers[1].grid_variables.u_grid
julia> v = simulation.diagnostic_variables.layers[1].grid_variables.v_grid
julia> vor = SpeedyTransforms.curl(u,v) / spectral_grid.radius Note that the operators in SpeedyTransforms all act on the unit sphere, so we divide by the radius
julia> vor_grid = gridded(vor,Grid=spectral_grid.Grid);
julia> f = SpeedyWeather.coriolis(vor_grid);
julia> fζ_g = spectral_grid.Grid(vor_grid .* f ./ model.planet.gravity) The last line is currently a bit awkward because Now we invert the Laplace operator in spectral space and don't forget to account for the omitted radius scaling of that operation. You can now use julia> fζ_g_spectral = spectral(fζ_g,one_more_degree=true);
julia> η = SpeedyTransforms.∇⁻²(fζ_g_spectral) * spectral_grid.radius^2
julia> η_grid = gridded(η,Grid=spectral_grid.Grid)
The velocity field we started from looks like with an actual corresponding Strikingly similar! The remaining differences are the ageostrophic motions but also note that the mean is off! This is because geostrophy only use/defines the gradient of |
Thanks @milankl for your detailed explanations. I made a mistake on this. IIUC, you are talking about how to calculate But sometimes we need |
@milankl thanks a lot! I followed your codes but an error was encountered at: vor = SpeedyTransforms.curl(u,v) with error: MethodError: no method matching curl(::OctahedralGaussianGrid{Float32}, ::OctahedralGaussianGrid{Float32}) Also, I tried the given using SpeedyWeather
spectral_grid = SpectralGrid(trunc=63,nlev=1)
orography = NoOrography(spectral_grid)
initial_conditions = ZonalJet()
model = ShallowWaterModel(;spectral_grid, orography, initial_conditions)
simulation = initialize!(model)
run!(simulation,n_days=6,output=true) The purpose is to get the output's lon/lat grid. After running, I interpolated ERA5 data at SpeedyWeather's output lon/lat. using SpeedyWeather
u = FullGaussianGrid(u)
v = FullGaussianGrid(v)
eta = FullGaussianGrid(eta)
RingGrids.scale_coslat⁻¹!(u)
RingGrids.scale_coslat⁻¹!(v)
RingGrids.scale_coslat⁻¹!(eta)
us = spectral(u,one_more_degree=true)
vs = spectral(v,one_more_degree=true)
etas = spectral(eta,one_more_degree=true)
div = SpeedyTransforms.divergence(us,vs)
vor = SpeedyTransforms.curl(us,vs) spectral_grid = SpectralGrid(trunc=63,nlev=1)
initial_conditions = StartFromRest()
output = OutputWriter(spectral_grid,ShallowWater,
output_vars=[:u,:v,:pres,:vor])
model = ShallowWaterModel(;spectral_grid,initial_conditions,output=output)
simulation = initialize!(model) simulation.prognostic_variables.layers[1].timesteps[1].vor .= vor/spectral_grid.radius
simulation.prognostic_variables.layers[1].timesteps[1].div .= div/spectral_grid.radius
simulation.prognostic_variables.surface.timesteps[1].pres .= etas/spectral_grid.radius
run!(simulation,n_days=100,output=true) Finally, I plotted the output first time of |
The you start from rest initial_conditions = StartFromRest() and set simulation = initialize!(model)
# say you have some data on a grid
eta = randn(FullClenshawGrid,24)
# transform to spectral, depending on input data resolution or model resolution you may need to
# use the `spectral_truncation` function to get the LowerTriangularMatrix` into the right size
eta_spectral = spectral(eta)
# trunc = spectral_grid.trunc
# eta_spectral = spectral_truncation(eta_spectral,trunc+1,trunc)
simulation.prognostic_variables.surface.timesteps[1].pres .= eta_spectral
run!(simulation) Reminder to self (or if anyone else would like to contribute something to SpeedyWeather!) that this might be easier with a set!(simulation.prognostic_variables,η=my_eta_as_grid_or_spectral) function. |
This is because you didn't use the
I believe ERA5 data comes on a regular lon-lat grid, which is almost identical to the
Only vectors need to be scaled by 1/coslat before taking a divergence or curl. Comment out this line.
With #392 merged you can also directly do
Same here.
Don't divide https://speedyweather.github.io/SpeedyWeather.jl/dev/barotropic/#scaling Maybe we should have a single clearer section on how to use SpeedyTransforms with the various aspects of scaling which are scattered across the documentation. I feel this question would come up often. If anyone here would like to give this section a go and create a pull request after what you learned, I'd be happy to review that! Would make it easier for anyone else who has similar questions!
Don't scale eta by 1/coslat, don't divide by the radius and let me know if it's still off! |
The example here is also added to the documentation with #397, I'll close this issue if that PR is merged. However, feel always free to add more comments, questions or open a new issue! |
Hi, It's awesome work here! I want to run a global shallow water model, and I'm reading the documentation. Now, I can run the example like this:
Next, I want to use myself initial field, such as the u,v in 500hpa. How can I add this customized data?
Also, I have a few minor problems in other example of documentation - sometimes errors are reported:
with error:
with error:
Ps: I use the v0.6.0. And I am pretty new to both numerical models and speaking English. So if I'm not clear, please let me know.
The text was updated successfully, but these errors were encountered: