/
diffusives.jl
130 lines (114 loc) · 4.7 KB
/
diffusives.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
###############################################################################
#
# Calculate diffusive thermo and SIF
#
###############################################################################
"""
diffusive_S(τ_dd::Array{FT},
ρ_dd::Array{FT},
S⁻::Array{FT},
S⁺::Array{FT},
boundary_top::Array{FT},
boundary_bottom::Array{FT},
rsoil::Array{FT}
) where {FT<:AbstractFloat}
Computes 2-stream diffusive radiation transport (used for thermal and SIF) given:
- `τ_dd` A 2D Array with layer reflectances
- `ρ_dd` A 2D Array with layer transmissions
- `S⁻` A 2D Array with layer source terms in the downwelling direction
- `S⁺` A 2D Array with layer source terms in the upwelling direction
- `boundary_top` A 1D array with downwelling radiation at the top (top of canopy)
- `boundary_bottom` A 1D array with upwnwelling radiation at the bottom (soil)
- `rsoil` A 1D array with soil reflectance
"""
function diffusive_S(
τ_dd::Array{FT},
ρ_dd::Array{FT},
S⁻::Array{FT},
S⁺::Array{FT},
boundary_top::Array{FT},
boundary_bottom::Array{FT},
rsoil::Array{FT}
) where {FT<:AbstractFloat}
# Get dimensions (1st is wavelength, 2nd is layers), for Stefab Boltzmann
# just one effective wavelength
nWL,nl = size(τ_dd);
Xdd = similar(τ_dd);
Rdd = zeros(FT,nWL,nl+1)
# Create Y,U matrices (see mSCOPE paper, eqs 30-39)
Y = similar(τ_dd);
U = similar(Rdd);
E⁻ = similar(Rdd);
E⁺ = similar(Rdd);
net_diffuse = similar(τ_dd);
Rdd[:,end] = rsoil
# Source at TOC (0 for SIF, downwelling LW from atmosphere for thermal)
E⁻[:,1] = boundary_top;
# Source at bottom layer (0 for SIF, emitted from soil for thermal)
U[:,end].= boundary_bottom;
@inbounds for j=nl:-1:1 # bottom to top
dnorm = 1 .-ρ_dd[:,j].*Rdd[:,j+1];
Xdd[:,j] = τ_dd[:,j]./dnorm;
Rdd[:,j] = ρ_dd[:,j]+τ_dd[:,j].*Rdd[:,j+1].*Xdd[:,j];
Y[:,j] = (ρ_dd[:,j].*U[:,j+1]+S⁻[:,j])./dnorm;
U[:,j] = τ_dd[:,j].*(Rdd[:,j+1].*Y[:,j]+U[:,j+1])+S⁺[:,j];
end
@inbounds for j=1:nl # from top to bottom
E⁻[:,j+1]= Xdd[:,j].*E⁻[:,j]+Y[:,j];
E⁺[:,j] = Rdd[:,j].*E⁻[:,j]+U[:,j];
end
E⁺[:,end] = Rdd[:,end].*E⁻[:,end]+U[:,end];
# compute net diffuse radiation per layer:
@inbounds for j=1:nl
net_diffuse[:,j]= (E⁻[:,j] + E⁺[:,j+1]).*(1 .-(τ_dd[:,j]+ρ_dd[:,j]))
end
return E⁻,E⁺,net_diffuse
end
"""
diffusive_S!(
sf_con::SFCache{FT},
soil::SoilOpticals{FT},
rt_dim::RTDimensions
) where {FT<:AbstractFloat}
Computes 2-stream diffusive radiation transport (used for thermal and SIF),
given
- `sf_con` [`SFCache`](@ref) type cache
- `soil` [`SoilOpticals`](@ref) type struct
- `rt_dim` [`RTDimensions`](@ref) type struct
"""
function diffusive_S!(
sf_con::SFCache{FT},
soil::SoilOpticals{FT},
rt_dim::RTDimensions
) where {FT<:AbstractFloat}
# 1. unpack values from sf_con
@unpack dnorm, F⁻, F⁺, net_diffuse, Rdd, S⁻, S⁺, U, Xdd, Y, zeroB, ρ_dd,
τ_dd = sf_con;
@unpack ρ_SW_SIF = soil;
@unpack nLayer, nLevel = rt_dim;
# Get dimensions (1st is wavelength, 2nd is layers), for Stefan Boltzmann
# just one effective wavelength
dnorm .= 1 .- view(ρ_dd, :, 1);
Rdd[:,end] .= ρ_SW_SIF;
# Source at TOC (0 for SIF, downwelling LW from atmosphere for thermal)
F⁻[:,1] .= zeroB;
# Source at bottom layer (0 for SIF, emitted from soil for thermal)
U[:,end] .= zeroB;
@inbounds for j=nLayer:-1:1 # bottom to top
dnorm .= 1 .- view(ρ_dd, :, j) .* view(Rdd, :, j+1);
Xdd[:,j] .= view(τ_dd, :, j) ./ dnorm;
Rdd[:,j] .= view(ρ_dd, :, j) .+ view(τ_dd, :, j) .* view(Rdd, :, j+1) .* view(Xdd, :, j);
Y[:,j] .= (view(ρ_dd, :, j) .* view(U, :, j+1) .+ view(S⁻, :, j)) ./ dnorm;
U[:,j] .= view(τ_dd, :, j) .* (view(Rdd, :, j+1) .* view(Y, :, j) .+ view(U, :, j+1)) .+ view(S⁺, :, j);
end
@inbounds for j=1:nLayer # from top to bottom
F⁻[:,j+1] .= view(Xdd, :, j) .* view(F⁻, :, j) .+ view(Y, :, j);
F⁺[:,j ] .= view(Rdd, :, j) .* view(F⁻, :, j) .+ view(U, :, j);
end
F⁺[:,end] .= view(Rdd, :, nLevel) .* view(F⁻, :, nLevel) .+ view(U, :, nLevel);
# compute net diffuse radiation per layer:
@inbounds for j=1:nLayer
net_diffuse[:,j] .= (view(F⁻, :, j) .+ view(F⁺, :, j+1)) .* (1 .- (view(τ_dd, :, j) .+ view(ρ_dd, :, j)));
end
return nothing
end