-
Notifications
You must be signed in to change notification settings - Fork 17
Open
Labels
Description
@AnasAbdelR To emulate SpeedyWeather for the RainMaker challenge (10 parameters, 1 output parameter) I suggest the following
using RainMaker # current main, I will release a new version at JuliaEO
using SpeedyWeather
const PARAMETER_KEYS = (
:orography_scale, # [1], default: 1, scale of global orography
:mountain_height, # [m], default: 0, height of an additional azores mountain
:mountain_size, # [˚], default: 1, horizontal size of an additional azores mountain
:mountain_lon, # [˚E], default: -27.25, longitude of an additional azores mountain
:mountain_lat, # [˚N], default: 38.7, latitude of an additional azores mountain
:temperature_equator, # [K], default: 300, sea surface temperature at the equator
:temperature_pole, # [K], default: 273, sea surfaec temperature at the poles
:temperature_atlantic, # [K], default: 0, sea surface temperature anomaly in the atlantic
:temperature_azores, # [K], default: 0, sea surface temperature anomaly at the azores
:zonal_wind, # [m/s], default: 35, zonal wind speed
)
const PARAMETER_DEFAULTS = [1, 0, 1, -27.25, 38.7, 300, 273, 0, 0, 35]
function max_precipitation(parameters::AbstractVector)
parameter_tuple = NamedTuple{PARAMETER_KEYS}(parameters)
return max_precipitation(parameter_tuple)
end
function max_precipitation(parameters::NamedTuple)
# define resolution. Use trunc=42, 63, 85, 127, ... for higher resolution, cubically slower
spectral_grid = SpectralGrid(trunc=31, nlayers=8)
# Define AquaPlanet ocean, for idealised sea surface temperatures
# but don't change land-sea mask = retain real ocean basins
ocean = AquaPlanet(spectral_grid,
temp_equator=parameters.temperature_equator,
temp_poles=parameters.temperature_pole)
initial_conditions = InitialConditions(
vordiv = ZonalWind(u₀=parameters.zonal_wind),
temp = JablonowskiTemperature(u₀=parameters.zonal_wind),
pres = PressureOnOrography(),
humid = ConstantRelativeHumidity())
orography = EarthOrography(spectral_grid, scale=parameters.orography_scale)
# construct model
model = PrimitiveWetModel(spectral_grid; ocean, initial_conditions, orography)
# Add rain gauge, locate on Terceira Island
rain_gauge = RainGauge(spectral_grid, lond=-27.25, latd=38.7)
add!(model, rain_gauge)
# Initialize
simulation = initialize!(model, time=DateTime(2025, 1, 10))
# Add additional mountain
H = parameters.mountain_height
λ₀, φ₀, σ = parameters.mountain_lon, parameters.mountain_lat, parameters.mountain_size
set!(model, orography=(λ,φ) -> H*exp(-spherical_distance((λ,φ), (λ₀,φ₀), radius=360/2π)^2/2σ^2), add=true)
# set sea surface temperature anomalies
# 1. Atlantic
set!(simulation, sea_surface_temperature=
(λ, φ) -> (30 < φ < 60) && (270 < λ < 360) ? parameters.temperature_atlantic : 0, add=true)
# 2. Azores
A = parameters.temperature_azores
λ_az, φ_az, σ_az = -27.25, 38.7, 4 # location [˚], size [˚] of Azores
set!(simulation, sea_surface_temperature=
(λ, φ) -> A*exp(-spherical_distance((λ,φ), (λ_az,φ_az), radius=360/2π)^2/2σ_az^2), add=true)
# Run simulation for 20 days, maybe longer for more stable statistics? Could be increased to 30, 40, ... days ?
run!(simulation, period=Day(20))
# skip first 5 days, as is done in the RainMaker challenge
RainMaker.skip!(rain_gauge, Day(5))
# evaluate rain gauge
lsc = rain_gauge.accumulated_rain_large_scale
conv = rain_gauge.accumulated_rain_convection
total_precip = maximum(lsc) + maximum(conv)
return total_precip
end
So that for example
julia> max_precipitation(PARAMETER_DEFAULTS)
[ Info: RainGauge{Float32, AnvilInterpolator{Float32, OctahedralGaussianGrid}} callback added with key callback_rZgV
Weather is speedy: 100%|█████████████████████| Time: 0:00:06 (775.84 years/d
ay)
12.624438f0
yields 12.6mm of rain, which is the value we want to maximise. So you can simply pass on a vector of length 10 to explore the parameter space. Not all parameter values make sense or are even stable. When the model blows up, there's a warning printed and the precipitation will not further be accumulated. E.g.
julia> max_precipitation(randn(10))
[ Info: RainGauge{Float32, AnvilInterpolator{Float32, OctahedralGaussianGrid}} callback added with key callback_l8vG
┌ Warning: NaN or Inf detected at time step 1
└ @ SpeedyWeather ~/git/SpeedyWeather.jl/src/output/feedback.jl:144
0.0f0
blows up immediately, likely because of negative temperatures. Hope this is a good starting point. We can probably iterate here over the next days? Also very happy to reserve some time at the workshop, given we're only presenting on the Friday