Skip to content

Commit 1b8f227

Browse files
committed
docs [skip ci]
1 parent 34cadc8 commit 1b8f227

File tree

7 files changed

+210
-68
lines changed

7 files changed

+210
-68
lines changed

docs/list_tutorials.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ tutorials = [
2626
"Coarse Sand Evaporation" => "standalone/Soil/evaporation.jl",
2727
"Gilat Loess Evaporation" => "standalone/Soil/evaporation_gilat_loess.jl",
2828
"Bare soil site" => "standalone/Soil/sublimation.jl",
29+
"Changing soil parameterizations" => "standalone/Soil/changing_soil_parameterizations.jl",
2930
],
3031
"Canopy" => [
3132
"Standalone Canopy" => "standalone/Canopy/canopy_tutorial.jl",
33+
"Changing canopy parameterizations" => "standalone/Canopy/changing_canopy_parameterizations.jl",
3234
],
3335
"Snow" => [
3436
"standalone/Snow/base_tutorial.jl",

docs/src/APIs/ClimaLand.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
```@meta
44
CurrentModule = ClimaLand
55
```
6-
## LSM Model Types and methods
6+
## Integrated Land Model Types and methods
77

88
```@docs
9+
ClimaLand.LandModel
10+
ClimaLand.SoilCanopyModel
11+
ClimaLand.LandHydrology
912
ClimaLand.LandSoilBiogeochemistry
1013
ClimaLand.LandHydrology
1114
ClimaLand.land_components
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,127 @@
11
# # Fluxnet forcing data: LAI, radiation, and atmospheric variables
2+
3+
# To access the forcing data (LAI from MODIS, SW_d, LW_d, T_air, q_air,
4+
# P_air, and precipitation from fluxtower data), you first need the
5+
# the fluxtower site ID.
6+
# Currently, ClimaLand provides an interface for working with four
7+
# fluxtower sites; adding support for a much larger set of sites is
8+
# in progress. The sites we support are Vaira Ranch (US_Var),
9+
# Missouri Ozark (US-MOz), Niwot Ridge (US-NR1), and Harvard Forest
10+
# (US-Ha1).
11+
12+
using Dates
13+
import ClimaParams as CP
14+
using ClimaLand
15+
using ClimaLand.Domains: Column
16+
import ClimaLand.Parameters as LP
17+
using DelimitedFiles
18+
using CairoMakie
19+
import ClimaLand.FluxnetSimulations as FluxnetSimulations
20+
21+
# Pick a site ID; convert the dash to an underscore:
22+
site_ID = "US-NR1";
23+
site_ID_val = FluxnetSimulations.replace_hyphen(site_ID)
24+
# The functions we use below use multiple dispatch, treating the
25+
# site_ID_val as a Julia type.
26+
27+
# First, we need the latitude and longitude of the site. These are used
28+
# to get the zenith angle as a function of time, and to look up
29+
# default parameters using the global ClimaLand parameter maps. We also
30+
# need the offset of the local time of the site in hours from UTC. This is
31+
# because ClimaLand simulations are carried out in UTC, while the fluxtower
32+
# data is reported in local time.
33+
(; time_offset, lat, long) =
34+
FluxnetSimulations.get_location(FT, Val(site_ID_var));
35+
36+
# ClimaLand also needs to know the height at which the atmospheric data
37+
# was recorded.
38+
(; atmos_h) = FluxnetSimulations.get_fluxtower_height(FT, Val(site_ID));
39+
40+
# It is also useful to know the bounds of the data,
41+
# in UTC, to use as the start and stop date of the simulation.
42+
(start_date, stop_date) =
43+
FluxnetSimulations.get_data_dates(site_ID, time_offset);
44+
45+
# Define the floating point precision desired (64 or 32 bit), and get the
46+
# parameter set holding constants used across CliMA Models.
47+
const FT = Float32;
48+
earth_param_set = LP.LandParameters(FT);
49+
50+
# Now we can construct the forcing objects. Under the hood, this
51+
# function finds the local path to the fluxtower data (and downloads it
52+
# if it is not present) and reads the data in. It then creates
53+
# two objects, one called `atmos`, of type `PrescibedAtmosphere`, and
54+
# one called `radiation`, of type `PrescribedRadiativeFluxes`. These
55+
# encode the data in interpolating functions which allow us to
56+
# estimate the forcing at any time during the simulation using linear
57+
# interpolation across gaps in the data.
58+
(; atmos, radiation) = FluxnetSimulations.prescribed_forcing_fluxnet(
59+
site_ID,
60+
lat,
61+
long,
62+
time_offset,
63+
atmos_h,
64+
start_date,
65+
earth_param_set,
66+
FT,
67+
);
68+
# The atmosphere object holds the air temperature, pressure, specific
69+
# humidity, wind speed, and liquid and solid precipitation fluxes.
70+
# Since many fluxtower sites do not measure the snow and rain fluxes
71+
# separately, we estimate them internally. This is optional, and by providing
72+
# the kwarg `split_precip = false`, you can change the behavior to
73+
# return all measured precip as a liquid water flux.
74+
# The radiation object holds the downwelling short and long wave
75+
# radiative fluxes. The diffuse fraction is estimated internally
76+
# using an empirical function, and the zenith angle is computed
77+
# analytically.
78+
79+
# The simulation time is measured in seconds since the `start_date`. We
80+
# can get the atmospheric temperature at the `start_date` as follows:
81+
sim_time = 0.0
82+
T = [NaN]
83+
evaluate!(T, atmos.T, sim_time);
84+
@show T
85+
# Note that `evaluate!` updates `T` in place. This is important: in our
86+
# simulations, we allocate memory for the forcing, and then update the values
87+
# at each step. If we did not do this, the dynamic memory allocation
88+
# would cause the simulation to be incredibly slow.
89+
# We can also plot the interpolated air temperature for the first day:
90+
sim_times = 0.0:1800.0:86400.0 # one day in seconds
91+
air_temps = [atmos.T(t) for t in sim_times] # allocates
92+
fig = CairoMakie.Figure()
93+
ax = CairoMakie.Axis(
94+
fig[1, 1],
95+
ylabel = "Temperature (K)",
96+
xlabel = "Date",
97+
title = "Near-surface air temperature at Niwot Ridge",
98+
)
99+
lines!(ax, sim_times .+ start_date, air_temps)
100+
CairoMakie.save("air_temp.png", fig);
101+
# ![](air_temp.png)
102+
103+
# We do something very similar with LAI, but now the data is coming
104+
# from MODIS. In this case, we linearly interpolate from the gridded
105+
# MODIS data to the latitude and longitude of the site. To do spatial
106+
# interpolation, we need to create a ClimaLand domain.
107+
domain = Column(; zlim = (-3.0, 0.0), nelements = 10, longlat = (long, lat))
108+
surface_space = domain.space.surface
109+
# Get the paths to each year of MODIS data within the start and stop dates.
110+
modis_lai_ncdata_path = ClimaLand.Artifacts.modis_lai_multiyear_paths(;
111+
context = ClimaComms.context(surface_space),
112+
start_date,
113+
end_date = stop_date,
114+
)
115+
LAI = ClimaLand.prescribed_lai_modis(
116+
modis_lai_ncdata_path,
117+
surface_space,
118+
start_date,
119+
);
120+
121+
# Just like with the air temperature, the LAI is an object that we can use
122+
# to linearly interpolate observed LAI to any simulation time.
123+
124+
# It can also be useful to know the maximum LAI at a site. To do so, we
125+
# can call, for the first year of data (first element of `modis_lai_ncdata_path`):
126+
maxLAI =
127+
FluxnetSimulations.get_maxLAI_at_site(modis_lai_ncdata_path[1], lat, long)

docs/src/tutorials/integrated/snowy_land_fluxnet_tutorial.jl

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
# # Fluxnet simulations with the full land model: snow, soil, canopy
22

33
# In the
4-
# [`previous tutorial`](@ref https://clima.github.io/ClimaLand.jl/dev/generated/soil_canopy_tutorial/),
4+
# [canopy and soil tutorial](docs/src/tutorials/integrated/soil_canopy_fluxnet_tutorial.md),
55
# we demonstrated how to run the an integrated model with a soil and
66
# canopy component at the US-MOz fluxnet site.
77
# Here we add in a snow component, and run the site at the Niwot Ridge site instead.
8-
# Again, the focus of this tutorial is to learn the steps towards setting up and
9-
# running an integrated simulation, and less on the parameterization choices.
10-
# As such, the default parameters are implicitly set. To experiment with
11-
# modularity in the parameters and parameterizations, please see tutorial X.
8+
9+
# The focus of this tutorial is to learn the steps towards setting up and
10+
# running an integrated simulation, and less on the parameterization
11+
# choices. As such, the default parameters are implicitly set.
12+
# To experiment with modularity in the parameters and parameterizations, please see the [canopy parameterizations tutorial](docs/src/tutorials/standalone/Canopy/changing_canopy_parameterizations.md) or the [soiil parameterizations tutorial](docs/src/tutorials/standalone/Soil/changing_soil_parameterizations.md).
1213

1314
# # Preliminary Setup
1415
using Dates
@@ -19,35 +20,35 @@ using ClimaLand.Domains: Column
1920
using ClimaLand.Simulations
2021
import ClimaLand.Parameters as LP
2122
using DelimitedFiles
22-
FluxnetSimulationsExt =
23-
Base.get_extension(ClimaLand, :FluxnetSimulationsExt).FluxnetSimulationsExt;
23+
import ClimaLand.FluxnetSimulations as FluxnetSimulations
2424
using CairoMakie, ClimaAnalysis, GeoMakie, Poppler_jll, Printf, StatsBase
25-
LandSimulationVisualizationExt =
26-
Base.get_extension(
27-
ClimaLand,
28-
:LandSimulationVisualizationExt,
29-
).LandSimulationVisualizationExt;
25+
import ClimaLand.LandSimVis as LandSimVis;
3026

3127
# Define the floating point precision desired (64 or 32 bit), and get the
3228
# parameter set holding constants used across CliMA Models.
3329

3430
const FT = Float32;
3531
earth_param_set = LP.LandParameters(FT);
3632

37-
# We will use prescribed atmospheric and radiative drivers from the
38-
# US-NR1 tower, which we read in here. We also
33+
# We will use prescribed atmospheric and radiative forcing from the
34+
# US-NR1 tower. We also
3935
# read in the MODIS LAI and let that vary in time in a prescribed manner.
40-
site_ID = "US-NR1"
41-
time_offset = 7 # Timezone (offset from UTC in hrs)
42-
lat = FT(40.0329) # degree
43-
long = FT(-105.5464) # degree
44-
atmos_h = FT(21.5); # Height of the sensor at the site (m)
36+
site_ID = "US-NR1";
37+
site_ID_val = FluxnetSimulations.replace_hyphen(site_ID)
38+
# Get the latitude and longitude in degrees, as well as the
39+
# time offset in hours of local time from UTC
40+
(; time_offset, lat, long) =
41+
FluxnetSimulations.get_location(FT, Val(site_ID_val));
42+
# Get the height of the sensors in m
43+
(; atmos_h) = FluxnetSimulations.get_fluxtower_height(FT, Val(site_ID_val));
44+
# Set a start and stop date of the simulation in UTC, as well as
45+
# a timestep in seconds
4546
(start_date, stop_date) =
46-
FluxnetSimulationsExt.get_data_dates(site_ID, time_offset) # in UTC
47-
Δt = 450.0; # seconds
47+
FluxnetSimulations.get_data_dates(site_ID, time_offset)
48+
Δt = 450.0;
4849

4950
# Forcing data for the site - this uses our interface for working with Fluxnet data
50-
forcing = FluxnetSimulationsExt.prescribed_forcing_fluxnet(
51+
forcing = FluxnetSimulations.prescribed_forcing_fluxnet(
5152
site_ID,
5253
lat,
5354
long,
@@ -67,20 +68,23 @@ LAI = ClimaLand.prescribed_lai_modis(
6768
domain.space.surface,
6869
start_date,
6970
);
70-
# Setup the domain for the model:
71-
zmin = FT(-5) # in m
71+
# Setup the domain for the model. This corresponds to
72+
# a column of 2m in depth, with 10 equally spaced layers.
73+
# The lat and long are provided so that we can look up default parameters
74+
# for this location using the default ClimaLand parameter maps.
75+
zmin = FT(-2) # in m
7276
zmax = FT(0) # in m
7377
domain = Column(; zlim = (zmin, zmax), nelements = 10, longlat = (long, lat))
7478

7579
# # Setup the integrated model
7680

7781
# We want to simulate the canopy-soil-snow system together, so the model type
78-
# [`LandModel`](https://clima.github.io/ClimaLand.jl/dev/APIs/ClimaLand/#LSM-Model-Types-and-methods)
82+
# [`LandModel`](https://clima.github.io/ClimaLand.jl/dev/APIs/ClimaLand/#Integrated-Land-Model-Types-and-methods)
7983
# is chosen. Here we use the highest level model constructor, which uses default parameters,
8084
# and parameterizations, for the soil, snow, and canopy models.
81-
# A different tutorial will show you how to change these parameters and parameterizations.
85+
8286
land_model = LandModel{FT}(forcing, LAI, earth_param_set, domain, Δt);
83-
set_ic! = FluxnetSimulationsExt.make_set_fluxnet_initial_conditions(
87+
set_ic! = FluxnetSimulations.make_set_fluxnet_initial_conditions(
8488
site_ID,
8589
start_date,
8690
time_offset,
@@ -119,3 +123,4 @@ LandSimulationVisualizationExt.make_timeseries(
119123
short_names = ["swc", "si", "swe"],
120124
spinup_date = start_date + Day(20),
121125
);
126+
# ![](variable_timeseries.png)

docs/src/tutorials/integrated/soil_canopy_fluxnet_tutorial.jl

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
# # Fluxnet simulations with an integrated soil and canopy model
22

33
# In the
4-
# [`previous tutorial`](@ref https://clima.github.io/ClimaLand.jl/dev/generated/soil_plant_hydrology_tutorial/),
4+
# [standalone canopy tutorial](docs/src/tutorials/standalone/Canopy/canopy_tutorial.md),
55
# we demonstrated how to run the canopy model in
6-
# standalone mode using prescribed values for the inputs of soil moisture
7-
# and ground temperature
8-
# into the canopy hydraulics model. However, ClimaLand can also
9-
# integrate the canopy model with a soil model and timestep the two
10-
# components together to simulate an interacting canopy-soil system. This tutorial
11-
# demonstrates how to setup and run an integrated simulation, again using
12-
# initial conditions, atmospheric and radiative flux conditions, and leaf
13-
# area index observed at the US-MOz flux tower, a flux tower located within an
14-
# oak-hickory forest in Ozark, Missouri, USA.
6+
# standalone mode using a prescribed soil moisture
7+
# and ground temperature. ClimaLand can also
8+
# integrate the canopy model with a prongostic soil model
9+
# and timestep the two components together to simulate an
10+
# interacting canopy-soil system. This tutorial
11+
# demonstrates how to set that up.
12+
# We use initial conditions, atmospheric and radiative flux conditions,
13+
# and leaf area index observed at the US-MOz flux tower, a flux tower
14+
# located within an oak-hickory forest in Ozark, Missouri, USA.
15+
1516
# The focus of this tutorial is to learn the steps towards setting up and
16-
# running an integrated simulation, and less on the parameterization choices.
17-
# As such, the default parameters are implicitly set. To experiment with
18-
# modularity in the parameters and parameterizations, please see tutorial X.
17+
# running an integrated simulation, and less on the parameterization
18+
# choices. As such, the default parameters are implicitly set.
19+
# To experiment with modularity in the parameters and parameterizations, please see the [canopy parameterizations tutorial](docs/src/tutorials/standalone/Canopy/changing_canopy_parameterizations.md) or the [soiil parameterizations tutorial](docs/src/tutorials/standalone/Soil/changing_soil_parameterizations.md).
1920

2021
# # Preliminary Setup
2122
using Dates
@@ -26,35 +27,36 @@ using ClimaLand.Domains: Column
2627
using ClimaLand.Simulations
2728
import ClimaLand.Parameters as LP
2829
using DelimitedFiles
29-
FluxnetSimulationsExt =
30-
Base.get_extension(ClimaLand, :FluxnetSimulationsExt).FluxnetSimulationsExt;
30+
import ClimaLand.FluxnetSimulations as FluxnetSimulations
3131
using CairoMakie, ClimaAnalysis, GeoMakie, Poppler_jll, Printf, StatsBase
32-
LandSimulationVisualizationExt =
33-
Base.get_extension(
34-
ClimaLand,
35-
:LandSimulationVisualizationExt,
36-
).LandSimulationVisualizationExt;
32+
import ClimaLand.LandSimVis as LandSimVis;
3733

3834
# Define the floating point precision desired (64 or 32 bit), and get the
3935
# parameter set holding constants used across CliMA Models.
4036

4137
const FT = Float32;
4238
earth_param_set = LP.LandParameters(FT);
4339

44-
# We will use prescribed atmospheric and radiative drivers from the
45-
# US-MOz tower, which we read in here. We also
40+
# We will use prescribed atmospheric and radiative forcing from the
41+
# US-MOz tower. We also
4642
# read in the MODIS LAI and let that vary in time in a prescribed manner.
47-
site_ID = "US-MOz"
48-
time_offset = 7 # Timezone (offset from UTC in hrs)
49-
lat = FT(38.7441) # degree
50-
long = FT(-92.2000) # degree
51-
atmos_h = FT(32); # Height of the sensor at the site (m)
43+
site_ID = "US-MOz";
44+
site_ID_val = FluxnetSimulations.replace_hyphen(site_ID)
45+
# Get the latitude and longitude in degrees, as well as the
46+
# time offset in hours of local time from UTC
47+
(; time_offset, lat, long) =
48+
FluxnetSimulations.get_location(FT, Val(site_ID_val));
49+
# Get the height of the sensors in m
50+
(; atmos_h) = FluxnetSimulations.get_fluxtower_height(FT, Val(site_ID_val));
51+
52+
# Set a start and stop date of the simulation in UTC, as well as
53+
# a timestep in seconds
54+
start_date = DateTime("2010-05-01", "yyyy-mm-dd")
55+
stop_date = DateTime("2010-09-01", "yyyy-mm-dd")
56+
Δt = 450.0;
5257

53-
start_date = DateTime("2010-05-01", "yyyy-mm-dd") # in UTC
54-
stop_date = DateTime("2010-09-01", "yyyy-mm-dd") # in UTC
55-
Δt = 450.0; # seconds
5658
# Forcing data for the site - this uses our interface for working with Fluxnet data
57-
forcing = FluxnetSimulationsExt.prescribed_forcing_fluxnet(
59+
forcing = FluxnetSimulations.prescribed_forcing_fluxnet(
5860
site_ID,
5961
lat,
6062
long,
@@ -75,20 +77,22 @@ LAI = ClimaLand.prescribed_lai_modis(
7577
start_date,
7678
);
7779

78-
# Setup the domain for the model:
80+
# Setup the domain for the model. This corresponds to
81+
# a column of 2m in depth, with 10 equally spaced layers.
82+
# The lat and long are provided so that we can look up default parameters
83+
# for this location using the default ClimaLand parameter maps.
7984
zmin = FT(-2) # in m
8085
zmax = FT(0) # in m
81-
domain = Column(; zlim = (zmin, zmax), nelements = 10, longlat = (long, lat))
86+
domain = Column(; zlim = (zmin, zmax), nelements = 10, longlat = (long, lat));
8287

8388
# # Setup the integrated model
8489

85-
# We want to simulate the canopy-soil system together, so the model type
86-
# [`SoilCanopyModel`](https://clima.github.io/ClimaLand.jl/dev/APIs/ClimaLand/#LSM-Model-Types-and-methods)
87-
# is chosen. Here we use the highest level model constructor, which uses default parameters,
90+
# We want to simulate the canopy-soil system together, so we pick the model type
91+
# [`SoilCanopyModel`](https://clima.github.io/ClimaLand.jl/dev/APIs/ClimaLand/#Integrated-Land-Model-Types-and-methods)
92+
# Here we use the highest level model constructor, which uses default parameters,
8893
# and parameterizations, for the soil and canopy models.
89-
# A different tutorial will show you how to change these parameters and parameterizations.
9094
land_model = SoilCanopyModel{FT}(forcing, LAI, earth_param_set, domain);
91-
set_ic! = FluxnetSimulationsExt.make_set_fluxnet_initial_conditions(
95+
set_ic! = FluxnetSimulations.make_set_fluxnet_initial_conditions(
9296
site_ID,
9397
start_date,
9498
time_offset,
@@ -115,8 +119,8 @@ simulation = Simulations.LandSimulation(
115119
);
116120
solve!(simulation);
117121

118-
# # Plotting results
119-
LandSimulationVisualizationExt.make_diurnal_timeseries(
122+
# # Plotting results, ignoring the first 20 days as spinup
123+
LandSimVis.make_diurnal_timeseries(
120124
simulation;
121125
short_names = ["gpp", "shf", "lhf", "swu", "lwu"],
122126
spinup_date = start_date + Day(20),
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

0 commit comments

Comments
 (0)