@@ -82,43 +82,116 @@ state.
8282compute_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 )
9899end
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 )
120119end
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
0 commit comments