Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
c49edbe
first implementation of LST-DA
jjokella Dec 5, 2024
0fb734a
bugfix: re-introduce default for general update
jjokella Dec 12, 2024
b186564
bugfix: lai is a patch-array
jjokella Dec 12, 2024
35c9c93
bugfix: typo
jjokella Dec 12, 2024
929471f
dev: skin temperature state vector, first implementation
jjokella Dec 12, 2024
0f3738b
dev: skin temperature state vector, first implementation II
jjokella Dec 12, 2024
53998fb
bugfix: t_skin declarations
jjokella Dec 13, 2024
75ac19f
bugfix: location of `newgridcell = .false`
jjokella Jan 23, 2025
34a47ca
LST-DA with TSKIN: use same obs_index_p setting as for TG/TV
jjokella Jan 23, 2025
43d1ba3
LST-DA: state-vector with TSKIN, plus TG and TV
jjokella Jan 23, 2025
3df6fd0
LST-DA: state-vector with TSKIN, plus TSOIL and TV
jjokella Jan 23, 2025
9e88c2a
LST-DA: add debug output for first layer `t_soisno`
jjokella Jan 24, 2025
ff0373a
LST-DA: all temperature layers updated
jjokella Jan 28, 2025
4bd276d
bugfix: LST-DA missing `end do`
jjokella Jan 29, 2025
75eb0ec
Merge branch 'tsmp-pdaf-patched' into tsmp-pdaf-patched-lstda
jjokella Mar 17, 2025
d41c6b2
Merge branch 'tsmp-pdaf-patched' into tsmp-pdaf-patched-lstda
jjokella Apr 25, 2025
0778801
introduce `clmupdate_T.eq.4`
jjokella Apr 25, 2025
6d8babe
Merge branch 'tsmp-pdaf-patched' into tsmp-pdaf-patched-lstda
jjokella Oct 9, 2025
fb67c10
fortitude fixes
jjokella Oct 9, 2025
75f2b8d
keep indentation of SM-case
jjokella Oct 9, 2025
2b7f957
syntax fix
jjokella Oct 9, 2025
6a6706a
line length fixes
jjokella Oct 9, 2025
90cefc6
Merge branch 'tsmp-pdaf-patched' into tsmp-pdaf-patched-lstda
jjokella Oct 17, 2025
9936414
CI-fix: handle clmswc_mask_snow as integer (#29)
jjokella Oct 29, 2025
9625bee
Merge branch 'tsmp-pdaf-patched' into tsmp-pdaf-patched-lstda
jjokella Nov 14, 2025
319bd8c
style changes
jjokella Nov 14, 2025
35b1dc0
set_clm_statevec_T: debug output to dedicated subroutine
jjokella Nov 14, 2025
58501ab
update_clm_T: all declarations to dedicated subroutine
jjokella Nov 14, 2025
3847db7
compilation fixes
jjokella Nov 14, 2025
ee6cc3e
compilation fixes for DEBUG
jjokella Nov 14, 2025
7174f1b
add LSTDA of TSKIN/TVEG (clmupdate_T==5)
jjokella Nov 20, 2025
5c307e5
LSTDA for local filters: first implementation
jjokella Dec 11, 2025
d1cb4d3
bugfix
jjokella Dec 11, 2025
afc7202
bugfix: initialize and use begp, endp throughout init_n_domains_clm
jjokella Dec 11, 2025
95a0e5f
Merge branch 'tsmp-pdaf-patched' into tsmp-pdaf-patched-lstda
jjokella Dec 18, 2025
f9e886b
Merge branch 'tsmp-pdaf-patched-lstda' into tsmp-pdaf-patched-lstda-l…
jjokella Dec 18, 2025
747dee9
correct condition for tsoisno_mype.update.* debug output
jjokella Dec 19, 2025
58025fa
Merge branch 'tsmp-pdaf-patched-lstda' into tsmp-pdaf-patched-lstda-l…
jjokella Dec 19, 2025
38ffe0e
LSTDA: remove unused variants
jjokella Jan 23, 2026
2a5657f
Merge branch 'tsmp-pdaf-patched-lstda' into tsmp-pdaf-patched-lstda-l…
jjokella Jan 23, 2026
e67133a
remove unused index array
jjokella Jan 23, 2026
8eee110
small change
jjokella Jan 23, 2026
249c4ad
remove unused variable `pc`
jjokella Jan 24, 2026
1203bae
remove unused clmupdate_T values
jjokella Jan 24, 2026
b3d0415
LSTDA: remodel clmupdate_T==2 with gridcell-averages
jjokella Jan 24, 2026
78266fc
CLM:T_mask_snow: possibility to remove snow from LSTDA
jjokella Jan 30, 2026
43916e8
LSTDA: only update of first-layer-soil-temperature > freezing point
jjokella Jan 30, 2026
eb2f6bd
Merge branch 'tsmp-pdaf-patched' into tsmp-pdaf-patched-lstda-v2-3
jjokella Feb 13, 2026
cc24bd1
input CLM:T_mask_T: setting the temperature theshold for T-update
jjokella Feb 13, 2026
3cb7dbe
Merge branch 'tsmp-pdaf-patched-lstda' into tsmp-pdaf-patched-lstda-v2-3
jjokella Feb 13, 2026
aebde39
LST-DA: input option CLM:increment_type
jjokella Feb 25, 2026
9eaf7f5
LST-DA: input option CLM:T_max_increment
jjokella Feb 25, 2026
7a39038
Merge branch 'tsmp-pdaf-patched-lstda' into tsmp-pdaf-patched-lstda-v2-3
jjokella Feb 25, 2026
9b58f24
bugfix: remove the increment_type
jjokella Feb 25, 2026
b1f7664
LSTDA: clmupdate_T==3, added t_grnd to state vector
jjokella Feb 25, 2026
5583f0e
bugfixes: if-condition names
jjokella Feb 25, 2026
e6dcd08
LSTDA-bugfix: non-update set correctly
jjokella Feb 26, 2026
bde2960
LSTDA: restrict updates to clmT_max_increment
jjokella Feb 26, 2026
790316b
Merge branch 'tsmp-pdaf-patched-lstda' into tsmp-pdaf-patched-lstda-v2-3
jjokella Feb 27, 2026
2b707f9
LSTDA: smarter increment warning structure
jjokella Feb 27, 2026
2c06239
LSTDA: make observation indexing clmupdate_T independent
jjokella Mar 3, 2026
37dff5d
docs: small update
jjokella Mar 3, 2026
9fa596f
docs: updated documentation for CLM:update_T
jjokella Mar 3, 2026
8bb4e93
lstda: remove per-patch warnings
jjokella Mar 4, 2026
bb57ce5
fortitude fixes
jjokella Mar 5, 2026
7cdf348
docs: LST-DA documentation
jjokella Mar 12, 2026
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
1 change: 1 addition & 0 deletions docs/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ parts:
- file: users_guide/running_tsmp_pdaf/input_cmd
- file: users_guide/running_tsmp_pdaf/input_obs
- file: users_guide/running_tsmp_pdaf/input_enkfpf
- file: users_guide/running_tsmp_pdaf/lst_da

- file: users_guide/debugging_tsmp_pdaf/README
title: Debugging TSMP-PDAF
Expand Down
3 changes: 3 additions & 0 deletions docs/users_guide/running_tsmp_pdaf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ COSMO](cos)). Additionally, a control file for the data assimilation
Furthermore, some command line options ([Command line options](cmd))
need to be specified when TSMP-PDAF is executed.

For assimilation of land surface temperature observations into CLM, see
[Land Surface Temperature Data Assimilation](lstda).

See the Virtual Machine download on webpage
<https://datapub.fz-juelich.de/slts/tsmp-vm/index.html>.

Expand Down
95 changes: 88 additions & 7 deletions docs/users_guide/running_tsmp_pdaf/input_enkfpf.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ statevec_max_layer =
t_printensemble =
watmin_switch =
swc_mask_snow =
T_mask_snow =
increment_type =
T_mask_T =
T_max_increment =

[COSMO]
nprocs =
Expand Down Expand Up @@ -479,16 +483,37 @@ CLM (standalone only).
manual
<https://escomp.github.io/ctsm-docs/versions/release-clm5.0/html/tech_note/index.html>)

(enkfpf:clm:update_T)=
### CLM:update_T ###

`CLM:update_T`: (integer) Flag for updating of ground and vegetation
temperature.
`CLM:update_T`: (integer) Flag for updating temperature variables in
eCLM via LST data assimilation.

Currently only CLM3.5
State vector variables updated for each option:

- 0: No update of ground and vegetation temperature
- 0: No update of temperature variables.

- 1: Update of ground and vegetation temperature
- 1: Update of ground temperature (`t_grnd`) and vegetation
temperature (`t_veg`) directly. The simulated LST is computed from
`t_grnd` and `t_veg` using a radiometric mixing formula
([Kustas & Anderson, 2009](https://doi.org/10.1016/j.agrformet.2009.05.016),
Eq. 7) with LAI.

- 2: Gridcell-mean update of skin temperature (`t_skin`, not
prognostic), soil/snow temperatures (`t_soisno`, all `nlevgrnd`
layers), and vegetation temperature (`t_veg`). Each patch/column is
updated based on gridcell-mean increments and according to selected
[increment type](enkfpf:clm:increment_type). The observation
operator uses the skin temperature (TSKIN) as the simulated LST
equivalent.

- 3: Like `2`, but additionally updates ground temperature
(`t_grnd`). State vector: `t_skin`, `t_soisno` (`nlevgrnd`
layers), `t_veg`, `t_grnd`.


See [Land Surface Temperature Data Assimilation](lstda) for a detailed
description.

### CLM:print_swc ###

Expand Down Expand Up @@ -595,12 +620,62 @@ are allowed.
`CLM:swc_mask_snow`: (integer) Switch for masking columns with snow
cover from SWC updates.

Snow covers larger than 1mm are switched off for the update.
Columns with snow depth ≥ 1 mm are excluded from the update.

Only takes effect if `CLM:update_swc``is switched on.

Default setting is `0`: No masking of columns with snow cover.

(enkfpf:clm:T_mask_snow)=
### CLM:T_mask_snow ###

`CLM:T_mask_snow`: (integer) Switch for masking columns with snow
cover from T updates.

Snow covers larger than 1mm are switched off for the update.

Only takes effect if `CLM:update_T` is switched on.

Default setting is `0`: No masking of columns with snow cover.

(enkfpf:clm:increment_type)=
### CLM:increment_type ###

`CLM:increment_type`: (integer) Switch for changing increment type in
T-update.

- `0`: Multiplicative increment
- `1`: Additive increment

Only takes effect if `CLM:update_T` is switched on.

Default setting is `0`: Multiplicative increment.

(enkfpf:clm:T_max_increment)=
### CLM:T_max_increment ###

`CLM:T_max_increment`: (double) Maximum allowed magnitude of the
additive temperature increment (K).

Only takes effect if `CLM:update_T` is switched on and
`CLM:increment_type` is set to `1`.

Default setting is `5.0`: Updates larger than 5K are not applied.

(enkfpf:clm:T_mask_T)=
### CLM:T_mask_T ###

`CLM:T_mask_T`: (double) Offset above freezing (K) used as the
lower-temperature masking threshold. The update is suppressed whenever

```
t_soisno(:,1) < 273.15 K + CLM:T_mask_T.
```

Only takes effect if `CLM:update_T` is switched on.

Default setting is `0.`: Masking updates below freezing temperatures.

(enkfpf:cosmo)=
## [COSMO] ##

Expand Down Expand Up @@ -862,7 +937,7 @@ Default: 0, output turned off.
## Parameter Summary ##

| section | parameter | default value |
|:---------:|:-----------------------:|:-------------:|
|:----------|:------------------------|:--------------|
| `[PF]` | | |
| | `problemname` | \- |
| | `nprocs` | 0 |
Expand Down Expand Up @@ -892,6 +967,8 @@ Default: 0, output turned off.
| | `problemname` | \- |
| | `nprocs` | 0 |
| | `update_swc` | 1 |
| | `update_texture` | 0 |
| | `update_T` | 0 |
| | `print_swc` | 0 |
| | `print_et` | 0 |
| | `statevec_allcol` | 0 |
Expand All @@ -900,6 +977,10 @@ Default: 0, output turned off.
| | `statevec_max_layer` | 25 |
| | `t_printensemble` | -2 |
| | `watmin_switch` | 0 |
| | `T_mask_snow` | 0 |
| | `increment_type` | 0 |
| | `T_max_increment` | 5.0 |
| | `T_mask_T` | 0.0 |
| `[COSMO]` | | |
| | `nprocs` | 0 |
| | `dtmult` | 0 |
Expand Down
166 changes: 166 additions & 0 deletions docs/users_guide/running_tsmp_pdaf/lst_da.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
(lstda)=
# Land Surface Temperature Data Assimilation #

Land Surface Temperature data assimilation (LST-DA) in TSMP-PDAF enables
the assimilation of remotely-sensed land surface temperature (LST)
observations into the eCLM land-surface model. The analysis step updates
one or more temperature variables in the CLM state, and auxiliary masking
and increment-clipping parameters allow the update to be restricted to
physically meaningful regimes.

## Configuration ##

LST-DA is controlled by five parameters in the [`[CLM]` section of
`enkfpf.par`](enkfpf:clm):

- [`CLM:update_T`](enkfpf:clm:update_T): selects which CLM temperature
variables are placed in the state vector and updated after the analysis
step.
- [`CLM:T_mask_snow`](enkfpf:clm:T_mask_snow): optionally masks out
columns with snow cover from the temperature update.
- [`CLM:increment_type`](enkfpf:clm:increment_type): switches between
multiplicative (default) and additive increments.
- [`CLM:T_max_increment`](enkfpf:clm:T_max_increment): clips additive
increments to a maximum magnitude (only relevant when
`CLM:increment_type=1`).
- [`CLM:T_mask_T`](enkfpf:clm:T_mask_T): masks out columns whose
surface-layer soil temperature falls below a threshold close to
freezing.

When LST-DA is active (`CLM:update_T != 0`), the temperature state
variables replace the soil water content (SWC) in the state vector.
Simultaneous assimilation of SWC and LST in the same PDAF update step is
not supported.

## State Vector ##

The state vector content depends on `CLM:update_T`. For options 2 and 3
the state vector is defined at the gridcell level (one value per grid
cell); for option 1 it is defined at the patch level.

| `update_T` | State vector variables |
|:-----------|:-------------------------------------------------------------|
| `1` | `t_grnd` (per patch) + `t_veg` (per patch) |
| `2` | `t_skin` (per gridcell) + `t_soisno` (all `nlevgrnd` layers) |
| | + `t_veg` (per gridcell) |
| `3` | Same as `2`, plus `t_grnd` (per gridcell) |

## Observation Operator ##

The observation operator maps the CLM state to a simulated LST:

- **Option 1**: The simulated LST is computed from `t_grnd` and
`t_veg` using the radiometric mixing formula of [Kustas & Anderson
(2009)](https://doi.org/10.1016/j.agrformet.2009.05.016) (Eq. 7),
weighted by leaf area index (LAI).
- **Options 2 and 3**: The skin temperature `t_skin` is used directly as
the simulated LST. Observations are indexed at the gridcell level
(one observation per grid cell).

## Increment Application ##

After the PDAF analysis step, the updated state vector values are written
back to the CLM temperature arrays. Two increment modes are available,
selected via [`CLM:increment_type`](enkfpf:clm:increment_type):

**Multiplicative increment** (`CLM:increment_type=0`, default):
Each temperature variable is scaled by the ratio of the posterior to the
prior gridcell-mean skin temperature:

```
t_update = t_prior × (TSKIN_out / TSKIN_in)
```

**Additive increment** (`CLM:increment_type=1`):
The difference between posterior and prior gridcell-mean TSKIN is added
directly to each temperature variable:

```
t_update = t_prior + (TSKIN_out - TSKIN_in)
```

When `CLM:increment_type=1`, the increment is clipped to
`±CLM:T_max_increment` (default 5 K). Increments that exceed this
threshold are replaced by the clipped value and a warning counter is
incremented; the total number of clipped increments is printed after each
analysis step.

## Masking ##

Two independent masking conditions can suppress the update for individual
columns or grid cells:

**Snow masking** (`CLM:T_mask_snow`): When set to `1`, columns with a
snow depth ≥ 1 mm are excluded from the temperature update. This avoids
applying a bare-soil LST increment to snow-covered grid cells.

**Freeze masking** (`CLM:T_mask_T`): The update is suppressed whenever
the soil/snow temperature of the surface layer (`t_soisno(:,1)`) falls
below `T_freeze + CLM:T_mask_T`. With the default value of `0`, this
masks all grid cells at or below the freezing point (273.15 K).

Both masks are evaluated independently for each patch or column.

## Safety Checks ##

- NaN checks are applied to all updated temperature variables; a warning
is printed to stdout if a NaN value is detected.
- Clipped additive increments are counted per analysis step and the total
is printed for `t_skin`, `t_soisno`, `t_veg`, and `t_grnd` separately.
- The update is skipped entirely for a given patch/column if the
gridcell-mean TSKIN change falls below `1e-7 K` (numerical tolerance).

## Configuration Examples ##

### Assimilate LST into ground and vegetation temperature (option 1) ###

```text
[CLM]
update_T = 1
increment_type = 0
```

The simulated LST is computed from `t_grnd` and `t_veg` via the
[Kustas & Anderson (2009)](https://doi.org/10.1016/j.agrformet.2009.05.016)
radiometric mixing formula. Both variables are updated with a
multiplicative increment.

### Assimilate LST into skin and soil temperature (option 2) ###

```text
[CLM]
update_T = 2
increment_type = 0
T_mask_snow = 1
T_mask_T = 0.0
```

TSKIN is used as the simulated LST. After analysis, `t_skin`, all
`t_soisno` layers, and `t_veg` are scaled by the TSKIN increment factor.
Snow-covered columns are excluded from the update.

### Assimilate LST with additive increment and clipping (option 2) ###

```text
[CLM]
update_T = 2
increment_type = 1
T_max_increment = 3.0
T_mask_T = 2.0
```

The TSKIN increment is applied additively and clipped to ±3 K. Grid cells
whose surface-layer temperature falls below 275.15 K (freezing + 2 K) are
excluded.

### Assimilate LST including ground temperature (option 3) ###

```text
[CLM]
update_T = 3
increment_type = 0
T_mask_snow = 1
```

Like option 2, but `t_grnd` is additionally included in the state vector
and updated. Snow-covered columns are masked out.
Loading
Loading