Skip to content

Commit cfe233d

Browse files
committed
rft: separate vertical and full strain
1 parent 576ac23 commit cfe233d

File tree

7 files changed

+100
-33
lines changed

7 files changed

+100
-33
lines changed

src/cache/diagnostic_edmf_precomputed_quantities.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,8 +1376,7 @@ NVTX.@annotate function set_diagnostic_edmf_precomputed_quantities_env_closures!
13761376
# TODO: Currently the shear production only includes vertical gradients
13771377
ᶠu = p.scratch.ᶠtemp_C123
13781378
@. ᶠu = C123(ᶠinterp(Y.c.uₕ)) + C123(ᶠu³)
1379-
ᶜstrain_rate = p.scratch.ᶜtemp_UVWxUVW
1380-
ᶜstrain_rate .= compute_strain_rate_center(ᶠu)
1379+
ᶜstrain_rate = compute_strain_rate_center_vertical(ᶠu)
13811380
@. ᶜstrain_rate_norm = norm_sqr(ᶜstrain_rate)
13821381

13831382
ρatke_flux_values = Fields.field_values(ρatke_flux)

src/cache/prognostic_edmf_precomputed_quantities.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,7 @@ NVTX.@annotate function set_prognostic_edmf_precomputed_quantities_explicit_clos
451451
# TODO: Currently the shear production only includes vertical gradients
452452
ᶠu = p.scratch.ᶠtemp_C123
453453
@. ᶠu = C123(ᶠinterp(Y.c.uₕ)) + C123(ᶠu³)
454-
ᶜstrain_rate = p.scratch.ᶜtemp_UVWxUVW
455-
ᶜstrain_rate .= compute_strain_rate_center(ᶠu)
454+
ᶜstrain_rate = compute_strain_rate_center_vertical(ᶠu)
456455
@. ᶜstrain_rate_norm = norm_sqr(ᶜstrain_rate)
457456

458457
ρatke_flux_values = Fields.field_values(ρatke_flux)

src/prognostic_equations/edmfx_sgs_flux.jl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -499,8 +499,7 @@ function edmfx_sgs_diffusive_flux_tendency!(
499499
end
500500

501501
# Momentum diffusion
502-
ᶠstrain_rate = p.scratch.ᶠtemp_UVWxUVW
503-
ᶠstrain_rate .= compute_strain_rate_face(ᶜu⁰)
502+
ᶠstrain_rate = compute_strain_rate_face_vertical(ᶜu⁰)
504503
@. Yₜ.c.uₕ -= C12(ᶜdivᵥ(-(2 * ᶠρaK_u * ᶠstrain_rate)) / Y.c.ρ)
505504
end
506505
return nothing
@@ -625,8 +624,7 @@ function edmfx_sgs_diffusive_flux_tendency!(
625624
end
626625

627626
# Momentum diffusion
628-
ᶠstrain_rate = p.scratch.ᶠtemp_UVWxUVW
629-
ᶠstrain_rate .= compute_strain_rate_face(ᶜu)
627+
ᶠstrain_rate = compute_strain_rate_face_vertical(ᶜu)
630628
@. Yₜ.c.uₕ -= C12(ᶜdivᵥ(-(2 * ᶠρaK_u * ᶠstrain_rate)) / Y.c.ρ)
631629
end
632630

src/prognostic_equations/gm_sgs_closures.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ NVTX.@annotate function compute_gm_mixing_length(Y, p)
8484
# TODO: move strain rate calculation to separate function
8585
ᶠu = p.scratch.ᶠtemp_C123
8686
@. ᶠu = C123(ᶠinterp(Y.c.uₕ)) + C123(ᶠu³)
87-
ᶜstrain_rate = p.scratch.ᶜtemp_UVWxUVW
88-
ᶜstrain_rate .= compute_strain_rate_center(ᶠu)
87+
ᶜstrain_rate = compute_strain_rate_center_vertical(ᶠu)
8988
@. ᶜstrain_rate_norm = norm_sqr(ᶜstrain_rate)
9089

9190
ᶜprandtl_nvec = p.scratch.ᶜtemp_scalar_2

src/prognostic_equations/vertical_diffusion_boundary_layer.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ function vertical_diffusion_boundary_layer_tendency!(
104104
end
105105

106106
if !disable_momentum_vertical_diffusion(p.atmos.vertical_diffusion)
107-
ᶠstrain_rate = p.scratch.ᶠtemp_UVWxUVW
108-
ᶠstrain_rate .= compute_strain_rate_face(ᶜu)
107+
ᶠstrain_rate = compute_strain_rate_face_vertical(ᶜu)
109108
@. Yₜ.c.uₕ -= C12(
110109
ᶜdivᵥ(-2 * ᶠinterp(Y.c.ρ) * ᶠinterp(ᶜK_h) * ᶠstrain_rate) / Y.c.ρ,
111110
) # assumes ᶜK_u = ᶜK_h

src/utils/utilities.jl

Lines changed: 91 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -82,43 +82,116 @@ state.
8282
compute_kinetic(Y::Fields.FieldVector) = compute_kinetic(Y.c.uₕ, Y.f.u₃)
8383

8484
"""
85-
ϵ .= compute_strain_rate_center(u::Field)
85+
ϵ .= compute_strain_rate_center_vertical(ᶠu)
8686
87-
Compute the strain_rate at cell centers from velocity at cell faces.
87+
Compute the strain rate at cell centers from velocity at cell faces, with vertical gradients only.
88+
89+
Returns a lazy representation of the strain rate tensor.
8890
"""
89-
function compute_strain_rate_center(u::Fields.Field)
90-
@assert eltype(u) <: C123
91+
function compute_strain_rate_center_vertical(ᶠu)
9192
axis_uvw = Geometry.UVWAxis()
9293
return @. lazy(
9394
(
94-
Geometry.project((axis_uvw,), ᶜgradᵥ(UVW(u))) +
95-
adjoint(Geometry.project((axis_uvw,), ᶜgradᵥ(UVW(u))))
95+
Geometry.project((axis_uvw,), ᶜgradᵥ(UVW(ᶠu))) +
96+
adjoint(Geometry.project((axis_uvw,), ᶜgradᵥ(UVW(ᶠu))))
9697
) / 2,
9798
)
9899
end
99100

100101
"""
101-
ϵ .= compute_strain_rate_face(u::Field)
102+
ϵ .= compute_strain_rate_face_vertical(ᶜu::Field)
103+
104+
Compute the strain rate at cell faces from velocity at cell centers, with vertical gradients only.
102105
103-
Compute the strain_rate at cell faces from velocity at cell centers.
106+
Returns a lazy representation of the strain rate tensor.
104107
"""
105-
function compute_strain_rate_face(u::Fields.Field)
106-
@assert eltype(u) <: C123
107-
∇ᵥuvw_boundary =
108-
Geometry.outer(Geometry.WVector(0), Geometry.UVWVector(0, 0, 0))
109-
ᶠgradᵥ = Operators.GradientC2F(
110-
bottom = Operators.SetGradient(∇ᵥuvw_boundary),
111-
top = Operators.SetGradient(∇ᵥuvw_boundary),
112-
)
108+
function compute_strain_rate_face_vertical(ᶜu)
109+
∇ᵥuvw_boundary = Geometry.outer(Geometry.WVector(0), Geometry.UVWVector(0, 0, 0))
110+
∇bc = Operators.SetGradient(∇ᵥuvw_boundary)
111+
ᶠgradᵥ = Operators.GradientC2F(bottom = ∇bc, top = ∇bc)
113112
axis_uvw = Geometry.UVWAxis()
114113
return @. lazy(
115114
(
116-
Geometry.project((axis_uvw,), ᶠgradᵥ(UVW(u))) +
117-
adjoint(Geometry.project((axis_uvw,), ᶠgradᵥ(UVW(u))))
115+
Geometry.project((axis_uvw,), ᶠgradᵥ(UVW(ᶜu))) +
116+
adjoint(Geometry.project((axis_uvw,), ᶠgradᵥ(UVW(ᶜu))))
118117
) / 2,
119118
)
120119
end
121120

121+
"""
122+
compute_strain_rate_center_full!(ᶜε, ᶜu, ᶠu)
123+
124+
Compute the full strain rate tensor at cell centers from velocity
125+
126+
# Arguments
127+
- `ᶜε`: Preallocated `UVW x UVW` tensor field for the strain rate at cell centers
128+
- `ᶜu, ᶠu`: Velocity field at cell centers and faces, respectively.
129+
Both reconstructions are needed to compute the full strain rate tensor.
130+
131+
See also [`compute_strain_rate_face_full!`](@ref) for the analogous calculation on cell faces.
132+
133+
# Notes:
134+
- it is recommended to use `ᶠu` and `ᶜu` as computed by
135+
[`set_velocity_quantities!`](@ref) and [`set_implicit_precomputed_quantities_part1!`](@ref)
136+
- Because the computation involves both vertical and horizontal gradients, this
137+
calculation cannot be lazified (for now). It requires a pre-allocated output field.
138+
"""
139+
function compute_strain_rate_center_full!(ᶜε, ᶜu, ᶠu)
140+
axis_uvw = (Geometry.UVWAxis(),)
141+
@. ᶜε = Geometry.project(axis_uvw, ᶜgradᵥ(UVW(ᶠu))) # vertical component
142+
@. ᶜε += Geometry.project(axis_uvw, gradₕ(UVW(ᶜu))) # horizontal component
143+
@. ᶜε = (ᶜε + adjoint(ᶜε)) / 2
144+
return ᶜε
145+
end
146+
147+
"""
148+
compute_strain_rate_face_full!(ᶠε, ᶜu, ᶠu)
149+
150+
Compute the full strain rate tensor at cell faces from velocity
151+
152+
# Arguments
153+
- `ᶠε`: Preallocated `UVW x UVW` tensor field for the strain rate at cell centers
154+
- `ᶜu, ᶠu`: Velocity field at cell centers and faces, respectively.
155+
Both reconstructions are needed to compute the full strain rate tensor.
156+
157+
See also [`compute_strain_rate_center_full!`](@ref) for the analogous calculation on cell centers.
158+
159+
# Notes:
160+
- it is recommended to use `ᶠu` and `ᶜu` as computed by
161+
[`set_velocity_quantities!`](@ref) and [`set_implicit_precomputed_quantities_part1!`](@ref)
162+
- Because the computation involves both vertical and horizontal gradients, this
163+
calculation cannot be lazified (for now). It requires a pre-allocated output field.
164+
- The calculation assumes no-flux boundary conditions
165+
"""
166+
function compute_strain_rate_face_full!(ᶠε, ᶜu, ᶠu)
167+
∇ᵥuvw_boundary = Geometry.outer(Geometry.WVector(0), UVW(0, 0, 0))
168+
∇bc = Operators.SetGradient(∇ᵥuvw_boundary)
169+
ᶠgradᵥ = Operators.GradientC2F(bottom = ∇bc, top = ∇bc)
170+
axis_uvw = (Geometry.UVWAxis(),)
171+
@. ᶠε = Geometry.project(axis_uvw, ᶠgradᵥ(UVW(ᶜu))) # vertical component
172+
@. ᶠε += Geometry.project(axis_uvw, gradₕ(UVW(ᶠu))) # horizontal component
173+
@. ᶠε = (ᶠε + adjoint(ᶠε)) / 2
174+
return ᶠε
175+
end
176+
177+
"""
178+
strain_rate_norm(S, axis = Geometry.UVWAxis())
179+
180+
Return a lazy representation of the strain rate norm `|S| = √(2 ∘ S : S)`
181+
182+
If `axis` is provided, project the strain rate tensor `S` onto the specified axis
183+
before computing the norm.
184+
185+
For example,
186+
- `axis = Geometry.UVAxis()` computes the horizontal strain rate norm, while
187+
- `axis = Geometry.WAxis()` computes the vertical strain rate norm.
188+
"""
189+
function strain_rate_norm(S, axis = Geometry.UVWAxis())
190+
S_proj = @. lazy(Geometry.project((axis,), S, (axis,)))
191+
S_norm = @. lazy((2 * norm_sqr(S_proj)))
192+
return S_norm
193+
end
194+
122195
"""
123196
g³³_field(space)
124197

test/utilities.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ end
8989
end
9090

9191
@testset "compute_strain_rate (c.f. analytical function)" begin
92-
# Test compute_strain_rate_face
92+
# Test compute_strain_rate_face_vertical
9393
(; helem, cent_space, face_space) = get_cartesian_spaces()
9494
ccoords, fcoords = get_coords(cent_space, face_space)
9595
FT = eltype(ccoords.x)
@@ -118,8 +118,8 @@ end
118118
ᶠu = @. UVW(Geometry.UVector(ᶠu)) +
119119
UVW(Geometry.VVector(ᶠv)) +
120120
UVW(Geometry.WVector(ᶠw))
121-
ᶜϵ .= CA.compute_strain_rate_center(Geometry.Covariant123Vector.(ᶠu))
122-
ᶠϵ .= CA.compute_strain_rate_face(Geometry.Covariant123Vector.(ᶜu))
121+
ᶜϵ .= CA.compute_strain_rate_center_vertical(Geometry.Covariant123Vector.(ᶠu))
122+
ᶠϵ .= CA.compute_strain_rate_face_vertical(Geometry.Covariant123Vector.(ᶜu))
123123

124124
# Center valued strain rate
125125
@test ᶜϵ.components.data.:1 == ᶜϵ.components.data.:1 .* FT(0)

0 commit comments

Comments
 (0)